2014-10-14 11 views
5

मेरे एप्लिकेशन में उपयोगकर्ता गैलरी से अपलोड करें और अपलोड करें। कई उपकरणों पर मेरा कोड सही काम करता है लेकिन नए उपकरणों (आदि: सैमसंग एस 5, एलजी जी 2, सैमसंग एस 4) पर फोटो चुनते समय एप्लिकेशन दुर्घटनाग्रस्त हो जाता है। मैंने Google Play Store पर एप्लिकेशन अपलोड किया और इन डिवाइसों को डाउनलोड किया, फिर ऐप क्रैश होने पर Google Play पर रिपोर्ट भेज दी। यह मेरी चुनिंदा तस्वीर है और कोड का आकार बदलता है।नए डिवाइस पर फोटो चुनते समय एंड्रॉइड एप्लिकेशन क्रैश

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

} 

ये रिपोर्ट सैमसंग एस 5 और एलजी जी 2 से आई हैं।

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 

मैं इस समस्या का समाधान कैसे कर सकते हैं?

+1

मेनफेस्ट में जोड़ा गया android.permission.READ_EXTERNAL_STORAGE –

+1

मुझे याद है कि मुझे पहले इस समस्या का सामना करना पड़ा। यह अलग-अलग, अपरिचित यूआरआई के कारण हुआ था जो ऐप द्वारा लौटाया गया है (जैसा कि आपके स्टैक ट्रेस 'डेटा = ...' में दिखाया गया है। सैमसंग एस 5 के लिए: [यह सवाल] (http://stackoverflow.com/questions/20028319/how-to-convert-content-media-external-images-media-y-to-file-storage-sdc)। एलजी जी 2 के लिए: [यह सवाल] (http://stackoverflow.com/questions/19834842/android-gallery-on-kitkat-returns- अलग-uri-for-intent-action-get-content) –

उत्तर

20

क्योंकि एंड्रॉइड किटकैट के बाद से, आप सामान्य तरीके से छवि स्थानीय पथ नहीं चुन सकते हैं। कृपया डिवाइस एंड्रॉइड संस्करण की जांच करें, यदि संस्करण < किटकैट, तो आप अपना रास्ता उपयोग कर सकते हैं। यदि संस्करण किटकैट है या बाद में, आप फ़ाइल पथ प्राप्त करने के लिए इस कोड को आजमा सकते हैं, तो आप बिटमैप या जो कुछ भी चाहते हैं उसे कनवर्ट कर सकते हैं।

/** 
* 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()); 
} 
+0

एलजी पर सही काम कर रहा है G2। लेकिन मैं इस शाम को एस 5 पर परीक्षण करूंगा। मैं आशा करता हूँ यह काम करेगा। लेकिन मुझे एक और समस्या है। मैं छवि का आकार बदल रहा हूं 'बिटमैप myBitmap = getResizedBitmap (BitmapFactory.decodeFile (imagepath), 200,200); imageview.setImageBitmap (myBitmap); ' लेकिन अपलोड करते समय मैं छविपथ का उपयोग कर रहा हूं। तो अपलोड में बहुत समय लगता है। मैं आकार बदलकर छवि कैसे अपलोड कर सकता हूं? मदद के लिए धन्यवाद – sipdorus

+0

@sipdorus: जब आप फ़ाइल पथ प्राप्त करते हैं, तो आप फ़ाइल को बिटमैप में कनवर्ट करने के लिए इस कोड का उपयोग कर सकते हैं, फिर अपनी आकार बदलें विधि: BitmapFactory.Options विकल्प = new BitmapFactory.Options(); विकल्प.in संरक्षित कॉनफिग = बिटमैप.कॉन्फिग.एआरबीबी_8888; बिटमैप बिटमैप = बिटमैप फैक्टरी।decodeFile (फोटोपाथ, विकल्प); –

+0

क्षमा करें मुझे – sipdorus

2

यह कोड आपके 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()); 

यह AsyncTask से बुलाया जा रहा है, क्योंकि कभी कभी छवियों/फ़ाइलें संग्रहीत नहीं किया जा सकता है स्थानीय स्तर पर की तरह छवियों गूगल +, या Google डिस्क का समर्थन किया। जैसा कि इस Devbyte video में अनुशंसित है, हमेशा इसे पृष्ठभूमि थ्रेड पर कॉल करें।

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

} 

यह Storage Client Sample के लिए नमूना कोड से है और मैं Kitkat और लॉलीपॉप पर यह परीक्षण किया है।

पुराने संस्करणों और अद्यतनों पर परीक्षण करेगा। अगर कोई पुराने संस्करण पर इसका परीक्षण करता है, तो मुझे बताएं।

अद्यतन: जेलीबीन पर परीक्षण किया गया और यह काम करता है।

संबंधित मुद्दे