0

我根本無法獲得從SD卡上的圖庫中選擇的圖像的路徑,但存儲在設備上的圖像沒有問題。有幾十個這樣的類似或重複的問題,但他們都沒有工作。獲取從圖庫中選擇的圖像的路徑(在SD卡上)

最推薦的方法(通過@Commonsware)是使用ContentResolver並調用openInputStream(),所以我試圖從openInputStream()讀取字節,然後創建一個臨時文件,並使用這條道路,沒有運氣。我的「字節讀取:」System.err.println調用顯示0字節讀取。

我也試過thisthisthisthisthis,並且this,沒有工作。很多這些答案導致調用BitmapFactory#decodeStream(),問題是,我不關心顯示圖像,我只是需要路徑!

請幫忙!

到目前爲止的代碼:

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 

    if(resultCode == Activity.RESULT_OK){ 

     switch(requestCode){ 

      case SELECT_FROM_GALLERY: 
       fromGallery = true; 
       path = getRealPathFromURI(data.getData()); 
       System.err.println("*******path: " + path + "*********"); 

       break; 

     } 

    } 

} 

public String getRealPathFromURI(Uri contentUri) { 
    String thePath = null; 
    String[] filePathColumn = {MediaStore.Images.Media.DATA}; 
    Cursor cursor = getContext().getContentResolver().query(contentUri, filePathColumn, null, null, null); 
    if(cursor.moveToFirst()){ 
     int columnIndex = cursor.getColumnIndex(filePathColumn[0]); 
     thePath = cursor.getString(columnIndex); 
    } 
    cursor.close(); 

    if(thePath == null){ 
     return getImagePathExternal(contentUri); 
    }else { 
     return thePath; 
    } 
} 

public String getImagePathExternal(Uri uri){ 
    Cursor cursor = getContext().getContentResolver().query(uri, null, null, null, null); 
    cursor.moveToFirst(); 
    String document_id = cursor.getString(0); 
    document_id = document_id.substring(document_id.lastIndexOf(":")+1); 
    cursor.close(); 

    cursor = getContext().getContentResolver().query(
      android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
      null, MediaStore.Images.Media._ID + " = ? ", new String[]{document_id}, null); 
    cursor.moveToFirst(); 
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); 
    cursor.close(); 

    if(path == null){ 

     System.err.println("****************trying bytes route******************"); 
     try{ 

      InputStream in = getContext().getContentResolver().openInputStream(uri); 

      byte[] resultBuff = new byte[0]; 
      byte[] buff = new byte[1024]; 
      int k ; 
      while((k = in.read(buff, 0, buff.length)) > -1) { 
       byte[] tbuff = new byte[resultBuff.length + k]; // temp buffer size = bytes already read + bytes last read 
       System.arraycopy(resultBuff, 0, tbuff, 0, resultBuff.length); // copy previous bytes 
       System.arraycopy(buff, 0, tbuff, resultBuff.length, k); // copy current lot 
       resultBuff = tbuff; // call the temp buffer as your result buff 
      } 

      System.err.println("****************bytes read: "+resultBuff.length+" ******************"); 

      File tem = new File(_tempImageDir, "temp.jpg"); 

      FileOutputStream out = new FileOutputStream(tem); 

      out.write(resultBuff, 0, resultBuff.length); 

      return tem.getAbsolutePath(); 

     }catch(Exception e){ 
      e.printStackTrace(); 
      return null; 
     } 

    } 

    return path; 
} 

logcat的(此異常從未改變,無論哪種方法我用):

E/AndroidRuntime: FATAL EXCEPTION: main 
                    Process: com.venon.nakomangsp, PID: 20610 
                    java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=132074, result=-1, data=Intent { dat=content://media/external/images/media/4147 (has extras) }} to activity {com.venon.nakomangsp/com.venon.nakomangsp.SignUpActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference 
                     at android.app.ActivityThread.deliverResults(ActivityThread.java:4058) 
                     at android.app.ActivityThread.handleSendResult(ActivityThread.java:4101) 
                     at android.app.ActivityThread.access$1400(ActivityThread.java:177) 
                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1497) 
                     at android.os.Handler.dispatchMessage(Handler.java:102) 
                     at android.os.Looper.loop(Looper.java:145) 
                     at android.app.ActivityThread.main(ActivityThread.java:5942) 
                     at java.lang.reflect.Method.invoke(Native Method) 
                     at java.lang.reflect.Method.invoke(Method.java:372) 
                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 
                    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference 
                     at id.zelory.compressor.ImageUtil.getScaledBitmap(ImageUtil.java:62) 
                     at id.zelory.compressor.ImageUtil.compressImage(ImageUtil.java:161) 
                     at id.zelory.compressor.Compressor.compressToFile(Compressor.java:48) 
                     at com.venon.nakomangsp.SignUpFragment.preparePicture(SignUpFragment.java:870) 
                     at com.venon.nakomangsp.SignUpFragment.onActivityResult(SignUpFragment.java:783) 
                     at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:165) 
                     at com.venon.nakomangsp.SignUpActivity.onActivityResult(SignUpActivity.java:37) 
                     at android.app.Activity.dispatchActivityResult(Activity.java:6549) 
                     at android.app.ActivityThread.deliverResults(ActivityThread.java:4054) 
                     at android.app.ActivityThread.handleSendResult(ActivityThread.java:4101)  
                     at android.app.ActivityThread.access$1400(ActivityThread.java:177)  
                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1497)  
                     at android.os.Handler.dispatchMessage(Handler.java:102)  
                     at android.os.Looper.loop(Looper.java:145)  
                     at android.app.ActivityThread.main(ActivityThread.java:5942)  
                     at java.lang.reflect.Method.invoke(Native Method)  
                     at java.lang.reflect.Method.invoke(Method.java:372)  
                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)  
                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)  
+0

沒有路徑。你爲什麼想要一條路? – ianhanniballake

+0

畫廊中沒有圖像的路徑?這不能是因爲如果我選擇了一張不在SD卡上的圖像,我會得到一條路徑。我需要它來製作圖像的壓縮版本並將其發送到我的服務器 – BiGGZ

+0

您不需要路徑來調用[compress()](https://developer.android.com/reference/android/graphics/Bitmap .html#compress(android.graphics.Bitmap.CompressFormat,%20int,%20java.io.OutputStream))[BitmapFactory.decodeStream()]創建的位圖(https://developer.android.com/reference/android /graphics/BitmapFactory.html#decodeStream(java.io.InputStream))。是什麼讓你覺得你需要一條路來做到這一點? – ianhanniballake

回答

2

應用沒有任何的SD卡中的內容直接文件訪問。因此,即使您可以獲得某種「路徑」,您的應用程序也無法從該位置讀取任何內容。

可靠地訪問這些文件內容的唯一方法是通過ContentResolver.openInputStream()(或其他open方法,如果您需要AssetFileDescriptor等)。

你絕對可以將文件複製到own cache directory,然後根據圖像做任何你想做的事情。

+0

該文件可以被複制而不需要路徑嗎? –

+1

@WaqasAhmedAnsari - 當然,你'openInputStream()'並將其寫入'FileOutputStream'。沒有路徑需要。 – ianhanniballake

+0

我明白了。剛剛發生了一些奇怪的行爲。我刪除了設備上的所有照片,只留下了SD卡上的照片,然後從我的應用程序外部拍攝了一張照片並將其保存到設備中,中提琴......一切都按預期工作。我從兩個照片中選擇了一張照片並且設法在不使用openInputStream的情況下獲取路徑。你有任何線索,爲什麼可能發生? – BiGGZ

1

如果使用的是API 24,那麼你應該使用FileProvide,官方網站的介紹:https://developer.android.com/reference/android/support/v4/content/FileProvider.html 你應該這樣寫:

  1. 使用元素的子元素指定XML中存儲區域和路徑的內容。例如,以下pathsmann告訴FileProvider您打算請求您的私有文件區域的images /子目錄的內容URI。

    <Manifest> 
        <Application> 
            <Provider 
                Android: name = "android.support.v4.content.FileProvider" 
                Android: authorities = "com.mydomain.fileprovider" 
                Android: exported = "false" 
                Android: grantUriPermissions = "true" 
               <Meta-data 
               Android: name = "android.support.FILE_PROVIDER_PATHS" 
               Android: resource = "@ xml/file_paths" /> 
            </ Provider> 
        </ Application> 
    </ Manifest> 
    
    
    <? Xml version = "1.0" encoding = "utf-8"?> 
    <Resources> 
        <Paths> 
            <External-path 
                Name = "external_files" 
                Path = "." /> 
            <Root-path 
                Name = "external_files" 
                Path = "/ storage /" /> 
        </ Paths> `enter code here` 
    </ Resources> 
    
  2. 第三步:文件是道路

    Uri contentUri = getUriForFile (getContext(), getPackageName() + ".provider", file); 
    
0

不同手機擁有不同的行爲。經過大量研究並嘗試不同的可能性後,我想出了一個解決方案,該解決方案適用於我測試過的所有手機(LG G2,Nexus 5,ZTE,Note 5,Nexus 6,Infinix Note 3 Pro和其他一些我不記得)。試試這個,如果它的工作。根據你的需要。它還包括從相機捕捉圖片,複製它並獲取它的路徑。

//SELECT PICTURE FROM GALLERY OR CAPTURE FROM CAMERA 
private void selectPicture(View view) { 
    tempView = view; 
    final CharSequence[] items; 
    if(view.getClass().getName().equalsIgnoreCase("android.widget.ImageView")) 
      items = new CharSequence[]{ "Take Photo", "Choose from Library", "Remove Photo", "Cancel" }; 
    else items = new CharSequence[]{ "Take Photo", "Choose from Library", "Cancel" }; 

    AlertDialog.Builder builder = new AlertDialog.Builder(ActivityAddMemory.this); 
    builder.setTitle("Add Image"); 
    builder.setItems(items, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int item) { 
      if (items[item].equals("Take Photo")) { 
       showCamera(); 
      } else if (items[item].equals("Choose from Library")) { 
       Intent intent = new Intent(
         Intent.ACTION_PICK, 
         MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 
       intent.setType("image/*"); 
       startActivityForResult(
         Intent.createChooser(intent, "Select File"), 
         SELECT_FILE); 
      } else if(items[item].equals("Remove Photo")) { 
       imgLinearLayout.removeView(tempView); 
       imagesList.remove(tempView.getId()); 
       if(imagesList.size() < 1) { 
        imgLinearLayout.setVisibility(View.GONE); 
       } 

       if(btnAddPhoto.getVisibility() == View.GONE) 
        btnAddPhoto.setVisibility(View.VISIBLE); 
      } else if (items[item].equals("Cancel")) { 
       dialog.dismiss(); 
      } 
     } 
    }); 
    builder.show(); 
} 


//OPEN CAMERA IF WANT TO CAPTURE 
private void showCamera() { 

    try { 
     File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "DCIM"); 
     if (!file.exists()) { 
      file.mkdirs(); 
     } 

     File localFile2 = new File(file + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg"); 
     imageUri = Uri.fromFile(localFile2); 

     Intent cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE"); 

     cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 
      cameraIntent.setClipData(ClipData.newRawUri(null, Uri.fromFile(localFile2))); 
     } 

     startActivityForResult(cameraIntent, REQUEST_CAMERA); 
    } catch (Exception localException) { 
     Toast.makeText(ActivityAddMemory.this, "Exception:" + localException, Toast.LENGTH_SHORT).show(); 
    } 
} 


//GET PATH FROM URI IF SELECTED FROM GALLERY 
public String getRealPathFromURI(Uri uri){ 
    String filePath = ""; 
    String[] filePahColumn = {MediaStore.Images.Media.DATA}; 
    Cursor cursor = getContentResolver().query(uri, filePahColumn, null, null, null); 
    if (cursor != null) { 
     if(cursor.moveToFirst()){ 
      int columnIndex = cursor.getColumnIndex(filePahColumn[0]); 
      filePath = cursor.getString(columnIndex); 
     } 
     cursor.close(); 
    } 
    return filePath; 
} 


//DO WHAT YOU WANT WHEN RESULT IS RETURNED 
@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent intent) { 
    super.onActivityResult(requestCode, resultCode, intent); 

    if(resultCode == RESULT_OK) { 

     String path=null; 
     Uri uri; 

     if (intent == null || intent.getData() == null) 
      uri = this.imageUri; 
     else 
      uri = intent.getData(); 

     if(requestCode == SELECT_FILE) { 
      path = getRealPathFromURI(uri); 
     } else if(requestCode == REQUEST_CAMERA){ 
      path = uri.getEncodedPath(); 
     } 

     //THIS IS THE PATH YOU WOULD NEED 

    } 

}