通過uri獲取文件路徑的正確姿勢(兼容7.0以上)

關聯文件需要注意事項

最近爲項目進行功能擴展,需要在安卓系統中關聯文件格式,這一步需要在項目的配置文件中進行相應的配置即可,相關的代碼網上很多,不需多言,需要說明的是

 <data android:scheme="file"/>
 <data android:scheme="content"/>

其中第一條schema="file"一般指的是在文件管理器中點擊打開相應的文件來調起app,這種情況下一般是知道文件的真實地址的。

第二第,content類型,是在安卓7.0以上開始使用的,主要是爲了保護用戶的隱私,不同app間不能暴露文件的真實地址,所以這個時候是無法獲取文件的真實地址的。

在Activity中如何獲取文件的地址呢?

首先剛纔上文中說過了,content類型是無法獲取文件的地址的,那麼我們怎麼辦呢?這裏的主要思路是通過讀取inputstream流來將文件複製到自己定義的一個臨時文件夾中,然後對其進行相關的操作。當然這種情況只適用於小體積的文件,你要是一個文件動不動上百M我覺得這種方法也不怎麼適合。

下面直接貼代碼。

 private String getFilePathFromUri(Uri uri) {
        if (uri == null) {
            return "";
        }
        switch (uri.getScheme()) {
            case "content":
                return getFileFromContentUri(uri);
            case "file":
                return uri.getPath();
            default:
                return "";
        }
    }

    /**
     *
     * @param contentUri
     * @return
     */
    private String getFileFromContentUri(Uri contentUri) {
        if (contentUri == null) {
            return null;
        }
        File file = null;
        String filePath = "";
        String fileName;
        String[] filePathColumn = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME};
        ContentResolver contentResolver = getContentResolver();
        Cursor cursor = contentResolver.query(contentUri, filePathColumn, null,
                null, null);
        if (cursor != null) {
            cursor.moveToFirst();
            int index = cursor.getColumnIndex(filePathColumn[0]);
            //這裏有可能爲空 所以要做判斷
            if (index > -1) {
                filePath = cursor.getString(index);
            }

            fileName = cursor.getString(cursor.getColumnIndex(filePathColumn[1]));
            cursor.close();

            if (!Check.isEmpty(filePath)) {
                file = new File(filePath);
                if (!file.exists() || file.length() <= 0) {
                    filePath = getPathFromInputStreamUri(contentUri, fileName);
                }
            } else {
                filePath = getPathFromInputStreamUri(contentUri, fileName);
            }
        }
        return filePath;
    }

    /**
     * 用流拷貝文件一份到自己APP目錄下
     *
     * @param uri
     * @param fileName
     * @return
     */
    public String getPathFromInputStreamUri(Uri uri, String fileName) {
        InputStream inputStream = null;
        String filePath = null;

        if (uri.getAuthority() != null) {
            try {
                inputStream = getContentResolver().openInputStream(uri);
                File file = FileIoTools.createTemporalFileFrom(this, inputStream, fileName);
                filePath = file.getPath();

            } catch (Exception e) {
                Log.e(getClass().getSimpleName(), e.toString());
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (Exception e) {
                    Log.e(getClass().getSimpleName(), e.toString());
                }
            }
        }

        return filePath;
    }
 /**
     * 將文件通過流的方式複製到臨時文件夾
     * @param context
     * @param inputStream
     * @param fileName
     * @return
     * @throws IOException
     */
    public static File createTemporalFileFrom(Context context, InputStream inputStream, String fileName)
            throws IOException {
        File targetFile = null;

        if (inputStream != null) {
            int read;
            byte[] buffer = new byte[8 * 1024];
            //自己定義拷貝文件路徑
            targetFile = new File(PATH_CACHE, fileName);
            if (targetFile.exists()) {
                targetFile.delete();
            }
            OutputStream outputStream = new FileOutputStream(targetFile);

            while ((read = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, read);
            }
            outputStream.flush();

            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return targetFile;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章