Новые URI KitKat не отвечают на Intent.ACTION_VIEW
Так как KitKat изменил URI от сборщиков до уровня
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+ Фото, но когда выбрано, Галерея просто показывает пустые экраны, в Фото сказано, что "medium not found"
То же самое со звуками, я использую
public static void playSound(Fragment f, Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "audio/*");
f.startActivity(intent);
}
который использовался для показа Google Play Музыки в предыдущих версиях, с небольшим пользовательским интерфейсом белого воспроизведения. С новыми URI я получаю исключение, что ни одно приложение не может справиться с этим намерением.
//С фотографиями смешно, что при выборе "Галерея" вместо "Картинки" в новом пользовательском интерфейсе KK picker он возвращает старые URI, которые работают.
Любые идеи?
Являются ли системные приложения просто не готовыми к новому урису? Должен ли я каким-то образом взломать новый уристать старым, чтобы они работали? Или я что-то упускаю?
Спасибо!
Ответы
Ответ 1
Решение состоит в том, чтобы передать флаг FLAG_GRANT_READ_URI_PERMISSION
в намерение (на KitKat и выше):
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Также убедитесь, что это содержимое Uri было извлечено из намерения ACTION_OPEN_DOCUMENT, как описано здесь: fooobar.com/questions/12209/...
Ответ 2
Вы можете использовать следующее намерение, чтобы выбрать изображение из галереи
Intent i = new Intent (Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, 2);
и получить выбранное изображение в onActivityResult, например,
@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 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);
}