実現したいこと
Uriの中身(存在)チェックのやり方について
前提
Androidアプリ(java)でギャラリーから写真を選択しImageViewに表示させる処理を実装しています。
アプリ再起動後も表示出来るようにUri情報をプリファレンスデータに保存して、起動後はそのプリファレンスデータのUri情報を使用して表示させています。
表示までは出来たのですが、例外処理で選択した写真が削除された場合、データが存在せず落ちてしまいます。
Uriのデータが存在しているかのチェックはどのように実装すれば良いのでしょうか。
該当のソースコード
・Uriで表示させる処理
String DataPhoto = PreferencesData.getString(PreDataPhoto, null); //写真データのUri情報をプリファレンスデータから取得(uri文字列データ) //写真データが登録されていたら表示する if (DataPhoto != null) { Uri uri = Uri.parse(DataPhoto); ImageView imageView = (ImageView) findViewById(pageImageViewID); ★この時にデータが削除されていると落ちる imageView.setImageURI(uri); }
20230525 追加
整理する為、以下別アクティビティで本件の処理をコーディングしました。
しかし同様に「★1」の箇所で落ちてしまいました。
package com.example.handbook; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.ImageView; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; public class TestActivity1 extends AppCompatActivity implements View.OnClickListener { SharedPreferences PreferencesData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test1); findViewById(R.id.page999PhotoIcon).setOnClickListener(this); ImageView imageView = findViewById(R.id.page999Image); PreferencesData = getSharedPreferences("testData2022aaa", Context.MODE_PRIVATE); String uriStr = PreferencesData.getString("Data999Photo", null); if(uriStr != null) { Uri uri = Uri.parse(uriStr); ★2 //Log.d(LOG_TAG, "pref uri=" + uri); //imageView.setImageURI(uri); try(InputStream is = new BufferedInputStream(getContentResolver().openInputStream(uri))) { ★1 Bitmap bitmap = BitmapFactory.decodeStream(is); imageView.setImageBitmap(bitmap); } catch(IOException e) { e.printStackTrace(); } } } // 各ビューのクリック時の操作処理 @SuppressLint("ResourceType") public void onClick(View v) { switch (v.getId()) { case R.id.page999PhotoIcon: //P6-1写真アイコンのクリック処理 //ギャラリーを開く launcher999.launch(new String[]{"image/*"}); break; default: break; } } ActivityResultLauncher<String[]> launcher999 = registerForActivityResult(new ActivityResultContracts.OpenDocument(), uri -> { if (uri != null) { //写真を表示する ImageView imageView = (ImageView) findViewById(R.id.page999Image); imageView.setImageURI(uri); //パーミッション付与 if (Build.VERSION.SDK_INT >= 19) { getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); } //プレファレンスデータに保存 PreferencesData.edit().putString("Data999Photo", uri.toString()).commit(); } }); }
Logcatを見ると以下ログが出ました。
2023-05-25 13:22:43.509 2662-2662/com.rapp.handbook E/AndroidRuntime: FATAL EXCEPTION: main Process: com.rapp.handbook, PID: 2662 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rapp.handbook/com.example.handbook.TestActivity1}: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{e328407 2662:com.rapp.handbook/u0a310} (pid=2662, uid=10310) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3641) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3798) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2216) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7902) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:583) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1009) Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{e328407 2662:com.rapp.handbook/u0a310} (pid=2662, uid=10310) requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs at android.os.Parcel.createExceptionOrNull(Parcel.java:2426) at android.os.Parcel.createException(Parcel.java:2410) at android.os.Parcel.readException(Parcel.java:2393) at android.os.Parcel.readException(Parcel.java:2335) at android.app.IActivityManager$Stub$Proxy.getContentProvider(IActivityManager.java:5853) at android.app.ActivityThread.acquireProvider(ActivityThread.java:7036) at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:3340) at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:2561) at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:2045) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1876) at android.content.ContentResolver.openInputStream(ContentResolver.java:1536) at com.example.handbook.TestActivity1.onCreate(TestActivity1.java:44) at android.app.Activity.performCreate(Activity.java:8049) at android.app.Activity.performCreate(Activity.java:8029) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1330) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3614) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3798) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2216) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7902) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:583) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1009) Caused by: android.os.RemoteException: Remote stack trace: at com.android.server.am.ContentProviderHelper.checkAssociationAndPermissionLocked(ContentProviderHelper.java:611) at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:235) at com.android.server.am.ContentProviderHelper.getContentProvider(ContentProviderHelper.java:125) at com.android.server.am.ActivityManagerService.getContentProvider(ActivityManagerService.java:6131) at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2442)
Permissionと記載があったので「★2」に以下を追加した所以下Logcatに変わりました。
getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
2023-05-25 13:21:57.778 2379-2379/com.rapp.handbook E/AndroidRuntime: FATAL EXCEPTION: main Process: com.rapp.handbook, PID: 2379 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rapp.handbook/com.example.handbook.TestActivity1}: java.lang.SecurityException: No persistable permission grants found for UID 10310 and Uri content://com.android.providers.media.documents/document/image:1000000489 <文字数制限の為抜粋> Caused by: java.lang.SecurityException: No persistable permission grants found for UID 10310 and Uri content://com.android.providers.media.documents/document/image:1000000489 <文字数制限の為抜粋> Caused by: android.os.RemoteException: Remote stack trace: <文字数制限の為抜粋>
いまだいまいち原因の特定が分かりません。
アドバイス頂けると助かります。
以上、宜しくお願い致します。
回答2件
あなたの回答
tips
プレビュー