2017-05-10 80 views
0

我目前正試圖將我保存到我的MySQLite數據庫的圖像加載到RecyclerView中。從uri載入圖像android

用於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(); 
} 
+0

的祕密被稱作運行時權限https://developer.android.com/training/permissions/requesting.html – Opiatefuchs

+0

@Opiatefuchs:其實,我懷疑,在這種情況下。 – CommonsWare

+0

@pavlos:你究竟是怎麼得到原來的'Uri'的? 'ACTION_GET_CONTENT'? 'ACTION_OPEN_DOCUMENT'?還有別的嗎? – CommonsWare

回答

2

首先,getPath()是完全錯誤的。充其量,它將適用於從MediaStore返回的圖像的一些子集。完全擺脫它。使用an image-loading library填充您的ImageView

就你的問題而言,你從ACTION_GET_CONTENT得到的Uri可以被你的活動使用,只要該活動實例在附近。當且僅當您包含FLAG_GRANT_READ_URI_PERMISSION時,您纔可以將該Uri傳遞給其他組件(例如,其他活動)。一旦你的程序終止,你將失去訪問內容的所有權利。因此,請停止將Uri保留到數據庫,或切換到ACTION_OPEN_DOCUMENT並持久保留Uri權限。

+0

我改變將ACTION_GET_CONTENT轉換爲ACTION_OPEN_DOCUMENT並加載。我應該仍然擺脫'getPath()'功能? – pavlos

+0

@pavlos:是的,因爲它不可靠工作。 – CommonsWare

0

看起來像你所得到的圖像URI(通常是從畫廊),這將被看作一個內容URI(內容://)。這個內容URI帶有臨時權限,當它丟失當前上下文時會丟失。因此,下次加載URI時,您可能沒有權限在當前上下文中加載它。

我建議你存儲在數據庫中的圖像內容,並在需要時加載它。可以應用各種圖像優化,如圖像壓縮。您也可以查看這個Glide圖書館的圖片管理,這是Google推薦的。