2014-02-19 2 views
11

С KitKat изменил идентификаторы URI из сборщиков в подобныхНовые KitKat URIs не отвечают на Intent.ACTION_VIEW

content://com.android.providers.media.documents/document/image:3951 

тогда ни один из моих ACTION_VIEW намерений работать больше. Когда, например, пользователь выбирает изображение, я использую

public static void openImage(Fragment f, Uri uri) { 
     Intent intent = new Intent(Intent.ACTION_VIEW); 
     intent.setDataAndType(uri, "image/*"); 

     f.startActivity(intent); 
    } 

и Android Галерея Google+ Фото и придумать, но при выборе, галерея просто показывает пустой экран, фотографии говорят «среда не найдена»

В То же самое со звуками, я привык использовать

public static void playSound(Fragment f, Uri uri) { 
    Intent intent = new Intent(Intent.ACTION_VIEW); 
    intent.setDataAndType(uri, "audio/*"); 

    f.startActivity(intent); 
} 

Который используется, чтобы показать Google Play Music в предыдущих версиях, с небольшим количеством белого играя диалогового интерфейса. С новыми URI я получаю исключение, что ни одно приложение не может справиться с этим намерением.

// С фотографиями смешно, что при выборе «Галерея» вместо «Картинки» в новом пользовательском интерфейсе KK, он возвращает старые URI, которые работают.

Любые идеи? Являются ли системные приложения просто не готовыми к новому урису? Должен ли я каким-то образом взломать новый уристать старым, чтобы они работали? Или я чего-то не хватает?

Спасибо!

+0

Google изменил это из-за нового StorageProvider. Я думаю, вы можете посмотреть здесь: http://s.stefma.ws/62ad44 – StefMa

+0

Хорошо, ладно, я понимаю, почему они это сделали. Но пока они нарушили намерение ACTION_VIEW. Все, что я вижу, заключается в том, как импортировать через inputStream или parcelFileDescriptor, которые я не хочу использовать в моем случае использования. Я просто хочу хранить uris в своей базе данных и просматривать их во время работы во внешних приложениях. – urSus

+0

Похоже, что принимающие приложения не обрабатывают uri правильно в этом случае, например. они пытаются разобрать их, а не 'openInputStream()' на них. – botteaap

ответ

5

Решение передать флаг FLAG_GRANT_READ_URI_PERMISSION намерению (на KitKat и выше):

intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 

Также убедитесь, что это содержание Ури было извлечено из ACTION_OPEN_DOCUMENT намерения, как описано здесь: https://stackoverflow.com/a/19874645/334209

+0

Работает как ожидалось, спасибо –

0

Вы можете использовать следующее намерение, чтобы выбрать изображение из галереи

Intent i = new Intent (Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 
startActivityForResult(i, 2); 

и получить выбранный IMA ge in onActivityResult like,

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 

    super.onActivityResult(requestCode, resultCode, data); 

    if(data==null)return; 

    try { 
     Bitmap bit = scaleImage(this, data.getData()); 
     img.setImageBitmap(bit); 
    } catch (FileNotFoundException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

public static Bitmap scaleImage(Context context, Uri photoUri) throws IOException { 
     InputStream is = context.getContentResolver().openInputStream(photoUri); 

     BitmapFactory.Options dbo = new BitmapFactory.Options(); 

     dbo.inJustDecodeBounds = true; 

     BitmapFactory.decodeStream(is, null, dbo); 

     is.close(); 

     int rotatedWidth, rotatedHeight; 
     int orientation = getOrientation(context, photoUri); 

     if (orientation == 90 || orientation == 270) { 
      rotatedWidth = dbo.outHeight; 
      rotatedHeight = dbo.outWidth; 
     } else { 
      rotatedWidth = dbo.outWidth; 
      rotatedHeight = dbo.outHeight; 
     } 

     Bitmap srcBitmap; 
     is = context.getContentResolver().openInputStream(photoUri); 
     if (rotatedWidth > 100 || rotatedHeight > 100) { 
      float widthRatio = ((float) rotatedWidth)/((float) 100); 
      float heightRatio = ((float) rotatedHeight)/((float) 100); 
      float maxRatio = Math.max(widthRatio, heightRatio); 

      // Create the bitmap from file 
      BitmapFactory.Options options = new BitmapFactory.Options(); 
      options.inSampleSize = (int) maxRatio; 
      srcBitmap = BitmapFactory.decodeStream(is, null, options); 
     } else { 
      srcBitmap = BitmapFactory.decodeStream(is); 
     } 
     is.close(); 

     /* 
     * if the orientation is not 0 (or -1, which means we don't know), we 
     * have to do a rotation. 
     */ 
     if (orientation > 0) { 
      Matrix matrix = new Matrix(); 
      matrix.postRotate(orientation); 

      srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(), 
        srcBitmap.getHeight(), matrix, true); 
     } 

     String type = context.getContentResolver().getType(photoUri); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     if (type.equals("image/png")) { 
      srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); 
     } else if (type.equals("image/jpg") || type.equals("image/jpeg")) { 
      srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos); 
     } 
     byte[] bMapArray = baos.toByteArray(); 
     baos.close(); 
     return BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length); 
    } 

    public static int getOrientation(Context context, Uri photoUri) { 
     /* it's on the external media. */ 
     Cursor cursor = context.getContentResolver().query(photoUri, 
       new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null); 

     if (cursor.getCount() != 1) { 
      return -1; 
     } 

     cursor.moveToFirst(); 
     return cursor.getInt(0); 
    } 
Смежные вопросы