【问题标题】:Loading image from uri android从uri android加载图像
【发布时间】:2017-05-10 11:53:21
【问题描述】:

我目前正在尝试将我保存到我的 MySQLite 数据库中的图像的 Uri 加载到 RecyclerView 中。

RecyclerViewAdapter 的代码:

public void onBindViewHolder(MyCatchesAdapter.MyViewHolder holder, int position) {
    MyCatch myCatch = myCatchArrayList.get(position);
    holder.txtName.setText(myCatch.get_name());
    holder.txtLocation.setText(myCatch.get_location());
    holder.txtDate.setText(myCatch.get_date());

    holder.catchImage.setImageURI(Uri.parse(myCatch.get_catchImage()));
}

除图像外,所有数据都加载到回收站视图中。我从 Logcat 得到以下信息

Unable to open content: content://com.android.externalstorage.documents/document/primary%3ADownload%2Fsunrise.png

java.lang.SecurityException: Permission Denial: opening provider com.android.externalstorage.ExternalStorageProvider from ProcessRecord
{ee1a504 28074:com.example.pavlos.myproject/u0a74} (pid=28074, uid=10074) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS

我的清单权限是:

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

我有什么遗漏的吗?

编辑: 我如何获得 Uri:

catchImage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), SELECT_PICTURE);
        }
    });

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            selectedImagePath = getPath(selectedImageUri);
            catchImage.setImageURI(selectedImageUri);
            imagePath = selectedImageUri;
            Log.d("imagePath","URI "+selectedImageUri);
        }
    }
}
public String getPath(Uri uri) {
    // just some safety built in
    if( uri == null ) {
        // TODO perform some logging or show user feedback
        return null;
    }
    // try to retrieve the image from the media store first
    // this will only work for images selected from gallery
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if( cursor != null ){
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String path = cursor.getString(column_index);
        cursor.close();
        return path;
    }
    // this is our fallback here
    return uri.getPath();
}

【问题讨论】:

  • @Opiatefuchs:实际上,我怀疑在这种情况下。
  • @pavlos:你最初是如何准确得到Uri的? ACTION_GET_CONTENT? ACTION_OPEN_DOCUMENT?还有什么?
  • 来自文档:MANAGE_DOCUMENTS:此权限只能由平台文档管理应用程序请求。此权限不能授予第三方应用.....您不能使用此权限,您的应用必须是系统应用...
  • @CommonsWare 我编辑了问题以展示我如何获得 Uri

标签: java android imageview uri


【解决方案1】:

首先,getPath() 是完全错误的。充其量,它适用于从MediaStore 返回的图像子集。完全摆脱它。使用an image-loading library 填充您的ImageView

就您的问题而言,您从ACTION_GET_CONTENT 返回的Uri 可以被您的活动使用,只要该活动实例存在。当且仅当您包含 FLAG_GRANT_READ_URI_PERMISSION 时,您可以将 Uri 传递给其他组件(例如,另一个活动)。一旦您的流程终止,您将失去访问内容的所有权利。所以,停止将Uri 持久化到数据库,或者切换到ACTION_OPEN_DOCUMENT 并获取可持久化的Uri 权限。

【讨论】:

  • 我将 ACTION_GET_CONTENT 更改为 ACTION_OPEN_DOCUMENT 并加载。我还应该摆脱getPath() 函数吗?
【解决方案2】:

看起来您正在获取将作为内容 URI (content://) 出现的图像 URI(通常来自图库)。此内容 URI 带有临时权限,当它丢失当前上下文时会丢失。所以下次加载 URI 时,可能没有权限在当前上下文中加载它。

我建议您将图像的内容存储在数据库中,并在需要时加载它。可以应用各种图像优化,如图像压缩。你也可以看看这个Glide 谷歌推荐的图片管理库。

【讨论】:

    猜你喜欢
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-06
    • 1970-01-01
    • 1970-01-01
    • 2014-03-13
    • 1970-01-01
    相关资源
    最近更新 更多