无法从uri访问文件

时间:2017-05-06 09:13:28

标签: android storage-access-framework

我正在尝试使用存储在本地存储的存储访问框架来访问文件并将其发送到服务器。但是当我尝试使用 URI 来获取文件时,我得到 NullPointerException 。但是我得到了文件的URI。但通过获取路径转换为文件时捕获异常。 最低API为17

  

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;
        }

3 个答案:

答案 0 :(得分:2)

  

我正在尝试使用存储在本地存储的存储访问框架来访问文件并将其发送到服务器。

欢迎您的用户选择他们想要的任何内容,但不包括您可以直接访问的文件(例如,在Google云端硬盘中,可移动存储上)。

  

但通过获取路径

转换为文件时捕获异常

你不能通过获取路径"转换为文件。 2 p2 red dalton 4 p4 blue apex content的路径部分是一组无意义的字符,用于标识特定内容。接下来,您将认为所有计算机的路径Uri上的本地文件系统上都有一个文件,因为/questions/43818723/unable-to-access-file-from-uri恰好是有效的https://stackoverflow.com/questions/43818723/unable-to-access-file-from-uri

所以,摆脱Uri

使用getPath()ContentResolver获取内容的openInputStream()。直接使用该流或将其与您自己文件中的InputStream结合使用,以制作可用作文件的内容的本地副本。

答案 1 :(得分:0)

@CommonsWare答案正确 这是代码段

要从Uri读取文件内容:

        // Use ContentResolver to access file from Uri
    InputStream inputStream = null;
    try {
        inputStream = mainActivity.getContentResolver().openInputStream(uri);
        assert inputStream != null;

        // read file content
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String mLine;
        StringBuilder stringBuilder = new StringBuilder();
        while ((mLine = bufferedReader.readLine()) != null) {
            stringBuilder.append(mLine);
        }
        Log.d(TAG, "reading file :" + stringBuilder);

要将文件从Uri保存到应用程序目录中的本地副本:

String dirPath = "/data/user/0/-your package name -/newLocalFile.name"

try (InputStream ins = mainActivity.getContentResolver().openInputStream(uri)) {

            File dest = new File(dirPath);

            try (OutputStream os = new FileOutputStream(dest)) {
                byte[] buffer = new byte[4096];
                int length;
                while ((length = ins.read(buffer)) > 0) {
                    os.write(buffer, 0, length);
                }
                os.flush();
      } catch (Exception e) {
            e.printStackTrace();
      }

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

            

答案 2 :(得分:-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());
}`