Android app crashes when selecting a photo on new devices

In my application, users select an image from the gallery and upload. On many devices, my code works fine, but on new devices (etc .: Samsung S5, LG G2, Samsung S4) the application crashes when you select a photo. I downloaded the application on the Google Play Store and downloaded these devices, and then canceled the report on Google Play when the application crashed. This is my image selection and code resizing.

Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Complete action using"), 1); public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) { int width = bm.getWidth(); int height = bm.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // create a matrix for the manipulation Matrix matrix = new Matrix(); // resize the bit map matrix.postScale(scaleHeight, scaleHeight); // recreate the new Bitmap Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false); return resizedBitmap; } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1 && resultCode == RESULT_OK) { //Bitmap photo = (Bitmap) data.getData().getPath(); Uri selectedImageUri = data.getData(); imagepath = getPath(selectedImageUri); Bitmap myBitmap = getResizedBitmap(BitmapFactory.decodeFile(imagepath),200,200); try { ExifInterface exif = new ExifInterface(imagepath); orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); Log.d("EXIF", "Exif: " + orientation); resimyon=Integer.toString(orientation); Matrix matrix = new Matrix(); if (orientation == 6) { matrix.postRotate(90); } else if (orientation == 3) { matrix.postRotate(180); } else if (orientation == 8) { matrix.postRotate(270); } myBitmap = Bitmap.createBitmap(myBitmap, 0, 0, myBitmap.getWidth(), myBitmap.getHeight(), matrix, true); // rotating bitmap } catch (Exception e) { } imageview.setImageBitmap(myBitmap); messageText.setText("Yรผklenecek dosya:" +imagepath); uploadButton.setEnabled(true); } 

These are reports from Samsung S5 and LG G2.

SAMSUNG S5

 java.lang.SecurityException konum: android.os.Parcel.readException java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { dat=content://media/external/images/media/1909 (has extras) }} to activity {com.turk.bakistik/com.turk.bakistik.Profilresimyukle}: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media/1909 from pid=29038, uid=10236 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission() at android.app.ActivityThread.deliverResults(ActivityThread.java:3663) at android.app.ActivityThread.handleSendResult(ActivityThread.java:3706) at android.app.ActivityThread.access$1400(ActivityThread.java:173) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1351) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5579) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaProvider uri content://media/external/images/media/1909 from pid=29038, uid=10236 requires android.permission.READ_EXTERNAL_STORAGE, or grantUriPermission() at android.os.Parcel.readException(Parcel.java:1465) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:185) at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137) at android.content.ContentProviderProxy.query(ContentProviderNative.java:413) at android.content.ContentResolver.query(ContentResolver.java:464) at android.content.ContentResolver.query(ContentResolver.java:407) at android.app.Activity.managedQuery(Activity.java:1898) at com.turk.bakistik.Profilresimyukle.getPath(Profilresimyukle.java:209) at com.turk.bakistik.Profilresimyukle.onActivityResult(Profilresimyukle.java:173) at android.app.Activity.dispatchActivityResult(Activity.java:5643) at android.app.ActivityThread.deliverResults(ActivityThread.java:3659) ... 11 more 

LG G2

 java.lang.NullPointerException konum: com.turk.bakistik.Profilresimyukle.getResizedBitmap java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { dat=content://com.android.providers.media.documents/document/image:41 flg=0x1 }} to activity {com.turk.bakistik/com.turk.bakistik.Profilresimyukle}: java.lang.NullPointerException at android.app.ActivityThread.deliverResults(ActivityThread.java:3382) at android.app.ActivityThread.handleSendResult(ActivityThread.java:3425) at android.app.ActivityThread.access$1300(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1248) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5105) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.NullPointerException at com.turk.bakistik.Profilresimyukle.getResizedBitmap(Profilresimyukle.java:123) at com.turk.bakistik.Profilresimyukle.onActivityResult(Profilresimyukle.java:175) at android.app.Activity.dispatchActivityResult(Activity.java:5467) at android.app.ActivityThread.deliverResults(ActivityThread.java:3378) ... 11 more 

How can I fix this problem?

+5
source share
2 answers

Because, since the Android kitkat, you cannot get the local image path of the image as a normal path. Please check the version of the Android device, if the version is <kitkat, you can use your path. If kitkat version or later, you can try this code to get the file path, then you can convert it to a bitmap or whatever.

 /** * Get a file path from a Uri. This will get the the path for Storage Access * Framework Documents, as well as the _data field for the MediaStore and * other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @author paulburke */ public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { // ExternalStorageProvider if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { return Environment.getExternalStorageDirectory() + "/" + split[1]; } // TODO handle non-primary volumes } // DownloadsProvider else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId( Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); return getDataColumn(context, contentUri, null, null); } // MediaProvider else if (isMediaDocument(uri)) { 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); } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { // Return the remote address if (isGooglePhotosUri(uri)) return uri.getLastPathSegment(); return getDataColumn(context, uri, null, null); } // File else if ("file".equalsIgnoreCase(uri.getScheme())) { return uri.getPath(); } return null; } /** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @param selection (Optional) Filter used in the query. * @param selectionArgs (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */ 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 index = cursor.getColumnIndexOrThrow(column); return cursor.getString(index); } } finally { if (cursor != null) cursor.close(); } return null; } /** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */ public static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */ public static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */ public static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); } /** * @param uri The Uri to check. * @return Whether the Uri authority is Google Photos. */ public static boolean isGooglePhotosUri(Uri uri) { return "com.google.android.apps.photos.content".equals(uri.getAuthority()); } 
+20
source

This code is in your onActivityResult:

 AsyncTask<Uri, Void, Bitmap> imageLoadAsyncTask = new AsyncTask<Uri, Void, Bitmap>() { @Override protected Bitmap doInBackground(Uri... uris) { return getBitmapFromUri(uris[0]); } @Override protected void onPostExecute(Bitmap bitmap) { //crop, resize, play, do whatever with the bitmap } }; imageLoadAsyncTask.execute(data.getData()); 

This is called from AsyncTask because sometimes images / files may not be stored locally, like images created on Google+ or Google Drive. As recommended in this Devbyte video , always call it in the background thread.

 private Bitmap getBitmapFromUri(Uri uri){ ParcelFileDescriptor parcelFileDescriptor = null; try { parcelFileDescriptor = getContentResolver().openFileDescriptor(uri, "r"); FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor); parcelFileDescriptor.close(); return bitmap; } catch (IOException e) { Log.e(tag, "Failed to load image.", e); e.printStackTrace(); return null; } finally{ try { if (parcelFileDescriptor != null) { parcelFileDescriptor.close(); } } catch (IOException e) { e.printStackTrace(); Log.e(tag, "Error closing ParcelFile Descriptor"); } } } 

This is from the sample code for the sample vault client , and I tested it on Kitkat and Lollipop.

Will check old versions and update them. If anyone checks this out on an older version, let me know.

Update : tested on JellyBean and it works.

+2
source

Source: https://habr.com/ru/post/1204625/


All Articles