访问 Android 中的图像时出现 SecurityException 9
SecurityException when Accessing Images in Android 9
这是我第一次 post 在这里,所以如果我的礼节不正确,请告诉我,我会更新。
我们制作了一个用于跟踪与宠物相关的数据的应用程序。设置宠物时,您可以拍一张新照片,也可以使用图库中的一张。在我的三星 s9 (Android 9 - API 28) 上完美运行。我们 运行 进入 API 29 的 SecurityException,我似乎无法弄清楚。这是崩溃报告:
java.lang.RuntimeException:
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3163)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3306)
at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1994)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:216)
at android.app.ActivityThread.main (ActivityThread.java:7263)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
Caused by: java.lang.SecurityException:
at android.os.Parcel.createException (Parcel.java:1966)
at android.os.Parcel.readException (Parcel.java:1934)
at android.os.Parcel.readException (Parcel.java:1884)
at android.app.IActivityManager$Stub$Proxy.getContentProvider (IActivityManager.java:4029)
at android.app.ActivityThread.acquireProvider (ActivityThread.java:6506)
at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider (ContextImpl.java:2825)
at android.content.ContentResolver.acquireUnstableProvider (ContentResolver.java:1835)
at android.content.ContentResolver.openTypedAssetFileDescriptor (ContentResolver.java:1449)
at android.content.ContentResolver.openAssetFileDescriptor (ContentResolver.java:1302)
at android.content.ContentResolver.openInputStream (ContentResolver.java:1022)
at android.provider.MediaStore$Images$Media.getBitmap (MediaStore.java:920)
at com.reptibox.reptileapp.EditReptileData.getReptileImage (EditReptileData.java:228)
at com.reptibox.reptileapp.EditReptileData.getReptileInfo (EditReptileData.java:298)
at com.reptibox.reptileapp.EditReptileData.onCreate (EditReptileData.java:197)
at android.app.Activity.performCreate (Activity.java:7353)
at android.app.Activity.performCreate (Activity.java:7344)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1275)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3143)
Caused by: android.os.RemoteException:
at com.android.server.am.ActivityManagerService.getContentProviderImpl (ActivityManagerService.java:15890)
at com.android.server.am.ActivityManagerService.getContentProviderImpl (ActivityManagerService.java:15799)
at com.android.server.am.ActivityManagerService.getContentProvider (ActivityManagerService.java:16364)
at android.app.IActivityManager$Stub.onTransact$getContentProvider$ (IActivityManager.java:11085)
at android.app.IActivityManager$Stub.onTransact (IActivityManager.java:295)
这是报告指向的方法:
public Bitmap getReptileImage(){
Cursor cursor = mDB.rawQuery("SELECT * FROM " + ReptileContract.ReptileImageEntry.TABLE_NAME +
" WHERE " + ReptileContract.ReptileImageEntry._ID + "='" + mReptileImageId +
"' ORDER BY " + ReptileContract.ReptileImageEntry._ID + " DESC;", null);
cursor.moveToFirst();
if (cursor.getCount() > 0) {
try {
Uri mImageURI = Uri.parse(cursor.getString(cursor.getColumnIndex(ReptileContract.ReptileImageEntry.COLUMN_REPTILE_URI)));
try{
if (android.os.Build.VERSION.SDK_INT >= 29){
// To handle deprecation use
return ImageDecoder.decodeBitmap(ImageDecoder.createSource(getContentResolver(),mImageURI));
} else{
// Use older version
//SECURITY EXCEPTION HERE
return android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), mImageURI);
}
// }
}
catch(IOException e){
Log.e("IMAGE LOADING", "IOException Error Caught");
e.printStackTrace();
cursor.close();
return null;
}
}
catch (NullPointerException e){
Log.e("IMAGE LOADING", "Normal for first loading, since nothing has URI's");
e.printStackTrace();
cursor.close();
return null;
}
}
else {
cursor.close();
return null;
}
}
如果您需要更多信息,请告诉我。我正在寻找解决此崩溃的方法,任何能为我指明正确方向的东西都会很棒!
您尝试访问的 URI 类型存在奇怪的问题。您得到的 content
类型的 Uri 有一些限制。
您通常可以毫无问题地存储和访问 file
类型的 Uri。但是,content
Uri 的访问时间有限。
这里您的选择非常有限,但我就是这样解决的。您可以将用户选择的文件复制到您的应用具有完全访问权限的 directory(例如 getFilesDir()
),存储复制文件的路径,并让您的应用访问副本而不是原来的。
这是我第一次 post 在这里,所以如果我的礼节不正确,请告诉我,我会更新。
我们制作了一个用于跟踪与宠物相关的数据的应用程序。设置宠物时,您可以拍一张新照片,也可以使用图库中的一张。在我的三星 s9 (Android 9 - API 28) 上完美运行。我们 运行 进入 API 29 的 SecurityException,我似乎无法弄清楚。这是崩溃报告:
java.lang.RuntimeException:
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3163)
at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3306)
at android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1994)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:216)
at android.app.ActivityThread.main (ActivityThread.java:7263)
at java.lang.reflect.Method.invoke (Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:494)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:975)
Caused by: java.lang.SecurityException:
at android.os.Parcel.createException (Parcel.java:1966)
at android.os.Parcel.readException (Parcel.java:1934)
at android.os.Parcel.readException (Parcel.java:1884)
at android.app.IActivityManager$Stub$Proxy.getContentProvider (IActivityManager.java:4029)
at android.app.ActivityThread.acquireProvider (ActivityThread.java:6506)
at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider (ContextImpl.java:2825)
at android.content.ContentResolver.acquireUnstableProvider (ContentResolver.java:1835)
at android.content.ContentResolver.openTypedAssetFileDescriptor (ContentResolver.java:1449)
at android.content.ContentResolver.openAssetFileDescriptor (ContentResolver.java:1302)
at android.content.ContentResolver.openInputStream (ContentResolver.java:1022)
at android.provider.MediaStore$Images$Media.getBitmap (MediaStore.java:920)
at com.reptibox.reptileapp.EditReptileData.getReptileImage (EditReptileData.java:228)
at com.reptibox.reptileapp.EditReptileData.getReptileInfo (EditReptileData.java:298)
at com.reptibox.reptileapp.EditReptileData.onCreate (EditReptileData.java:197)
at android.app.Activity.performCreate (Activity.java:7353)
at android.app.Activity.performCreate (Activity.java:7344)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1275)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3143)
Caused by: android.os.RemoteException:
at com.android.server.am.ActivityManagerService.getContentProviderImpl (ActivityManagerService.java:15890)
at com.android.server.am.ActivityManagerService.getContentProviderImpl (ActivityManagerService.java:15799)
at com.android.server.am.ActivityManagerService.getContentProvider (ActivityManagerService.java:16364)
at android.app.IActivityManager$Stub.onTransact$getContentProvider$ (IActivityManager.java:11085)
at android.app.IActivityManager$Stub.onTransact (IActivityManager.java:295)
这是报告指向的方法:
public Bitmap getReptileImage(){
Cursor cursor = mDB.rawQuery("SELECT * FROM " + ReptileContract.ReptileImageEntry.TABLE_NAME +
" WHERE " + ReptileContract.ReptileImageEntry._ID + "='" + mReptileImageId +
"' ORDER BY " + ReptileContract.ReptileImageEntry._ID + " DESC;", null);
cursor.moveToFirst();
if (cursor.getCount() > 0) {
try {
Uri mImageURI = Uri.parse(cursor.getString(cursor.getColumnIndex(ReptileContract.ReptileImageEntry.COLUMN_REPTILE_URI)));
try{
if (android.os.Build.VERSION.SDK_INT >= 29){
// To handle deprecation use
return ImageDecoder.decodeBitmap(ImageDecoder.createSource(getContentResolver(),mImageURI));
} else{
// Use older version
//SECURITY EXCEPTION HERE
return android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), mImageURI);
}
// }
}
catch(IOException e){
Log.e("IMAGE LOADING", "IOException Error Caught");
e.printStackTrace();
cursor.close();
return null;
}
}
catch (NullPointerException e){
Log.e("IMAGE LOADING", "Normal for first loading, since nothing has URI's");
e.printStackTrace();
cursor.close();
return null;
}
}
else {
cursor.close();
return null;
}
}
如果您需要更多信息,请告诉我。我正在寻找解决此崩溃的方法,任何能为我指明正确方向的东西都会很棒!
您尝试访问的 URI 类型存在奇怪的问题。您得到的 content
类型的 Uri 有一些限制。
您通常可以毫无问题地存储和访问 file
类型的 Uri。但是,content
Uri 的访问时间有限。
这里您的选择非常有限,但我就是这样解决的。您可以将用户选择的文件复制到您的应用具有完全访问权限的 directory(例如 getFilesDir()
),存储复制文件的路径,并让您的应用访问副本而不是原来的。