精华内容
下载资源
问答
  • Android 选择文件返回路径怎么就这么难? 这个问题纠结了我很长时间,终于有了比较好的解决方案。目前已知适配所有的机型,有问题就留言吧。 正确姿势来一遍 1. 打开系统自带的文件浏览器并限制类型 public void ...

    Android 选择文件返回路径怎么就这么难?

    这个问题纠结了我很长时间,终于有了比较好的解决方案。目前已知适配所有的机型,有问题就留言吧。

    正确姿势来一遍

    1. 打开系统自带的文件浏览器并限制类型

    public void OpenFile(View view) {
            // 指定类型
            String[] mimeTypes = {"*/*"};
           // String[] mimeTypes = {"application/octet-stream"}; // 指定bin类型
            Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            StringBuilder mimeTypesStr = new StringBuilder();
            for (String mimeType : mimeTypes) {
                mimeTypesStr.append(mimeType).append("|");
            }
            intent.setType(mimeTypesStr.substring(0, mimeTypesStr.length() - 1));
            startActivityForResult(Intent.createChooser(intent, "ChooseFile"), REQUEST_FILE_CODE);
        } 
    

    其中mimeTypes是指定文件的类型,比如图片,比如Excel,即使设置了该属性,在某些机型上没有效果,所以在选择文件后还需要判断格式是否正确。

    为了大家嫌麻烦,我把类型举例放在了文章末尾,方便大家进行查询。

    2. 返回选择的数据

    final int REQUEST_FILE_CODE = 1000;
    
     @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == REQUEST_FILE_CODE && resultCode == RESULT_OK) {
                Uri uri = data.getData();
                Log.d(TAG, "uri:" + uri);
                //String filePath = PickUtils.getPath(this, uri);
                //textView.setText(filePath);
            }
            super.onActivityResult(requestCode, resultCode, data);
        }
    

    重点来了,我们可以很轻松的拿到Uri, 但是转absolute path 在不同的机型却遇到了奇奇怪怪的问题,至今没有完全弄明白。

    大概的意思就是有些机型转path时会失败,比如在华为10.0的机型上,通过下载内容中打开Download的文件就会失败,场景是原本的documentid可以转为long型,但它变成了这个样子msf:123,导致转换失败。

    有很多人都存在这个问题,比如这个地址:https://stackoverflow.com/questions/58660420/api-level-29-intent-action-get-content-returning-wrong-id-from-downloads-folder

    解决方法:在转换绝对路径失败的情况,将文件拷贝到自己的app的缓存目录下,然后返回路径。 代码在文章末尾。

    3. 思考与拓展

    我们可以轻松的拿到Uri之后,实际上在不转绝对路径的情况下,用Uri已经可以做很多事情了,比如获取文件类型、比如获取文件的byte[]、获取文件名 等等。

    • 获取文件类型,返回的结果需要在类型对应中去对照。
    /**
         * 获取文件的类型。
         * @param context 上下文
         * @param uri uri
         * @return
         */
        public static String getFormatByUri(@NonNull Context context, @NonNull Uri uri) {
            String type = context.getContentResolver().getType(uri);
            if (TextUtils.isEmpty(type)) return null;
            return type;
        }
        
    
    • 获取字节数组
    /**
         * 根据uri获取 byte[]
         * @param context
         * @param uri
         * @return
         * @throws IOException
         */
        public static byte[] getBytesByUri(Context context, Uri uri) throws IOException {
            InputStream iStream = context.getContentResolver().openInputStream(uri);
            if (iStream == null) return null;
            return getBytes(iStream);
        }
    
        private static byte[] getBytes(InputStream inputStream) throws IOException {
            ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
            int bufferSize = 1024;
            byte[] buffer = new byte[bufferSize];
    
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                byteBuffer.write(buffer, 0, len);
            }
            return byteBuffer.toByteArray();
        }
        
    
    • 获取文件名
    /**
         * 获取文件名
         * @param uri uri
         * @return
         */
        public String getFileNameByUri(Uri uri) {
            String filename = "";
            Cursor returnCursor = getContentResolver().query(uri, null,
                    null, null, null);
            if (returnCursor != null) {
                int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                returnCursor.moveToFirst();
                filename = returnCursor.getString(nameIndex);
                returnCursor.close();
            }
            return filename;
        }
    

    4. URI 转 Path

    当然,这个完美的工具类还是提供给大家。出处我不记得了,我稍微改了一点,目前用下来非常完美。 只是在转path不成功的情况下,会拷贝文件放到应用的缓存目录,大家需要注意下清理缓存的时机。

    import android.annotation.SuppressLint;
    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;
    import android.provider.OpenableColumns;
    import android.support.annotation.NonNull;
    import android.support.annotation.Nullable;
    import android.util.Log;
    
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * Created by pangw on 2018/5/23.
     */
    public class PickUtils {
    
        public static final String DOCUMENTS_DIR = "documents";
    
        @SuppressLint("NewApi")
        public static 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);
                    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);
    
                    if (id != null && id.startsWith("raw:")) {
                        return id.substring(4);
                    }
    
                    String[] contentUriPrefixesToTry = new String[]{
                            "content://downloads/public_downloads",
                            "content://downloads/my_downloads"
                    };
    
                    for (String contentUriPrefix : contentUriPrefixesToTry) {
                        try {
                            // note: id 可能为字符串,如在华为10.0系统上,选择文件后id为:"msf:254",导致转Long异常
                            Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.parseLong(id));
                            String path = getDataColumn(context, contentUri, null, null);
                            if (path != null && !path.equals("")) {
                                return path;
                            }
                        } catch (Exception e) {
                        }
                    }
    
                    // path could not be retrieved using ContentResolver, therefore copy file to accessible cache using streams
                    String fileName = getFileName(context, uri);
                    File cacheDir = getDocumentCacheDir(context);
                    File file = generateFileName(fileName, cacheDir);
                    String destinationPath = null;
                    if (file != null) {
                        destinationPath = file.getAbsolutePath();
                        saveFileFromUri(context, uri, destinationPath);
                    }
    
                    return destinationPath;
                }
                // 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())) {
                String path = getDataColumn(context, uri, null, null);
                if (path != null && !path.equals("")) return path;
    
                // path could not be retrieved using ContentResolver, therefore copy file to accessible cache using streams
                String fileName = getFileName(context, uri);
                File cacheDir = getDocumentCacheDir(context);
                File file = generateFileName(fileName, cacheDir);
                String destinationPath = null;
                if (file != null) {
                    destinationPath = file.getAbsolutePath();
                    saveFileFromUri(context, uri, destinationPath);
                }
                return destinationPath;
            }
            // File
            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());
        }
    
        public static String getDataColumn(Context context, Uri uri, String selection,
                                           String[] selectionArgs) {
    
            Cursor cursor = null;
            final String column = "_data";
            final String[] projection = {column};
            String path = "";
            try {
                cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                        null);
                if (cursor != null && cursor.moveToFirst()) {
                    final int column_index = cursor.getColumnIndexOrThrow(column);
                    path = cursor.getString(column_index);
                    return path;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (cursor != null)
                    cursor.close();
            }
            return path;
        }
    
        public static String getFileName(@NonNull Context context, Uri uri) {
            String mimeType = context.getContentResolver().getType(uri);
            String filename = null;
            if (mimeType == null && context != null) {
                String path = getPath(context, uri);
                if (path == null) {
                    filename = getName(uri.toString());
                } else {
                    File file = new File(path);
                    filename = file.getName();
                }
            } else {
                Cursor returnCursor = context.getContentResolver().query(uri, null,
                        null, null, null);
                if (returnCursor != null) {
                    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                    returnCursor.moveToFirst();
                    filename = returnCursor.getString(nameIndex);
                    returnCursor.close();
                }
            }
    
            return filename;
        }
    
        public static String getName(String filename) {
            if (filename == null) {
                return null;
            }
            int index = filename.lastIndexOf('/');
            return filename.substring(index + 1);
        }
    
        public static File getDocumentCacheDir(@NonNull Context context) {
            Log.d("PickUtils", "getDocumentCacheDir");
            File dir = new File(context.getCacheDir(), DOCUMENTS_DIR);
            if (!dir.exists()) {
                dir.mkdirs();
            }
    
            return dir;
        }
    
        @Nullable
        public static File generateFileName(@Nullable String name, File directory) {
            if (name == null) {
                return null;
            }
    
            File file = new File(directory, name);
    
            if (file.exists()) {
                String fileName = name;
                String extension = "";
                int dotIndex = name.lastIndexOf('.');
                if (dotIndex > 0) {
                    fileName = name.substring(0, dotIndex);
                    extension = name.substring(dotIndex);
                }
    
                int index = 0;
    
                while (file.exists()) {
                    index++;
                    name = fileName + '(' + index + ')' + extension;
                    file = new File(directory, name);
                }
            }
    
            try {
                if (!file.createNewFile()) {
                    return null;
                }
            } catch (IOException e) {
                return null;
            }
    
            return file;
        }
    
    
        private static void saveFileFromUri(Context context, Uri uri, String destinationPath) {
            InputStream is = null;
            BufferedOutputStream bos = null;
            try {
                is = context.getContentResolver().openInputStream(uri);
                bos = new BufferedOutputStream(new FileOutputStream(destinationPath, false));
                byte[] buf = new byte[1024];
                is.read(buf);
                do {
                    bos.write(buf);
                } while (is.read(buf) != -1);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (is != null) is.close();
                    if (bos != null) bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
    
    
    

    5. 类型对应

    private 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"},
     
      {"", "*/*"}
     
      };
    
    
    展开全文
  • Window---->Perferences---->Content Types 选择Text下的JSP,后在下面的Default encoding中填上GBK即可

    Window---->Perferences---->Content Types     选择Text下的JSP,后在下面的Default encoding中填上GBK即可


    展开全文
  • pycharm和Spyder的python文件、python控制台、jupyter的优缺点、怎么选择 代码以块为一个整体运行的话: 1. python文件文件的块是所有行的代码 优点:通用,阅读代码方便,适用于大型的项目 缺点:需要从头运行...

    pycharm和Spyder的python文件、python控制台、jupyter的优缺点、怎么选择

    代码以块为一个整体运行的话:

    1. python文件:文件的块是所有行的代码

    优点:通用,阅读代码方便,适用于大型的项目
    缺点:需要从头运行(Spyder可以F9以任意行为块运行)

    2. python控制台:以任意行为块,运行的(ctrl+shift 换行)

    优点:显示每个变量属性
    缺点:不利于代码阅读及修改

    3. jupyter:以任意行为块,运行的

    优点:利于代码阅读及修改
    缺点:环境需要配置

    展开全文
  • Android 文件选择/文件管理

    千次阅读 2018-08-03 14:14:43
    但是如果说现在需要上传pdf,zip,或者其他类似xxx.sb文件类型时,你该怎么搞了?调用系统文件管理(呵呵)!我就遇到过这种需求,而且遇到两次了!为了以后轻松的完成工作,所以已经把项目中的代码全部提取出来重构...

    大家应该都有遇到过这种需求:上传图片,视频文件时,直接调用相册即可,无需过多的操作!但是如果说现在需要上传pdf,zip,或者其他类似xxx.sb文件类型时,你该怎么搞了?调用系统文件管理(呵呵)!我就遇到过这种需求,而且遇到不止两次了!我们写程序的都是干大事的,这种繁琐的工作怎么可以难住我了。所以 ZFileManager 就诞生了!完整代码已上传至GitHub ,记得start一下哦!!!

    小声BB:图片选择框架也有哦GitHub

    ZFileManager 特点

    • 默认支持 音频,视频,图片,txt,zip,word,excel,ppt,pdf 9种文件
    • 支持音频、视频播放,图片查看,zip解压,文件重命名、复制、移动、删除、查看详情
    • 支持查看指定文件类型,支持文件类型拓展
    • 支持多选,数量、文件大小限制、实时排序、指定文件路径访问
    • 支持QQ、微信文件选择(支持自定义获取)
    • 高度可定制化,支持AndroidX、DSL,兼容Java

    部分截图

    使用(Java使用

    温馨提示: targetSdkVersion >= 29 清单文件中加上 android:requestLegacyExternalStorage=“true”

    Step 0. 添加依赖

    	implementation 'com.github.zp:z_file:1.2.6'
    
    	如果报错加上
        
        // Kotlin Parcelable 支持
        androidExtensions {
            experimental = true
        }
    
    

    Step 1. 实现ZFileImageListener,并在调用前或Application中初始化

    
    class MyFileImageListener : ZFileImageListener() {
    
        override fun loadImage(imageView: ImageView, file: File) {
            // 以Glide为例
            Glide.with(imageView.context)
                .load(file)
                .apply(RequestOptions().apply {
                    placeholder(R.drawable.ic_zfile_other)
                    error(R.drawable.ic_zfile_other)
                })
                .into(imageView)
        }
    }
    
    // 在调用前或Application中初始化 
    getZFileHelp().init(MyFileImageListener())
    

    Step 2. 在Activity或Fragment中使用

    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            main_defaultMangerBtn.setOnClickListener {
                // 打开文件管理
                getZFileHelp()
                    .result(this) {
                        val sb = StringBuilder()
                        this?.forEach {
                            sb.append(it).append("\n\n")
                        }
                        main_resultTxt.text = sb.toString()
                    }
            }
        }
    
    }
    
    
    

    高级用法

    ZFileManager提供了对外的帮助类 ZFileHelp

    文件类型拓展

    Step 1. 新建一个类:ZFileType,重写里面的openFile()、loadingFile()方法

    
    // 自定义的类型
    const val APK = "apk"
    
    /**
     * 自定义Apk文件类型
     */
    class ApkType : ZFileType() {
    
        /**
         * 打开文件
         * @param filePath  文件路径
         * @param view      当前视图
         */
        override fun openFile(filePath: String, view: View) {
            Toast.makeText(view.context, "打开自定义拓展文件", Toast.LENGTH_SHORT).show()
        }
    
        /**
         * 加载文件
         * @param filePath 文件路径
         * @param pic      文件展示的图片
         */
        override fun loadingFile(filePath: String, pic: ImageView) {
            pic.setImageResource(R.mipmap.ic_launcher_round)
        }
        
    }
    
    

    Step 2. 新建一个类:ZFileTypeListener,重写里面的getFileType()方法 (有多个自定义类型,公用即可)

    
    class MyFileTypeListener : ZFileTypeListener() {
    
        override fun getFileType(filePath: String) =
            when (ZFileHelp.getFileTypeBySuffix(filePath)) {
                APK -> ApkType()
                else -> super.getFileType(filePath)
            }
    }
    
    

    Step 3. 在调用前或Application中配置

    getZFileHelp().setFileTypeListener(MyFileTypeListener())
    
    

    QQ或微信文件选择

    
        super_qqTxt.setOnClickListener {
            // 打开QQ文件选择
            getZFileHelp().setConfiguration(getZFileConfig().apply {
                filePath = ZFileConfiguration.QQ // 必须设置
            }).result(this) {
                setResult(this)
            }
        }
    
        super_wechatTxt.setOnClickListener {
            // 打开微信文件选择
            getZFileHelp().setConfiguration(getZFileConfig().apply {
                filePath = ZFileConfiguration.WECHAT // 必须设置
            }).result(this) {
                setResult(this)
            }
        }
    
        private fun setResult(selectList: MutableList<ZFileBean>?) {
            val sb = StringBuilder()
            selectList?.forEach {
                sb.append(it).append("\n\n")
            }
            super_resultTxt.text = sb.toString()        
        }
    
    

    DSL

        zfile {
                imageLoade {
                    // 配置 ZFileImageListener
                }
                fileLoade {
                    // 配置 ZFileLoadListener
                }
                qwLoade {
                    // 配置 ZQWFileLoadListener
                }
                config {
                    // 配置 ZFileConfiguration
                }
                fileType {
                    // 配置 ZFileTypeListener
                }
                fileOperate {
                    // 配置 ZFileOperateListener
                }
                fileOpen {
                    // 配置 ZFileOpenListener
                }
                result {
                    // 获取结果
                }
            }
    

    举个栗子

    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            main_defaultMangerBtn.setOnClickListener {
                dsl()
            }
        }
        
        private fun dsl() {
            zfile {
                fileType {
                    MyFileTypeListener()
                }
                config {
                    ZFileConfiguration().apply {
                        filePath = ZFileConfiguration.WECHAT
                    }
                }
                result {
                    val sb = StringBuilder()
                    this?.forEach {
                        sb.append(it).append("\n\n")
                    }
                    main_resultTxt.text = sb.toString()
                }
            }
        }
    
    }
    
        
    
    搞定,是不是很简单 ^ _ ^
    切,简单是简单,但是你这个获取文件实现的方式不优雅,你这个QQ、微信文件根本不能获取,你界面上的图片太丑了,打开文件你全部都是调用系统方式打开的(作者你个渣渣),我只想选择文件,不想要长按事件,文件操作我怎么用都感觉不正确,还有长按事件弹出的功能有些不是我想要的…
    扶我起来,我要搞死杠精

    自定义文件获取

    
    /**
     * 获取文件
     * 此方式,排序、是否显示隐藏文件、过滤规则等等操作都需要自己实现
     * Kotlin 获取配置信息:getZFileConfig()
     * Java 获取配置信息:ZFileManageHelp.getInstance().getConfiguration()
     */
    class MyFileLoadListener : ZFileLoadListener {
    
        /**
         * 获取手机里的文件List
         * @param filePath String?          指定的文件目录访问,空为SD卡根目录
         * @return MutableList<ZFileBean>?  list
         */
        override fun getFileList(context: Context?, filePath: String?) =
            getFileList(context, filePath)
    
        private fun getFileList(context: Context?, filePath: String?): MutableList<ZFileBean> {
             
        }
    }
    
    // 在调用前或Application中配置
    getZFileHelp().setFileLoadListener(MyFileLoadListener())
    
    
    

    自定义QQ、微信文件获取

    
    class MyQWFileListener : ZQWFileLoadListener() {
    
        /**
         * 获取标题
         * @return Array<String>
         */
        override fun getTitles(): Array<String>? {
            return arrayOf("图片", "媒体", "文档", "其他")
        }
    
        /**
         * 获取过滤规则
         * @param fileType Int      文件类型 see [ZFILE_QW_PIC] [ZFILE_QW_MEDIA] [ZFILE_QW_DOCUMENT] [ZFILE_QW_OTHER]
         */
        override fun getFilterArray(fileType: Int): Array<String> {
            return when (fileType) {
                ZFILE_QW_PIC -> arrayOf(PNG, JPG, JPEG, "gif")
                ZFILE_QW_MEDIA -> arrayOf(MP4, "3gp", "mp3")
                ZFILE_QW_DOCUMENT -> arrayOf(PDF, PPT, DOC, XLS)
                else -> arrayOf(TXT, JSON, XML, ZIP, "rar")
            }
        }
    
        /**
         * 获取 QQ 或 WeChat 文件路径
         * @param qwType String         QQ 或 WeChat  see [ZFileConfiguration.QQ] [ZFileConfiguration.WECHAT]
         * @param fileType Int          文件类型 see [ZFILE_QW_PIC] [ZFILE_QW_MEDIA] [ZFILE_QW_DOCUMENT] [ZFILE_QW_OTHER]
         * @return MutableList<String>  文件路径集合(因为QQ或WeChat保存的文件可能存在多个路径)
         */
        override fun getQWFilePathArray(qwType: String, fileType: Int): MutableList<String> {
            val listArray = arrayListOf<String>()
            if (qwType == ZFileConfiguration.QQ) { // QQ
                when (fileType) {
                    ZFILE_QW_PIC -> { 
                        listArray.add("/storage/emulated/0/tencent/QQ_Images/")
                        listArray.add("/storage/emulated/0/Pictures/") // QQ文件保存路径1,仅做演示
                        listArray.add("/storage/emulated/0/DCIM/") // QQ文件保存路径2,仅做演示
                        listArray.add("/storage/emulated/0/Pictures/QQ/")
                    }
                    ZFILE_QW_MEDIA -> {
                        listArray.add("/storage/emulated/0/Pictures/QQ/")
                    }
                    ZFILE_QW_DOCUMENT -> {
                        listArray.add("/storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/QQfile_recv/")
                        listArray.add("/storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/QQ_business/")
                    }
                    else -> {
                        listArray.add("/storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/QQfile_recv/")
                        listArray.add("/storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/QQ_business/")
                    }
                }
            } else { // WeChat
                when (fileType) {
                    ZFILE_QW_PIC -> {
                        listArray.add("/storage/emulated/0/tencent/MicroMsg/WeiXin/")
                        listArray.add("/storage/emulated/0/tencent/MicroMsg/WeiXin23/") // 微信文件保存路径1,仅做演示
                        listArray.add("/storage/emulated/0/tencent/MicroMsg/WeiXin233/") // 微信文件保存路径2,仅做演示
                    }
                    ZFILE_QW_MEDIA -> {
                        listArray.add("/storage/emulated/0/tencent/MicroMsg/WeiXin/")
                        listArray.add("/storage/emulated/0/Pictures/WeiXin/") // 微信文件保存路径
                    }
                    ZFILE_QW_DOCUMENT -> {
                        listArray.add("/storage/emulated/0/tencent/MicroMsg/Download/")
                    }
                    else -> {
                        listArray.add("/storage/emulated/0/tencent/MicroMsg/Download/")
                    }
                }
            }
            return listArray
        }
    
        /**
         * 获取数据
         * @param fileType Int                          文件类型 see [ZFILE_QW_PIC] [ZFILE_QW_MEDIA] [ZFILE_QW_DOCUMENT] [ZFILE_QW_OTHER]
         * @param qwFilePathArray MutableList<String>   QQ 或 WeChat 文件路径集合
         * @param filterArray Array<String>             过滤规则
         */
        override fun getQWFileDatas(fileType: Int, qwFilePathArray: MutableList<String>, filterArray: Array<String>): MutableList<ZFileBean> {
            val pathListFile = arrayListOf<Array<File>?>()
            qwFilePathArray.forEach {
                val file = File(it)
                if (file.exists()) {
                    pathListFile.add(file.listFiles(MyQWFilter(filterArray)))
                }
            }
            if (pathListFile.isEmpty()) return mutableListOf()
            val list = mutableListOf<ZFileBean>()
            pathListFile.forEach { item ->
                item?.forEach {
                    if (!it.isHidden) {
                        val bean = ZFileBean(
                                it.name,
                                it.isFile,
                                it.path,
                                ZFileHelp.getFormatFileDate(it),
                                it.lastModified().toString(),
                                ZFileHelp.getFileSize(it.path),
                                it.length()
                        )
                        list.add(bean)
                    }
                }
            }
            if (!list.isNullOrEmpty()) {
                list.sortByDescending { it.originalDate }
            }
            return list
        }
    
        class MyQWFilter(private var filterArray: Array<String>) : FileFilter {
    
            override fun accept(file: File): Boolean {
                filterArray.forEach {
                    if (file.name.accept(it)) {
                        return true
                    }
                }
                return false
            }
    
            private fun String.accept(type: String) =
                    this.endsWith(type.toLowerCase(Locale.CHINA)) || this.endsWith(type.toUpperCase(Locale.CHINA))
        }
    }
    
    // 在调用前或Application中配置
    getZFileHelp().setQWFileLoadListener(MyQWFileListener())
    
    
    

    UI 或操作自定义 更多可查看 ZFileConfigurationvalues

    
        /**
         * 起始访问位置,非空为指定访问目录,空为SD卡根目录
         * 还可指定QQ或微信目录
         */
        var filePath: String? = null
    
        ...
        ...
        ...
    
        /**
         * 是否需要长按事件
         */
        var needLongClick = true
    
        /**
         * 默认只有文件才有长按事件
         */
        var isOnlyFileHasLongClick = true
    
        /**
         * 长按后需要显示的操作类型
         */
        var longClickOperateTitles: Array<String>? = null
    
        /**
         * 相关资源配置 设置:[ZFILE_DEFAULT] 将使用默认资源
         * @property audioRes Int        音频
         * @property txtRes Int          文本
         * @property pdfRes Int          PDF
         * @property pptRes Int          PPT
         * @property wordRes Int         Word
         * @property excelRes Int        Excel
         * @property zipRes Int          ZIP
         * @property otherRes Int        其他类型
         * @property emptyRes Int        空资源
         * @property folderRes Int       文件夹
         * @property lineColor Int       列表分割线颜色
         */
        @Parcelize
        data class ZFileResources @JvmOverloads constructor(
            var audioRes: Int = R.drawable.ic_zfile_audio,
            var txtRes: Int = R.drawable.ic_zfile_txt,
            var pdfRes: Int = R.drawable.ic_zfile_pdf,
            var pptRes: Int = R.drawable.ic_zfile_ppt,
            var wordRes: Int = R.drawable.ic_zfile_word,
            var excelRes: Int = R.drawable.ic_zfile_excel,
            var zipRes: Int = R.drawable.ic_zfile_zip,
            var otherRes: Int = R.drawable.ic_zfile_other,
            var emptyRes: Int = R.drawable.ic_zfile_empty,
            var folderRes: Int = R.drawable.ic_zfile_folder,
            var lineColor: Int = R.color.zfile_line_color
        ) : Serializable, Parcelable
        
        // 在调用前或Application中配置
         getZFileHelp().setConfiguration(getZFileConfig().apply {
                resources = ZFileResources(R.drawable.ic_diy_audio)
                maxLength = 6
                maxLengthStr = "666"
                ...
                ...
                ...
            })
        
        // 其他自定义方式 如:Txt类型展示的图片不符合你的要求,继承自TxtType,重写相关方法即可,
        // 这种方式对于内置的文件类型可以达到完全自定义操作
    
    

    自定义打开默认支持的文件

    
    class MyFileOpenListener : ZFileOpenListener() {
    
        override fun openAudio(filePath: String, view: View) = Unit // 音频
        override fun openImage(filePath: String, view: View) = Unit // 图片
        override fun openVideo(filePath: String, view: View) = Unit // 视频
        override fun openTXT(filePath: String, view: View) = Unit // 文本
        override fun openZIP(filePath: String, view: View) = Unit // zip压缩包
        override fun openDOC(filePath: String, view: View) = Unit // word
        override fun openXLS(filePath: String, view: View) = Unit // xls
        override fun openPPT(filePath: String, view: View) = Unit // ppt
        override fun openPDF(filePath: String, view: View) = Unit // pdf
        override fun openOther(filePath: String, view: View) = Unit // 其他文件
    }
    
    // 在调用前或Application中配置
    getZFileHelp().setFileOpenListener(MyFileOpenListener())
    
    

    自定义文件操作

    
    class MyFileOperateListener : ZFileOperateListener() {
    
        /**
         * 文件重命名(该方式只需要实现重命名逻辑即可)
         * @param filePath String       文件路径
         * @param fileNewName String    新名字
         * @param context Context       Context
         * @param block Function2<Boolean, String, Unit> Boolean:成功或失败;String:新名字
         */
        open fun renameFile(
            filePath: String,
            fileNewName: String,
            context: Context,
            block: (Boolean, String) -> Unit
        ) {
           
        }
    
        /**
         * 复制文件 耗时操作,建议放在非UI线程中执行
         * @param sourceFile String     源文件地址
         * @param targetFile String     目标文件地址
         * @param context Context       Context
         * @param block                 文件操作成功或失败后的监听
         */
        override fun copyFile(
            sourceFile: String,
            targetFile: String,
            context: Context,
            block: Boolean.() -> Unit
        ) {
           thread {
               val success = MyFileUtil.copyFile(sourceFile, targetFile, context)
               (context as? Activity)?.let { 
                   it.runOnUiThread { 
                       block.invoke(success)
                   }
               }
           }
        }
    
        /**
         * 移动文件 耗时操作,建议放在非UI线程中执行
         */
        override fun moveFile(
            sourceFile: String,
            targetFile: String,
            context: Context,
            block: Boolean.() -> Unit
        ) {
        
        }
    
        /**
         * 删除文件 耗时操作,建议放在非UI线程中执行
         */
        override fun deleteFile(filePath: String, context: Context, block: Boolean.() -> Unit) {
             
        }
    
        /**
         * 解压文件 耗时操作,建议放在非UI线程中执行
         */
        override fun zipFile(
            sourceFile: String,
            targetFile: String,
            context: Context,
            block: Boolean.() -> Unit
        ) {
        }
    
        /**
         * 文件详情
         */
        override fun fileInfo(bean: ZFileBean, context: Context) {
            
        }
    }
    
    // 在调用前或Application中配置
    getZFileHelp().setFileOperateListener(MyFileOperateListener())
    
    
    更多操作请查看demo 如果觉得可以记得 star 一下哦

    小声BB:图片选择框架也有哦GitHub

    一切都源自之前的项目,从简单的一个文件选取列表 到 需要预览文件,再到QQ微信文件选择,每一次的需求变更都意味着又TM要重写了。干脆全部推倒重来,于是乎该库就诞生了… 下个版本将支持 Android 11,干就完事了…

    展开全文
  • 我有一个文本文件(textfile1.txt),有几行例子:123This is the line 1This is the line 2This is the line 3我可以在python脚本中以书面形式返回文本文件所有内容:123456def textFile1(self):my_file = open(&...
  • [MFC]目录选择文件选择

    万次阅读 2013-01-04 22:04:26
    最近项目中有下面需求: 1. 弹出目录或文件选择对话框 2. 当选中目录时将该目录下所有.c文件的绝对路径获取出来 3. 当选中文件时,判断是否...下面我面先看一下一般目录选择文件选择怎么实现的吧: #include
  • Android文件选择

    千次阅读 2017-09-15 18:10:50
    项目中用到文件选择器,功能是可以筛选出常用的文件也可以在所有文件选择。 先看一下效果图: 图中,左面是可以选择常用的文件,右边就是从手机跟目录开始一层一层的选择。 UI 方面就不多说啦,使用两个...
  • https://segmentfault.com/q/1010000003946095 工程目录下有很多图片路径要修改,很多散落在各个文件夹。 2015年11月03日提问 评论 邀请回答 编辑 ...按shift+cmd+f, 在where里选择要搜索...
  • 如何清理电脑C盘,c盘东西太多双击打开“计算机”,然后选择“工具”,再点“文件夹选项”,选择查看,选中显示隐藏的文件、文件夹和驱动器。电脑c盘满了怎么清理——进行碎片整理。开始-程序-附件-系统工具-碎片...
  • Winscp使用的是putty作为SSH...如果是pub类型的需要转换为putty类型的,文件类型里选择所有文件,选择密钥文件会提示你是否转换,按提示操作转换保存后就会自动选择转换后的.ppk密钥文件了。   WinSCP :: ...
  • 工程下个AndroidManifest.xml,所有的Activity都要在里面注册,其中那个Activity中含有 <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android....
  • 怎么选择SSL证书

    2019-04-26 15:25:44
    SSL证书是在通过CA机构验证服务器身份后颁发的,具有服务器身份验证和数据传输加密功能的文件,百度,搜狐等一些主流搜索引擎,鼓励HTTP到HTTPS的升级,SSL证书在国内越来越受欢迎,怎么选择SSL证书,我们来从下面几...
  • 疑难:java语言写代码实现“读取sqlserver备份文件bak中的多备份集列表并可选择性还原”怎么做,可有什么好方案或实例。 需求描述: 一个bak文件中,在备份时选择了追加,最后bak文件中有多个备份集,想通过程序...
  • Qt中怎么用Ui文件

    2012-08-10 13:37:34
    Qt中怎么用Ui文件 第一步, 制作ui文件。 首先应该用Qt Designer绘制一个自己的界面,并存为myform.ui(这里的myform可以用自己喜欢的名字代替)。 在制作自己的界面文件时要注意以下几个要点: 1、要记住ui文件的...
  • 我页面中只写了: ``` 一键导出 ``` js代码部分要怎么实现点击网页上的这个按钮,弹出路径选择框,然后导出所有多媒体文件(图片,音视频)到选择的目录下
  • 电脑中毒后很多隐藏文件不能看到,影响杀毒,通过文件夹选项处理后总是被恶意修改回来,很让人恼火。...打开任意文件夹》》工具》》文件夹选项》》查看选项卡》》显示所有文件和文件夹 确定后即可解决问题。
  • 永久删除文件是很常见的数据恢复故障。被误删的文件怎么寻回接下来我们还需要了解...步骤4:打钩所有需要恢复的文件,右击选择《复制选中的文件》,程序会将打钩的文件COPY出来。 步骤5:最后一步只需要坐等软件将文件
  • Ctrl+ H 以后进入search界面,如果你有很多项目,则进入File Search选项卡,在containing text里输入你要搜索的字符串,比如我要找five,右边可以选择是否强制大小写,或者又regularexpression,如果你有这个需要的...
  • 很多要求大一点的库会依赖很多相关的依赖库,这样一来,就算安装好了所有的依赖库,运行时还是会显示ImportError,找不到指定模块。 例如很多高级一点的库:tensorflow、skimage、scrapy等。 所以选对版本至关重要:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,309
精华内容 523
关键字:

怎么选择所有文件