打开系统文件选择器,获取文件真实路径

xxx
常用的mime type
多种文件类型选择办法

记得先申请sdcard的存储权限额
清单文件添加如下这种权限

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

23以上需要动态获取权限,获取成功以后下边才好执行,否则没有 权限就异常了。
清单文件里忘了写权限了,结果运行就挂,来个弹框
软件包安装程序已停止

调用下边的 方法启动,主要是看type,如果不显示文件类型,那就“/”,其他类型可以自己查下

    private void openFileChoose(){
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("video/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent,123);
    }

    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(data!=null){
            Uri uri=data.getData();
            System.out.println("uri============="+uri);
        }
    }

使用记录

首先,可能要求选择多种类型都可以,主要就是传个参数EXTRA_MIME_TYPES,后边是你需要的类型数组
然后type里就写/了。
代码如下

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"audio/*", "video/*", "image/*"});
      
        intent.setType("*/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, 1234);

然后实际需求是一次可以选多个文件,刚开始以为做不到,后边无聊查了下Intent,发现还真有一个可以用

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true);

看下源码说明

    /**
     * Extra used to indicate that an intent can allow the user to select and
     * return multiple items. This is a boolean extra; the default is false. If
     * true, an implementation is allowed to present the user with a UI where
     * they can pick multiple items that are all returned to the caller. When
     * this happens, they should be returned as the {@link #getClipData()} part
     * of the result Intent.
     *
     * @see #ACTION_GET_CONTENT
     * @see #ACTION_OPEN_DOCUMENT
     */
    public static final String EXTRA_ALLOW_MULTIPLE =
            "android.intent.extra.ALLOW_MULTIPLE";

使用这个,返回的数据就不是getData了,而是getClipData(),这个拿到ClipData,点下方法就知道了,可以拿到count,可以getItemAt获取item,里边该有的数据都有了。

public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
  data.getClipData()

copy的


import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

public String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
//                Log.i(TAG,"isExternalStorageDocument***"+uri.toString());
//                Log.i(TAG,"docId***"+docId);
//                以下是打印示例:
//                isExternalStorageDocument***content://com.android.externalstorage.documents/document/primary%3ATset%2FROC2018421103253.wav
//                docId***primary:Test/ROC2018421103253.wav
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
//                Log.i(TAG,"isDownloadsDocument***"+uri.toString());
                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)) {
//                Log.i(TAG,"isMediaDocument***"+uri.toString());
                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())) {
//            Log.i(TAG,"content***"+uri.toString());
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
//            Log.i(TAG,"file***"+uri.toString());
            return uri.getPath();
        }
        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public String getDataColumn(Context context, Uri uri, String selection,
                                String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    
    public boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }
    
    public boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    public boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

调用权限的工具类
这里默认的requestCode是从1开始自增的,记得别和activity里其他冲突了。

import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.SparseArray;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;

public class FragmentPermissionHolder extends Fragment {

    public static void checkPermission(FragmentActivity fragmentActivity,String[] permissions,RequestListener requestListener){
        if (PermissionChecker.checkCallingOrSelfPermission(fragmentActivity,
                permissions[0]) != PackageManager.PERMISSION_GRANTED){
            getInstance(fragmentActivity).requestPermissions(permissions,requestListener);
        }else{
            requestListener.onSuccess(permissions);
        }
    }

    public static final String TAG_FRAGMENT="tag_fragment_temp";
    public static FragmentPermissionHolder getInstance(FragmentActivity fragmentActivity){

        FragmentPermissionHolder fragment= (FragmentPermissionHolder) fragmentActivity.getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
        if(fragment==null){
            fragment=new FragmentPermissionHolder();
            FragmentManager fragmentManager=fragmentActivity.getSupportFragmentManager();
            fragmentManager.beginTransaction().add(fragment, TAG_FRAGMENT).commitAllowingStateLoss();
            fragmentManager.executePendingTransactions();
        }
        return  fragment;
    }

    private SparseArray<RequestListener> callbackMap=new SparseArray<>();
    private int code=0;
    public void  requestPermissions(String[] permissions,RequestListener requestListener){
        code++;
        callbackMap.put(code,requestListener);
        requestPermissions(permissions,code);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        RequestListener callback=callbackMap.get(requestCode);
        callbackMap.delete(requestCode);
        for(int i=0;i<grantResults.length;i++){
            if(grantResults[i]!= PermissionChecker.PERMISSION_GRANTED){
                callback.onFailed(permissions);
                return;
            }
        }
        callback.onSuccess(permissions);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    public interface RequestListener{
        void onSuccess(String[] permissions);
        void onFailed(String[] permissions);
    }
}

代码中使用如下,传入自己要申请的权限即可

    private void permissionCheck() {
        FragmentPermissionHolder.checkPermission(getActivity(),new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE},
                new FragmentPermissionHolder.RequestListener() {
                    @Override
                    public void onSuccess(String[] permissions) {
                        openFileChoose();
                    }

                    @Override
                    public void onFailed(String[] permissions) {
                        dismissAllowingStateLoss();
                    }
                });
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,883评论 0 10
  • 毕业那年,我二十二。提着两个行李包,带着四年的记忆到了张家港,一个小却干净的城市。晚上八点可以肆意走在大街上,不用...
    stonerain阅读 451评论 3 11
  • 每一个走进你生命的人,都不是偶然。缘分,并非是简单的上天安排, 人人都是一方神秘的磁场,吸引着类似气质的同伴。 遇...
    丽漫群阅读 601评论 5 12
  • 宇宙是由一个时空构成的自然生命活体,她充满着一个巨大的生命智慧生化的网络系统。它的生发演化过程如同人的生老病死一样...
    佛罗瑞特阅读 1,147评论 0 1