Android BitmapFactory работает в одном приложении, но не работает в другом - PullRequest
1 голос
/ 08 мая 2020

Я написал библиотеку со следующим кодом. Цель этого кода - получить объект 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 - не работает

Еще нужно знать, почему и как происходит такое поведение , чтобы я мог обновиться в будущем.

...