Я попробовал несколько ответов здесь, и я думаю, что у меня есть решение, которое будет работать каждый раз и управлять разрешениями.
Он основан на умном решении от LEO. Этот пост должен содержать весь код, необходимый для работы, и он должен работать на любом телефоне и любой версии Android;)
Чтобы иметь возможность выбирать файл с SD-карты, вам понадобится следующее в манифесте:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Константы:
private static final int PICK_IMAGE = 456; // Whatever number you like
public static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL = 28528; // Whatever number you like
public static final String FILE_TEMP_NAME = "temp_image"; // Whatever file name you like
Проверьте разрешение и, если возможно, запуститеImagePick
if (ContextCompat.checkSelfPermission(getThis(),
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getThis(),
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL);
}
else {
launchImagePick();
}
Разрешение ответа
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull
String permissions[],
@NonNull
int[] grantResults) {
if (manageReadExternalPermissionResponse(this, requestCode, grantResults)) {
launchImagePick();
}
}
Управление ответом на разрешение
public static boolean manageReadExternalPermissionResponse(final Activity activity, int requestCode, int[] grantResults) {
if (requestCode == MY_PERMISSIONS_REQUEST_READ_EXTERNAL) {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission was granted, yay! Do the
// contacts-related task you need to do.
return true;
} else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
boolean showRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.READ_EXTERNAL_STORAGE);
if (!showRationale) {
// The user also CHECKED "never ask again".
// You can either enable some fall back,
// disable features of your app
// or open another dialog explaining
// again the permission and directing to
// the app setting.
} else {
// The user did NOT check "never ask again".
// This is a good place to explain the user
// why you need the permission and ask if he/she wants
// to accept it (the rationale).
}
} else {
// Permission denied, boo! Disable the
// functionality that depends on this permission.
}
}
return false;
}
Запуск выбора изображения
private void launchImagePick() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, PICK_IMAGE);
// see onActivityResult
}
Управление ответом на выбор изображения
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE) {
if (resultCode == Activity.RESULT_OK) {
if (data != null && data.getData() != null) {
try {
InputStream inputStream = getContentResolver().openInputStream(data.getData())
if (inputStream != null) {
// No special persmission needed to store the file like that
FileOutputStream fos = openFileOutput(FILE_TEMP_NAME, Context.MODE_PRIVATE);
final int BUFFER_SIZE = 1 << 10 << 3; // 8 KiB buffer
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) > -1) {
fos.write(buffer, 0, bytesRead);
}
inputStream.close();
fos.close();
File tempImageFile = new File(getFilesDir()+"/"+FILE_TEMP_NAME);
// Do whatever you want with the File
// Delete when not needed anymore
deleteFile(FILE_TEMP_NAME);
}
}
catch (Exception e) {
e.printStackTrace();
}
} else {
// Error display
}
} else {
// The user did not select any image
}
}
}
Это все, ребята; это работает у меня на всех телефонах, которые у меня есть.
person
Quentin G.
schedule
16.03.2017
Uri
должен быть открыт как поток черезContentResolver
. Я давно нервничал по поводу приложений, которые предполагают, чтоcontent://
Uri
, представляющий файл, всегда можно преобразовать вFile
. - person CommonsWare   schedule 07.11.2013ContentResolver
и работать сUri
вместо URL-адресов файлов. Я сделаю это. Это также позволяет лучше обрабатыватьUri
, не относящиеся к галерее. - person Michael Greifeneder   schedule 08.11.2013InputStream
наContentResolver
, в заранее обозначенное место, чтобы оно имело известное имя файла. Однако для меня это звучит расточительно. Есть другие предложения? - person darrenp   schedule 15.01.2014InputStream
поверх JNI? К сожалению, для вас не так много вариантов. - person CommonsWare   schedule 15.01.2014InputStream
вместо файла (что отлично). Только чтение тегов EXIF немного сложно и требует библиотеки Дрю Ноакса. Большое спасибо за ваши комментарии. - person darrenp   schedule 16.01.2014