2017-05-06 93 views
0

我正在嘗試使用存儲訪問框架訪問存儲在本地的文件並將其發送到服務器。但是當我嘗試使用URI我得到NullPointerException。但是我得到了文件的URI。但通過獲取路徑轉換爲文件時會捕獲異常。 最低API是17無法訪問來自uri的文件

uriString中= 內容://com.android.providers.downloads.documents/document/349

 warantyButton.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        Intent intent = new Intent(Intent. ACTION_OPEN_DOCUMENT); 
        intent.addCategory(Intent.CATEGORY_OPENABLE); 
        intent.setType("*/*"); 
        Intent i = Intent.createChooser(intent, "File"); 
        getActivity().startActivityForResult(i, FILE_REQ_CODE); 
        //Toast.makeText(getContext(),"Files",Toast.LENGTH_SHORT).show(); 
       } 
      }); 


    @Override 
     public void onActivityResult(int requestCode, int resultCode, Intent data) { 
      super.onActivityResult(requestCode, resultCode, data); 
      if (requestCode == FILE_REQ_CODE) { 
       if (resultCode == RESULT_OK) { 
        String path=""; 
        Uri uri = data.getData(); 
        if (uri != null) { 
         try { 
          file = new File(getPath(getContext(),uri)); 
          if(file!=null){ 
           ext = getMimeType(uri); 
           sendFileToServer(file,ext); 
          } 

         } catch (Exception e) { 
          Toast.makeText(getContext(),getString(R.string.general_error_retry),Toast.LENGTH_SHORT).show(); 
          e.printStackTrace(); 
         } 
        } 
       } 

      } 

     } 



public static String getPath(Context context, Uri uri) throws URISyntaxException { 
     if ("content".equalsIgnoreCase(uri.getScheme())) { 
      String[] projection = { "_data" }; 
      Cursor cursor = null; 

      try { 
       cursor = context.getContentResolver().query(uri, projection, null, null, null); 
       int column_index = cursor.getColumnIndexOrThrow("_data"); 
       if (cursor.moveToFirst()) { 
        return cursor.getString(column_index); 
       } 
      } catch (Exception e) { 
       // Eat it 
      } 
     } 
     else if ("file".equalsIgnoreCase(uri.getScheme())) { 
      return uri.getPath(); 
     } 

      return null; 
     } 
+0

你使用'getPath(getContext(),uri)'的方法是什麼?它來自哪一類? –

+0

對不起,我的答案錯過了部分代碼 –

回答

2

我想使用存儲訪問框架,我已經存儲在一個文件本地並將其發送到服務器。

你歡迎廣大用戶選擇他們想要的任何東西,這不包括您可以直接訪問(例如,在谷歌驅動器,移動存儲)文件。

但轉換通過獲取路徑

你不能「轉化通過獲取文件路徑」,以文件時捕獲異常。 contentUri的路徑部分是標識特定內容的無意義字符集合。接下來,您會認爲所有的計算機都在其本地文件系統上有一個文件,路徑爲/questions/43818723/unable-to-access-file-from-uri,這是因爲https://stackoverflow.com/questions/43818723/unable-to-access-file-from-uri碰巧是有效的Uri

所以,擺脫getPath()

使用ContentResolveropenInputStream()獲取關於內容的InputStream。直接使用該流或將其與您自己的文件上的FileOutputStream一起使用,以製作可用作文件的本地內容副本。

-2

試試下面的代碼對於獲取路徑:

public String getPath(Uri uri) throws URISyntaxException { 
    final boolean needToCheckUri = Build.VERSION.SDK_INT >= 19; 
    String selection = null; 
    String[] selectionArgs = null; 
    // Uri is different in versions after KITKAT (Android 4.4), we need to 
    // deal with different Uris. 
    if (needToCheckUri && DocumentsContract.isDocumentUri(mainActivity, uri)) { 
     if (isExternalStorageDocument(uri)) { 
      final String docId = DocumentsContract.getDocumentId(uri); 
      final String[] split = docId.split(":"); 
      return Environment.getExternalStorageDirectory() + "/" + split[1]; 
     } else if (isDownloadsDocument(uri)) { 
      final String id = DocumentsContract.getDocumentId(uri); 
      uri = ContentUris.withAppendedId(
        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); 
     } else if (isMediaDocument(uri)) { 
      final String docId = DocumentsContract.getDocumentId(uri); 
      final String[] split = docId.split(":"); 
      final String type = split[0]; 
      if ("image".equals(type)) { 
       uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 
      } else if ("video".equals(type)) { 
       uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 
      } else if ("audio".equals(type)) { 
       uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 
      } 
      selection = "_id=?"; 
      selectionArgs = new String[] { 
        split[1] 
      }; 
     } 
    } 
    if ("content".equalsIgnoreCase(uri.getScheme())) { 
     String[] projection = { 
       MediaStore.Images.Media.DATA 
     }; 
     Cursor cursor = null; 
     try { 
      cursor = mainActivity.getContentResolver() 
        .query(uri, projection, selection, selectionArgs, null); 
      int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); 
      if (cursor.moveToFirst()) { 
       return cursor.getString(column_index); 
      } 
     } catch (Exception e) { 

     } 
    } else if ("file".equalsIgnoreCase(uri.getScheme())) { 
     return uri.getPath(); 
    } 
    return null; 
}`/** 
* @param uri The Uri to check. 
* @return Whether the Uri authority is ExternalStorageProvider. 
*/ 
public static boolean isExternalStorageDocument(Uri uri) { 
    return "com.android.externalstorage.documents".equals(uri.getAuthority()); 
} 

/** 
* @param uri The Uri to check. 
* @return Whether the Uri authority is DownloadsProvider. 
*/ 
public static boolean isDownloadsDocument(Uri uri) { 
    return "com.android.providers.downloads.documents".equals(uri.getAuthority()); 
} 

/** 
* @param uri The Uri to check. 
* @return Whether the Uri authority is MediaProvider. 
*/ 
public static boolean isMediaDocument(Uri uri) { 
    return "com.android.providers.media.documents".equals(uri.getAuthority()); 
}` 
+1

這比無用的更糟糕。它對各種提供商的內部實施做出了假設,這些假設不必在Android OS版本甚至不同製造商的設備之間進行。它也不處理大多數'content''Uri'值,例如來自使用'FileProvider'的應用程序的值。 – CommonsWare