Ý định Android ACTION_IMAGE_CAPTURE


163

Chúng tôi đang cố gắng sử dụng ứng dụng máy ảnh gốc để cho phép người dùng chụp ảnh mới. Nó hoạt động tốt nếu chúng ta bỏ qua EXTRA_OUTPUT extravà trả về hình ảnh Bitmap nhỏ. Tuy nhiên, nếu chúng tôi có putExtra(EXTRA_OUTPUT,...)ý định trước khi bắt đầu, mọi thứ sẽ hoạt động cho đến khi bạn cố gắng nhấn nút "Ok" trong ứng dụng máy ảnh. Nút "Ok" không làm gì cả. Ứng dụng camera vẫn mở và không có gì khóa. Chúng tôi có thể hủy bỏ nó, nhưng tập tin không bao giờ được viết. Chính xác thì chúng ta phải làm gì để có ACTION_IMAGE_CAPTUREthể viết bức ảnh được chụp vào một tập tin?

Chỉnh sửa: Điều này được thực hiện thông qua MediaStore.ACTION_IMAGE_CAPTUREý định, chỉ để rõ ràng

Câu trả lời:


144

Đây là một lỗi được ghi chép tốt trong một số phiên bản của Android. nghĩa là, trên các bản dựng kinh nghiệm của google trên Android, chụp ảnh không hoạt động như tài liệu. những gì tôi thường sử dụng là một cái gì đó như thế này trong một lớp tiện ích.

public boolean hasImageCaptureBug() {

    // list of known devices that have the bug
    ArrayList<String> devices = new ArrayList<String>();
    devices.add("android-devphone1/dream_devphone/dream");
    devices.add("generic/sdk/generic");
    devices.add("vodafone/vfpioneer/sapphire");
    devices.add("tmobile/kila/dream");
    devices.add("verizon/voles/sholes");
    devices.add("google_ion/google_ion/sapphire");

    return devices.contains(android.os.Build.BRAND + "/" + android.os.Build.PRODUCT + "/"
            + android.os.Build.DEVICE);

}

sau đó khi tôi khởi chạy chức năng chụp ảnh, tôi tạo ra một ý định kiểm tra lỗi.

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (hasImageCaptureBug()) {
    i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/tmp")));
} else {
    i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
startActivityForResult(i, mRequestCode);

sau đó trong hoạt động mà tôi trở lại, tôi làm những việc khác nhau dựa trên thiết bị.

protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
     switch (requestCode) {
         case GlobalConstants.IMAGE_CAPTURE:
             Uri u;
             if (hasImageCaptureBug()) {
                 File fi = new File("/sdcard/tmp");
                 try {
                     u = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), fi.getAbsolutePath(), null, null));
                     if (!fi.delete()) {
                         Log.i("logMarker", "Failed to delete " + fi);
                     }
                 } catch (FileNotFoundException e) {
                     e.printStackTrace();
                 }
             } else {
                u = intent.getData();
            }
    }

điều này giúp bạn tiết kiệm được việc phải viết một ứng dụng máy ảnh mới, nhưng mã này cũng không tuyệt vời. những vấn đề lớn là

  1. bạn không bao giờ có được hình ảnh kích thước đầy đủ từ các thiết bị có lỗi. bạn nhận được hình ảnh rộng 512px được chèn vào nhà cung cấp nội dung hình ảnh. trên các thiết bị không có lỗi, mọi thứ đều hoạt động như tài liệu, bạn sẽ có được một bức tranh lớn bình thường.

  2. bạn phải duy trì danh sách như đã viết, các thiết bị có thể được flash với phiên bản Android (giả sử bản dựng của cyanogenmod ) đã sửa lỗi. Nếu điều đó xảy ra, mã của bạn sẽ bị sập. Cách khắc phục là sử dụng toàn bộ dấu vân tay của thiết bị.


21
trên Galaxy S: aim.getData () trả về null và hơn nữa, ứng dụng máy ảnh trên Galaxy tự chèn ảnh mới vào thư viện, nhưng không có uri nào quay lại. Vì vậy, nếu bạn chèn ảnh từ tệp vào thư viện, sẽ có ảnh trùng lặp.
Arseniy

1
hey thiết bị của tôi không được liệt kê ở đây và tôi đã triển khai theo cách của bạn. Nhưng ứng dụng của tôi vẫn gặp sự cố. Tôi không biết lý do. Xin hãy giúp tôi
Geetanjali

sử dụng mã này trên các thiết bị droid-x và sony xpheria. Cả hai thiết bị trả về giá trị mục đích là null. còn droidx trả về mã kết quả là 0 trong khi xpheria trả về mã kết quả là -1. Bất cứ ai cũng biết tại sao nên như vậy.
rOrlig

5
Liên kết đến "lỗi tài liệu tốt" ở đầu câu trả lời của yanokwa là không chính xác. Lỗi đó là về việc gọi ứng dụng máy ảnh mà không cần đặtExtra (EXTRA_OUTPUT, ...)
Frank Harper

code.google.com/p/android/issues/detail?id=1480 Vâng, làm thế nào để bạn giải thích điều này sau đó?
Bút chì

50

Tôi biết điều này đã được trả lời trước đây nhưng tôi biết rất nhiều người bị vấp phải điều này, vì vậy tôi sẽ thêm một bình luận.

Tôi đã có vấn đề chính xác tương tự xảy ra trên Nexus One của tôi. Đây là từ tệp không tồn tại trên đĩa trước khi ứng dụng camera bắt đầu. Do đó, tôi chắc chắn rằng tệp hiện có trước khi khởi động ứng dụng camera. Đây là một số mã mẫu mà tôi đã sử dụng:

String storageState = Environment.getExternalStorageState();
        if(storageState.equals(Environment.MEDIA_MOUNTED)) {

            String path = Environment.getExternalStorageDirectory().getName() + File.separatorChar + "Android/data/" + MainActivity.this.getPackageName() + "/files/" + md5(upc) + ".jpg";
            _photoFile = new File(path);
            try {
                if(_photoFile.exists() == false) {
                    _photoFile.getParentFile().mkdirs();
                    _photoFile.createNewFile();
                }

            } catch (IOException e) {
                Log.e(TAG, "Could not create file.", e);
            }
            Log.i(TAG, path);

            _fileUri = Uri.fromFile(_photoFile);
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE );
            intent.putExtra( MediaStore.EXTRA_OUTPUT, _fileUri);
            startActivityForResult(intent, TAKE_PICTURE);
        }   else {
            new AlertDialog.Builder(MainActivity.this)
            .setMessage("External Storeage (SD Card) is required.\n\nCurrent state: " + storageState)
            .setCancelable(true).create().show();
        }

Trước tiên tôi tạo một tên tệp duy nhất (phần nào) bằng hàm băm MD5 và đặt nó vào thư mục thích hợp. Sau đó tôi kiểm tra xem nó có tồn tại không (không nên, nhưng dù sao thì nó cũng nên kiểm tra). Nếu nó không tồn tại, tôi lấy thư mục mẹ (một thư mục) và tạo cấu trúc phân cấp thư mục theo nó (do đó nếu các thư mục dẫn đến vị trí của tệp không tồn tại, chúng sẽ theo dòng này. Tôi tạo tập tin. Một khi tập tin được tạo, tôi lấy Uri và chuyển nó cho mục đích và sau đó nút OK hoạt động như mong đợi và tất cả đều là vàng.

Bây giờ, khi nhấn nút Ok trên ứng dụng camera, tập tin sẽ có mặt ở vị trí đã cho. Trong ví dụ này, nó sẽ là /sdcard/Android/data/com.example.myapp/files/234asdioue23498ad.jpg

Không cần phải sao chép tệp trong "onActivityResult" như đã đăng ở trên.


13
Hãy chắc chắn rằng bạn có <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />trong bảng kê khai của mình nếu bạn đang sử dụng Android 1.5 mới hơn - đã dành vài giờ để gỡ lỗi các công cụ máy ảnh và điều này không được bao gồm để tiết kiệm của tôi luôn thất bại.
swanson

Điều này hoạt động tốt với tôi, nhưng cứ khoảng 10 hình ảnh trở lên, tệp trống không bị ghi đè và tôi kết thúc bằng một tệp 0 byte trong đó hình ảnh phải có. Nó rất khó chịu và rất khó để theo dõi.
joey_g216

2
trên một số thiết bị, chẳng hạn như nexus 7 với thạch đậu, bạn cần thay đổi Môi trường.getExternalStorageDirectory (). getName () để sử dụng .getAbsolutePath () thay vì .getName ()
Keith

35

Tôi đã trải qua một số chiến lược chụp ảnh và dường như luôn có một trường hợp, một nền tảng hoặc một số thiết bị nhất định, trong đó một số hoặc tất cả các chiến lược trên sẽ thất bại theo những cách không ngờ tới. Tôi đã có thể tìm thấy một chiến lược sử dụng mã tạo URI bên dưới, dường như hoạt động trong hầu hết các trường hợp.

mPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
            new ContentValues());
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri);
startActivityForResult(intent,CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE_CONTENT_RESOLVER);

Để đóng góp thêm cho cuộc thảo luận và giúp đỡ những người mới tham gia Tôi đã tạo một ứng dụng mẫu / thử nghiệm cho thấy một số chiến lược khác nhau để thực hiện chụp ảnh. Đóng góp của các triển khai khác chắc chắn được khuyến khích để thêm vào cuộc thảo luận.

https://github.com/deepwinter/AndroidCameraTester


Điều này thật tuyệt Tôi chưa thử nghiệm điều này trên tất cả các thiết bị của mình, nhưng tôi cho rằng bạn đã làm như vậy khá nhiều rồi. Có quá nhiều tiếng ồn về chủ đề này, và câu trả lời đặc biệt này rất đơn giản và rõ ràng. Hoạt động trên Nexus 5 cho đến nay, đó là nơi đầu tiên tôi nhận được rất nhiều báo cáo rằng ACTION_IMAGE_CAPTURE không hoạt động mà không có EXTRA_OUTPUT. Tôi hy vọng điều này hoạt động trên tất cả các bảng, nhưng cho đến nay là rất tốt. Thx
Giàu

1
@deepwinter - Cảm ơn ngài. Tôi đã nhổ tóc ra nhưng giải pháp giải quyết nội dung của bạn hoạt động tốt trên tất cả các tình huống có vấn đề tôi gặp phải.
Billy Coover

Loại muộn của bữa tiệc này nhưng đây là giải pháp duy nhất để làm việc cho tôi. Cảm ơn nhiều!
StackJP

Tôi bằng cách nào đó có thể truy xuất MediaStore.EXTRA_OUTPUT onActivityResulthoặc tôi thực sự phải nhớ nó? Tôi sẽ phải liên tục lưu nó để ứng dụng của tôi thậm chí còn nhớ nó nếu nó bị phá hủy trong khi một bức ảnh được chụp ...
prom85

Nó không hoạt động trên samsung galaxy note 3 với lolipop: ava.lang.NullPulumException: Cố gắng gọi phương thức ảo 'java.lang.String android.net.Uri.getScheme ()' trên một tham chiếu đối tượng null
Igor Janković

30

Tôi gặp vấn đề tương tự khi nút OK trong ứng dụng máy ảnh không làm gì cả, cả trên trình giả lập và trên nexus.

Vấn đề đã biến mất sau khi chỉ định tên tệp an toàn không có khoảng trắng, không có ký tự đặc biệt, ngoài MediaStore.EXTRA_OUTPUT ra, nếu bạn chỉ định một tệp nằm trong thư mục chưa được tạo, trước tiên bạn phải tạo nó. Ứng dụng máy ảnh không làm mkdir cho bạn.


1
Và hãy chắc chắn rằng bạn sử dụng mkdirs()thay vì mkdir()nếu đường dẫn của bạn có nhiều cấp độ thư mục và bạn muốn tất cả chúng được tạo ( mkdirchỉ tạo cái cuối cùng, thư mục 'lá'). Tôi đã có một số vấn đề với điều đó, và câu trả lời này đã giúp tôi.
Diana

chúng ta có thể sử dụng dấu thời gian đơn giản không ?? hoặc cũng có thể làm cho một số lỗi ?? những lời cầu xin hãy gắn thẻ tôi khi được trả lời :)
Rakeeb Rajbhandari

@ user2247689 Tôi không chắc chắn về tên tệp bạn đã tạo bởi "dấu thời gian đơn giản" nhưng miễn là chúng không chứa các ký tự đặc biệt không được định dạng FAT cho phép trên thẻ SD thì tôi nghĩ là ổn.
Yenchi

28

Quy trình công việc bạn mô tả nên hoạt động như bạn đã mô tả. Nó có thể hữu ích nếu bạn có thể chỉ cho chúng tôi mã xung quanh việc tạo ra Ý định. Nói chung, mẫu sau sẽ cho phép bạn làm những gì bạn đang cố gắng.

private void saveFullImage() {
  Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  File file = new File(Environment.getExternalStorageDirectory(), "test.jpg");
  outputFileUri = Uri.fromFile(file);
  intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
  startActivityForResult(intent, TAKE_PICTURE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if ((requestCode == TAKE_PICTURE) && (resultCode == Activity.RESULT_OK)) {
    // Check if the result includes a thumbnail Bitmap
    if (data == null) {    
      // TODO Do something with the full image stored
      // in outputFileUri. Perhaps copying it to the app folder
    }
  }
}

Lưu ý rằng đó là Hoạt động máy ảnh sẽ tạo và lưu tệp và thực tế nó không phải là một phần của ứng dụng của bạn, vì vậy nó sẽ không có quyền ghi vào thư mục ứng dụng của bạn. Để lưu tệp vào thư mục ứng dụng của bạn, hãy tạo một tệp tạm thời trên thẻ SD và di chuyển tệp đó vào thư mục ứng dụng của bạn trong onActivityResulttrình xử lý.


Điều này / nên / làm việc, nhưng nút ok của ứng dụng máy ảnh không làm gì cả. Chúng tôi đã làm cho nó hoạt động bằng văn bản vào thẻ SD, vì vậy tôi nghi ngờ đây là sự cố về quyền tệp (mặc dù tôi nghĩ rằng một ứng dụng tự động có quyền ghi vào thư mục cá nhân của nó). cảm ơn đã giúp đỡ!
vẽ

1
Ứng dụng của bạn có quyền ghi vào thư mục cá nhân - ứng dụng máy ảnh (đang chụp ảnh) thì không. Bạn có thể di chuyển tệp trong onActivityResult, vì đó là trong ứng dụng của bạn. Ngoài ra, bạn có thể tự triển khai camera Hoạt động, nhưng điều đó có vẻ quá mức cần thiết.
Reto Meier

Làm lại ứng dụng máy ảnh dường như là một cách tiếp cận phổ biến nhưng tẻ nhạt ... Khi chúng tôi sử dụng getDir ("hình ảnh", MODE_WORLD_WRITEABLE), quyền đó không áp dụng cho bất kỳ tệp nào chúng tôi bảo nó tạo trong thư mục đó?
vẽ

Không cần thiết. Quyền cho thư mục, không nhất thiết phải cho các tệp trong đó.
Reto Meier

Tôi đã thử nghiệm mã với các thiết bị Android với Android 2.2 trở lên và tất cả chúng đều lưu hình ảnh vào đường dẫn được cung cấp. Vì vậy, tôi đoán rằng đây phải là hành vi tiêu chuẩn để có được hình ảnh.
Janusz

7

Để theo dõi nhận xét của Yenchi ở trên, nút OK cũng sẽ không làm gì nếu ứng dụng máy ảnh không thể ghi vào thư mục được đề cập.

Điều đó có nghĩa là bạn không thể tạo tệp ở một nơi chỉ có thể ghi được bằng ứng dụng của bạn (ví dụ: một cái gì đó dưới getCacheDir())cái gì đó getExternalFilesDir()phải hoạt động, tuy nhiên.

Sẽ thật tuyệt nếu ứng dụng máy ảnh in thông báo lỗi vào nhật ký nếu nó không thể ghi vào EXTRA_OUTPUTđường dẫn đã chỉ định , nhưng tôi đã không tìm thấy.


4

để camera ghi vào sdcard nhưng giữ một Album mới trên ứng dụng thư viện Tôi sử dụng cái này:

 File imageDirectory = new File("/sdcard/signifio");
          String path = imageDirectory.toString().toLowerCase();
           String name = imageDirectory.getName().toLowerCase();


            ContentValues values = new ContentValues(); 
            values.put(Media.TITLE, "Image"); 
            values.put(Images.Media.BUCKET_ID, path.hashCode());
            values.put(Images.Media.BUCKET_DISPLAY_NAME,name);

            values.put(Images.Media.MIME_TYPE, "image/jpeg");
            values.put(Media.DESCRIPTION, "Image capture by camera");
           values.put("_data", "/sdcard/signifio/1111.jpg");
         uri = getContentResolver().insert( Media.EXTERNAL_CONTENT_URI , values);
            Intent i = new Intent("android.media.action.IMAGE_CAPTURE"); 

            i.putExtra(MediaStore.EXTRA_OUTPUT, uri);

            startActivityForResult(i, 0); 

Xin lưu ý rằng bạn sẽ cần tạo một tên tệp duy nhất mỗi lần và thay thế teh 1111.jpg mà tôi đã viết. Điều này đã được thử nghiệm với nexus một. uri được khai báo trong lớp riêng, vì vậy trên kết quả hoạt động tôi có thể tải hình ảnh từ uri sang imageView để xem trước nếu cần.


cột "_data" đến từ đâu? không có hằng số cho nó?
Matthias

3
à, đó là developer.android.com/reference/android/provider/ mài Bạn thực sự không nên sử dụng chuỗi ma thuật trong mã.
Matthias

1

Tôi đã có cùng một vấn đề và tôi đã sửa nó bằng cách sau:

Vấn đề là khi bạn chỉ định một tệp mà chỉ ứng dụng của bạn có quyền truy cập (ví dụ: bằng cách gọi getFileStreamPath("file");)

Đó là lý do tại sao tôi chỉ đảm bảo rằng tệp đã cho thực sự tồn tại và MỌI NGƯỜI có quyền truy cập ghi vào nó.

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File outFile = getFileStreamPath(Config.IMAGE_FILENAME);
outFile.createNewFile();
outFile.setWritable(true, false);
intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT,Uri.fromFile(outFile));
startActivityForResult(intent, 2);

Bằng cách này, ứng dụng camera có quyền truy cập ghi vào Uri đã cho và nút OK hoạt động tốt :)


Trình giả lập AndroidR.78 (trình giả lập 2.1) ném NoSuchMethodError: java.io.File.setWritable
jwadsack

1

Tôi khuyên bạn nên theo dõi bài huấn luyện android để chụp ảnh. Họ cho thấy trong một ví dụ làm thế nào để chụp ảnh nhỏ và lớn. Bạn cũng có thể tải mã nguồn từ đây


0

Tôi đã tạo thư viện đơn giản để quản lý việc chọn hình ảnh từ các nguồn khác nhau (Thư viện, Máy ảnh), có thể lưu nó vào một số vị trí (Thẻ SD hoặc bộ nhớ trong) và trả lại hình ảnh để vui lòng sử dụng và cải thiện nó - Android-ImageChooser .


liên kết của bạn không hoạt động nữa !! tại sao, tôi đã thấy nó 2 tuần trước và tôi muốn sử dụng nó :(
Mohammad Ersan

0

Các tập tin cần phải được ghi lại bằng máy ảnh, như Praveen chỉ ra.

Trong cách sử dụng của tôi, tôi muốn lưu trữ tệp trong bộ nhớ trong. Tôi đã làm điều này với:

Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (i.resolveActivity(getPackageManager()!=null)){
    try{
        cacheFile = createTempFile("img",".jpg",getCacheDir());
        cacheFile.setWritavle(true,false);
    }catch(IOException e){}
    if(cacheFile != null){
        i.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(cacheFile));
        startActivityForResult(i,REQUEST_IMAGE_CAPTURE);
    }
}

Đây cacheFilelà một tập tin toàn cầu được sử dụng để chỉ tập tin được viết. Sau đó, trong phương thức kết quả, ý định trả về là null. Sau đó, phương thức xử lý ý định trông như sau:

protected void onActivityResult(int requestCode,int resultCode,Intent data){
    if(requestCode != RESULT_OK){
        return;
    }
    if(requestCode == REQUEST_IMAGE_CAPTURE){
        try{
            File output = getImageFile();
            if(output != null && cacheFile != null){
                copyFile(cacheFile,output);

                //Process image file stored at output

                cacheFile.delete();
                cacheFile=null;
            }
        }catch(IOException e){}
    }
}

Dưới đây getImageFile()là một phương thức tiện ích để đặt tên và tạo tệp trong đó hình ảnh sẽ được lưu trữ và copyFile()là phương pháp để sao chép tệp.


0

Bạn có thể sử dụng mã này

private Intent getCameraIntent() {

    PackageManager packageManager = mContext.getPackageManager();
    List<ApplicationInfo> list = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
    Intent main = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    List<ResolveInfo> launchables = packageManager.queryIntentActivities(main, 0);
    if (launchables.size() == 1)
        return packageManager.getLaunchIntentForPackage(launchables.get(0).activityInfo.packageName);
    else
        for (int n = 0; n < list.size(); n++) {
            if ((list.get(n).flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
                Log.d("TAG", "Installed Applications  : " + list.get(n).loadLabel(packageManager).toString());
                Log.d("TAG", "package name  : " + list.get(n).packageName);
                String defaultCameraPackage = list.get(n).packageName;


                if (launchables.size() > 1)
                    for (int i = 0; i < launchables.size(); i++) {
                        if (defaultCameraPackage.equals(launchables.get(i).activityInfo.packageName)) {
                            return packageManager.getLaunchIntentForPackage(defaultCameraPackage);
                        }
                    }
            }
        }
    return null;
}

0

Rất đơn giản để giải quyết vấn đề này với Mã kết quả hoạt động Đơn giản thử phương pháp này

if (reqCode == RECORD_VIDEO) {
   if(resCode == RESULT_OK) {
       if (uri != null) {
           compress();
       }
    } else if(resCode == RESULT_CANCELED && data!=null){
       Toast.makeText(MainActivity.this,"No Video Recorded",Toast.LENGTH_SHORT).show();
   }
}

Đoạn mã không đầy đủ ở trên không xứng đáng với sự đơn giản mà nó tuyên bố. Chắc chắn, có những phức tạp tiềm ẩn cho những du khách xa lạ. Chẳng hạn như quét sự hiện diện hoặc vắng mặt của tập tin. Chẳng hạn như héo nó là có sẵn công khai hoặc riêng tư cho ứng dụng. Chẳng hạn như sự cần thiết của một nhà cung cấp hoặc nhận được kích thước chỉ hình thu nhỏ. Đây là những lỗ hổng thông tin cho khách du lịch không cần thiết phải nhận thức được.
Truthadjustr

0
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_CANCELED)
    {
        //do not process data, I use return; to resume activity calling camera intent
        enter code here
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.