#android #android-studio
#Android #android-studio
Вопрос:
мое приложение внезапно начало сбоить после попытки выбрать изображение из любой галереи. Он работает с этим же кодом в течение очень долгого времени. Недавно я подготовил его для Android 11, и после того, как я закончил редактировать код, он все еще работал. Сегодня он решил выбросить это исключение:
E/BitmapFactory: Unable to decode stream: java.io.FileNotFoundException:
/storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20200915-WA0003.jpg: open failed: EACCES (Permission denied)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.file.to.text, PID: 6149
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { dat=content://com.google.android.apps.photos.contentprovider/-1/1/content://media/external/images/media/63620/ORIGINAL/NONE/image/jpeg/2126822588 flg=0x1 clip={text/uri-list U:content://com.google.android.apps.photos.contentprovider/-1/1/content://media/external/images/media/63620/ORIGINAL/NONE/image/jpeg/2126822588} }} to activity {*mypackagename*/*mypackagename*.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:4846)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4887)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2017)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7403)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference
at com.file.to.text.MainActivity.getBase64String(MainActivity.kt:171)
at com.file.to.text.MainActivity.onActivityResult(MainActivity.kt:138)
at android.app.Activity.dispatchActivityResult(Activity.java:8119)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4839)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4887)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2017)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7403)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:935)
Я не знаю, что является причиной этого, разрешения на чтение из внешнего хранилища и запись во внешнее хранилище разрешены, и это исключение возникает с каждой галереей.
Я тестирую на устройстве со стандартным Android 10.
Я использовал этот код в своем приложении для выбора галерей изображений:
fun pickimage(view: View) {
//val getIntent = Intent(Intent.ACTION_GET_CONTENT)
//getIntent.type = "image/*"
val pickIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
pickIntent.type = "image/*"
//val chooserIntent = Intent.createChooser(getIntent, "Select Image")
//chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(pickIntent))
startActivityForResult(pickIntent, PICK_IMAGE)
pic.isEnabled = false
}
Результат onActivityResult():
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != RESULT_CANCELED amp;amp; resultCode == RESULT_OK) {
if (requestCode == PICK_IMAGE) {
val selectedImage = data!!.data
val picturePath = getPath(applicationContext, selectedImage)
val encoded = getBase64String(picturePath, press) //press - some integer
}
}
}
Строка getBase64String():
private fun getBase64String(path: String, press: Int): String {
val bitmap = BitmapFactory.decodeFile(path)
val byteArrayOutputStream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, press, byteArrayOutputStream)
val byteArray = byteArrayOutputStream.toByteArray()
return Base64.encodeToString(byteArray, Base64.DEFAULT)
}
Я был бы рад любой помощи.
Комментарии:
1. Выбросьте эту функцию getPath(). Вы можете использовать полученный uri напрямую для открытия inputstream и использовать поток в decodeStream() вместо этого. Тогда вы тоже будете готовы к Android 11.
2. @blackapps Большое вам спасибо, работает отлично. У меня есть небольшой вопрос, я использую функцию getPath(), чтобы также получить размер изображений и соответственно установить целое число «press», как я могу получить размер изображения без этой функции?
Ответ №1:
Uri uri = data.getData();
String projection [] = {
MediaStore.Images.Media.DATA
, MediaStore.Images.Media.DISPLAY_NAME
, MediaStore.Images.Media.SIZE};
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
if ( cursor==null)
{
Toast.makeText(context, "cursor==nullnncould not query content resolver fornn" uri.toString(), Toast.LENGTH_LONG).show();
return;
}
cursor.moveToFirst();
String data = cursor.getString(0);
String displayName = cursor.getString(1);
String size = cursor.getString(2);
Toast.makeText(context, "query() oknn" uri.toString()
"nnDISPLAY_NAME: " displayName
"nDATA: " data
"nSIZE: " size
, Toast.LENGTH_LONG).show();
cursor.close();