【问题标题】:copy a picture from android photo-library causes error从 android 照片库复制图片导致错误
【发布时间】:2015-04-02 04:42:16
【问题描述】:

当我尝试通过 phonegap 解析本地文件系统 uri 时出现此错误:

java.lang.SecurityException: Permission Denial: reading com.android.providers.media.MediaDocumentsProvider

我使用相机访问照片库并接收此 file_uri:

content://com.android.providers.media.documents/document/image%3A355

然后我尝试访问本地文件系统:

window.resolveLocalFileSystemURI(file_uri, function(a){console.log("success");}, function(b){console.log("fail");});

这就是我收到此错误的地方:

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)

顺便说一句:我在 iOS 上尝试过这个场景,它没有问题。

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" />

【问题讨论】:

  • 你能给出你的 manifest.xml 权限列表吗?

标签: android cordova


【解决方案1】:

以下是解决此问题的简单方法:

替换这个:

content://com.android.providers.media.documents/document/image%3A352

通过这个:

content://com.android.providers.media.documents/document/image%253A352

如果您使用的是 JavaScript,则可以使用以下代码:

var path = content://com.android.providers.media.documents/document/image%3A352;
path = path.replace("%", "%25");

这种技术会强制 uri 按原样传递“%3A”,而不将其更改为“:”,

【讨论】:

    【解决方案2】:

    每当一些uri 被传递到&lt;img src="uri" /&gt; 时,它都会被隐式解码

    content://com.android.providers.media.documents/document/image%3A9888 (1)

    进入

    content://com.android.providers.media.documents/document/image:9888 (2)

    但是,从Intent.ACTION_OPEN_DOCUMENTIntent.ACTION_GET_CONTENT 返回后,Android 为您提供(1) 的读取权限,而不是(2)。在这种情况下,WebView 会期望记录一个错误:

    java.lang.SecurityException: Permission Denial: 读取 com.android.providers.media.MediaDocumentsProvider uri 内容://com.android.providers.media.documents/document/image:9888 从 pid=13163, uid=10165 需要 android.permission.MANAGE_DOCUMENTS 或 grantUriPermission()

    无法打开内容网址

    代码 sn-p

    你只需要解决这个问题就是

        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;
            }
        }
    

    在您的 Java 代码中传递 uri 到 HTML/JS 之前,以确保 (1) 将被实际加载。

    我已经在 4.4.2、4.4.4 和 5.0 上进行了测试。有趣的是,Android 4.4.2 在内部对uri 进行了两次解码。

    【讨论】:

      【解决方案3】:

      您是否尝试向 manifest.xml 添加正确的权限?

      <uses-permission android:name="android.permission.READ_PROFILE" />
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
      

      【讨论】:

      猜你喜欢
      • 2014-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多