關(guān)于Android文件的那些事

前言

在了解Android文件相關(guān)知識前,先來了解下Android文件相關(guān)常用的API

Log.i("相關(guān)API調(diào)用", "=======Environment調(diào)用=======\n"
                + "getRootDirectory = " + Environment.getRootDirectory().getPath() + "\n"
                + "getDownloadCacheDirectory = " + Environment.getDownloadCacheDirectory().getPath() + "\n"
                + "getDataDirectory = " + Environment.getDataDirectory().getPath() + "\n"
                + "getExternalStorageDirectory = " + Environment.getExternalStorageDirectory().getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NOTIFICATIONS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES).getPath() + "\n"
                + "=======Environment調(diào)用結(jié)束=======\n \n"
                + "=======Context調(diào)用出的目錄=======\n"
                + "getCacheDir = " + getCacheDir().getPath() + "\n"
                + "getDataDir = " + getDataDir().getPath() + "\n"http://Android7.0
                + "getFilesDir = " + getFilesDir().getPath() + "\n"
                + "getExternalMediaDirs = " + Arrays.toString(getExternalMediaDirs()) + "\n"
                + "getExternalCacheDir = " + getExternalCacheDir() + "\n"
                + "getExternalCacheDirs = " + Arrays.toString(getExternalCacheDirs()) + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(null) + "\n"
                + "getExternalFilesDirs = " + Arrays.toString(getExternalFilesDirs(null)) + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_ALARMS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_DCIM).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_MOVIES).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_MUSIC).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_NOTIFICATIONS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_PICTURES).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_PODCASTS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_RINGTONES).getPath() + "\n"
                + "=======Context調(diào)用出的目錄結(jié)束=======\n");

輸出如下:

I/相關(guān)API調(diào)用: =======Environment調(diào)用=======
    getRootDirectory = /system
    getDownloadCacheDirectory = /data/cache
    getDataDirectory = /data
    getExternalStorageDirectory = /storage/emulated/0
    getExternalStoragePublicDirectory = /storage/emulated/0/Documents
    getExternalStoragePublicDirectory = /storage/emulated/0/Alarms
    getExternalStoragePublicDirectory = /storage/emulated/0/DCIM
    getExternalStoragePublicDirectory = /storage/emulated/0/Movies
    getExternalStoragePublicDirectory = /storage/emulated/0/Music
    getExternalStoragePublicDirectory = /storage/emulated/0/Download
    getExternalStoragePublicDirectory = /storage/emulated/0/Notifications
    getExternalStoragePublicDirectory = /storage/emulated/0/Pictures
    getExternalStoragePublicDirectory = /storage/emulated/0/Podcasts
    getExternalStoragePublicDirectory = /storage/emulated/0/Ringtones
    =======Environment調(diào)用結(jié)束=======
     
    =======Context調(diào)用出的目錄=======
    getCacheDir = /data/user/0/com.xxx.xxxxx/cache
    getDataDir = /data/user/0/com.xxx.xxxxx
    getFilesDir = /data/user/0/com.xxx.xxxxx/files
    getExternalMediaDirs = [/storage/emulated/0/Android/media/com.xxx.xxxxx]
    getExternalCacheDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/cache
    getExternalCacheDirs = [/storage/emulated/0/Android/data/com.xxx.xxxxx/cache]
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files
    getExternalFilesDirs = [/storage/emulated/0/Android/data/com.xxx.xxxxx/files]
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Documents
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Alarms
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/DCIM
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Movies
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Music
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Download
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Notifications
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Pictures
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Podcasts
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Ringtones
    =======Context調(diào)用出的目錄結(jié)束=======

1励翼、獲取文件夾蜈敢、文件和Uri

1.1、Android7.0前

在Android6.0之前和Android6.0之后汽抚,只是獲取文件需要增加一個讀取權(quán)限的區(qū)別而已

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

而獲取文件目錄都是如下

Environment.getExternalStorageDirectory().getPath()+"子目錄";
//或者
Environment.getExternalStoragePublicDirectory(String type).getPath()+"子目錄";

//若想要取以上文件夾中的其他文件夾或者文件扶认,則在后面拼接即可,如下
String testFileTest = Environment.getExternalStoragePublicDirectory(String type).getPath()+File.separator+"test(.文件后綴)";

獲取文件Uri
Uri uri = Uri.fromFile(file);

1.2殊橙、Android7.0后

Android7.0和Android7.0之后,獲取文件目錄的方式跟Android7.0之前沒什么區(qū)別
只不過要在Manifest.xml文件中增加FileProvider配置狱从,否則取不到File膨蛮,并且不能再直接通過File方式獲取文件輸入輸出流對文件進行讀寫和其他操作

<!--FileProvider-->
<provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.test.provider.xxxxxx"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/public_file_path" />
</provider>

上面android:authorities="com.test.provider.xxxxxx"的內(nèi)容為com.test.provider.xxxxxx,一般情況下季研,android:authorities的值為包名+其他敞葛,這個值關(guān)系到后面如何獲取文件的Uri

//獲取外部存儲空間目錄及其子文件夾目錄下的文件夾和文件的Uri,即通過Environment.getXXXDir獲取到的目錄和文件獲取Uri的方式
Uri uri = FileProvider.getUriForFile(this, getPackageName(), file);
//如果android:authorities的值不止有包名与涡,則獲取方式為
Uri uri = FileProvider.getUriForFile(this, getPackageName()+"其他", file);

//而Context調(diào)出的目錄惹谐,例如getExternalCacheDir()目錄下用這種方式取得Uri
Uri uri = Uri.fromFile(file);

//得到uri之后才可以根據(jù)Uri得到輸入輸出流對文件進行操作
InputStream inputStream = context.getContentResolver().openInputStream(uri);
OutputStream outputStream = context.getContentResolver().openOutputStream(uri);

到這里為止,根據(jù)以上的所得Android7.0前和Android7.0及之后驼卖,在獲取外部存儲空間Uri時的兼容代碼可以如下

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    Uri uri = FileProvider.getUriForFile(this, getPackageName()+"其他", file);
} else {
    Uri uri = Uri.fromFile(file);           
}

而Context調(diào)出的目錄氨肌,例如getExternalCacheDir()目錄下文件的Uri獲取方式則不變

1.3、Android Q后

Android Q 在外部存儲設(shè)備中為每個應(yīng)用提供了一個“隔離存儲沙盒”(例如 /sdcard)酌畜。任何其他應(yīng)用都無法直接訪問您應(yīng)用的沙盒文件怎囚。自己本應(yīng)用訪問自己保存在沙盒中的文件屬于私有,所以訪問不需要任何權(quán)限桥胞。如果需要訪問系統(tǒng)媒體文件恳守,需要申請新的媒體權(quán)限:READ_MEDIA_IMAGES,READ_MEDIA_VIDEO,READ_MEDIA_AUDIO
對于Android Q來說考婴,沙盒還算是剛開始,所以官方的限制也沒那么嚴格催烘,可以通過在<application>中配置android:requestLegacyExternalStorage="true"沥阱,那么同樣能訪問系統(tǒng)的相關(guān)媒體文件
對于沙盒存儲,文件存放都要存放到對應(yīng)的位置伊群,如一張圖片要放到
getExternalFilesDir(Environment.DIRECTORY_PICTURES)當中考杉,若getExternalFilesDir(Environment.DIRECTORY_PICTURES)為空,則放到
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)當中在岂,這樣能將對應(yīng)類型的文件放到對應(yīng)的文件目錄下奔则,不至于亂放

理解:沙盒存儲,就是將對應(yīng)的文件類型蔽午,放到對應(yīng)的目錄或者Android/data/對應(yīng)的包名文件當中去

1.3.1易茬、獲取Uri

對于Android Q來說,設(shè)置了android:requestLegacyExternalStorage="true"依然可以跟之前一樣及老,存放文件并沒有一定要求完全沙盒存儲
Android Q以下或者Android Q設(shè)置了android:requestLegacyExternalStorage="true"抽莱,依然可以在Environment.getExternalStorageDirectory().getPath();目錄下存放文件和操作文件

//Uri獲取
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    Uri uri = FileProvider.getUriForFile(this, getPackageName()+"其他", file);
} else {
    Uri uri = Uri.fromFile(file);           
}

若無設(shè)置android:requestLegacyExternalStorage或者大于Android Q來說,則必須按照完全沙盒存儲

//文件存儲和操作目錄必須放于該公共目錄下
Environment.getExternalStoragePublicDirectory(String type).getPath();
//或者私有存儲
getExternalFilesDir(String type).getPath()

//Uri獲取
Uri uri = Uri.fromFile(file);        

2骄恶、創(chuàng)建文件夾

2.1食铐、創(chuàng)建文件夾和其子目錄

if(!file.exists()){
    file.mkdirs();
}

2.2、創(chuàng)建單一文件夾

if(!file.exists()){
    file.mkdir();
}

3僧鲁、獲取文件輸入輸出流

3.1虐呻、根據(jù)Uri獲取輸入輸出流

InputStream inputStream = context.getContentResolver().openInputStream(uri);
OutputStream outputStream = context.getContentResolver().openOutputStream(uri);

3.2、根據(jù)File獲取輸入輸出流

根據(jù)File獲取輸入輸出流是有前提的寞秃,那就是文件路徑必須對斟叼。
這個前提看似很簡單,但是根據(jù)以上說的版本差異春寿,經(jīng)常會出現(xiàn)兼容未做好而導(dǎo)致通過File獲取輸入輸出流或者對文件進行操作時朗涩,提示:FileNotFoundException: open failed: EPERM (Operation not permitted)
所以必須根據(jù)版本差異,是使用非沙盒存儲還是沙盒存儲绑改,這點是必須要注意的

File file = new File(path);
//path一定谢床,一定,一定要根據(jù)是否沙盒確定好存放路徑厘线,并且申請相關(guān)權(quán)限
InputStream inputStream = new FileInputStream(file);
OutputStream outputStream = new FileOutputStream(file);

4识腿、FileProvider配置

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!--1、對應(yīng)內(nèi)部內(nèi)存卡根目錄:Context.getFileDir()/com.xxx.xxx-->
    <files-path
        name="int_root"
        path="com.xxx.xxx/" />
    <!--2造壮、對應(yīng)應(yīng)用默認緩存根目錄:Context.getCacheDir()/com.xxx.xxx-->
    <cache-path
        name="app_cache"
        path="com.xxx.xxx/" />
    <!--3覆履、對應(yīng)外部內(nèi)存卡根目錄:Environment.getExternalStorageDirectory()/com.xxx.xxx-->
    <external-path
        name="ext_root"
        path="com.xxx.xxx/" />
    <!--4、對應(yīng)外部內(nèi)存卡根目錄下的APP公共目錄:Context.getExternalFileDir(String)/com.xxx.xxx-->
    <external-files-path
        name="ext_pub"
        path="com.xxx.xxx/" />
    <!--5、對應(yīng)外部內(nèi)存卡根目錄下的APP緩存目錄:Context.getExternalCacheDir()/com.xxx.xxx-->
    <external-cache-path
        name="ext_cache"
        path="com.xxx.xxx/" />
</paths>

5硝全、copy文件

    /**
     * 復(fù)制文件
     * @param context 上下文對象
     * @param sourceUri 被復(fù)制文件的Uri
     * @param savePath 粘貼路徑
     * @return 返回File
     */
    public static File copyFile(Context context, Uri sourceUri, String savePath) {
        InputStream inputStream = null;
        OutputStream fos = null;
        try {
            inputStream = context.getContentResolver().openInputStream(sourceUri);
            String path = sourceUri.getPath();
            if (path == null) {
                return null;
            }
            int i = path.lastIndexOf("/") + 1;
            String substring = path.substring(i);
            File directory = new File(savePath);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            File file = new File(savePath, substring);
            if (file.exists()) {
                if (inputStream != null) {
                    inputStream.close();
                }
                return file;
            }
            fos = new FileOutputStream(file);
//            long sum = 0;
            byte[] buf = new byte[2048];
            int len;
            while (inputStream != null && (len = inputStream.read(buf)) != -1) {
                fos.write(buf, 0, len);
//                sum += len;
            }
            fos.flush();
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

使用

File file;
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    //想放到公共目錄栖雾,理論上可被復(fù)制的文件也可被訪問,故而大多情況下復(fù)制到沙盒公共目錄下是多余的
    file = FileUtils.copyFile(this, uri,
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath()
                    + File.separator + Env.DIR_PUBLIC);
    //或者放到私有目錄沙盒
    file = FileUtils.copyFile(this, uri,
            getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getPath()
                    + File.separator + Env.DIR_PUBLIC);

    uri = Uri.fromFile(file);
} else {
    file = FileUtils.copyFile(this, uri,Environment.getExternalStorageDirectory().getPath()+ File.separator + Env.DIR_PUBLIC);

    uri = FileProvider.getUriForFile(this, getPackageName() + "其他", file);
}

6伟众、根據(jù)路徑路徑以合適的程序打開文件

//建立一個文件類型與文件后綴名的匹配表
    private static final String[][] MIME_MapTable = {
            //{后綴名析藕, MIME類型}
            {".3gp", "video/3gpp"},
            {".apk", "application/vnd.android.package-archive"},
            {".asf", "video/x-ms-asf"},
            {".avi", "video/x-msvideo"},
            {".bin", "application/octet-stream"},
            {".bmp", "image/bmp"},
            {".c", "text/plain"},
            {".class", "application/octet-stream"},
            {".conf", "text/plain"},
            {".cpp", "text/plain"},
            {".doc", "application/msword"},
            {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {".xls", "application/vnd.ms-excel"},
            {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {".exe", "application/octet-stream"},
            {".gif", "image/gif"},
            {".gtar", "application/x-gtar"},
            {".gz", "application/x-gzip"},
            {".h", "text/plain"},
            {".htm", "text/html"},
            {".html", "text/html"},
            {".jar", "application/java-archive"},
            {".java", "text/plain"},
            {".jpeg", "image/jpeg"},
            {".jpg", "image/jpeg"},
            {".js", "application/x-javascript"},
            {".log", "text/plain"},
            {".m3u", "audio/x-mpegurl"},
            {".m4a", "audio/mp4a-latm"},
            {".m4b", "audio/mp4a-latm"},
            {".m4p", "audio/mp4a-latm"},
            {".m4u", "video/vnd.mpegurl"},
            {".m4v", "video/x-m4v"},
            {".mov", "video/quicktime"},
            {".mp2", "audio/x-mpeg"},
            {".mp3", "audio/x-mpeg"},
            {".mp4", "video/mp4"},
            {".mpc", "application/vnd.mpohun.certificate"},
            {".mpe", "video/mpeg"},
            {".mpeg", "video/mpeg"},
            {".mpg", "video/mpeg"},
            {".mpg4", "video/mp4"},
            {".mpga", "audio/mpeg"},
            {".msg", "application/vnd.ms-outlook"},
            {".ogg", "audio/ogg"},
            {".pdf", "application/pdf"},
            {".png", "image/png"},
            {".pps", "application/vnd.ms-powerpoint"},
            {".ppt", "application/vnd.ms-powerpoint"},
            {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {".prop", "text/plain"},
            {".rc", "text/plain"},
            {".rmvb", "audio/x-pn-realaudio"},
            {".rtf", "application/rtf"},
            {".sh", "text/plain"},
            {".tar", "application/x-tar"},
            {".tgz", "application/x-compressed"},
            {".txt", "text/plain"},
            {".wav", "audio/x-wav"},
            {".wma", "audio/x-ms-wma"},
            {".wmv", "audio/x-ms-wmv"},
            {".wps", "application/vnd.ms-works"},
            {".xml", "text/plain"},
            {".z", "application/x-compress"},
            {".zip", "application/x-zip-compressed"},
            {"", "*/*"}
    };

/**
     * 根據(jù)路徑打開文件
     *
     * @param context 上下文
     * @param path    文件路徑
     */
    public static void openFileByPath(Context context, String path) {
        try {
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            //設(shè)置intent的Action屬性
            intent.setAction(Intent.ACTION_VIEW);
            File file = new File(path);
            //獲取文件file的MIME類型
            String type = getMIMEType(file);
            //設(shè)置intent的data和Type屬性。android 7.0以上crash,改用provider
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                Uri fileUri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);//android 7.0以上
                intent.setDataAndType(fileUri, type);
                grantUriPermission(context, fileUri, intent);
            } else {
                intent.setDataAndType(/*uri*/Uri.fromFile(file), type);
            }
            //跳轉(zhuǎn)
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String getMIMEType(File file) {

        String type = "*/*";
        String fName = file.getName();
        //獲取后綴名前的分隔符"."在fName中的位置凳厢。
        int dotIndex = fName.lastIndexOf(".");
        if (dotIndex < 0) {
            return type;
        }
        /* 獲取文件的后綴名 */
        String end = fName.substring(dotIndex).toLowerCase();
        if (end.equals("")) return type;
        //在MIME和文件類型的匹配表中找到對應(yīng)的MIME類型账胧。
        for (int i = 0; i < MIME_MapTable.length; i++) { //MIME_MapTable??在這里你一定有疑問,這個MIME_MapTable是什么先紫?
            if (end.equals(MIME_MapTable[i][0]))
                type = MIME_MapTable[i][1];
        }
        return type;
    }

    private static void grantUriPermission(Context context, Uri fileUri, Intent intent) {
        List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
    }

7治泥、根據(jù)Uri得到文件路徑

    /**
     * 根據(jù)公共存儲目錄文件Uri得到文件路徑
     * @param context 上下文對象
     * @param uri 需要查找文件的Uri
     * @return 返回路徑
     */
    public static String getPath(final Context context, final Uri uri) {
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市遮精,隨后出現(xiàn)的幾起案子居夹,更是在濱河造成了極大的恐慌,老刑警劉巖本冲,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件准脂,死亡現(xiàn)場離奇詭異,居然都是意外死亡檬洞,警方通過查閱死者的電腦和手機狸膏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來添怔,“玉大人湾戳,你說我怎么就攤上這事」懔希” “怎么了院塞?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長性昭。 經(jīng)常有香客問我,道長县遣,這世上最難降的妖魔是什么糜颠? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮萧求,結(jié)果婚禮上其兴,老公的妹妹穿的比我還像新娘。我一直安慰自己夸政,他們只是感情好元旬,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般匀归。 火紅的嫁衣襯著肌膚如雪坑资。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天穆端,我揣著相機與錄音袱贮,去河邊找鬼。 笑死体啰,一個胖子當著我的面吹牛攒巍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播荒勇,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼柒莉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沽翔?” 一聲冷哼從身側(cè)響起兢孝,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎搀擂,沒想到半個月后西潘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡哨颂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年喷市,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片威恼。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡品姓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出箫措,到底是詐尸還是另有隱情腹备,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布斤蔓,位于F島的核電站植酥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏弦牡。R本人自食惡果不足惜友驮,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望驾锰。 院中可真熱鬧卸留,春花似錦、人聲如沸椭豫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喳整,卻和暖如春谆构,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背算柳。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工低淡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瞬项。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓蔗蹋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親囱淋。 傳聞我的和親對象是個殘疾皇子猪杭,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容