Намерение камеры не сохраняет фото
Я успешно использовал этот фрагмент кода раньше, но с файлом, указывающим где-то на 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);
}