Я написал библиотеку со следующим кодом. Цель этого кода - получить объект Bitmap из пути к файлу и при необходимости повернуть его:
private fun rotateBitmap(imageURI: String) : File {
val options = BitmapFactory.Options()
val bitmap = BitmapFactory.decodeFile(imageURI, options)
val rotation = getRotation() // some function, always returns null in this scenario
var newBitmap = if (rotation != 0f) {
//New rotation matrix
val matrix = Matrix()
matrix.preRotate(rotation)
//Bitmap.createBitmap(bitmap, 0, 0, 1000, 1000, matrix, true)
Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
} else {
//No need to rotate
BitmapFactory.decodeFile(imageURI, options)
}
// ..... do some more stuff
}
Я использую эту библиотеку в трех разных приложениях. Приложения почти идентичны, за исключением некоторых ресурсов, таких как строки, цвета и т. Д. c. Все они работают одинаково, открывая галерею, чтобы позволить пользователю выбрать локальное изображение и передавая путь к файлу этого изображения этому методу как параметр imageURI
. Эта функция написана один раз и используется всеми ими одинаково, поэтому различия в реализации невозможны, поскольку они используют один и тот же код.
Во всех трех приложениях я выбираю один и тот же файл, что делает его передайте одинаковые imageURI
для каждого из них. rotation
всегда 0, что означает, что библиотека всегда выполняет часть else
. Благодаря отладке я знаю, что три приложения запускают rotateBitmap
точно одинаково, за исключением возвращаемого значения decodeFile
.
В приложении A
и B
он работает как предназначена. В приложении C
он всегда возвращает null
как для bitmap
, так и для newBitmap
, не выбрасывая Exception
.
Все три приложения имеют одинаковые разрешения.
Ресурсы как и память, также ведут себя примерно так же, потому что, как я уже сказал, приложения почти идентичны.
Я проверил документацию и несколько вопросов / ответов SO:
Но ни один из них не обращается и не объясняет, казалось бы, недетерминированное c поведение.
Любая идея как объяснить и / или решить эту проблему.
РЕДАКТИРОВАТЬ:
Согласно предложению CommonsWare , ошибка может возникнуть там, где imageURI
определен. Эта часть также работает точно так же во всех трех приложениях и дает одинаковые imageURI
во всех трех из них. Итак, здесь я включаю код, который его определяет:
Начальное действие для выбора изображения
(после получения разрешения)
val intent = Intent()
intent.type = "image/*"
intent.action = Intent.ACTION_GET_CONTENT
intent.putExtra(
MediaStore.EXTRA_OUTPUT,
Uri.fromFile(File(getExternalStorageDirectory(), "chosenImage"))
)
val photoIntent = Intent.createChooser(intent, "Select Picture")
startActivityForResult(photoIntent, PickImage)
Ответ процесса обработки
uri = "content://com.android.providers.media.documents/document/image%3A24655"
final String docId = DocumentsContract.getDocumentId(uri);
final String [] split = docId . split (":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String [] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
uri = "content://media/external/images/media"
selection = "_id=?"
selectionArgs = ["24655"]
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs)
{
Cursor cursor = null;
final String column = "_data";
final String [] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
Полученный imageURI
выглядит так = /storage/emulated/0/Download/tenor (1).gif
Это загруженный образ.
EDIT2:
Я не Обратите внимание, что приложение C
, которое имело нежелательное поведение, было скомпилировано с compileSdkVersion 29
и targetSdkVersion 29
, в то время как другие были скомпилированы с 28/28
.
Поэтому я попытался скомпилировать с compileSdkVersion 29
и targetSdkVersion 28
. Что заставило его работать. Однако, когда я перезаписал 29/29
, это тоже сработало.
После удаления и компиляции с compileSdkVersion 29
и targetSdkVersion 29
с самого начала это снова не сработало.
Итак.
- 28/28 - работает
- 29/29 - не работает
- 29/28 - работает
- 29 / 28 и перезапись на 29/29 - работает
- 29/28, удалить, переустановить с 29/29 - не работает
Еще нужно знать, почему и как происходит такое поведение , чтобы я мог обновиться в будущем.