我的应用程序中有一个活动允许用户逐个从设备中选择多个文件,我使用的是这样的意图:
Intent intent = new Intent();
intent.setType("*/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, getString(R.string.select_attachments_activity_chooser_label)), SELECT_PICTURE);
Run Code Online (Sandbox Code Playgroud)
这工作得非常好,我正在选择Uri的文件,它们看起来像这样:
content://com.android.providers.media.documents/document/image%3A42555
Run Code Online (Sandbox Code Playgroud)
然后,如果文件是图像,我正在解码它:
InputStream streamForDecodeBitmap = MyApp.getContext().getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(streamForDecodeBitmap, null, options);
Run Code Online (Sandbox Code Playgroud)
当用户单击按钮时,我通过意图将Uris列表传递给另一个活动,在此活动中,在AsyncTask中,我在base64中编码该文件以通过网络发送它:
InputStream is = MyApp.getContext().getContentResolver().openInputStream(uri);
byte[] inputData = getBytes(is);
is.close();
return Base64.encodeToString(inputData, Base64.DEFAULT);
Run Code Online (Sandbox Code Playgroud)
问题是当我打开inputStream时,有时它可以工作,但大多数时候我得到这个异常:
E/AndroidRuntime(22270): Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{42858fe0 22270:co.uk.manifesto.freeagentapp/u0a246} (pid=22270, uid=10246) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
Run Code Online (Sandbox Code Playgroud)
这些是我的清单中的所有权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>
Run Code Online (Sandbox Code Playgroud)
我正在使用KITKAT(API 19)测试设备.
Par*_*rth 35
请检查以下问题:
Android KitKat securityException尝试从MediaStore读取
权限拒绝:打开提供程序
对于KitKat上的同样问题,我使用了这个.这是我从其中一个Stack Overflow链接找到的选项/解决方法,您可以从Downloads/Recent中选择文件.
public static final int KITKAT_VALUE = 1002;
Intent intent;
if (Build.VERSION.SDK_INT < 19) {
intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, KITKAT_VALUE);
} else {
intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, KITKAT_VALUE);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == KITKAT_VALUE ) {
if (resultCode == Activity.RESULT_OK) {
// do something here
}
}
}
Run Code Online (Sandbox Code Playgroud)
参考: KitKat上的Android Gallery为Intent.ACTION_GET_CONTENT返回不同的Uri http://developer.android.com/guide/topics/providers/document-provider.html#client
小智 20
当控件和数据返回到您的活动时
protected void onActivityResult(int reqCode, int resultCode, Intent data)
Run Code Online (Sandbox Code Playgroud)
同时,您的活动被授予访问传递的意图中的图像URL的权限.您的活动将能够读取意图中的网址并显示图像.但是,您无法将任何权限传递给其他活动或新的执行线程.这就是为什么你得到android.permission.MANAGE_DOCUMENTS的SecurityException.
避免权限问题的一种方法是获取具有权限的活动中的数据.在您的情况下,从具有权限的活动执行您的编码
InputStream is = getContentResolver().openInputStream(uri);
byte[] inputData = getBytes(is);
is.close();
String encoded = Base64.encodeToString(inputData, Base64.DEFAULT);
Run Code Online (Sandbox Code Playgroud)
一旦有了编码字符串,就可以将它传递给可能需要它的任何其他活动,或者你可以将它传递给AsyncTask以便发送到其他地方.
Alé*_*lho 10
确保您正在使用请求内容的Activity中的ContentResolver,例如:
activity.getContentResolver()
Run Code Online (Sandbox Code Playgroud)
代替 MyApp.getContext().getContentResolver()
对我来说显然是这样,它不需要添加android.permission.MANAGE_DOCUMENTS到清单.
并且您使用以下方法调用intent:
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
intent.setAction(Intent.ACTION_GET_CONTENT);
} else {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
}
Run Code Online (Sandbox Code Playgroud)
更多信息:https://developer.android.com/guide/topics/providers/document-provider.html#client
Writing ACTION_OPEN_DOCUMENT is not helping entirely. After a restart your URI Permission is gone even with this action.
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
intent.setAction(Intent.ACTION_GET_CONTENT);
} else {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
}
Run Code Online (Sandbox Code Playgroud)
To complete Alécio Carvalho's answer look at this documentation on the same page. There is a good explanation regarding URI Permissions and how to make them persist.
Just add this to your onActivityResult method and your permission persists through a device restart. (Tested with a Google Pixel.)
override fun onActivityResult(requestCode:Int, resultCode:Int, intent:Intent?) {
if(requestCode == SELECT_PICTURE && intent != null){
val uri = intent.getData()
val takeFlags = intent.getFlags() and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
activity.getContentResolver().takePersistableUriPermission(uri, takeFlags)
PreferenceHelper.setHeaderImageUri(activity, uri.toString())
}
}
Run Code Online (Sandbox Code Playgroud)
(sorry kotlin lover...java version is inside the link)
| 归档时间: |
|
| 查看次数: |
22838 次 |
| 最近记录: |