Reputation: 3272
get this error when I try to resolve the local filesystem uri by phonegap:
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider
I use the camera to access the photo-library and receive this file_uri:
content://com.android.providers.media.documents/document/image%3A355
Then I try to access the local filesystem:
window.resolveLocalFileSystemURI(file_uri, function(a){console.log("success");}, function(b){console.log("fail");});
That's where I receive this error:
02-18 10:13:14.546 app W/System.err﹕ java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com.android.providers.media.documents/document/image:355 from pid=22659, uid=10098 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()
02-18 10:13:14.546 app W/System.err﹕ at android.os.Parcel.readException(Parcel.java:1465)
02-18 10:13:14.546 app W/System.err﹕ at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:185)
02-18 10:13:14.546 app W/System.err﹕ at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
02-18 10:13:14.546 app W/System.err﹕ at android.content.ContentProviderProxy.query(ContentProviderNative.java:413)
02-18 10:13:14.546 app W/System.err﹕ at android.content.ContentResolver.query(ContentResolver.java:461)
02-18 10:13:14.546 app W/System.err﹕ at android.content.ContentResolver.query(ContentResolver.java:404)
02-18 10:13:14.546 app W/System.err﹕ at android.app.Activity.managedQuery(Activity.java:1796)
02-18 10:13:14.546 app W/System.err﹕ at org.apache.cordova.file.FileUtils.resolveLocalFileSystemURI(FileUtils.java:263)
02-18 10:13:14.546 app W/System.err﹕ at org.apache.cordova.file.FileUtils.execute(FileUtils.java:150)
02-18 10:13:14.546 app W/System.err﹕ at org.apache.cordova.CordovaPlugin.execute(CordovaPlugin.java:65)
02-18 10:13:14.546 app W/System.err﹕ at org.apache.cordova.PluginManager.execHelper(PluginManager.java:229)
02-18 10:13:14.556 app W/System.err﹕ at org.apache.cordova.PluginManager.exec(PluginManager.java:214)
02-18 10:13:14.556 app W/System.err﹕ at org.apache.cordova.ExposedJsApi.exec(ExposedJsApi.java:53)
02-18 10:13:14.556 app W/System.err﹕ at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
02-18 10:13:14.556 app W/System.err﹕ at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27)
02-18 10:13:14.556 app W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102)
02-18 10:13:14.556 app W/System.err﹕ at android.os.Looper.loop(Looper.java:136)
02-18 10:13:14.556 app W/System.err﹕ at android.os.HandlerThread.run(HandlerThread.java:61)
Btw.: I tried this scenario on iOS and it works without a problem.
AndroidManifest.xml:
<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="0.0.1" android:windowSoftInputMode="adjustPan" package="app" xmlns:android="http://schemas.android.com/apk/res/android">
<supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
<uses-permission android:name="android.permission.INTERNET" />
<application android:debuggable="true" android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/app_name" android:name="openApi" android:theme="@android:style/Theme.Black.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/*"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="audio/*" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_VIDEO" />
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Upvotes: 4
Views: 3549
Reputation: 814
Here is a simple fix to this problem:
replace this:
content://com.android.providers.media.documents/document/image%3A352
by this:
content://com.android.providers.media.documents/document/image%253A352
if you are using JavaScript you can use this code:
var path = content://com.android.providers.media.documents/document/image%3A352;
path = path.replace("%", "%25");
this technique force the uri to let pass "%3A" as it is, without changing it to ":",
Upvotes: 3
Reputation: 8258
Whenever some uri
is passed into <img src="uri" />
it's implicitly decoded from
content://com.android.providers.media.documents/document/image%3A9888 (1)
into
content://com.android.providers.media.documents/document/image:9888 (2)
However, after returning from Intent.ACTION_OPEN_DOCUMENT
or Intent.ACTION_GET_CONTENT
Android provides you with the read permission for (1), not (2). In this case WebView
will expectantly log an error:
java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider uri content://com.android.providers.media.documents/document/image:9888 from pid=13163, uid=10165 requires android.permission.MANAGE_DOCUMENTS, or grantUriPermission()
or
Unable to open content URL
Code snippet
All you need to resolve the issue is
String uriToUseInWebView = transformForWebView(uri.toString());
private String transformForWebView(String uri) {
for (int i = 0; i < timesDecodingWebView(); i++)
uri = uri.replace("%", Uri.encode("%"));
return uri;
}
private int timesDecodingWebView() {
if (Build.VERSION.RELEASE.equals("4.4.2")) {
return 2;
} else {
return 1;
}
}
in your Java code before passing uri
into HTML/JS to ensure that (1) will be actually loaded.
I've tested that on 4.4.2, 4.4.4 and 5.0. The funny part is that Android 4.4.2 decodes the uri
internally twice.
Upvotes: 2
Reputation: 12768
Have you tried to add the correct permission to manifest.xml?
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Upvotes: 1