2 Star 12 Fork 7

molihuan / mlhfileselectorlib

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

Banner

mlhfileselector

Maven CentraljitpackAPI: 19-33 (shields.io)license: Apache-2.0 (shields.io)Starbilibili: 玲莫利 (shields.io)CSDN: molihuan (shields.io)

Andriod上提供文件或路径选择的第三方库

自动申请存储权限,支持安卓4.4 ~ 13,支持Android/data和Android/obb目录访问,

支持自定义UI,支持SD卡。

(Library that provides file or path selection on Android, automatically apply for storage permission, support Android 4.4 to 13, support Android/data and Android/obb directory access, support custom UI,support SD card.The Keyword:file selector operator android/data android 11 android 13)

语言(Language)

中文 | English

为什么选择我

自动申请存储权限,支持 Android4.4 ~ 13,再也不用为了适配各种版本而苦恼了,快速集成,一句代码搞定,完善的文档,支持无root权限访问和操作Android/data和Android/obb目录(适配Android 13),支持SD卡,高度自定义UI满足你的所有需求,使用非常灵活,支持国际化,对于Android文件选择你只需要关注你的业务代码即可其他的都交给它。

特性

  • 自动申请存储权限(可以控制)
  • 安卓 4.4 ~ 13
  • Android/data和Android/obb目录访问和操作
  • SD卡
  • 高度自定义UI
  • 国际化
  • 搜索功能
  • 自定义图标
  • 显示隐藏文件

前言

在开始之前可以给项目一个Star吗?非常感谢,你的支持是我唯一的动力。欢迎Star和Issues!

我们需要你的Pr,注意(请提交到dev分支)

项目地址:

Github地址
Gitee地址

demo演示:

系统版本:Android 13

下载链接:体验APP

pathSelectorDemo.gif

一、快速开始

第1步:添加仓库:

  • 如果你的项目 Gradle 配置是在 7.0 以下,需要在 build.gradle 文件中加入
allprojects {
    repositories {
        ...
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}
  • 如果你的 Gradle 配置是 7.0 及以上,则需要在 settings.gradle 文件中加入
dependencyResolutionManagement {
    repositories {
    	...
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}

第2步:添加远程依赖:

  • 配置完远程仓库后,在项目 app 模块下的 build.gradle 文件中加入远程依赖
  • 最新发布版:Maven Central
dependencies {
    ...
    // 建议使用最新发布版,最新发布版请看上面
    // 请将"版本"替换成具体的版本号,如 1.1.16
    implementation 'io.github.molihuan:pathselector:版本'
}

第3步:基本用法示范:

//如果没有权限会自动申请权限
PathSelector.build(this, MConstants.BUILD_DIALOG)//Dialog构建方式
        .setMorePopupItemListeners(
                new CommonItemListener("OK") {
                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {
                        
                        /**取消dialog弹窗
 * pathSelectFragment.close();
 */

                        StringBuilder builder = new StringBuilder();
                        builder.append("you selected:\n");
                        for (FileBean fileBean : selectedFiles) {
                            builder.append(fileBean.getPath() + "\n");
                        }
                        Mtools.toast(builder.toString());

                        return false;
                    }
                }
        )
        .show();//开始构建

二、基本设置

打开调试模式

//开启调试模式,生产环境请关闭
PathSelectorConfig.setDebug(true);
//或者PathSelector.setDebug(true);

1、Activity构建模式:

//Activity构建方式
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_ACTIVITY)
        .setRequestCode(635)
        .setMorePopupItemListeners(
                new CommonItemListener("OK") {
                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {

                        StringBuilder builder = new StringBuilder();
                        builder.append("you selected:\n");
                        for (FileBean fileBean : selectedFiles) {
                            builder.append(fileBean.getPath() + "\n");
                        }
                        Mtools.toast(builder.toString());

                        return false;
                    }
                }
        )
        .show();

2、Fragment构建模式:

第1步:在你需要显示的布局文件xml中使用FrameLayout占位
<FrameLayout
    android:id="@+id/fragment_select_show_area"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
第2步:编写代码
//获取PathSelectFragment实例然后在onBackPressed中处理返回按钮点击事件
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_FRAGMENT)
        .setFrameLayoutId(R.id.fragment_select_show_area)//加载位置,FrameLayout的ID
        .setMorePopupItemListeners(
                new CommonItemListener("OK") {
                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {

                        StringBuilder builder = new StringBuilder();
                        builder.append("you selected:\n");
                        for (FileBean fileBean : selectedFiles) {
                            builder.append(fileBean.getPath() + "\n");
                        }
                        
                        Mtools.toast(builder.toString());
                        return false;
                    }
                }
        )
        .show();//开始构建
第3步:重写onBackPressed()方法让路径选择器优先处理返回按钮点击事件
非常重要!!!
非常重要!!!
非常重要!!!
重要的事情说三遍
@Override
public void onBackPressed() {

    //让PathSelectFragment先处理返回按钮点击事件
    if (selector != null && selector.onBackPressed()) {
        return;
    }
    ......
    super.onBackPressed();
}

3、Dialog构建模式 & 常用设置:

//获取PathSelectFragment实例然后在onBackPressed中处理返回按钮点击事件
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
        //.setBuildType(MConstants.BUILD_DIALOG)//已经在build中已经设置了
        //.setContext(this)//已经在build中已经设置了
        .setRootPath("/storage/emulated/0/")//初始路径
        .setShowSelectStorageBtn(true)//是否显示内部存储选择按钮
        .setShowTitlebarFragment(true)//是否显示标题栏
        .setShowTabbarFragment(true)//是否显示面包屑
        .setAlwaysShowHandleFragment(true)//是否总是显示长按弹出选项
        .setShowFileTypes("", "mp3", "mp4")//只显示(没有后缀)或(后缀为mp3)或(后缀为mp4)的文件
        .setSelectFileTypes("", "mp3")//只能选择(没有后缀)或(后缀为mp3)的文件
        .setMaxCount(3)//最多可以选择3个文件,默认是-1不限制
        .setRadio()//单选(如果需要单选文件夹请使用setMaxCount(0)来替换)
        .setSortType(MConstants.SORT_NAME_ASC)//按名称排序
        .setTitlebarMainTitle(new FontBean("My Selector"))//设置标题栏主标题,还可以设置字体大小,颜色等
        .setTitlebarBG(Color.GREEN)//设置标题栏颜色
        .setFileItemListener(//设置文件item点击回调(点击是文件才会回调,如果点击是文件夹则不会)
                new FileItemListener() {
                    @Override
                    public boolean onClick(View v, FileBean file, String currentPath, BasePathSelectFragment pathSelectFragment) {
                        Mtools.toast("you clicked path:\n" + file.getPath());
                        return false;
                    }
                }
        )
        .setMorePopupItemListeners(//设置右上角选项回调
                new CommonItemListener("SelectAll") {
                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {
                        pathSelectFragment.selectAllFile(true);
                        return false;
                    }
                },
                new CommonItemListener("DeselectAll") {
                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {
                        pathSelectFragment.selectAllFile(false);
                        return false;
                    }
                }
        )
        .setHandleItemListeners(//设置长按弹出选项回调
                new CommonItemListener("OK") {
                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {
                        StringBuilder builder = new StringBuilder();
                        builder.append("you selected:\n");
                        for (FileBean fileBean : selectedFiles) {
                            builder.append(fileBean.getPath() + "\n");
                        }
                        Mtools.toast(builder.toString());
                        return false;
                    }
                },
                new CommonItemListener("cancel") {
                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {
                        pathSelectFragment.openCloseMultipleMode(false);
                        return false;
                    }
                }
        )
        .show();

三、高级设置(自定义UI)

UI布局:

UiLayout.png

1、自定义选项样式(以HandleItem为例子)

方式1:通过FontBean来设置样式
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
        .setHandleItemListeners(//设置长按弹出选项回调
                //FontBean可以设置文本、字的大小、字的颜色、字左边的图标
    			//R.drawable.ic_test_mlh是你自己的图片资源id
                new CommonItemListener(new FontBean("OK", 18, Color.RED, R.drawable.ic_test_mlh)) {
                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {
                        Mtools.toast("You Click");
                        return false;
                    }
                }
        )
        .show();
什么?这种方式还不能满足你,那么试试方式2
方式2:重写CommonItemListener的setViewStyle方法来自定义样式
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
        .setHandleItemListeners(
                //重写CommonItemListener的setViewStyle方法来自定义样式
                new CommonItemListener("OK") {
                    @Override
                    public boolean setViewStyle(RelativeLayout container, ImageView leftImg, TextView textView) {
                        textView.setTextSize(18);
                        textView.setTextColor(Color.RED);
                        //默认是不显示图标的
                        leftImg.setVisibility(View.VISIBLE);
                        leftImg.setImageResource(R.drawable.ic_test_mlh);
                        leftImg.getLayoutParams().width = 90;
                        leftImg.getLayoutParams().height = 90;
                        return true;
                    }

                    @Override
                    public boolean onClick(View v, TextView tv, List<FileBean> selectedFiles, String currentPath, BasePathSelectFragment pathSelectFragment) {
                        Mtools.toast("You Click");
                        return false;
                    }
                }
        )
        .show();

什么?什么?这种方式还不能满足你,那么你来写UI它来帮你添加,试试高度自定义UI

2、高度自定义UI(以Titlebar为例子):

第1步:新建一个布局文件,如:fragment_custom_titlebar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <Button
        android:id="@+id/my_btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="btn1" />

    <Button
        android:id="@+id/my_btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="selectAll" />
    
</LinearLayout>
第2步:新建一个类,如:CustomTitlebarFragment.class使其继承AbstractTitlebarFragment并关联第1步中的布局文件
public class CustomTitlebarFragment extends AbstractTitlebarFragment {
    private Button btn1;
    private Button btn2;
    
    @Override
    public int setFragmentViewId() {
        return R.layout.fragment_custom_titlebar;
    }

    @Override
    public void getComponents(View view) {
        btn1 = view.findViewById(R.id.my_btn1);
        btn2 = view.findViewById(R.id.my_btn2);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Mtools.toast("The current path is:\n" + psf.getCurrentPath());
            }
        });
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                psf.selectAllFile(true);
            }
        });
    }
}
第3步:编写代码
//获取PathSelectFragment实例然后在onBackPressed中处理返回按钮点击事件
PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
        .setTitlebarFragment(new CustomTitlebarFragment())
        .show();

3、自定义列表item图标

PathSelectFragment selector = PathSelector.build(this, MConstants.BUILD_DIALOG)
        .setFileBeanController(new AbstractFileBeanController() {
            @Override
            public int getFileBeanImageResource(boolean isDir, String extension, FileBean fileBean) {
                int resourceId;
                switch (extension) {
                    case "jpg":
                    case "jpeg":
                    case "png":
                        //开发者自己的图片资源id
                        resourceId = R.drawable.ic_launcher_foreground;
                        break;
                    case "mp3":
                        resourceId = R.drawable.ic_launcher_foreground;
                        break;
                    case "mp4":
                        //也可以使用默认的图片资源id
                        resourceId = com.molihuan.pathselector.R.mipmap.movie;
                        break;
                    default:
                        if (isDir) {
                            //开发者自己的图片资源id
                            resourceId = R.drawable.ml192;
                        } else {
                            resourceId = R.drawable.ic_launcher_background;
                        }
                        break;
                }
                return resourceId;
            }
        })
        .show();

四、接口与方法(尽量看源码,都写了注释,懒得写文档)

IConfigDataBuilder
方法 作用 备注
setFrameLayoutId(int id) 设置加载位置FrameLayoutID 当构建模式为MConstants.BUILD_FRAGMENT时必须设置
setRequestCode(int code) 设置请求码 当构建模式为MConstants.BUILD_ACTIVITY时必须设置
setRootPath(String path) 设置开始默认路径 默认为内部存储根路径
setMaxCount(int maxCount) 设置最大选择数量 不设置默认为-1 即无限
setShowFileTypes(String... fileTypes) 设置显示文件类型 没有后缀请用""
setSelectFileTypes(String... fileTypes) 设置选择文件类型 没有后缀请用""
setSortType(int sortType) 设置排序规则 类型请看MConstants
setRadio() 设置单选(如果需要单选文件夹请使用setMaxCount(0)来替换) 默认多选
setShowSelectStorageBtn(boolean var) 设置是否显示内部存储选择按钮 默认true
setShowTitlebarFragment(boolean var) 是否显示标题栏 默认true
setShowTabbarFragment(boolean var) 是否显示面包屑 默认true
setAlwaysShowHandleFragment(boolean var) 是否总是显示长按弹出选项 默认false
setTitlebarMainTitle(FontBean titlebarMainTitle) 设置标题栏主标题 还可以设置字体大小,颜色等
setTitlebarBG(Integer titlebarBG) 设置标题栏背景颜色
setFileItemListener(FileItemListener fileItemListener) 设置文件item点击回调 点击是文件才会回调,如果点击是文件夹则不会
setMorePopupItemListeners(CommonItemListener... morePopupItemListener) 设置右上角选项回调
setHandleItemListeners(CommonItemListener... handleItemListener) 设置长按弹出选项回调
setTitlebarFragment(AbstractTitlebarFragment titlebarFragment) 设置自定义标题栏UI 自己的Fragment必须继承AbstractTitlebarFragment
setHandleFragment(AbstractHandleFragment handleFragment) 设置长按弹出自定义UI 自己的Fragment必须继承AbstractHandleFragment
setLifeCycle(AbstractLifeCycle lifeCycle) 设置一些生命周期钩子 重写对应的方法即可
start() 开始构建 必须调用
...... ......

五、!!!特别注意 !!!

分区存储

该库以及适配了分区存储,不需要额外适配,你只需要写你的业务代码即可,其他的交给它。
  • 注意该库已经在库的AndroidManifest.xml中添加了:

    <!-- 外部存储的写权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- 安卓11额外权限 -->
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        tools:ignore="ScopedStorage" />
    <!-- 已经适配了分区存储特性 -->
    <application
            android:preserveLegacyExternalStorage="true"
            android:requestLegacyExternalStorage="true"
            >
  • 可能会报错:

    Execution failed for task ':app:processDebugMainManifest'.
    > Manifest merger failed with multiple errors, see logs

    请在你的项目中的AndroidManifest.xml设置一致

包含Android Support库

  • 如果你的项目使用Androidx库,因为此库引用了getActivity/XXPermissions库,其包含旧版Support库,会导致冲突而报错。解决办法为在project主目录下的gradle.properties中添加

    android.enableJetifier=true

版本升级

  • 新版本往往解决了旧版本的一些问题、增加了性能、可扩展性......建议升级新版本
  • 请注意因为重构了项目导致了旧版本与新版本不兼容。1.0.x升级1.1.x为非兼容升级,请注意学习新的API

体积过大

  • 已经集成了Blankj/AndroidUtilCode

    如果项目对大小有严格要求请自行下载源码并精简AndroidUtilCode模块

代码混淆

  • 一般来说无需配置,会自动导入混淆规则

特别鸣谢

开源项目以及其依赖项目。

LICENSE

Copyright [2020] molihuan

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [2020] molihuan Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

🔥🔥🔥文件或路径选择,自动申请存储权限,支持安卓4.4 ~ 12,支持Android/data目录访问,支持自定义UI,支持SD卡。(Provide file or path selection, automatically apply for storage permission, support Android 4.4 to 12, support Android/data directory access, support custom UI,Support SD card.The Keyword:file selector operator android/data android 11) 展开 收起
Java
Apache-2.0
取消

发行版 (6)

全部

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/molihuan/mlhfileselectorlib.git
git@gitee.com:molihuan/mlhfileselectorlib.git
molihuan
mlhfileselectorlib
mlhfileselectorlib
master

搜索帮助