'SecurityException using scoped storage in some devices
Im looking in google play crashes in some devices, like Samsung and Nokia, api 29 and 30.
Logs:
Caused by: java.lang.SecurityException:
at android.os.Parcel.createExceptionOrNull (Parcel.java:2385)
at android.os.Parcel.createException (Parcel.java:2369)
at android.os.Parcel.readException (Parcel.java:2352)
at android.os.Parcel.readException (Parcel.java:2294)
at android.app.IActivityManager$Stub$Proxy.getContentProvider (IActivityManager.java:6680)
at android.app.ActivityThread.acquireProvider (ActivityThread.java:7643)
at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider (ContextImpl.java:3090)
at android.content.ContentResolver.acquireUnstableProvider (ContentResolver.java:2484)
at android.content.ContentResolver.query (ContentResolver.java:1170)
at android.content.ContentResolver.query (ContentResolver.java:1118)
at android.content.ContentResolver.query (ContentResolver.java:1074)
at FileUtils.getFileName (FileUtils.java:69)
at MainActivity.onCreate (MainActivity.java:88)
at android.app.Activity.performCreate (Activity.java:8198)
at android.app.Activity.performCreate (Activity.java:8182)
at android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3765)
Caused by: android.os.RemoteException:
at com.android.server.am.ActivityManagerService.getContentProviderImpl (ActivityManagerService.java:8965)
at com.android.server.am.ActivityManagerService.getContentProviderImpl (ActivityManagerService.java:8804)
at com.android.server.am.ActivityManagerService.getContentProvider (ActivityManagerService.java:9505)
at android.app.IActivityManager$Stub.onTransact (IActivityManager.java:2840)
at com.android.server.am.ActivityManagerService.onTransact (ActivityManagerService.java:3617)
Permissions only for android < 28:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
The crash code:
public static String getFileName(Context context, Uri uri) {
String result = null;
if (uri.getScheme().equals("content")) {
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
}
if (result == null) {
result = uri.getPath();
int cut = result.lastIndexOf('/');
if (cut != -1) {
result = result.substring(cut + 1);
}
}
return result;
}
Manifest:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
<activity
android:name=".presentation.MainActivity"
android:exported="true"
android:theme="@style/Theme.MaterialComponents.Light.NoActionBar">
<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/pdf"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="application/pdf"/>
</intent-filter>
</activity>
provider_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
<cache-path name="cache" path="." />
</paths>
This is working well in the 90% of the devices. Any idea why is crashing? I think that can be for open some file without permissions, but I'm unable to reproduce it
Solution 1:[1]
The app that owns the file that triggers the intent to open a document may have not granted READ permissions. For example
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // user's app may not have specified this
Your app needs to do the following for Android 10 and above:
Following the best practices outlined in Request App Permissions, request the READ_EXTERNAL_STORAGE permission.
If the URI points to files in restricted locations like
Android/data
andAndroid/obb
, your app would not be able to READ it even if it has theREAD_EXTERNAL_STORAGE
permission. In this case, your app should catch theException
and show an appropriate error message to the user.
So in your MainActivity
's onCreate
do something like the following
protected void onCreate(Bundle savedInstanceState) {
// on Android 10+ request READ_EXTERNAL_STORAGE permission
if (hasPermissions(READ_EXTERNAL_STORAGE)) {
try {
String name = FileUtils.getFileName(this, URI);
} catch (Exception e) {
showToast("Error loading file");
}
} else {
requestPermission(READ_EXTERNAL_STORAGE);
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | cyberman |