2

Я пытаюсь использовать BitmapFactory.decodefile(), чтобы создать уменьшенную версию фотографии камеры и установить ее в изображение в моем кадре. Am следуя следующим инструкциям из разработчиков Android: https://developer.android.com/training/camera/photobasics.html В этих инструкциях файлы создаются и хранятся внутри fileprovider который содержит какой-либо файл мета-данных в формате в формате XML. Так или иначе, BitmapFactory.decodefile(), похоже, не может получить доступ к этому файлу, в котором хранится изображение, содержимое которого uri находится внутри fileprovider. fileprovider создается внутри androidmanifest файла следующим образом:Создание пути FileProvider и проблемы с BitmapFactory.decodefile в Android

<provider 
android:authorities="mypackagename.fileprovider" 
android:name="android.support.v4.content.FileProvider" 
android:exported="false" android:grantUriPermissions="true"> 
<meta-data 
android:name="android.support.FILE_PROVIDER_PATHS" 
android:resource="@xml/file_paths" > 
</meta-data> 
</provider> 

файл file_paths XML выглядит следующим образом:

<?xml version="1.0" encoding="utf-8"?> 
<paths xmlns:android="http://schemas.android.com/apk/res/android"> 
<external-path name="my_images"   path="Android/data/mypackagename/files/Pictures/" /> 
</paths> 

Имя файла, где изображение будет находиться генерируется с помощью этого метода:

private File createImageFile() throws IOException { 
// Create an image file name 
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
String imageFileName = "JPEG_" + timeStamp + "_"; 
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); 
File image = File.createTempFile(imageFileName,".jpg",storageDir); 

// Save a file: path for use with ACTION_VIEW intents 
mCurrentPhotoPath = image.getAbsolutePath(); 
Log.d("absolute",""+image.getAbsolutePath()); 
return image; 
} 

код начинается намерение, чтобы сделать снимок с startactivityforresult(), как это:

Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
// Ensure that there's a camera activity to handle the intent 
if (i.resolveActivity(getPackageManager()) != null) { 
// Create the File where the photo should go 
photoFile = null; 
try { 
photoFile = createImageFile(); 
} catch (IOException ex) { 
// Error occurred while creating the File 

} 
// Continue only if the File was successfully created 
if (photoFile != null) { 
Uri photoURI = FileProvider.getUriForFile (this,"mypackagename.fileprovider",photoFile); 

i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoURI); 
startActivityForResult(i,TAKE_PICTURE); 
} 
} 

Теперь метод onActivityForResult() начинается, но если я могу установить, если заявление, как этот если (requestCode == TAKE_PICTURE & & ResultCode == RESULT_OK) он не работает. Я не знаю почему. От чтения справочных документов по android на классе fileprovider, я вижу, что Я должен открыть photoUri, который передается как дополнительный в моих намерениях. Согласно документам, я должен открыть его с помощью ContentResolver.openFileDescriptor, который вернет ParcelFileDescriptor. Каким-то образом это место, где находится только что сделанная камера. Как-то мне нужно получить доступ к имени файла из этого объекта ParcelFileDescriptor и передать его в файл BitmapFactory.decode, чтобы уменьшить изображение-растровое изображение и установить его на моем изображении. Я не знаю, как это сделать

При попытке масштабирования растрового изображения у меня есть следующий код, который возвращает -1, что означает, что «в соответствии с справочными документами android для класса BitmapFactory» была проблема декодирования файла ". Я не знаю, почему возникла проблема. Вот код, который возвращает -1:

BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions); 

int photoW = bmOptions.outWidth; 
int photoH = bmOptions.outHeight; 

И фотоW и фотоH возвращаются -1. Помните, что переменная mCurrentPhotoPath была инициализирована внутри метода CreateImageFile(), все в верхней части этого вопроса.

Я также попытался,

BitmapFactory.decodeFile(photoFile.getAbsolutePath(), bmOptions); 

Но все-таки тот же самый результат, на самом деле mCurrentPhotoPath и photoFile.getAbsolutePath() равные строки.

Я думаю, что каким-то образом файлпровайдер с его метаданным XML-файлом каким-то образом скрывает путь к файлу из BitmapFactory.decodefile().

Снимок сделан, когда я тестирую приложение и также хранятся в моей галерее фотографий телефона.

Просьба предоставить любые рекомендации или предложения, поскольку мне необходимо продолжить работу с библиотекой tess-two и выполнить OCR с изображениями с камеры.

Спасибо за ваши предложения

+0

попробуйте добавить временное разрешение для созданного файла - i.addFlags (Intent.FLAG_GRANT_WRITE_URI_PERMISSION); и повторите попытку. дай мне знать, если это работает. –

+0

Вы запрашиваете разрешение на хранение во время выполнения? –

ответ

3

я столкнулся точно с такой же проблемой, и это, как я съезжались с этим: в первую очередь установить i.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);, как было отмечено выше, перед запуском камеры. Затем, НЕ используйте метод BitmapFactory.decodeFile(), как он работает только с file:/// типом Юриса извлеченного с помощью Uri.fromFile(), но не с content:// типа Юриса извлекаться с помощью FileProvider.getUriForFile(), который необходимый путь для API,> = 24.

Вместо этого, использовать ContentResolver открыть InputStream и декодировать изображение следующим образом:

BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
bmOptions.inJustDecodeBounds = true; 
ContentResolver cr = getActivity().getContentResolver(); 
InputStream input = null; 
InputStream input1 = null; 
try { 
    input = cr.openInputStream(photoUri); 
    BitmapFactory.decodeStream(input, null, bmOptions); 
    if (input != null) { 
     input.close(); 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} 

int photoW = bmOptions.outWidth; 
int photoH = bmOptions.outHeight; 
try { 
    input1 = cr.openInputStream(photoUri); 
    Bitmap takenImage = BitmapFactory.decodeStream(input1);     
    if (input1 != null) { 
     input1.close(); 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} 

Обратите внимание, что для того, чтобы получить Bitmap, вы открыть поток 2-й вход, так как первый не может быть повторно.