首页 > 解决方案 > Android BitmapFactory 在一个应用程序中有效,但在另一个应用程序中无效

问题描述

我编写了一个包含以下代码的库。此代码的目的是从文件路径中获取位图对象并在需要时对其进行旋转:

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
}

我在三个不同的应用程序中使用这个库。这些应用程序几乎相同,除了一些资源,如字符串、颜色等。它们都工作相同,打开图库让用户选择本地图片并将该图片的文件路径作为imageURI参数传递给此方法。此功能只编写一次并由所有人以相同的方式使用,因此实现上的差异是不可能的,因为它们共享相同的代码。

在所有三个应用程序中,我选择了相同的文件,这使得imageURI每个应用程序都通过相同的文件。rotation始终为 0,这意味着库始终执行该部分else。通过调试我知道这三个应用程序运行rotateBitmap 完全一样,除了返回值decodeFile.

在应用程序中AB它按预期工作。在 AppC中,它总是返回null,bitmapnewBitmap,而不抛出任何 Exception.

所有三个应用程序都具有相同的权限。

像内存这样的资源的行为也几乎完全相同,因为正如我所说,这些应用程序几乎相同。

我检查了文档和一些 SO 问题/答案:

但他们都没有解决或解释看似不确定的行为。

关于如何解释和/或解决这个问题的任何想法都会有所帮助。

编辑:

正如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)

处理活动响应

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);
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

它是一个下载的图像。

编辑2:

我没有注意到C具有不良行为的 App 是用 和 编译的compileSdkVersion 29targetSdkVersion 29而其他的则是用28/28.

所以我尝试用compileSdkVersion 29and编译targetSdkVersion 28。这使它起作用。但是,当我用 覆盖时29/29,它也有效。

卸载并从头开始编译后compileSdkVersion 29targetSdkVersion 29它再次不起作用。

所以。

仍然需要知道为什么以及如何发生这种行为,以便我将来可以更新。

标签: androidkotlinbitmapandroid-bitmap

解决方案


推荐阅读