私のアプリケーションでは、画像をサーバーに渡すために、ゲラから画像を選択しようとしています。
コードはAndroid 5以下では問題なく機能していますが、Android 6の場合、画像情報を取得できません。取得したログトレース
注:コードはAndroid 5以下のバージョンで正常に動作しています
11-06 12:27:43.736: W/System.err(31678): Java.lang.SecurityException: Permission Denial: reading com.google.Android.apps.photos.contentprovider.MediaContentProvider uri content://com.google.Android.apps.photos.contentprovider/0/1/content%3A//media/external/images/media/19138/ACTUAL/94710853 from pid=31678, uid=10111 requires the provider be exported, or grantUriPermission()
11-06 12:27:43.757: W/System.err(31678):
at Android.os.Parcel.readException(Parcel.Java:1599)
11-06 12:27:43.757: W/System.err(31678):
at Android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.Java:183)
11-06 12:27:43.757: W/System.err(31678):
at Android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.Java:135)
11-06 12:27:43.757: W/System.err(31678):
at Android.content.ContentProviderProxy.query(ContentProviderNative.Java:421)
11-06 12:27:43.757: W/System.err(31678):
at Android.content.ContentResolver.query(ContentResolver.Java:491)
11-06 12:27:43.757: W/System.err(31678):
at Android.content.ContentResolver.query(ContentResolver.Java:434)
11-06 12:27:43.758: W/System.err(31678):
at org.Apache.cordova.file.ContentFilesystem.openCursorForURL(ContentFilesystem.Java:258)
11-06 12:27:43.758: W/System.err(31678):
at org.Apache.cordova.file.ContentFilesystem.getFileMetadataForLocalURL(ContentFilesystem.Java:169)
11-06 12:27:43.758: W/System.err(31678):
at org.Apache.cordova.file.FileUtils.getFileMetadata(FileUtils.Java:822)
11-06 12:27:43.758: W/System.err(31678):
at org.Apache.cordova.file.FileUtils.access$500(FileUtils.Java:52)
11-06 12:27:43.758: W/System.err(31678):
at org.Apache.cordova.file.FileUtils$15.run(FileUtils.Java:394)
11-06 12:27:43.758: W/System.err(31678):
at org.Apache.cordova.file.FileUtils$25.run(FileUtils.Java:551)
11-06 12:27:43.758: W/System.err(31678):
at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1113)
11-06 12:27:43.758: W/System.err(31678):
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:588)
11-06 12:27:43.758: W/System.err(31678):
at Java.lang.Thread.run(Thread.Java:818)
このようにしてください...ボタンをクリックしてSDKバージョンを確認してください
if (Build.VERSION.SDK_INT >= 23){
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
// MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}else{
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
}
}else {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);
}
その後、OverrideメソッドonRequestPermissionsResultに次のコードを記述します。
case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {
// 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.
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
その後
@Override
protected void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);
switch (reqCode) {
case SELECT_PHOTO:
if (resultCode == RESULT_OK) {
try {
final Uri imageUri = data.getData();
final InputStream imageStream = getContentResolver().openInputStream(imageUri);
final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
contactimage.setImageBitmap(selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
実行時にユーザーに権限をリクエストする必要があると思います(これは、api 22から23で最も顕著な変更の1つです)。
Android開発者の許可ページ から抽出したこのスニペットを試すことができます
if (Build.VERSION.SDK_INT >= 23){
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_EXTERNAL_STORAGE)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
// MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
}
問題が解決したかどうかをお知らせください。
同じ問題がありました。を使用してギャラリーから画像を選択した後、Imageviewに表示された画像
Intent galleryIntent = new Intent(Intent.ACTION_PICK, Android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent, videoIdentifier);
そして、URIからビットマップ画像をデコードします
ただし、将来の使用のためにURIを保存し、アプリを再度開いて、保存されたURIを再利用することはできませんでした。 URIからビットマップをデコードできませんでした。
URIパスから元のコンテンツURIを抽出することで問題を解決しました
public String RemoveUnwantedString(String pathUri){
//pathUri = "content://com.google.Android.apps.photos.contentprovider/-1/2/content://media/external/video/media/5213/ORIGINAL/NONE/2106970034"
String[] d1 = pathUri.split("content://");
for (String item1:d1) {
if (item1.contains("media/")) {
String[] d2 = item1.split("/ORIGINAL/");
for (String item2:d2) {
if (item2.contains("media/")) {
pathUri = "content://" + item2;
break;
}
}
break;
}
}
//pathUri = "content://media/external/video/media/5213"
return pathUri;
}
マシュマロのギャラリーから画像を取得するには、実行時にREAD_EXTERNAL_STORAGE権限を付与する必要があります。 AndroidバージョンMは、アプリケーションへのアクセス許可の付与方法を変更しました。
マシュマロの前は、必要なすべての権限が一度に付与され、それはインストール時に行われます。ただし、マシュマロでは、ユーザーはその許可が必要な場合にのみ許可を求められ、ユーザーはその許可を許可または拒否する必要があります。
以下の2つのリンクは、さらに役立ちます。リンク1はAndroidの公式ドキュメントからのものであり、リンク2は実際の例を使用してこの問題を説明したブログです。
Link1: http://developer.Android.com/training/permissions/requesting.html
これは私が他の例で作成した簡単な方法です
必要な場所でCHECKGALLERYPERMISSION()メソッドを呼び出し、メソッド内にコードを貼り付けます
private void CHECKGALLERYPERMISSION()
{
int MY_READ_PERMISSION_REQUEST_CODE =1 ;
int PICK_IMAGE_REQUEST = 2;
if (ContextCompat.checkSelfPermission(YourActivity.this, Android.Manifest.permission.READ_EXTERNAL_STORAGE)== PackageManager.PERMISSION_GRANTED)
{
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
}
else
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
requestPermissions(
new String[]{Android.Manifest.permission.READ_EXTERNAL_STORAGE},
MY_READ_PERMISSION_REQUEST_CODE);
}
else
{
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[]
permissions, int[] grantResults) {
if (requestCode == MY_READ_PERMISSION_REQUEST_CODE
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null)
{
Uri uri = data.getData();
try
{
Bitmap bitmap = MediaStore.Images.Media.getBitmap(YourActivity.this.getContentResolver(), uri);
imageview.setImageBitmap(bitmap);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}