'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/dataandAndroid/obb, your app would not be able to READ it even if it has theREAD_EXTERNAL_STORAGEpermission. In this case, your app should catch theExceptionand 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 |
