Намерение камеры не сохраняет фото

Я успешно использовал этот фрагмент кода раньше, но с файлом, указывающим где-то на SD-карте.

final File temp = new File(getCacheDir(), "temp.jpg");
temp.delete();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(temp));
startActivityForResult(intent, CONFIG.Intents.Actions.SELECT_CAMERA_PHOTO);

Однако, когда я использую getCacheDir вместо loc на SD-карте, кажется, что фотография никогда не сохраняется. Является ли это ограничением кеша и захвата изображения?

Ответ 1

Технически это связано с тем, что при использовании приложения "Камера" для записи изображения не поддерживается запись во внутреннюю память. Фактически вы можете заметить исключение, напечатанное в logcat, в котором указано Writing to internal storage is not supported. Однако реальная причина, по которой это не работает, заключается в том, что по умолчанию вы создаете файл, который является приватным для вашего пакета приложений, а другое приложение (например, приложение "Камера" ) не может получить доступ к этому файлу, поскольку оно не имеет разрешения на Сделай так. Внешнее хранилище является единственной доступной в глобальном масштабе частью файловой системы.

Обходной путь - создать файл с глобальными (WORLD_WRITEABLE) разрешениями. Как правило, это позволяет приложению камеры получать доступ к файлу через переданный Uri. На самом деле нет методов для этого непосредственно на File, поэтому вам нужно создать файл, используя методы, доступные в Context, а затем захватить с ним дескриптор:

//Remove if exists, the file MUST be created using the lines below
File f = new File(getFilesDir(), "Captured.jpg");
f.delete();
//Create new file
FileOutputStream fos = openFileOutput("Captured.jpg", Context.MODE_WORLD_WRITEABLE);
fos.close();
//Get reference to the file
File f = new File(getFilesDir(), "Captured.jpg");

Это также некоторые ограничения, в которых вы можете поместить файл, так как методы Context по существу создают файлы в корневом каталоге "файлы", и вы не можете перенаправить это в каталог кэша.

НТН

Ответ 2

Лучшее решение, которое я нашел, это: FileProvider (требуется поддержка-library-v4) Он использует внутреннее хранилище! https://developer.android.com/reference/android/support/v4/content/FileProvider.html

  • Определите свой FileProvider в манифесте в элементе приложения:

    <provider
          android:name="android.support.v4.content.FileProvider"
          android:authorities="your.package.name.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true" >
          <meta-data
                     android:name="android.support.FILE_PROVIDER_PATHS"
                     android:resource="@xml/image_path" />
    </provider>
    
  • Добавить разрешения в явном корневом элементе:

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" android:required="false" />
    
  • Определите пути изображения, например, res/xml/image_path.xml:

    <paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="captured_image" path="your/path/"/>
    </paths>
    
  • Java:

    private static final int IMAGE_REQUEST_CODE = 1;
    // your authority, must be the same as in your manifest file 
    private static final String CAPTURE_IMAGE_FILE_PROVIDER = "your.package.name.fileprovider";
    

4.1 цель захвата изображения:

    File path = new File(activity.getFilesDir(), "your/path");
    if (!path.exists()) path.mkdirs();
    File image = new File(path, "image.jpg");
    Uri imageUri = FileProvider.getUriForFile(activity, CAPTURE_IMAGE_FILE_PROVIDER, image);
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
    startActivityForResult(intent, IMAGE_REQUEST_CODE);

4.2 onActivityResult():

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (requestCode == IMAGE_REQUEST_CODE) {
            if (resultCode == Activity.RESULT_OK) {
                File path = new File(getFilesDir(), "your/path");
                if (!path.exists()) path.mkdirs();
                File imageFile = new File(path, "image.jpg");
                // use imageFile to open your image
            }
        }
        super.onActivityResult(requestCode, resultCode, intent);
    }