[
  {
    "path": ".gitignore",
    "content": ".gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.externalNativeBuild\nbintrayKey\ngradle.properties\n*.iml"
  },
  {
    "path": ".idea/codeStyles/Project.xml",
    "content": "<component name=\"ProjectCodeStyleConfiguration\">\n  <code_scheme name=\"Project\" version=\"173\">\n    <Objective-C-extensions>\n      <file>\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Import\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Macro\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Typedef\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Enum\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Constant\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Global\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Struct\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"FunctionPredecl\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Function\" />\n      </file>\n      <class>\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Property\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"Synthesize\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"InitMethod\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"StaticMethod\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"InstanceMethod\" />\n        <option name=\"com.jetbrains.cidr.lang.util.OCDeclarationKind\" value=\"DeallocMethod\" />\n      </class>\n      <extensions>\n        <pair source=\"cpp\" header=\"h\" fileNamingConvention=\"NONE\" />\n        <pair source=\"c\" header=\"h\" fileNamingConvention=\"NONE\" />\n      </extensions>\n    </Objective-C-extensions>\n  </code_scheme>\n</component>"
  },
  {
    "path": ".idea/copyright/Ess.xml",
    "content": "<component name=\"CopyrightManager\">\n  <copyright>\n    <option name=\"myName\" value=\"Ess\" />\n  </copyright>\n</component>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/app\" />\n            <option value=\"$PROJECT_DIR$/filepicker\" />\n          </set>\n        </option>\n        <option name=\"resolveModulePerSourceSet\" value=\"false\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"NullableNotNullManager\">\n    <option name=\"myDefaultNullable\" value=\"android.support.annotation.Nullable\" />\n    <option name=\"myDefaultNotNull\" value=\"android.support.annotation.NonNull\" />\n    <option name=\"myNullables\">\n      <value>\n        <list size=\"4\">\n          <item index=\"0\" class=\"java.lang.String\" itemvalue=\"org.jetbrains.annotations.Nullable\" />\n          <item index=\"1\" class=\"java.lang.String\" itemvalue=\"javax.annotation.Nullable\" />\n          <item index=\"2\" class=\"java.lang.String\" itemvalue=\"edu.umd.cs.findbugs.annotations.Nullable\" />\n          <item index=\"3\" class=\"java.lang.String\" itemvalue=\"android.support.annotation.Nullable\" />\n        </list>\n      </value>\n    </option>\n    <option name=\"myNotNulls\">\n      <value>\n        <list size=\"4\">\n          <item index=\"0\" class=\"java.lang.String\" itemvalue=\"org.jetbrains.annotations.NotNull\" />\n          <item index=\"1\" class=\"java.lang.String\" itemvalue=\"javax.annotation.Nonnull\" />\n          <item index=\"2\" class=\"java.lang.String\" itemvalue=\"edu.umd.cs.findbugs.annotations.NonNull\" />\n          <item index=\"3\" class=\"java.lang.String\" itemvalue=\"android.support.annotation.NonNull\" />\n        </list>\n      </value>\n    </option>\n  </component>\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_8\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/modules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n      <module fileurl=\"file://$PROJECT_DIR$/FilePicker.iml\" filepath=\"$PROJECT_DIR$/FilePicker.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/app/app.iml\" filepath=\"$PROJECT_DIR$/app/app.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/filepicker/filepicker.iml\" filepath=\"$PROJECT_DIR$/filepicker/filepicker.iml\" />\n    </modules>\n  </component>\n</project>"
  },
  {
    "path": ".idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 aj\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "### 介绍\n\n# 由于暂时没有更多的精力在此项目上，现将此项目转让给其他人，谁来认领一下，一起把这个库搞下去，加我微信bo_744172447，谢谢！\n\n---\n\n1. 可在文件浏览器中选择指定后缀名文件\n2. 可通过扫描全盘的方式，选择指定后缀名的文件\n3. 类似微信图片选择器选择图片或视频\n4. 图片选择页面可以自定义主题\n5. 支持Activity、Fragment\n\n### Example\n\n---\n![FilePicker](https://github.com/imLibo/FilePicker/blob/master/screenshot/Screenshot_20180307-124655.png)  ![FilePicker](https://github.com/imLibo/FilePicker/blob/master/screenshot/Screenshot_2018-03-07-13-51.png)  ![FilePicker](https://github.com/imLibo/FilePicker/blob/master/screenshot/Screenshot_20180307-124316.png)  \n![FilePicker](https://github.com/imLibo/FilePicker/blob/master/screenshot/Screenshot_20180307-124556.png)  ![FilePicker](https://github.com/imLibo/FilePicker/blob/master/screenshot/Screenshot_20180307-124202.png)  ![FilePicker](https://github.com/imLibo/FilePicker/blob/master/screenshot/Screenshot_20180307-124213.png)\n\n---\n\n### 可下载APK直接体验\n[Demo.apk](https://fir.im/filepicker)\n\n\n---\n\n### 用法\n\n\n```\nimplementation 'cn.imlibo:FilePicker:v0.0.5_alpha'\n```\n\n\n\n##### 一、 在文件浏览器中选择指定文件\n```\nFilePicker.from(this)\n                .chooseForBrowser()\n                .setMaxCount(2)\n                .setFileTypes(\"png\", \"doc\",\"apk\", \"mp3\", \"gif\", \"txt\", \"mp4\", \"zip\")\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n```\n\n##### 二、 分类查找指定后缀名文件\n\n```\nFilePicker\n                .from(this)\n                .chooseForMimeType()\n                .setMaxCount(10)\n                .setFileTypes(\"png\", \"doc\",\"apk\", \"mp3\", \"gif\", \"txt\", \"mp4\", \"zip\")\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n```\n##### 三、 在图片选择器中选择图片或视频\n\n```\nFilePicker\n                .from(this)\n                .chooseMedia()\n                .enabledCapture(true)\n                .setTheme(R.style.FilePicker_Dracula)\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n```\n\n##### 四、 接收返回的文件数据，在 ++onActivityResult++ 方法中获取。选中文件以链表方式返回， ++EssFile++ 类为载体\n\n\n```\n@Override\n    protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n        super.onActivityResult(requestCode, resultCode, data);\n        if (resultCode != RESULT_OK) {\n            return;\n        }\n        if (requestCode == REQUEST_CODE_CHOOSE) {\n            ArrayList<EssFile> essFileList = data.getParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION);\n            StringBuilder builder = new StringBuilder();\n            for (EssFile file :\n                    essFileList) {\n                builder.append(file.getMimeType()).append(\" | \").append(file.getName()).append(\"\\n\\n\");\n            }\n            textView.setText(builder.toString());\n        }\n    }\n```\n\n\n\n### 属性列表\n\n---\n\n名称 | 描述 |  默认值\n---|---|---\nFileTypes | 需要显示的文件类型 | 无\nSortType | 排序类型 | 按名字排序 BY_NAME_ASC\nisSingle | 是否单选 |false\nmaxCount | 最大可选中数量 | 10\nrequest_code | 请求码 | 无\nonlyShowImages | 是否仅显示图片（仅当其实chooseMedia时有效） | false\nonlyShowVideos | 是否仅显示视频（仅当其实chooseMedia时有效） | false\nenabledCapture | chooseMedia时是否显示照相机 | false\nplaceHolder | 图片的PlaceHolder | png_holder\nthemeId | 主题ID | R.Style.FilePicker_Elec\n\n### 自定义主题\n\n---\n\n\n```\n<style name=\"FilePicker.Elec\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n\t\t<item name=\"colorPrimary\">@color/elec_primary</item>\n\t\t<item name=\"colorPrimaryDark\">@color/elec_primary_dark</item>\n\t\t<item name=\"toolbar\">@style/Toolbar.elec</item>\n\t\t<item name=\"album.dropdown.title.color\">@color/elec_album_dropdown_title_text</item>\n\t\t<item name=\"album.dropdown.count.color\">@color/elec_album_dropdown_count_text</item>\n\t\t<item name=\"album.element.color\">@android:color/white</item>\n\t\t<item name=\"album.thumbnail.placeholder\">@color/elec_album_dropdown_thumbnail_placeholder</item>\n\t\t<item name=\"album.emptyView\">@drawable/ic_empty_elec</item>\n\t\t<item name=\"album.emptyView.textColor\">@color/elec_album_empty_view</item>\n\t\t<item name=\"item.placeholder\">@color/elec_item_placeholder</item>\n\t\t<item name=\"item.checkCircle.backgroundColor\">@color/elec_item_checkCircle_backgroundColor</item>\n\t\t<item name=\"item.checkCircle.borderColor\">@color/elec_item_checkCircle_borderColor</item>\n\t\t<item name=\"page.bg\">@color/elec_page_bg</item>\n\t\t<item name=\"bottomToolbar.bg\">@color/elec_bottom_toolbar_bg</item>\n\t\t<item name=\"bottomToolbar.preview.textColor\">@color/elec_bottom_toolbar_preview</item>\n\t\t<item name=\"bottomToolbar.apply.textColor\">@color/elec_bottom_toolbar_apply</item>\n\t\t<item name=\"preview.bottomToolbar.back.textColor\">@color/elec_preview_bottom_toolbar_back_text</item>\n\t\t<item name=\"preview.bottomToolbar.apply.textColor\">@color/elec_preview_bottom_toolbar_apply</item>\n\t\t<item name=\"listPopupWindowStyle\">@style/Popup.elec</item>\n\t\t<item name=\"capture.textColor\">@color/elec_capture</item>\n\t</style>\n```\n\n\n### Feature TODO\n\n---\n\n- [ ] 根据文件类型打开/预览文件\n- [ ] 预览图片界面\n- [ ] 压缩图片\n- [ ] 裁剪图片\n- [ ] 自定义相机拍照\n- [ ] 去掉AndPermission依赖，用原生代码申请权限\n- [ ] 增加多种图片加载框架支持\n- [ ] 文件浏览器支持自定义主题\n- [ ] 分类选择文件界面支持自定义主题\n\n\n### THANKS\n\n---\n\n[陈宇明大师兄 BaseRecyclerViewAdapterHelper](https://github.com/CymChad/BaseRecyclerViewAdapterHelper)\n\n[Android-FilePicker](https://github.com/DroidNinja/Android-FilePicker)\n\n[Matisse](https://github.com/zhihu/Matisse)\n\n[AndroidPicker](https://github.com/gzu-liyujiang/AndroidPicker)\n\n\n## LICENSE\n\nMIT License\n\nCopyright (c) 2018\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 27\n    defaultConfig {\n        applicationId \"com.imlibo.essfilepicker\"\n        minSdkVersion 17\n        targetSdkVersion 26\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n    }\n    signingConfigs {\n        release {\n            storeFile file(\"../filepicker.jks\")\n            storePassword \"filepicker\"\n            keyAlias \"filepicker\"\n            keyPassword \"filepicker\"\n        }\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            signingConfig signingConfigs.release\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n\n}\n\ndependencies {\n    implementation fileTree(include: ['*.jar'], dir: 'libs')\n    implementation 'com.android.support:appcompat-v7:27.1.0'\n    implementation 'com.android.support.constraint:constraint-layout:1.0.2'\n    implementation 'com.android.support:support-v4:27.1.0'\n    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'\n    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'\n    implementation 'com.jakewharton:butterknife:8.8.1'\n    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'\n    implementation 'com.yanzhenjie:permission:2.0.0-rc2'\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'com.android.support.test:runner:1.0.1'\n    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'\n//    implementation 'cn.imlibo:FilePicker:v0.0.1_alpha'\n    implementation project(':filepicker')\n}\n\n\ntask copyApk(type: Copy) {\n    include '**/*.apk'\n    from '/build/outputs/release/apk'\n    into '../APK/'\n    rename { String fileName -> //在复制时重命名文件\n        fileName = \"filepicker-demo.apk\" // 重命名\n    }\n}\n\n//在task被添加的时候定义依赖关系\ntasks.whenTaskAdded {\n    task ->\n        if (task.name.startsWith(\"assemble\")) {\n            task.finalizedBy copyApk\n        }\n}\n\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "app/src/androidTest/java/com/ess/essfilepicker/ExampleInstrumentedTest.java",
    "content": "package com.ess.essfilepicker;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() throws Exception {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"com.imlibo.essfilepicker\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.ess.essfilepicker\">\n\n    <application\n        android:name=\".LApplication\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity android:name=\".FragmentTestActivity\"></activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/ess/essfilepicker/FragmentTestActivity.java",
    "content": "package com.ess.essfilepicker;\n\nimport android.support.v4.app.FragmentTransaction;\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.widget.FrameLayout;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\n\npublic class FragmentTestActivity extends AppCompatActivity {\n\n    @BindView(R.id.container_fragment)\n    FrameLayout mFrameLayout;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_fragment_test);\n        ButterKnife.bind(this);\n\n        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();\n        fragmentTransaction.add(R.id.container_fragment,TestFragment.newInstance());\n        fragmentTransaction.commit();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/ess/essfilepicker/LApplication.java",
    "content": "/*\n * Copyright (c) 2018. Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.\n * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.\n * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.\n * Vestibulum commodo. Ut rhoncus gravida arcu.\n */\n\npackage com.ess.essfilepicker;\n\nimport android.app.Application;\n\nimport com.squareup.leakcanary.LeakCanary;\n\n/**\n * LApplication\n * Created by 李波 on 2018/2/22.\n */\n\npublic class LApplication extends Application{\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        LeakCanary.install(this);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/ess/essfilepicker/MainActivity.java",
    "content": "package com.ess.essfilepicker;\n\nimport android.content.Intent;\nimport android.support.v4.app.Fragment;\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.view.View;\nimport android.widget.TextView;\n\nimport com.ess.filepicker.FilePicker;\nimport com.ess.filepicker.SelectCreator;\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.activity.SelectFileByBrowserActivity;\nimport com.ess.filepicker.activity.SelectFileByScanActivity;\nimport com.ess.filepicker.activity.SelectPictureActivity;\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.util.Const;\nimport com.ess.filepicker.util.DialogUtil;\nimport com.yanzhenjie.permission.Action;\nimport com.yanzhenjie.permission.AndPermission;\nimport com.yanzhenjie.permission.Permission;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\nimport butterknife.OnClick;\n\npublic class MainActivity extends AppCompatActivity {\n\n    @BindView(R.id.textView_filename)\n    TextView textView;\n\n    private static final int REQUEST_CODE_CHOOSE = 23;\n\n    @OnClick(R.id.button_browse)\n    public void onBrowse(View view) {\n        FilePicker.from(this)\n                .chooseForBrowser()\n                .setMaxCount(2)\n                .setFileTypes(\"png\", \"doc\",\"apk\", \"mp3\", \"gif\", \"txt\", \"mp4\", \"zip\")\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n    }\n\n    @OnClick(R.id.button_scan)\n    public void onScan(View view) {\n        FilePicker\n                .from(this)\n                .chooseForMimeType()\n                .setMaxCount(10)\n                .setFileTypes(\"png\", \"doc\",\"apk\", \"mp3\", \"gif\", \"txt\", \"mp4\", \"zip\")\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n    }\n\n\n    @OnClick(R.id.button_single_pick)\n    public void onSinglePick(View view) {\n        FilePicker\n                .from(this)\n                .chooseForBrowser()\n                .isSingle()\n                .setFileTypes(\"pdf\")\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n    }\n\n    @OnClick(R.id.button_select_pictures)\n    public void onSelectPictures(View view){\n        FilePicker\n                .from(this)\n                .chooseMedia()\n                .enabledCapture(true)\n                .setTheme(R.style.FilePicker_Dracula)\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n    }\n\n    @OnClick(R.id.button_fragment)\n    public void onFragment(View view){\n        startActivity(new Intent(this,FragmentTestActivity.class));\n    }\n\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n        ButterKnife.bind(this);\n        AndPermission\n                .with(this)\n                .permission(Permission.READ_EXTERNAL_STORAGE,Permission.WRITE_EXTERNAL_STORAGE)\n                .onDenied(new Action() {\n                    @Override\n                    public void onAction(List<String> permissions) {\n                        //拒绝权限\n                        DialogUtil.showPermissionDialog(MainActivity.this,Permission.transformText(MainActivity.this, permissions).get(0));\n                    }\n                })\n                .start();\n\n    }\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n        super.onActivityResult(requestCode, resultCode, data);\n        if (resultCode != RESULT_OK) {\n            return;\n        }\n        if (requestCode == REQUEST_CODE_CHOOSE) {\n            ArrayList<EssFile> essFileList = data.getParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION);\n            StringBuilder builder = new StringBuilder();\n            for (EssFile file :\n                    essFileList) {\n                builder.append(file.getMimeType()).append(\" | \").append(file.getName()).append(\"\\n\\n\");\n            }\n            textView.setText(builder.toString());\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/ess/essfilepicker/TestFragment.java",
    "content": "package com.ess.essfilepicker;\n\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.TextView;\n\n\nimport com.ess.filepicker.FilePicker;\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.util.Const;\n\nimport java.util.ArrayList;\n\nimport butterknife.BindView;\nimport butterknife.ButterKnife;\nimport butterknife.OnClick;\n\nimport static android.app.Activity.RESULT_OK;\n\n/**\n * TestFragment\n */\npublic class TestFragment extends Fragment {\n\n    @BindView(R.id.textView_filename)\n    TextView textView;\n\n    private static final int REQUEST_CODE_CHOOSE = 23;\n\n    @OnClick(R.id.button_browse)\n    public void onBrowse(View view) {\n        FilePicker.from(this)\n                .chooseForBrowser()\n                .setMaxCount(2)\n                .setFileTypes(\"png\", \"doc\",\"apk\", \"mp3\", \"gif\", \"txt\", \"mp4\", \"zip\")\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n    }\n\n    @OnClick(R.id.button_scan)\n    public void onScan(View view) {\n        FilePicker\n                .from(this)\n                .chooseForMimeType()\n                .setMaxCount(10)\n                .setFileTypes(\"png\", \"doc\",\"apk\", \"mp3\", \"gif\", \"txt\", \"mp4\", \"zip\")\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n    }\n\n    @OnClick(R.id.button_select_pictures)\n    public void onSelectPictures(View view){\n        FilePicker\n                .from(this)\n                .chooseMedia()\n                .enabledCapture(true)\n                .setTheme(R.style.FilePicker_Dracula)\n                .requestCode(REQUEST_CODE_CHOOSE)\n                .start();\n    }\n\n    public TestFragment() {\n    }\n\n    public static TestFragment newInstance() {\n        return new TestFragment();\n    }\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container,\n                             Bundle savedInstanceState) {\n        // Inflate the layout for this fragment\n        return inflater.inflate(R.layout.fragment_test, container, false);\n    }\n\n    @Override\n    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {\n        ButterKnife.bind(this,view);\n        super.onViewCreated(view, savedInstanceState);\n    }\n\n\n    @Override\n    public void onActivityResult(int requestCode, int resultCode, Intent data) {\n        super.onActivityResult(requestCode, resultCode, data);\n        if (resultCode != RESULT_OK) {\n            return;\n        }\n        if (requestCode == REQUEST_CODE_CHOOSE) {\n            ArrayList<EssFile> essFileList = data.getParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION);\n            StringBuilder builder = new StringBuilder();\n            for (EssFile file :\n                    essFileList) {\n                builder.append(file.getMimeType()).append(\" | \").append(file.getName()).append(\"\\n\\n\");\n            }\n            textView.setText(builder.toString());\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/drawable/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportHeight=\"108\"\n    android:viewportWidth=\"108\">\n    <path\n        android:fillColor=\"#26A69A\"\n        android:pathData=\"M0,0h108v108h-108z\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M9,0L9,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,0L19,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,0L29,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,0L39,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,0L49,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,0L59,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,0L69,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,0L79,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M89,0L89,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M99,0L99,108\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,9L108,9\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,19L108,19\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,29L108,29\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,39L108,39\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,49L108,49\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,59L108,59\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,69L108,69\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,79L108,79\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,89L108,89\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M0,99L108,99\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,29L89,29\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,39L89,39\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,49L89,49\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,59L89,59\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,69L89,69\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M19,79L89,79\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M29,19L29,89\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M39,19L39,89\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M49,19L49,89\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M59,19L59,89\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M69,19L69,89\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n    <path\n        android:fillColor=\"#00000000\"\n        android:pathData=\"M79,19L79,89\"\n        android:strokeColor=\"#33FFFFFF\"\n        android:strokeWidth=\"0.8\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    android:width=\"108dp\"\n    android:height=\"108dp\"\n    android:viewportHeight=\"108\"\n    android:viewportWidth=\"108\">\n    <path\n        android:fillType=\"evenOdd\"\n        android:pathData=\"M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z\"\n        android:strokeColor=\"#00000000\"\n        android:strokeWidth=\"1\">\n        <aapt:attr name=\"android:fillColor\">\n            <gradient\n                android:endX=\"78.5885\"\n                android:endY=\"90.9159\"\n                android:startX=\"48.7653\"\n                android:startY=\"61.0927\"\n                android:type=\"linear\">\n                <item\n                    android:color=\"#44000000\"\n                    android:offset=\"0.0\" />\n                <item\n                    android:color=\"#00000000\"\n                    android:offset=\"1.0\" />\n            </gradient>\n        </aapt:attr>\n    </path>\n    <path\n        android:fillColor=\"#FFFFFF\"\n        android:fillType=\"nonZero\"\n        android:pathData=\"M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z\"\n        android:strokeColor=\"#00000000\"\n        android:strokeWidth=\"1\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_fragment_test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/container_fragment\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:orientation=\"vertical\"\n    android:padding=\"40dp\"\n    android:background=\"#aa000000\"\n    >\n\n\n\n</FrameLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:padding=\"40dp\"\n    android:orientation=\"vertical\"\n    >\n\n    <android.support.v7.widget.Toolbar\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"/>\n\n    <Button\n        android:id=\"@+id/button_browse\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"文件夹中选择文件\"\n        />\n\n    <Button\n        android:id=\"@+id/button_scan\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"按文件类型选择文件\"\n        />\n\n    <Button\n        android:id=\"@+id/button_single_pick\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"单选特定文件\"\n        />\n\n    <Button\n        android:id=\"@+id/button_select_pictures\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"选择照片\"\n        />\n    <Button\n        android:id=\"@+id/button_fragment\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/fragment\"\n        />\n\n    <TextView\n        android:id=\"@+id/textView_filename\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"TextView\"\n        />\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_test.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#fff\"\n    android:orientation=\"vertical\"\n    >\n\n    <android.support.v7.widget.Toolbar\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"/>\n\n    <Button\n        android:id=\"@+id/button_browse\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"文件夹中选择文件\"\n        />\n\n    <Button\n        android:id=\"@+id/button_scan\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"按文件类型选择文件\"\n        />\n\n    <Button\n        android:id=\"@+id/button_select_pictures\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"选择照片\"\n        />\n\n    <TextView\n        android:id=\"@+id/textView_filename\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"TextView\"\n        />\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@drawable/ic_launcher_background\" />\n    <foreground android:drawable=\"@drawable/ic_launcher_foreground\" />\n</adaptive-icon>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#1bbc9b</color>\n    <color name=\"colorPrimaryDark\">#1bbc9b</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">文件浏览</string>\n\n    <!-- TODO: Remove or change this placeholder text -->\n    <string name=\"hello_blank_fragment\">Hello blank fragment</string>\n    <string name=\"fragment\">Fragment</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n        <!--自定义右侧溢出图标-->\n        <!--<item name=\"android:actionOverflowButtonStyle\">@style/OverflowButtonStyle</item>-->\n    </style>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\"/>\n\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\"/>\n\n\n</resources>\n"
  },
  {
    "path": "app/src/test/java/com/ess/essfilepicker/ExampleUnitTest.java",
    "content": "package com.ess.essfilepicker;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    \n    repositories {\n        google()\n        jcenter()\n        mavenCentral()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.1.1'\n        classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1'\n        classpath 'com.novoda:bintray-release:0.8.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n        maven { url \"https://jitpack.io\" }\n    }\n    tasks.withType(Javadoc) {\n        options.addStringOption('Xdoclint:none', '-quiet')\n        options.addStringOption('encoding', 'UTF-8')\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n\next {\n    userOrg = 'libo'\n    groupId = 'cn.imlibo'\n    uploadName = 'FilePicker'\n    publishVersion = 'v0.0.5_alpha'\n    desc = 'Android文件选择器、图片选择器、MIMEType分类选择器'\n    website = 'https://github.com/imLibo/FilePicker'\n    licences = ['MIT']\n}"
  },
  {
    "path": "filepicker/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "filepicker/build.gradle",
    "content": "apply plugin: 'com.android.library'\napply plugin: 'com.novoda.bintray-release'\n\nandroid {\n    compileSdkVersion 27\n\n    defaultConfig {\n        minSdkVersion 14\n        targetSdkVersion 27\n        versionCode 1\n        versionName \"1.0\"\n\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n\n    lintOptions {\n        abortOnError false\n    }\n\n\n}\n\ndependencies {\n    implementation fileTree(include: ['*.jar'], dir: 'libs')\n    implementation 'com.android.support:recyclerview-v7:27.1.0'\n    implementation 'com.android.support:appcompat-v7:27.1.0'\n    implementation 'com.android.support:design:27.1.0'\n    implementation 'com.android.support:appcompat-v7:27.1.0'\n    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'\n    implementation 'com.android.support.constraint:constraint-layout:1.0.2'\n    implementation 'com.github.bumptech.glide:glide:4.6.1'\n    implementation 'com.android.support:support-v4:27.1.0'\n    implementation 'org.greenrobot:eventbus:3.1.1'\n    implementation 'top.zibin:Luban:1.1.3'\n}\n\npublish {\n    userOrg = rootProject.userOrg\n    groupId = rootProject.groupId\n    artifactId = rootProject.uploadName\n    publishVersion = rootProject.publishVersion\n    desc = rootProject.desc\n    website = rootProject.website\n}\n\n\n\n\n"
  },
  {
    "path": "filepicker/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguardFiles setting in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n\n# Uncomment this to preserve the line number information for\n# debugging stack traces.\n#-keepattributes SourceFile,LineNumberTable\n\n# If you keep the line number information, uncomment this to\n# hide the original source file name.\n#-renamesourcefileattribute SourceFile\n"
  },
  {
    "path": "filepicker/src/androidTest/java/com/ess/filepicker/ExampleInstrumentedTest.java",
    "content": "package com.ess.filepicker;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumented test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() throws Exception {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"com.imlibo.filepicker.test\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.ess.filepicker\">\n\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n\n    <application>\n        <activity android:name=\"com.ess.filepicker.activity.SelectFileByBrowserActivity\" />\n        <activity android:name=\"com.ess.filepicker.activity.SelectPictureActivity\" />\n        <activity android:name=\"com.ess.filepicker.activity.SelectFileByScanActivity\" />\n\n        <provider\n            android:name=\"com.ess.filepicker.model.EssFileProvider\"\n            android:authorities=\"${applicationId}.ess.file.provider\"\n            android:exported=\"false\"\n            android:grantUriPermissions=\"true\">\n            <meta-data\n                android:name=\"android.support.FILE_PROVIDER_PATHS\"\n                android:resource=\"@xml/provider_paths\" />\n        </provider>\n\n        <activity android:name=\"com.ess.filepicker.activity.PicturesViewActivity\"/>\n    </application>\n\n</manifest>"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/BaseFileFragment.java",
    "content": "package com.ess.filepicker;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.os.Message;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentManager;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport java.lang.reflect.Field;\n\n/**\n * BaseFileFragment\n * Created by 李波 on 2018/2/23.\n */\n\npublic abstract class BaseFileFragment extends Fragment{\n\n    protected Activity mActivity = null;\n    protected Bundle bundle = null;\n    protected Fragment mFragment = null;\n    /**\n     * fragment管理器\n     */\n    protected FragmentManager mFManager = null;\n\n    protected boolean isVisible; //是否可见的标志\n\n    protected boolean isFirstLoad = true; //是否是第一次加载\n\n    protected boolean isPrepared = false; //是否已经准备好\n\n    protected boolean isOnDetach = false;\n\n\n    @Override\n    public void onAttach(Context context) {\n        super.onAttach(context);\n        this.mActivity = getActivity();\n        this.mFragment = this;\n        isOnDetach = false;\n        bundle = getArguments();\n        mFManager = getChildFragmentManager();\n    }\n\n    @Override\n    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        super.onCreateView(inflater, container, savedInstanceState);\n        View view = inflater.inflate(getFragmentLayout(), container, false);\n        initUI(view);\n        onVisible();\n        return view;\n    }\n\n\n    /**\n     * fragment布局文件\n     *\n     * @return\n     */\n    public abstract int getFragmentLayout();\n\n\n    /**\n     * 设置是否是第一次加载 用于刷新数据\n     *\n     * @param isFirstLoad\n     */\n    public void setFirstLoad(boolean isFirstLoad) {\n        this.isFirstLoad = isFirstLoad;\n    }\n\n    /**\n     * 在这里实现Fragment数据的缓加载.\n     *\n     * @param isVisibleToUser\n     */\n    @Override\n    public void setUserVisibleHint(boolean isVisibleToUser) {\n        super.setUserVisibleHint(isVisibleToUser);\n        if (getUserVisibleHint()) {\n            isVisible = true;\n            onVisible();\n        } else {\n            isVisible = false;\n            onInvisible();\n        }\n    }\n\n    /**\n     * 可见的时候\n     */\n    private void onVisible() {\n        if (isFirstLoad && isVisible && isPrepared) {\n            lazyLoad();\n            isFirstLoad = false;\n        }\n    }\n\n    /**\n     * 不可见时\n     */\n    protected void onInvisible() {\n\n    }\n\n    /**\n     * 初始化控件\n     * @param view\n     */\n    protected void initUI(View view) {\n        isPrepared = true;\n    }\n\n    /**\n     * 延迟加载\n     * 需要在\n     */\n    protected abstract void lazyLoad();\n\n    /**\n     * 刷新数据\n     *\n     * @param msg\n     */\n    protected void onRefresh(Message msg) {\n        if (!isOnDetach) {\n        }\n    }\n\n    @Override\n    public void onDetach() {\n        super.onDetach();\n        isOnDetach = true;\n        try {\n            Field childFragmentManager = Fragment.class.getDeclaredField(\"mChildFragmentManager\");\n            childFragmentManager.setAccessible(true);\n            childFragmentManager.set(this, null);\n        } catch (NoSuchFieldException e) {\n            throw new RuntimeException(e);\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/FilePicker.java",
    "content": "package com.ess.filepicker;\n\nimport android.app.Activity;\nimport android.support.v4.app.Fragment;\n\nimport java.lang.ref.WeakReference;\n\n\n/**\n * FilePicker 构造器\n * Created by 李波 on 2018/2/8.\n *\n */\n\npublic final class FilePicker {\n\n    private final WeakReference<Activity> mContext;\n    private final WeakReference<Fragment> mFragment;\n\n    private FilePicker(Activity activity) {\n        this(activity,null);\n    }\n\n    private FilePicker(Fragment fragment){\n        this(fragment.getActivity(),fragment);\n    }\n\n    private FilePicker(Activity mContext, Fragment mFragment) {\n        this.mContext = new WeakReference<>(mContext);\n        this.mFragment = new WeakReference<>(mFragment);\n    }\n\n    public static FilePicker from(Activity activity){\n        return new FilePicker(activity);\n    }\n\n    public static FilePicker from(Fragment fragment){\n        return new FilePicker(fragment);\n    }\n\n    public SelectCreator chooseForBrowser(){\n        return new SelectCreator(this,SelectOptions.CHOOSE_TYPE_BROWSER);\n    }\n\n    public SelectCreator chooseForMimeType(){\n        return new SelectCreator(this,SelectOptions.CHOOSE_TYPE_SCAN);\n    }\n\n    public SelectCreator chooseMedia(){\n        return new SelectCreator(this,SelectOptions.CHOOSE_TYPE_MEDIA);\n    }\n\n\n    public Activity getActivity() {\n        return mContext.get();\n    }\n\n    public Fragment getFragment() {\n        return mFragment != null ? mFragment.get() : null;\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/SelectCreator.java",
    "content": "package com.ess.filepicker;\n\nimport android.app.Activity;\nimport android.content.Intent;\nimport android.graphics.drawable.Drawable;\nimport android.support.annotation.StyleRes;\nimport android.support.v4.app.Fragment;\n\nimport com.ess.filepicker.activity.SelectFileByBrowserActivity;\nimport com.ess.filepicker.activity.SelectFileByScanActivity;\nimport com.ess.filepicker.activity.SelectPictureActivity;\n\nimport java.io.File;\n\n/**\n * SelectCreator\n * Created by 李波 on 2018/3/7.\n */\n\npublic final class SelectCreator {\n\n    private final FilePicker filePicker;\n    private final SelectOptions selectOptions;\n    private String chooseType;\n\n    public SelectCreator(FilePicker filePicker, String chooseType) {\n        selectOptions = SelectOptions.getCleanInstance();\n        this.chooseType = chooseType;\n        this.filePicker = filePicker;\n    }\n\n    public SelectCreator setMaxCount(int maxCount) {\n        selectOptions.maxCount = maxCount;\n        if (maxCount <= 1) {\n            selectOptions.maxCount = 1;\n            selectOptions.isSingle = true;\n        } else {\n            selectOptions.isSingle = false;\n        }\n        return this;\n    }\n\n    public SelectCreator setCompressImage(boolean compressImage){\n        selectOptions.compressImage = compressImage;\n        return this;\n    }\n\n    public SelectCreator setTargetPath(String path){\n        selectOptions.targetPath = path;\n        return this;\n    }\n\n    public SelectCreator setTheme(@StyleRes int theme) {\n        selectOptions.themeId = theme;\n        return this;\n    }\n\n    public SelectCreator setFileTypes(String... fileTypes) {\n        selectOptions.mFileTypes = fileTypes;\n        return this;\n    }\n\n    public SelectCreator setSortType(String sortType) {\n        selectOptions.mSortType = sortType;\n        return this;\n    }\n\n    public SelectCreator isSingle() {\n        selectOptions.isSingle = true;\n        selectOptions.maxCount = 1;\n        return this;\n    }\n\n    public SelectCreator onlyShowImages() {\n        selectOptions.onlyShowImages = true;\n        return this;\n    }\n\n    public SelectCreator onlyShowVideos() {\n        selectOptions.onlyShowVideos = true;\n        return this;\n    }\n\n    public SelectCreator placeHolder(Drawable placeHolder) {\n        selectOptions.placeHolder = placeHolder;\n        return this;\n    }\n\n    public SelectCreator enabledCapture(boolean enabledCapture) {\n        selectOptions.enabledCapture = enabledCapture;\n        return this;\n    }\n\n    public SelectCreator requestCode(int requestCode) {\n        selectOptions.request_code = requestCode;\n        return this;\n    }\n\n    public void start() {\n        final Activity activity = filePicker.getActivity();\n        if (activity == null) {\n            return;\n        }\n        Intent intent = new Intent();\n        if (SelectCreator.this.chooseType.equals(SelectOptions.CHOOSE_TYPE_BROWSER)) {\n            intent.setClass(activity, SelectFileByBrowserActivity.class);\n        } else if (SelectCreator.this.chooseType.equals(SelectOptions.CHOOSE_TYPE_SCAN)) {\n            intent.setClass(activity, SelectFileByScanActivity.class);\n        } else if (SelectCreator.this.chooseType.equals(SelectOptions.CHOOSE_TYPE_MEDIA)) {\n            intent.setClass(activity, SelectPictureActivity.class);\n        } else {\n            return;\n        }\n        Fragment fragment = filePicker.getFragment();\n        if (fragment != null) {\n            fragment.startActivityForResult(intent, selectOptions.request_code);\n        } else {\n            activity.startActivityForResult(intent, selectOptions.request_code);\n        }\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/SelectOptions.java",
    "content": "package com.ess.filepicker;\n\nimport android.graphics.drawable.Drawable;\nimport android.os.Environment;\nimport android.text.TextUtils;\n\nimport com.ess.filepicker.util.FileUtils;\nimport com.ess.filepicker.util.MimeType;\n\nimport java.io.File;\nimport java.util.Set;\n\n/**\n * SelectOptions\n * Created by 李波 on 2018/3/7.\n */\n\npublic class SelectOptions {\n\n    public static final String CHOOSE_TYPE_BROWSER = \"choose_type_browser\";\n    public static final String CHOOSE_TYPE_SCAN = \"choose_type_scan\";\n    public static final String CHOOSE_TYPE_MEDIA = \"choose_type_media\";\n\n    public static final String defaultTargetPath = Environment.getExternalStorageDirectory() + \"/essPictures\";\n\n    public String[] mFileTypes;\n    public String mSortType;\n    public boolean isSingle = false;\n    public int maxCount = 10;\n    public int request_code;\n    public boolean onlyShowImages = false;\n    public boolean onlyShowVideos = false;\n    public boolean enabledCapture = false;\n    public Drawable placeHolder;\n    public boolean compressImage = true;\n    public String targetPath = defaultTargetPath;\n    public int themeId = R.style.FilePicker_Elec;\n\n    public String[] getFileTypes() {\n        if (mFileTypes == null || mFileTypes.length == 0) {\n            return new String[]{};\n        }\n        return mFileTypes;\n    }\n\n    public int getSortType() {\n        if (TextUtils.isEmpty(mSortType)) {\n            return FileUtils.BY_NAME_ASC;\n        }\n        return Integer.valueOf(mSortType);\n    }\n\n    public String getTargetPath() {\n        if (!new File(targetPath).exists()) {\n            File file = new File(defaultTargetPath);\n            if (!file.exists()) {\n                file.mkdirs();\n            }\n            return defaultTargetPath;\n        }\n        return targetPath;\n    }\n\n    public void setSortType(int sortType) {\n        mSortType = String.valueOf(sortType);\n    }\n\n    public static SelectOptions getInstance() {\n        return InstanceHolder.INSTANCE;\n    }\n\n    public static SelectOptions getCleanInstance() {\n        SelectOptions options = getInstance();\n        options.reset();\n        return options;\n    }\n\n    private void reset() {\n        mFileTypes = new String[]{};\n        mSortType = String.valueOf(FileUtils.BY_NAME_ASC);\n        isSingle = false;\n        maxCount = 10;\n        onlyShowImages = false;\n        onlyShowVideos = false;\n        enabledCapture = false;\n        compressImage = true;\n        themeId = R.style.FilePicker_Elec;\n    }\n\n    private static final class InstanceHolder {\n        private static final SelectOptions INSTANCE = new SelectOptions();\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/activity/FileTypeListFragment.java",
    "content": "package com.ess.filepicker.activity;\n\n\nimport android.os.Bundle;\nimport android.support.design.widget.Snackbar;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.util.Log;\nimport android.view.View;\n\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.ess.filepicker.BaseFileFragment;\nimport com.ess.filepicker.R;\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.adapter.FileListAdapter;\nimport com.ess.filepicker.loader.EssMimeTypeCollection;\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.model.FileScanActEvent;\nimport com.ess.filepicker.model.FileScanFragEvent;\nimport com.ess.filepicker.model.FileScanSortChangedEvent;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.Subscribe;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * FileTypeListFragment\n */\npublic class FileTypeListFragment extends BaseFileFragment implements BaseQuickAdapter.OnItemClickListener,\n        EssMimeTypeCollection.EssMimeTypeCallbacks {\n\n    private static final String ARG_FileType = \"ARG_FileType\";\n    private static final String ARG_IsSingle = \"mIsSingle\";\n    private static final String ARG_MaxCount = \"mMaxCount\";\n    private static final String ARG_SortType = \"mSortType\";\n    private static final String ARG_Loader_Id = \"ARG_Loader_Id\";\n\n    private String mFileType;\n    private boolean mIsSingle;\n    private int mMaxCount;\n    private int mSortType;\n    private int mLoaderId;\n\n    private boolean mSortTypeHasChanged = false;\n\n    private List<EssFile> mSelectedFileList = new ArrayList<>();\n\n    private RecyclerView mRecyclerView;\n    private FileListAdapter mAdapter;\n    private EssMimeTypeCollection mMimeTypeCollection = new EssMimeTypeCollection();\n\n    public FileTypeListFragment() {\n    }\n\n    public static FileTypeListFragment newInstance(String param1, boolean IsSingle, int mMaxCount, int mSortType, int loaderId) {\n        FileTypeListFragment fragment = new FileTypeListFragment();\n        Bundle args = new Bundle();\n        args.putString(ARG_FileType, param1);\n        args.putBoolean(ARG_IsSingle, IsSingle);\n        args.putInt(ARG_MaxCount, mMaxCount);\n        args.putInt(ARG_SortType, mSortType);\n        args.putInt(ARG_Loader_Id, loaderId);\n        fragment.setArguments(args);\n        return fragment;\n    }\n\n    @Override\n    public void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        if (getArguments() != null) {\n            mFileType = getArguments().getString(ARG_FileType);\n            mIsSingle = getArguments().getBoolean(ARG_IsSingle);\n            mMaxCount = getArguments().getInt(ARG_MaxCount);\n            mSortType = getArguments().getInt(ARG_SortType);\n            mLoaderId = getArguments().getInt(ARG_Loader_Id);\n        }\n    }\n\n    @Override\n    public int getFragmentLayout() {\n        return R.layout.fragment_file_type_list;\n    }\n\n    @Override\n    protected void lazyLoad() {\n        mMimeTypeCollection.load(mFileType, mSortType,mLoaderId);\n    }\n\n    @Override\n    protected void initUI(View view) {\n        mMimeTypeCollection.onCreate(getActivity(), this);\n        EventBus.getDefault().register(this);\n        mRecyclerView = view.findViewById(R.id.rcv_file_list_scan);\n        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));\n        mAdapter = new FileListAdapter(new ArrayList<EssFile>());\n        mRecyclerView.setAdapter(mAdapter);\n        mAdapter.bindToRecyclerView(mRecyclerView);\n        mAdapter.setEmptyView(R.layout.loading_layout);\n        mAdapter.setOnItemClickListener(this);\n        super.initUI(view);\n    }\n\n    /**\n     * 接收到Activity刷新最大数量后\n     *\n     * @param event event\n     */\n    @Subscribe\n    public void onFreshCount(FileScanActEvent event) {\n        mMaxCount = event.getCanSelectMaxCount();\n    }\n\n    /**\n     * 接收到Activity改变排序方式后\n     */\n    @Subscribe\n    public void onFreshSortType(FileScanSortChangedEvent event) {\n        mSortType = event.getSortType();\n        if(mLoaderId == event.getCurrentItem()+EssMimeTypeCollection.LOADER_ID){\n            mMimeTypeCollection.load(mFileType, mSortType,mLoaderId);\n        }else {\n            mSortTypeHasChanged = true;\n        }\n    }\n\n    @Override\n    public void setUserVisibleHint(boolean isVisibleToUser) {\n        super.setUserVisibleHint(isVisibleToUser);\n        if(getUserVisibleHint()){\n            if(!isFirstLoad && mSortTypeHasChanged){\n                mSortTypeHasChanged = false;\n                mAdapter.setNewData(new ArrayList<EssFile>());\n                mAdapter.setEmptyView(R.layout.loading_layout);\n                mMimeTypeCollection.load(mFileType, mSortType,mLoaderId);\n            }\n        }\n    }\n\n    @Override\n    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {\n        EssFile item = mAdapter.getData().get(position);\n        //选中某文件后，判断是否单选\n        if (mIsSingle) {\n            mSelectedFileList.add(item);\n            EventBus.getDefault().post(new FileScanFragEvent(item, true));\n            return;\n        }\n        if (mAdapter.getData().get(position).isChecked()) {\n            int index = findFileIndex(item);\n            if (index != -1) {\n                mSelectedFileList.remove(index);\n                EventBus.getDefault().post(new FileScanFragEvent(item, false));\n                mAdapter.getData().get(position).setChecked(!mAdapter.getData().get(position).isChecked());\n                mAdapter.notifyItemChanged(position, \"\");\n            }\n        } else {\n            if (mMaxCount <= 0) {\n                //超出最大可选择数量后\n                Snackbar.make(mRecyclerView, \"您最多只能选择\" + SelectOptions.getInstance().maxCount + \"个。\", Snackbar.LENGTH_SHORT).show();\n                return;\n            }\n            mSelectedFileList.add(item);\n            EventBus.getDefault().post(new FileScanFragEvent(item, true));\n            mAdapter.getData().get(position).setChecked(!mAdapter.getData().get(position).isChecked());\n            mAdapter.notifyItemChanged(position, \"\");\n        }\n\n    }\n\n    /**\n     * 查找文件位置\n     */\n    private int findFileIndex(EssFile item) {\n        for (int i = 0; i < mSelectedFileList.size(); i++) {\n            if (mSelectedFileList.get(i).getAbsolutePath().equals(item.getAbsolutePath())) {\n                return i;\n            }\n        }\n        return -1;\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        EventBus.getDefault().unregister(this);\n        mMimeTypeCollection.onDestroy();\n    }\n\n    @Override\n    public void onFileLoad(List<EssFile> essFileList) {\n        Log.i(\"TAG\",\"size --> \"+essFileList.size());\n        mAdapter.setNewData(essFileList);\n        mRecyclerView.scrollToPosition(0);\n        if (essFileList.isEmpty()) {\n            mAdapter.setEmptyView(R.layout.empty_file_list);\n        }\n    }\n\n    @Override\n    public void onFileReset() {\n\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/activity/PicturesViewActivity.java",
    "content": "package com.ess.filepicker.activity;\n\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\n\nimport com.ess.filepicker.R;\nimport com.ess.filepicker.model.EssFile;\n\nimport java.util.List;\n\n/**\n * 图片浏览界面\n */\npublic class PicturesViewActivity extends AppCompatActivity {\n\n    /*要浏览的图片列表*/\n    private List<EssFile> mViewPicturesList;\n    /*当前所处位置*/\n    private int mCurPosition;\n    /*是否是预览图片选择中的图片*/\n    private boolean mIsViewForSelect;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_pictures_detail);\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/activity/SelectFileByBrowserActivity.java",
    "content": "package com.ess.filepicker.activity;\n\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.os.Environment;\nimport android.support.design.widget.Snackbar;\nimport android.support.v7.app.AlertDialog;\nimport android.support.v7.app.AppCompatActivity;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.support.v7.widget.Toolbar;\nimport android.view.LayoutInflater;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.WindowManager;\nimport android.widget.ImageView;\nimport android.widget.PopupWindow;\n\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.ess.filepicker.R;\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.adapter.BreadAdapter;\nimport com.ess.filepicker.adapter.FileListAdapter;\nimport com.ess.filepicker.adapter.SelectSdcardAdapter;\nimport com.ess.filepicker.model.BreadModel;\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.model.EssFileCountCallBack;\nimport com.ess.filepicker.model.EssFileListCallBack;\nimport com.ess.filepicker.task.EssFileCountTask;\nimport com.ess.filepicker.task.EssFileListTask;\nimport com.ess.filepicker.util.Const;\nimport com.ess.filepicker.util.FileUtils;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 文件浏览界面\n */\npublic class SelectFileByBrowserActivity extends AppCompatActivity\n        implements BaseQuickAdapter.OnItemClickListener, BaseQuickAdapter.OnItemChildClickListener,\n        View.OnClickListener, EssFileListCallBack, EssFileCountCallBack, FileListAdapter.onLoadFileCountListener {\n\n    /*todo 是否可预览文件，默认可预览*/\n    private boolean mCanPreview = true;\n\n    /*当前目录，默认是SD卡根目录*/\n    private String mCurFolder = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;\n    /*所有可访问存储设备列表*/\n    private List<String> mSdCardList;\n\n    private FileListAdapter mAdapter;\n    private RecyclerView mRecyclerView;\n    private RecyclerView mBreadRecyclerView;\n    private ImageView mImbSelectSdCard;\n    private Toolbar mToolBar;\n    private BreadAdapter mBreadAdapter;\n    private PopupWindow mSelectSdCardWindow;\n\n    /*是否刚才切换了SD卡路径*/\n    private boolean mHasChangeSdCard = false;\n    /*已选中的文件列表*/\n    private ArrayList<EssFile> mSelectedFileList = new ArrayList<>();\n    /*当前选中排序方式的位置*/\n    private int mSelectSortTypeIndex = 0;\n    private MenuItem mCountMenuItem;\n\n    private EssFileListTask essFileListTask;\n    private EssFileCountTask essFileCountTask;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_select_file);\n        // TODO: 2019/3/12 暂时移除\n//        EventBus.getDefault().register(this);\n\n        mSdCardList = FileUtils.getAllSdPaths(this);\n        if (!mSdCardList.isEmpty()) {\n            mCurFolder = mSdCardList.get(0) + File.separator;\n        }\n        initUi();\n        initData();\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.browse_menu, menu);\n        mCountMenuItem = menu.findItem(R.id.browser_select_count);\n        mCountMenuItem.setTitle(String.format(getString(R.string.selected_file_count), String.valueOf(mSelectedFileList.size()), String.valueOf(SelectOptions.getInstance().maxCount)));\n        return true;\n    }\n\n    private void initUi() {\n        mToolBar = findViewById(R.id.toolbar);\n        setSupportActionBar(mToolBar);\n        getSupportActionBar().setTitle(\"文件选择\");\n        getSupportActionBar().setDisplayHomeAsUpEnabled(true);\n        getSupportActionBar().setHomeButtonEnabled(true);\n        mToolBar.setNavigationOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                onBackPressed();\n            }\n        });\n\n        mRecyclerView = findViewById(R.id.rcv_file_list);\n        mBreadRecyclerView = findViewById(R.id.breadcrumbs_view);\n        mImbSelectSdCard = findViewById(R.id.imb_select_sdcard);\n        mImbSelectSdCard.setOnClickListener(this);\n        if (!mSdCardList.isEmpty() && mSdCardList.size() > 1) {\n            mImbSelectSdCard.setVisibility(View.VISIBLE);\n        }\n\n        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));\n        mAdapter = new FileListAdapter(new ArrayList<EssFile>());\n        mAdapter.setLoadFileCountListener(this);\n        mRecyclerView.setAdapter(mAdapter);\n        mAdapter.bindToRecyclerView(mRecyclerView);\n        mAdapter.setOnItemClickListener(this);\n\n        mBreadRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));\n        mBreadAdapter = new BreadAdapter(new ArrayList<BreadModel>());\n        mBreadRecyclerView.setAdapter(mBreadAdapter);\n        mBreadAdapter.bindToRecyclerView(mBreadRecyclerView);\n        mBreadAdapter.setOnItemChildClickListener(this);\n    }\n\n    private void initData() {\n        executeListTask(mSelectedFileList, mCurFolder, SelectOptions.getInstance().getFileTypes(), SelectOptions.getInstance().getSortType());\n    }\n\n    private void executeListTask(List<EssFile> essFileList, String queryPath, String[] types, int sortType) {\n        essFileListTask = new EssFileListTask(essFileList, queryPath, types, sortType, this);\n        essFileListTask.execute();\n    }\n\n    /**\n     * 查找到文件列表后\n     *\n     * @param queryPath 查询路径\n     * @param fileList  文件列表\n     */\n    @Override\n    public void onFindFileList(String queryPath, List<EssFile> fileList) {\n        if (fileList.isEmpty()) {\n            mAdapter.setEmptyView(R.layout.empty_file_list);\n        }\n        mCurFolder = queryPath;\n        mAdapter.setNewData(fileList);\n        List<BreadModel> breadModelList = FileUtils.getBreadModeListFromPath(mSdCardList, mCurFolder);\n        if (mHasChangeSdCard) {\n            mBreadAdapter.setNewData(breadModelList);\n            mHasChangeSdCard = false;\n        } else {\n            if (breadModelList.size() > mBreadAdapter.getData().size()) {\n                //新增\n                List<BreadModel> newList = BreadModel.getNewBreadModel(mBreadAdapter.getData(), breadModelList);\n                mBreadAdapter.addData(newList);\n            } else {\n                //减少\n                int removePosition = BreadModel.getRemovedBreadModel(mBreadAdapter.getData(), breadModelList);\n                if (removePosition > 0) {\n                    mBreadAdapter.setNewData(mBreadAdapter.getData().subList(0, removePosition));\n                }\n            }\n        }\n\n        mBreadRecyclerView.smoothScrollToPosition(mBreadAdapter.getItemCount() - 1);\n        //先让其滚动到顶部，然后再scrollBy，滚动到之前保存的位置\n        mRecyclerView.scrollToPosition(0);\n        int scrollYPosition = mBreadAdapter.getData().get(mBreadAdapter.getData().size() - 1).getPrePosition();\n        //恢复之前的滚动位置\n        mRecyclerView.scrollBy(0, scrollYPosition);\n    }\n\n    /**\n     * 显示选择SdCard的PopupWindow\n     * 点击其他区域隐藏，阴影\n     */\n    private void showPopupWindow() {\n        if (mSelectSdCardWindow != null) {\n            mSelectSdCardWindow.showAsDropDown(mImbSelectSdCard);\n            return;\n        }\n        View popView = LayoutInflater.from(this).inflate(R.layout.pop_select_sdcard, null);\n        mSelectSdCardWindow = new PopupWindow(popView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        mSelectSdCardWindow.setFocusable(true);\n        mSelectSdCardWindow.setOutsideTouchable(true);\n        RecyclerView recyclerView = popView.findViewById(R.id.rcv_pop_select_sdcard);\n        recyclerView.setLayoutManager(new LinearLayoutManager(this));\n        final SelectSdcardAdapter adapter = new SelectSdcardAdapter(FileUtils.getAllSdCardList(mSdCardList));\n        recyclerView.setAdapter(adapter);\n        adapter.bindToRecyclerView(recyclerView);\n        adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {\n            @Override\n            public void onItemClick(BaseQuickAdapter adapterIn, View view, int position) {\n                mSelectSdCardWindow.dismiss();\n                mHasChangeSdCard = true;\n                executeListTask(mSelectedFileList, FileUtils.getChangeSdCard(adapter.getData().get(position), mSdCardList), SelectOptions.getInstance().getFileTypes(), SelectOptions.getInstance().getSortType());\n            }\n        });\n        mSelectSdCardWindow.showAsDropDown(mImbSelectSdCard);\n    }\n\n    /**\n     * 设置添加屏幕的背景透明度\n     *\n     * @param bgAlpha bgAlpha\n     */\n    public void backgroundAlpha(float bgAlpha) {\n        WindowManager.LayoutParams lp = getWindow().getAttributes();\n        lp.alpha = bgAlpha; //0.0-1.0\n        getWindow().setAttributes(lp);\n    }\n\n\n    @Override\n    public void onFindChildFileAndFolderCount(int position, String childFileCount, String childFolderCount) {\n        mAdapter.getData().get(position).setChildCounts(childFileCount, childFolderCount);\n        mAdapter.notifyItemChanged(position, \"childCountChanges\");\n    }\n\n\n    @Override\n    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {\n        if (adapter.equals(mAdapter)) {\n            EssFile item = mAdapter.getData().get(position);\n            if (item.isDirectory()) {\n                //点击文件夹\n                //保存当前的垂直滚动位置\n                mBreadAdapter.getData().get(mBreadAdapter.getData().size() - 1).setPrePosition(mRecyclerView.computeVerticalScrollOffset());\n                executeListTask(mSelectedFileList, mCurFolder + item.getName() + File.separator, SelectOptions.getInstance().getFileTypes(), SelectOptions.getInstance().getSortType());\n            } else {\n                //选中某文件后，判断是否单选\n                if (SelectOptions.getInstance().isSingle) {\n                    mSelectedFileList.add(item);\n                    Intent result = new Intent();\n                    result.putParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION, mSelectedFileList);\n                    setResult(RESULT_OK, result);\n                    super.onBackPressed();\n                    return;\n                }\n                if (mAdapter.getData().get(position).isChecked()) {\n                    int index = findFileIndex(item);\n                    if (index != -1) {\n                        mSelectedFileList.remove(index);\n                    }\n                } else {\n                    if (mSelectedFileList.size() >= SelectOptions.getInstance().maxCount) {\n                        //超出最大可选择数量后\n                        Snackbar.make(mRecyclerView, \"您最多只能选择\" + SelectOptions.getInstance().maxCount + \"个。\", Snackbar.LENGTH_SHORT).show();\n                        return;\n                    }\n                    mSelectedFileList.add(item);\n                }\n                mAdapter.getData().get(position).setChecked(!mAdapter.getData().get(position).isChecked());\n                mAdapter.notifyItemChanged(position, \"\");\n                mCountMenuItem.setTitle(String.format(getString(R.string.selected_file_count), String.valueOf(mSelectedFileList.size()), String.valueOf(SelectOptions.getInstance().maxCount)));\n            }\n        }\n    }\n\n    /**\n     * 查找文件位置\n     */\n    private int findFileIndex(EssFile item) {\n        for (int i = 0; i < mSelectedFileList.size(); i++) {\n            if (mSelectedFileList.get(i).getAbsolutePath().equals(item.getAbsolutePath())) {\n                return i;\n            }\n        }\n        return -1;\n    }\n\n    @Override\n    public void onBackPressed() {\n        if (!FileUtils.canBackParent(mCurFolder, mSdCardList)) {\n            super.onBackPressed();\n            return;\n        }\n        executeListTask(mSelectedFileList, new File(mCurFolder).getParentFile().getAbsolutePath() + File.separator, SelectOptions.getInstance().getFileTypes(), SelectOptions.getInstance().getSortType());\n    }\n\n    @Override\n    public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {\n        if (adapter.equals(mBreadAdapter) && view.getId() == R.id.btn_bread) {\n            //点击某个路径时\n            String queryPath = FileUtils.getBreadModelListByPosition(mSdCardList, mBreadAdapter.getData(), position);\n            if (mCurFolder.equals(queryPath)) {\n                return;\n            }\n            executeListTask(mSelectedFileList, queryPath, SelectOptions.getInstance().getFileTypes(), SelectOptions.getInstance().getSortType());\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        // TODO: 2019/3/12 暂时移除\n//        EventBus.getDefault().unregister(this);\n        if(essFileListTask!=null){\n            essFileListTask.cancel(true);\n        }\n        if(essFileCountTask!=null){\n            essFileCountTask.cancel(true);\n        }\n    }\n\n    @Override\n    public void onClick(View v) {\n        int id = v.getId();\n        if (id == R.id.imb_select_sdcard) {\n            showPopupWindow();\n        }\n    }\n\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        int i = item.getItemId();\n        if (i == R.id.browser_select_count) {\n            //选中\n            if (mSelectedFileList.isEmpty()) {\n                return true;\n            }\n            //不为空\n            Intent result = new Intent();\n            result.putParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION, mSelectedFileList);\n            setResult(RESULT_OK, result);\n            super.onBackPressed();\n        } else if (i == R.id.browser_sort) {\n            //排序\n            new AlertDialog\n                    .Builder(this)\n                    .setSingleChoiceItems(R.array.sort_list, 0, new DialogInterface.OnClickListener() {\n                        @Override\n                        public void onClick(DialogInterface dialog, int which) {\n                            mSelectSortTypeIndex = which;\n                        }\n                    })\n                    .setNegativeButton(\"降序\", new DialogInterface.OnClickListener() {\n                        @Override\n                        public void onClick(DialogInterface dialog, int which) {\n                            switch (mSelectSortTypeIndex) {\n                                case 0:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_NAME_DESC);\n                                    break;\n                                case 1:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_TIME_ASC);\n                                    break;\n                                case 2:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_SIZE_DESC);\n                                    break;\n                                case 3:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_EXTENSION_DESC);\n                                    break;\n                            }\n                            //恢复排序\n                            mBreadAdapter.getData().get(mBreadAdapter.getData().size() - 1).setPrePosition(0);\n                            executeListTask(mSelectedFileList, mCurFolder, SelectOptions.getInstance().getFileTypes(), SelectOptions.getInstance().getSortType());\n                        }\n                    })\n                    .setPositiveButton(\"升序\", new DialogInterface.OnClickListener() {\n                        @Override\n                        public void onClick(DialogInterface dialog, int which) {\n                            switch (mSelectSortTypeIndex) {\n                                case 0:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_NAME_ASC);\n                                    break;\n                                case 1:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_TIME_DESC);\n                                    break;\n                                case 2:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_SIZE_ASC);\n                                    break;\n                                case 3:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_EXTENSION_ASC);\n                                    break;\n                            }\n                            //恢复排序\n                            mBreadAdapter.getData().get(mBreadAdapter.getData().size() - 1).setPrePosition(0);\n                            executeListTask(mSelectedFileList, mCurFolder, SelectOptions.getInstance().getFileTypes(), SelectOptions.getInstance().getSortType());\n                        }\n                    })\n                    .setTitle(\"请选择\")\n                    .show();\n\n        }\n        return true;\n    }\n\n    @Override\n    public void onLoadFileCount(int position) {\n        essFileCountTask = new EssFileCountTask(position, mAdapter.getData().get(position).getAbsolutePath(), SelectOptions.getInstance().getFileTypes(), this);\n        essFileCountTask.execute();\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/activity/SelectFileByScanActivity.java",
    "content": "package com.ess.filepicker.activity;\n\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.support.design.widget.TabLayout;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.view.ViewPager;\nimport android.support.v7.app.AlertDialog;\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.support.v7.widget.Toolbar;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\n\nimport com.ess.filepicker.R;\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.adapter.FragmentPagerAdapter;\nimport com.ess.filepicker.loader.EssMimeTypeCollection;\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.model.FileScanActEvent;\nimport com.ess.filepicker.model.FileScanFragEvent;\nimport com.ess.filepicker.model.FileScanSortChangedEvent;\nimport com.ess.filepicker.util.Const;\nimport com.ess.filepicker.util.FileUtils;\n\nimport org.greenrobot.eventbus.EventBus;\nimport org.greenrobot.eventbus.Subscribe;\n\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\n\n/**\n * 通过扫描来选择文件\n */\npublic class SelectFileByScanActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {\n\n    /*todo 是否可预览文件，默认可预览*/\n    private boolean mCanPreview = true;\n\n    private ViewPager mViewPager;\n    private TabLayout mTabLayout;\n    private Toolbar mToolBar;\n    private MenuItem mCountMenuItem;\n\n    private ArrayList<EssFile> mSelectedFileList = new ArrayList<>();\n    /*当前选中排序方式的位置*/\n    private int mSelectSortTypeIndex = 0;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_select_file_by_scan);\n        EventBus.getDefault().register(this);\n\n        initUi();\n        initData();\n    }\n\n    private void initData() {\n    }\n\n    private void initUi() {\n        mViewPager = findViewById(R.id.vp_select_file_scan);\n        mTabLayout = findViewById(R.id.tabl_select_file_scan);\n        mToolBar = findViewById(R.id.toolbar);\n        setSupportActionBar(mToolBar);\n        getSupportActionBar().setTitle(\"文件选择\");\n        getSupportActionBar().setDisplayHomeAsUpEnabled(true);\n        getSupportActionBar().setHomeButtonEnabled(true);\n        mToolBar.setNavigationOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                onBackPressed();\n            }\n        });\n\n        mTabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);\n        mTabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);\n\n        List<Fragment> fragmentList = new ArrayList<>();\n        for (int i = 0; i < SelectOptions.getInstance().getFileTypes().length; i++) {\n            fragmentList.add(FileTypeListFragment.newInstance(SelectOptions.getInstance().getFileTypes()[i],SelectOptions.getInstance().isSingle,SelectOptions.getInstance().maxCount,SelectOptions.getInstance().getSortType(),EssMimeTypeCollection.LOADER_ID+i));\n        }\n        FragmentPagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager(), fragmentList, Arrays.asList(SelectOptions.getInstance().getFileTypes()));\n        mViewPager.setAdapter(adapter);\n        mTabLayout.setupWithViewPager(mViewPager);\n        mViewPager.setOffscreenPageLimit(fragmentList.size() - 1);\n        mViewPager.addOnPageChangeListener(this);\n\n    }\n\n\n    /**\n     * Fragment中选择文件后\n     *\n     * @param event event\n     */\n    @Subscribe\n    public void onFragSelectFile(FileScanFragEvent event) {\n        if (event.isAdd()) {\n            if (SelectOptions.getInstance().isSingle) {\n                mSelectedFileList.add(event.getSelectedFile());\n                Intent result = new Intent();\n                result.putParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION, mSelectedFileList);\n                setResult(RESULT_OK, result);\n                super.onBackPressed();\n                return;\n            }\n            mSelectedFileList.add(event.getSelectedFile());\n        } else {\n            mSelectedFileList.remove(event.getSelectedFile());\n        }\n        mCountMenuItem.setTitle(String.format(getString(R.string.selected_file_count), String.valueOf(mSelectedFileList.size()), String.valueOf(SelectOptions.getInstance().maxCount)));\n        EventBus.getDefault().post(new FileScanActEvent(SelectOptions.getInstance().maxCount - mSelectedFileList.size()));\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        EventBus.getDefault().unregister(this);\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.browse_menu, menu);\n        mCountMenuItem = menu.findItem(R.id.browser_select_count);\n        mCountMenuItem.setTitle(String.format(getString(R.string.selected_file_count), String.valueOf(mSelectedFileList.size()), String.valueOf(SelectOptions.getInstance().maxCount)));\n        return true;\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        int i = item.getItemId();\n        if (i == R.id.browser_select_count) {\n            //选中\n            if (mSelectedFileList.isEmpty()) {\n                return true;\n            }\n            //不为空\n            Intent result = new Intent();\n            result.putParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION, mSelectedFileList);\n            setResult(RESULT_OK, result);\n            super.onBackPressed();\n        } else if (i == R.id.browser_sort) {\n            //排序\n            new AlertDialog\n                    .Builder(this)\n                    .setSingleChoiceItems(R.array.sort_list_scan, 0, new DialogInterface.OnClickListener() {\n                        @Override\n                        public void onClick(DialogInterface dialog, int which) {\n                            mSelectSortTypeIndex = which;\n                        }\n                    })\n                    .setNegativeButton(\"降序\", new DialogInterface.OnClickListener() {\n                        @Override\n                        public void onClick(DialogInterface dialog, int which) {\n                            switch (mSelectSortTypeIndex) {\n                                case 0:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_NAME_DESC);\n                                    break;\n                                case 1:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_TIME_ASC);\n                                    break;\n                                case 2:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_SIZE_DESC);\n                                    break;\n                            }\n                            EventBus.getDefault().post(new FileScanSortChangedEvent(SelectOptions.getInstance().getSortType(),mViewPager.getCurrentItem()));\n                        }\n                    })\n                    .setPositiveButton(\"升序\", new DialogInterface.OnClickListener() {\n                        @Override\n                        public void onClick(DialogInterface dialog, int which) {\n                            switch (mSelectSortTypeIndex) {\n                                case 0:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_NAME_ASC);\n                                    break;\n                                case 1:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_TIME_DESC);\n                                    break;\n                                case 2:\n                                    SelectOptions.getInstance().setSortType(FileUtils.BY_SIZE_ASC);\n                                    break;\n                            }\n                            EventBus.getDefault().post(new FileScanSortChangedEvent(SelectOptions.getInstance().getSortType(),mViewPager.getCurrentItem()));\n                        }\n                    })\n                    .setTitle(\"请选择\")\n                    .show();\n\n        }\n        return true;\n    }\n\n    @Override\n    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {\n\n    }\n\n    @Override\n    public void onPageSelected(int position) {\n        EventBus.getDefault().post(new FileScanActEvent(SelectOptions.getInstance().maxCount - mSelectedFileList.size()));\n    }\n\n    @Override\n    public void onPageScrollStateChanged(int state) {\n\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/activity/SelectPictureActivity.java",
    "content": "package com.ess.filepicker.activity;\n\nimport android.content.Intent;\nimport android.content.res.TypedArray;\nimport android.database.Cursor;\nimport android.graphics.PorterDuff;\nimport android.graphics.drawable.Drawable;\nimport android.support.design.widget.Snackbar;\nimport android.support.v7.app.ActionBar;\nimport android.support.v7.app.AppCompatActivity;\nimport android.os.Bundle;\nimport android.support.v7.widget.GridLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.support.v7.widget.Toolbar;\nimport android.util.Log;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.TextView;\n\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.ess.filepicker.R;\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.adapter.BuketAdapter;\nimport com.ess.filepicker.adapter.EssMediaAdapter;\nimport com.ess.filepicker.loader.EssAlbumCollection;\nimport com.ess.filepicker.loader.EssMediaCollection;\nimport com.ess.filepicker.model.Album;\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.util.Const;\nimport com.ess.filepicker.util.UiUtils;\nimport com.ess.filepicker.widget.MediaItemDecoration;\nimport com.ess.filepicker.widget.ToolbarSpinner;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\n\nimport top.zibin.luban.Luban;\nimport top.zibin.luban.OnCompressListener;\n\n\n/**\n * 选择图片界面\n */\npublic class SelectPictureActivity extends AppCompatActivity implements EssAlbumCollection.EssAlbumCallbacks, AdapterView.OnItemSelectedListener, EssMediaCollection.EssMediaCallbacks, BaseQuickAdapter.OnItemChildClickListener, BaseQuickAdapter.OnItemClickListener {\n\n    /*4. 最多可选择个数，默认10*/\n    private int mMaxCount = 10;\n    /*5. todo 是否需要压缩，默认返回压缩之后的图片*/\n    private boolean mNeedCompress = true;\n    /*6. todo 是否需要裁剪/旋转等，默认不裁剪*/\n    private boolean mNeedClip = false;\n    /*7. 是否需要显示照相机*/\n    private boolean mNeedCamera = true;\n    /*8. todo 相机为自定义相机还是系统相机，仅当mNeedCamera=true时有效*/\n    private boolean mUseCustomCamera = true;\n    /*9. todo 是否可预览图片，默认可预览*/\n    private boolean mCanPreview = true;\n\n    private RecyclerView mRecyclerView;\n    private TextView mTvSelectedFolder;\n    private BuketAdapter mBuketAdapter;\n    private EssMediaAdapter mMediaAdapter;\n\n    private final EssAlbumCollection mAlbumCollection = new EssAlbumCollection();\n    private final EssMediaCollection mMediaCollection = new EssMediaCollection();\n    private MenuItem mCountMenuItem;\n    private Set<EssFile> mSelectedFileList = new LinkedHashSet<>();\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        setTheme(SelectOptions.getInstance().themeId);\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_select_picture);\n//        EventBus.getDefault().register(this);\n        mRecyclerView = findViewById(R.id.rcv_file_picture_list);\n        mTvSelectedFolder = findViewById(R.id.selected_folder);\n\n        initUI();\n    }\n\n    private void initUI() {\n        Toolbar toolbar = findViewById(R.id.toolbar);\n        setSupportActionBar(toolbar);\n        ActionBar actionBar = getSupportActionBar();\n        if (actionBar != null) {\n            actionBar.setDisplayShowTitleEnabled(false);\n            actionBar.setDisplayHomeAsUpEnabled(true);\n        }\n        toolbar.setNavigationOnClickListener(new View.OnClickListener() {\n            @Override\n            public void onClick(View v) {\n                onBackPressed();\n            }\n        });\n        Drawable navigationIcon = toolbar.getNavigationIcon();\n        TypedArray ta = getTheme().obtainStyledAttributes(new int[]{R.attr.album_element_color});\n        int color = ta.getColor(0, 0);\n        ta.recycle();\n        if (navigationIcon != null) {\n            navigationIcon.setColorFilter(color, PorterDuff.Mode.SRC_IN);\n        }\n\n        mBuketAdapter = new BuketAdapter(this, null, false);\n        ToolbarSpinner spinner = new ToolbarSpinner(this);\n        spinner.setSelectedTextView((TextView) findViewById(R.id.selected_folder));\n        spinner.setPopupAnchorView(findViewById(R.id.toolbar));\n        spinner.setOnItemSelectedListener(this);\n        spinner.setAdapter(mBuketAdapter);\n\n        mAlbumCollection.onCreate(this, this);\n        mAlbumCollection.load();\n        mMediaCollection.onCreate(this, this);\n\n        mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));\n        mRecyclerView.addItemDecoration(new MediaItemDecoration());\n        mMediaAdapter = new EssMediaAdapter(new ArrayList<EssFile>());\n        mMediaAdapter.setImageResize(UiUtils.getImageResize(this, mRecyclerView));\n        mRecyclerView.setAdapter(mMediaAdapter);\n        mMediaAdapter.bindToRecyclerView(mRecyclerView);\n        mMediaAdapter.setOnItemChildClickListener(this);\n        if (SelectOptions.getInstance().isSingle || SelectOptions.getInstance().maxCount == 1) {\n            //单选\n            mMediaAdapter.setOnItemClickListener(this);\n        }\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        getMenuInflater().inflate(R.menu.media_menu, menu);\n        mCountMenuItem = menu.findItem(R.id.browser_select_count);\n        mCountMenuItem.setTitle(String.format(getString(R.string.selected_file_count), String.valueOf(mSelectedFileList.size()), String.valueOf(mMaxCount)));\n        return true;\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        mAlbumCollection.onDestroy();\n        mMediaCollection.onDestroy();\n    }\n\n    @Override\n    public void onAlbumMediaLoad(Cursor cursor) {\n        mBuketAdapter.swapCursor(cursor);\n        cursor.moveToFirst();\n        Album album = Album.valueOf(cursor);\n        mMediaCollection.load(album, mNeedCamera, mSelectedFileList);\n    }\n\n    @Override\n    public void onAlbumMediaReset() {\n\n    }\n\n    @Override\n    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {\n        mBuketAdapter.getCursor().moveToPosition(position);\n        Album album = Album.valueOf(mBuketAdapter.getCursor());\n        mMediaCollection.load(album, mNeedCamera, mSelectedFileList);\n    }\n\n    @Override\n    public void onNothingSelected(AdapterView<?> parent) {\n\n    }\n\n    @Override\n    public void onMediaLoad(List<EssFile> essFileList) {\n        mMediaAdapter.setNewData(essFileList);\n        if (essFileList == null || essFileList.isEmpty()) {\n            mMediaAdapter.setEmptyView(R.layout.empty_file_list);\n        }\n    }\n\n    @Override\n    public void onmMediaReset() {\n\n    }\n\n    @Override\n    public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {\n        EssFile item = mMediaAdapter.getItem(position);\n        if (!adapter.equals(mMediaAdapter)) {\n            return;\n        }\n        if (view.getId() == R.id.check_view) {\n            if (mSelectedFileList.size() >= SelectOptions.getInstance().maxCount && !item.isChecked()) {\n                mMediaAdapter.notifyItemChanged(position, \"\");\n                Snackbar.make(mRecyclerView, \"您最多只能选择\" + SelectOptions.getInstance().maxCount + \"个。\", Snackbar.LENGTH_SHORT).show();\n                return;\n            }\n            boolean addSuccess = mSelectedFileList.add(mMediaAdapter.getItem(position));\n            if (addSuccess) {\n                mMediaAdapter.getData().get(position).setChecked(true);\n            } else {\n                //已经有了就删掉\n                mSelectedFileList.remove(item);\n                mMediaAdapter.getData().get(position).setChecked(false);\n            }\n            mMediaAdapter.notifyItemChanged(position, \"\");\n            mCountMenuItem.setTitle(String.format(getString(R.string.selected_file_count), String.valueOf(mSelectedFileList.size()), String.valueOf(mMaxCount)));\n        } else if (view.getId() == R.id.media_thumbnail) {\n            //预览\n            // TODO: 2018/3/7  预览照片\n        } else if (view.getId() == R.id.capture) {\n            //照相\n            // TODO: 2018/3/7  自定义相机照相\n        }\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        int itemId = item.getItemId();\n        if (itemId == R.id.browser_select_count) {\n            //选中\n            if (mSelectedFileList.isEmpty()) {\n                return true;\n            }\n            if (SelectOptions.getInstance().compressImage) {\n                //需要压缩\n                final ArrayList<String> imageList = EssFile.getFilePathList(EssFile.getEssFileList(this, mSelectedFileList));\n                final int[] successCount = {0};\n                //todo 当目标文件夹存在此文件时不覆盖\n                Luban.with(this)\n                        .load(imageList)// 传人要压缩的图片列表\n                        .ignoreBy(100) // 忽略不压缩图片的大小\n                        .setTargetDir(SelectOptions.getInstance().getTargetPath())// 设置压缩后文件存储位置\n                        .setCompressListener(new OnCompressListener() { //设置回调\n                            @Override\n                            public void onStart() {\n\n                            }\n\n                            @Override\n                            public void onSuccess(File file) {\n                                successCount[0]++;\n                                if(successCount[0] == imageList.size()){\n                                    Intent result = new Intent();\n                                    result.putParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION, EssFile.getEssFileList(SelectPictureActivity.this, mSelectedFileList));\n                                    setResult(RESULT_OK, result);\n                                    onBackPressed();\n                                }\n                            }\n\n                            @Override\n                            public void onError(Throwable e) {\n                                Log.i(\"TAG\", e.toString());\n                            }\n                        })\n                        .launch();    //启动压缩\n            }else {\n                Intent result = new Intent();\n                result.putParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION, EssFile.getEssFileList(SelectPictureActivity.this, mSelectedFileList));\n                setResult(RESULT_OK, result);\n                onBackPressed();\n            }\n        }\n        return true;\n    }\n\n\n    @Override\n    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {\n        //单选\n        mSelectedFileList.add(mMediaAdapter.getData().get(position));\n        Intent result = new Intent();\n        result.putParcelableArrayListExtra(Const.EXTRA_RESULT_SELECTION, EssFile.getEssFileList(this, mSelectedFileList));\n        setResult(RESULT_OK, result);\n        super.onBackPressed();\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/adapter/BreadAdapter.java",
    "content": "package com.ess.filepicker.adapter;\n\n\nimport android.support.annotation.Nullable;\n\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.chad.library.adapter.base.BaseViewHolder;\nimport com.ess.filepicker.model.BreadModel;\nimport com.ess.filepicker.R;\n\nimport java.util.List;\n\n/**\n * BreadAdapter\n * Created by 李波 on 2018/2/5.\n */\n\npublic class BreadAdapter extends BaseQuickAdapter<BreadModel, BaseViewHolder> {\n\n    public BreadAdapter(@Nullable List<BreadModel> data) {\n        super(R.layout.bread_item,data);\n    }\n\n    @Override\n    protected void convert(BaseViewHolder helper, BreadModel item) {\n        helper.setText(R.id.btn_bread,item.getCurName());\n        helper.addOnClickListener(R.id.btn_bread);\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/adapter/BuketAdapter.java",
    "content": "package com.ess.filepicker.adapter;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.database.Cursor;\nimport android.graphics.drawable.Drawable;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.CursorAdapter;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.request.RequestOptions;\nimport com.ess.filepicker.R;\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.model.Album;\n\n/**\n * BuketAdapter\n * Created by 李波 on 2018/3/1.\n */\n\npublic class BuketAdapter extends CursorAdapter{\n\n    private final Drawable mPlaceholder;\n\n    public BuketAdapter(Context context, Cursor c, boolean autoRequery) {\n        super(context, c, autoRequery);\n        TypedArray ta = context.getTheme().obtainStyledAttributes(\n                new int[]{R.attr.album_thumbnail_placeholder});\n        mPlaceholder = ta.getDrawable(0);\n        ta.recycle();\n    }\n\n    @Override\n    public View newView(Context context, Cursor cursor, ViewGroup parent) {\n        return LayoutInflater.from(context).inflate(R.layout.buket_list_item, parent, false);\n    }\n\n    @Override\n    public void bindView(View view, Context context, Cursor cursor) {\n        Album album = Album.valueOf(cursor);\n        ((TextView) view.findViewById(R.id.album_name)).setText(album.getDisplayName(context));\n        ((TextView) view.findViewById(R.id.album_media_count)).setText(String.valueOf(album.getCount()));\n        RequestOptions options = new RequestOptions()\n                .centerCrop()\n                .placeholder(mPlaceholder);\n        Glide\n                .with(context)\n                .load(album.getCoverPath())\n                .apply(options)\n                .into((ImageView) view.findViewById(R.id.album_cover));\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/adapter/EssMediaAdapter.java",
    "content": "package com.ess.filepicker.adapter;\n\nimport android.support.annotation.Nullable;\nimport android.support.v7.widget.AppCompatCheckBox;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.request.RequestOptions;\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.chad.library.adapter.base.BaseViewHolder;\nimport com.ess.filepicker.R;\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.util.UiUtils;\n\nimport java.util.List;\n\n\n/**\n * EssMediaAdapter\n * Created by 李波 on 2018/3/2.\n */\n\npublic class EssMediaAdapter extends BaseQuickAdapter<EssFile, BaseViewHolder> {\n\n    private int mImageResize;\n\n    public EssMediaAdapter(@Nullable List<EssFile> data) {\n        super(R.layout.ess_media_item,data);\n    }\n\n    public void setImageResize(int imageSize) {\n        this.mImageResize = imageSize;\n    }\n\n    @Override\n    protected void convert(BaseViewHolder helper, EssFile item) {\n        if (item.getItemType() == EssFile.CAPTURE) {\n            helper.getView(R.id.media).setVisibility(View.GONE);\n            helper.getView(R.id.capture).setVisibility(View.VISIBLE);\n            helper.itemView.setLayoutParams(new ViewGroup.LayoutParams(mImageResize- UiUtils.dpToPx(mContext,4), mImageResize));\n            helper.addOnClickListener(R.id.capture);\n        } else {\n            helper.getView(R.id.capture).setVisibility(View.GONE);\n            helper.getView(R.id.media).setVisibility(View.VISIBLE);\n            helper.itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mImageResize));\n            ImageView imageView = helper.getView(R.id.media_thumbnail);\n            RequestOptions options = new RequestOptions()\n                    .centerCrop()\n                    .override(mImageResize, mImageResize)\n                    .placeholder(SelectOptions.getInstance().placeHolder == null ? mContext.getResources().getDrawable(R.mipmap.png_holder) : SelectOptions.getInstance().placeHolder);\n            Glide\n                    .with(mContext)\n                    .load(item.getUri())\n                    .apply(options)\n                    .into(imageView);\n            if(SelectOptions.getInstance().isSingle || SelectOptions.getInstance().maxCount == 1){\n                helper.setVisible(R.id.check_view,false);\n            }else {\n                AppCompatCheckBox checkBox = helper.getView(R.id.check_view);\n                helper.setVisible(R.id.check_view,true);\n                helper.addOnClickListener(R.id.check_view);\n                helper.addOnClickListener(R.id.media_thumbnail);\n                checkBox.setChecked(item.isChecked());\n            }\n        }\n\n    }\n\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/adapter/FileListAdapter.java",
    "content": "package com.ess.filepicker.adapter;\n\nimport android.support.annotation.Nullable;\nimport android.widget.ImageView;\nimport android.widget.TextView;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.request.RequestOptions;\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.chad.library.adapter.base.BaseViewHolder;\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.util.FileSizeUtil;\nimport com.ess.filepicker.util.FileUtils;\nimport com.ess.filepicker.R;\n\nimport java.util.List;\n\n/**\n * FileListAdapter\n * Created by 李波 on 2018/2/3.\n */\n\npublic class FileListAdapter extends BaseQuickAdapter<EssFile, BaseViewHolder> {\n\n    private onLoadFileCountListener loadFileCountListener;\n\n    public interface onLoadFileCountListener{\n        void onLoadFileCount(int posistion);\n    }\n\n    public onLoadFileCountListener getLoadFileCountListener() {\n        return loadFileCountListener;\n    }\n\n    public void setLoadFileCountListener(onLoadFileCountListener loadFileCountListener) {\n        this.loadFileCountListener = loadFileCountListener;\n    }\n\n    public FileListAdapter(@Nullable List<EssFile> data) {\n        super(R.layout.item_file_list, data);\n    }\n\n    @Override\n    protected void convert(BaseViewHolder helper, EssFile item) {\n        TextView textView = helper.getView(R.id.tv_item_file_list_desc);\n        if (item.isDirectory()) {\n            helper.setVisible(R.id.iv_item_file_select_right, true);\n            if(item.getChildFolderCount().equals(\"加载中\")){\n                //查找数量\n                if(loadFileCountListener!=null){\n                    loadFileCountListener.onLoadFileCount(helper.getAdapterPosition());\n                }\n            }\n            textView.setText(String.format(mContext.getString(R.string.folder_desc), item.getChildFileCount(),item.getChildFolderCount()));\n        } else {\n            helper.setVisible(R.id.iv_item_file_select_right, false);\n            textView.setText(String.format(mContext.getString(R.string.file_desc), FileUtils.getDateTime(item.getAbsolutePath()), FileSizeUtil.getAutoFileOrFilesSize(item.getFile())));\n        }\n        helper.setText(R.id.tv_item_file_list, item.getName());\n        if(item.isChecked()){\n            helper.setVisible(R.id.checkbox_item_file_list,true);\n        }else {\n            helper.setVisible(R.id.checkbox_item_file_list,false);\n        }\n        ImageView imageView = helper.getView(R.id.iv_item_file_select_left);\n        String fileNameExtension = FileUtils.getExtension(item.getName()).toLowerCase();\n        switch (fileNameExtension) {\n            case \"apk\":\n                imageView.setImageResource(R.mipmap.apk);\n                break;\n            case \"avi\":\n                imageView.setImageResource(R.mipmap.avi);\n                break;\n            case \"doc\":\n            case \"docx\":\n                imageView.setImageResource(R.mipmap.doc);\n                break;\n            case \"exe\":\n                imageView.setImageResource(R.mipmap.exe);\n                break;\n            case \"flv\":\n                imageView.setImageResource(R.mipmap.flv);\n                break;\n            case \"gif\":\n                RequestOptions options = new RequestOptions()\n                        .centerCrop()\n                        .placeholder(R.mipmap.gif);\n                Glide\n                        .with(mContext)\n                        .load(item.getAbsolutePath())\n                        .apply(options)\n                        .into(imageView);\n                break;\n            case \"jpg\":\n            case \"jpeg\":\n            case \"png\":\n                RequestOptions options2 = new RequestOptions()\n                        .centerCrop()\n                        .placeholder(R.mipmap.png);\n                Glide\n                        .with(mContext)\n                        .load(item.getAbsolutePath())\n                        .apply(options2)\n                        .into(imageView);\n                break;\n            case \"mp3\":\n                imageView.setImageResource(R.mipmap.mp3);\n                break;\n            case \"mp4\":\n            case \"f4v\":\n                imageView.setImageResource(R.mipmap.movie);\n                break;\n            case \"pdf\":\n                imageView.setImageResource(R.mipmap.pdf);\n                break;\n            case \"ppt\":\n            case \"pptx\":\n                imageView.setImageResource(R.mipmap.ppt);\n                break;\n            case \"wav\":\n                imageView.setImageResource(R.mipmap.wav);\n                break;\n            case \"xls\":\n            case \"xlsx\":\n                imageView.setImageResource(R.mipmap.xls);\n                break;\n            case \"zip\":\n                imageView.setImageResource(R.mipmap.zip);\n                break;\n            case \"ext\":\n            default:\n                if (item.isDirectory()) {\n                    imageView.setImageResource(R.mipmap.folder);\n                } else {\n                    imageView.setImageResource(R.mipmap.documents);\n                }\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/adapter/FragmentPagerAdapter.java",
    "content": "package com.ess.filepicker.adapter;\n\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentManager;\nimport android.support.v4.app.FragmentStatePagerAdapter;\nimport android.support.v4.app.FragmentTransaction;\nimport android.view.ViewGroup;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Fragment结合ViewPager一起使用的Adapter\n */\npublic class FragmentPagerAdapter extends FragmentStatePagerAdapter {\n\n    private List<Fragment> fragmentList;\n    private List<String> titleArray;\n    private FragmentManager fm;\n\n    public FragmentPagerAdapter(FragmentManager fm) {\n        super(fm);\n        this.fm = fm;\n    }\n\n    public FragmentPagerAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> titleArray) {\n        this(fm);\n        this.fragmentList = fragmentList;\n        this.titleArray = titleArray;\n    }\n\n    public FragmentPagerAdapter(FragmentManager fm, List<Fragment> fragmentList) {\n        this(fm);\n        this.fragmentList = fragmentList;\n    }\n\n    public void setFragments(ArrayList<Fragment> fragments) {\n        if (this.fragmentList != null) {\n            FragmentTransaction ft = fm.beginTransaction();\n            for (Fragment f : this.fragmentList) {\n                ft.remove(f);\n            }\n            ft.commit();\n            ft = null;\n            fm.executePendingTransactions();\n        }\n        this.fragmentList = fragments;\n        notifyDataSetChanged();\n    }\n\n    @Override\n    public CharSequence getPageTitle(int position) {\n        if (titleArray != null) {\n            return titleArray.get(position);\n        }\n        return \"\";\n    }\n\n    @Override\n    public int getCount() {\n        return fragmentList.size();\n    }\n\n    @Override\n    public Fragment getItem(int position) {\n        return fragmentList.get(position);\n    }\n\n    @Override\n    public int getItemPosition(Object object) {\n        return POSITION_NONE;\n    }\n\n    @Override\n    public Object instantiateItem(ViewGroup container, final int position) {\n        return super.instantiateItem(container, position);\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/adapter/OnFileSelectListener.java",
    "content": "package com.ess.filepicker.adapter;\n\nimport com.ess.filepicker.model.EssFile;\n\nimport java.util.List;\n\n/**\n * OnFileSelectListener\n * Created by 李波 on 2018/2/26.\n */\n\npublic interface OnFileSelectListener {\n    void onSelected(List<EssFile> essFileList);\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/adapter/SelectSdcardAdapter.java",
    "content": "package com.ess.filepicker.adapter;\n\nimport android.support.annotation.Nullable;\n\nimport com.chad.library.adapter.base.BaseQuickAdapter;\nimport com.chad.library.adapter.base.BaseViewHolder;\nimport com.ess.filepicker.R;\n\nimport java.util.List;\n\n/**\n * SelectSdcardAdapter\n * Created by 李波 on 2018/2/8.\n */\n\npublic class SelectSdcardAdapter extends BaseQuickAdapter<String,BaseViewHolder>{\n    public SelectSdcardAdapter(@Nullable List<String> data) {\n        super(R.layout.item_select_sdcard,data);\n    }\n\n    @Override\n    protected void convert(BaseViewHolder helper, String item) {\n        helper.setText(R.id.tv_item_select_sdcard,item);\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/loader/EssAlbumCollection.java",
    "content": "/*\n * Copyright (C) 2014 nohana, Inc.\n * Copyright 2017 Zhihu Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.ess.filepicker.loader;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.v4.app.FragmentActivity;\nimport android.support.v4.app.LoaderManager;\nimport android.support.v4.content.Loader;\n\nimport java.lang.ref.WeakReference;\n\npublic class EssAlbumCollection implements LoaderManager.LoaderCallbacks<Cursor> {\n    private static final int LOADER_ID = 1;\n    private WeakReference<Context> mContext;\n    private LoaderManager mLoaderManager;\n    private EssAlbumCallbacks mCallbacks;\n\n    @Override\n    public Loader<Cursor> onCreateLoader(int id, Bundle args) {\n        Context context = mContext.get();\n        if (context == null) {\n            return null;\n        }\n\n\n        return EssAlbumLoader.newInstance(context);\n    }\n\n    @Override\n    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {\n        Context context = mContext.get();\n        if (context == null) {\n            return;\n        }\n\n        mCallbacks.onAlbumMediaLoad(data);\n    }\n\n    @Override\n    public void onLoaderReset(Loader<Cursor> loader) {\n        Context context = mContext.get();\n        if (context == null) {\n            return;\n        }\n\n        mCallbacks.onAlbumMediaReset();\n    }\n\n    public void onCreate(@NonNull FragmentActivity context, @NonNull EssAlbumCallbacks callbacks) {\n        mContext = new WeakReference<Context>(context);\n        mLoaderManager = context.getSupportLoaderManager();\n        mCallbacks = callbacks;\n    }\n\n    public void onDestroy() {\n        mLoaderManager.destroyLoader(LOADER_ID);\n        mCallbacks = null;\n    }\n\n    public void load() {\n        Bundle args = new Bundle();\n        mLoaderManager.initLoader(LOADER_ID, args, this);\n    }\n\n    public interface EssAlbumCallbacks {\n\n        void onAlbumMediaLoad(Cursor cursor);\n\n        void onAlbumMediaReset();\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/loader/EssAlbumLoader.java",
    "content": "package com.ess.filepicker.loader;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.database.MatrixCursor;\nimport android.database.MergeCursor;\nimport android.net.Uri;\nimport android.provider.MediaStore;\nimport android.support.v4.content.CursorLoader;\n\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.model.Album;\n\n/**\n * EssAlbumLoader\n * Created by 李波 on 2018/2/27.\n */\n\npublic class EssAlbumLoader extends CursorLoader {\n\n    public static final String COLUMN_COUNT = \"count\";\n    private static final Uri QUERY_URI = MediaStore.Files.getContentUri(\"external\");\n    private static final String[] COLUMNS = {\n            MediaStore.Files.FileColumns._ID,\n            \"bucket_id\",\n            \"bucket_display_name\",\n            MediaStore.MediaColumns.DATA,\n            COLUMN_COUNT};\n    private static final String[] PROJECTION = {\n            MediaStore.Files.FileColumns._ID,\n            \"bucket_id\",\n            \"bucket_display_name\",\n            MediaStore.MediaColumns.DATA,\n            \"COUNT(*) AS \" + COLUMN_COUNT};\n\n    // === params for showSingleMediaType: false ===\n    private static final String SELECTION =\n            \"(\" + MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?\"\n                    + \" OR \"\n                    + MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?)\"\n                    + \" AND \" + MediaStore.MediaColumns.SIZE + \">0\"\n                    + \") GROUP BY (bucket_id\";\n    private static final String[] SELECTION_ARGS = {\n            String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE),\n            String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO),\n    };\n    // =============================================\n\n    // === params for showSingleMediaType: true ===\n    private static final String SELECTION_FOR_SINGLE_MEDIA_TYPE =\n            MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?\"\n                    + \" AND \" + MediaStore.MediaColumns.SIZE + \">0\"\n                    + \") GROUP BY (bucket_id\";\n\n    private static String[] getSelectionArgsForSingleMediaType(int mediaType) {\n        return new String[]{String.valueOf(mediaType)};\n    }\n    // =============================================\n\n    private static final String BUCKET_ORDER_BY = \"datetaken DESC\";\n\n    public EssAlbumLoader(Context context, String selection, String[] selectionArgs) {\n        super(context, QUERY_URI, PROJECTION, selection, selectionArgs, BUCKET_ORDER_BY);\n    }\n\n    public static CursorLoader newInstance(Context context) {\n        String selection;\n        String[] selectionArgs;\n        if (SelectOptions.getInstance().onlyShowImages) {\n            selection = SELECTION_FOR_SINGLE_MEDIA_TYPE;\n            selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE);\n        } else if (SelectOptions.getInstance().onlyShowVideos) {\n            selection = SELECTION_FOR_SINGLE_MEDIA_TYPE;\n            selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO);\n        } else {\n            selection = SELECTION;\n            selectionArgs = SELECTION_ARGS;\n        }\n        return new EssAlbumLoader(context, selection, selectionArgs);\n    }\n\n    @Override\n    public Cursor loadInBackground() {\n        Cursor albums = super.loadInBackground();\n        MatrixCursor allAlbum = new MatrixCursor(COLUMNS);\n        int totalCount = 0;\n        String allAlbumCoverPath = \"\";\n        if (albums != null) {\n            while (albums.moveToNext()) {\n                totalCount += albums.getInt(albums.getColumnIndex(COLUMN_COUNT));\n            }\n            if (albums.moveToFirst()) {\n                allAlbumCoverPath = albums.getString(albums.getColumnIndex(MediaStore.MediaColumns.DATA));\n            }\n        }\n        allAlbum.addRow(new String[]{Album.ALBUM_ID_ALL, Album.ALBUM_ID_ALL, Album.ALBUM_NAME_ALL, allAlbumCoverPath,\n                String.valueOf(totalCount)});\n\n\n\n        return new MergeCursor(new Cursor[]{allAlbum, albums});\n    }\n\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/loader/EssMediaCollection.java",
    "content": "package com.ess.filepicker.loader;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.os.Bundle;\nimport android.provider.MediaStore;\nimport android.support.annotation.NonNull;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.FragmentActivity;\nimport android.support.v4.app.LoaderManager;\nimport android.support.v4.content.Loader;\n\nimport com.ess.filepicker.model.Album;\nimport com.ess.filepicker.model.EssFile;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayList;\nimport java.util.LinkedHashSet;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * EssMediaCollection\n * Created by 李波 on 2018/3/2.\n */\n\npublic class EssMediaCollection implements LoaderManager.LoaderCallbacks<Cursor>{\n\n    private static final int LOADER_ID = 2;\n    private static final String ARGS_ALBUM = \"args_album\";\n    private static final String ARGS_ENABLE_CAPTURE = \"args_enable_capture\";\n    private static final String ARGS_ONLY_SHOWIMAGE = \"args_only_showimage\";\n    private WeakReference<Context> mContext;\n    private LoaderManager mLoaderManager;\n    private EssMediaCallbacks mCallbacks;\n    private Set<EssFile> essFileSet = new LinkedHashSet<>();\n\n    @Override\n    public Loader<Cursor> onCreateLoader(int id, Bundle args) {\n        Context context = mContext.get();\n        if (context == null) {\n            return null;\n        }\n\n        Album album = args.getParcelable(ARGS_ALBUM);\n        if (album == null) {\n            return null;\n        }\n\n        return EssMediaLoader.newInstance(context, album);\n    }\n\n    @Override\n    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {\n        Context context = mContext.get();\n        if (context == null) {\n            return;\n        }\n\n        List<EssFile> essFileList = new ArrayList<>();\n        while (data.moveToNext()){\n            EssFile essFile = new EssFile(data.getLong(data.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)),\n                    data.getString(data.getColumnIndexOrThrow(MediaStore.MediaColumns.MIME_TYPE)));\n            if(data.getLong(data.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))==-1){\n                //capture\n                essFile.setItemType(EssFile.CAPTURE);\n            }\n            if(essFileSet.contains(essFile)){\n                essFile.setChecked(true);\n            }\n            essFileList.add(essFile);\n        }\n\n        mCallbacks.onMediaLoad(essFileList);\n    }\n\n    @Override\n    public void onLoaderReset(Loader<Cursor> loader) {\n        Context context = mContext.get();\n        if (context == null) {\n            return;\n        }\n\n        mCallbacks.onmMediaReset();\n    }\n\n    public void onCreate(@NonNull FragmentActivity context, @NonNull EssMediaCallbacks callbacks) {\n        mContext = new WeakReference<Context>(context);\n        mLoaderManager = context.getSupportLoaderManager();\n        mCallbacks = callbacks;\n    }\n\n    public void onDestroy() {\n        mLoaderManager.destroyLoader(LOADER_ID);\n        mCallbacks = null;\n    }\n\n    public void load(@Nullable Album target) {\n        load(target, false, new LinkedHashSet<EssFile>());\n    }\n\n    public void load(@Nullable Album target, boolean enableCapture, Set<EssFile> essFileSet) {\n        Bundle args = new Bundle();\n        this.essFileSet = essFileSet;\n        args.putParcelable(ARGS_ALBUM, target);\n        args.putBoolean(ARGS_ENABLE_CAPTURE, enableCapture);\n        if(mContext.get() == null){\n            mLoaderManager.initLoader(LOADER_ID, args, this);\n        }else {\n            mLoaderManager.restartLoader(LOADER_ID,args,this);\n        }\n    }\n\n    public void load(@Nullable Album target, boolean enableCapture, boolean onlyShouwIMage) {\n        Bundle args = new Bundle();\n        args.putParcelable(ARGS_ALBUM, target);\n        args.putBoolean(ARGS_ENABLE_CAPTURE, enableCapture);\n        args.putBoolean(ARGS_ONLY_SHOWIMAGE, onlyShouwIMage);\n        if(mContext.get() == null){\n            mLoaderManager.initLoader(LOADER_ID, args, this);\n        }else {\n            mLoaderManager.restartLoader(LOADER_ID,args,this);\n        }\n    }\n\n    public interface EssMediaCallbacks {\n\n        void onMediaLoad(List<EssFile> cursor);\n\n        void onmMediaReset();\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/loader/EssMediaLoader.java",
    "content": "package com.ess.filepicker.loader;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.database.MatrixCursor;\nimport android.database.MergeCursor;\nimport android.net.Uri;\nimport android.provider.MediaStore;\nimport android.support.v4.content.CursorLoader;\n\nimport com.ess.filepicker.SelectOptions;\nimport com.ess.filepicker.model.Album;\nimport com.ess.filepicker.util.MediaStoreCompat;\n\n/**\n * EssMediaLoader\n * Created by 李波 on 2018/3/2.\n */\n\npublic class EssMediaLoader extends CursorLoader {\n\n    private static final Uri QUERY_URI = MediaStore.Files.getContentUri(\"external\");\n    private static final String[] PROJECTION = {\n            MediaStore.Files.FileColumns._ID,\n            MediaStore.MediaColumns.DISPLAY_NAME,\n            MediaStore.MediaColumns.MIME_TYPE,\n            MediaStore.MediaColumns.SIZE,\n            \"duration\"};\n\n    // === params for album ALL && showSingleMediaType: false ===\n    private static final String SELECTION_ALL =\n            \"(\" + MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?\"\n                    + \" OR \"\n                    + MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?)\"\n                    + \" AND \" + MediaStore.MediaColumns.SIZE + \">0\";\n    private static final String[] SELECTION_ALL_ARGS = {\n            String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE),\n            String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO),\n    };\n    // ===========================================================\n\n    // === params for album ALL && showSingleMediaType: true ===\n    private static final String SELECTION_ALL_FOR_SINGLE_MEDIA_TYPE =\n            MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?\"\n                    + \" AND \" + MediaStore.MediaColumns.SIZE + \">0\";\n\n    private static String[] getSelectionArgsForSingleMediaType(int mediaType) {\n        return new String[]{String.valueOf(mediaType)};\n    }\n    // =========================================================\n\n    // === params for ordinary album && showSingleMediaType: false ===\n    private static final String SELECTION_ALBUM =\n            \"(\" + MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?\"\n                    + \" OR \"\n                    + MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?)\"\n                    + \" AND \"\n                    + \" bucket_id=?\"\n                    + \" AND \" + MediaStore.MediaColumns.SIZE + \">0\";\n\n    private static String[] getSelectionAlbumArgs(String albumId) {\n        return new String[]{\n                String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE),\n                String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO),\n                albumId\n        };\n    }\n    // ===============================================================\n\n    // === params for ordinary album && showSingleMediaType: true ===\n    private static final String SELECTION_ALBUM_FOR_SINGLE_MEDIA_TYPE =\n            MediaStore.Files.FileColumns.MEDIA_TYPE + \"=?\"\n                    + \" AND \"\n                    + \" bucket_id=?\"\n                    + \" AND \" + MediaStore.MediaColumns.SIZE + \">0\";\n\n    private static String[] getSelectionAlbumArgsForSingleMediaType(int mediaType, String albumId) {\n        return new String[]{String.valueOf(mediaType), albumId};\n    }\n    // ===============================================================\n\n    private static final String ORDER_BY = MediaStore.Images.Media.DATE_TAKEN + \" DESC\";\n    private final boolean mEnableCapture;\n\n    private EssMediaLoader(Context context, String selection, String[] selectionArgs, boolean capture) {\n        super(context, QUERY_URI, PROJECTION, selection, selectionArgs, ORDER_BY);\n        mEnableCapture = capture;\n    }\n\n    public static CursorLoader newInstance(Context context, Album album) {\n        String selection;\n        String[] selectionArgs;\n        boolean enableCapture;\n        if (album.isAll()) {\n            if (SelectOptions.getInstance().onlyShowImages) {\n                selection = SELECTION_ALL_FOR_SINGLE_MEDIA_TYPE;\n                selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE);\n            } else if (SelectOptions.getInstance().onlyShowVideos) {\n                selection = SELECTION_ALL_FOR_SINGLE_MEDIA_TYPE;\n                selectionArgs = getSelectionArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO);\n            } else {\n                selection = SELECTION_ALL;\n                selectionArgs = SELECTION_ALL_ARGS;\n            }\n            enableCapture = SelectOptions.getInstance().enabledCapture;\n        } else {\n            if (SelectOptions.getInstance().onlyShowImages) {\n                selection = SELECTION_ALBUM_FOR_SINGLE_MEDIA_TYPE;\n                selectionArgs = getSelectionAlbumArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE,\n                        album.getId());\n            } else if (SelectOptions.getInstance().onlyShowVideos) {\n                selection = SELECTION_ALBUM_FOR_SINGLE_MEDIA_TYPE;\n                selectionArgs = getSelectionAlbumArgsForSingleMediaType(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO,\n                        album.getId());\n            } else {\n                selection = SELECTION_ALBUM;\n                selectionArgs = getSelectionAlbumArgs(album.getId());\n            }\n            enableCapture = false;\n        }\n        return new EssMediaLoader(context, selection, selectionArgs, enableCapture);\n    }\n\n    @Override\n    public Cursor loadInBackground() {\n        Cursor result = super.loadInBackground();\n        if (!mEnableCapture || !MediaStoreCompat.hasCameraFeature(getContext())) {\n            return result;\n        }\n        MatrixCursor dummy = new MatrixCursor(PROJECTION);\n        dummy.addRow(new Object[]{\"-1\", \"capture\", \"\", 0, \"\"});\n        return new MergeCursor(new Cursor[]{dummy, result});\n    }\n\n    @Override\n    public void onContentChanged() {\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/loader/EssMimeTypeCollection.java",
    "content": "/*\n * Copyright (C) 2014 nohana, Inc.\n * Copyright 2017 Zhihu Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.ess.filepicker.loader;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.os.Bundle;\nimport android.support.annotation.NonNull;\nimport android.support.v4.app.FragmentActivity;\nimport android.support.v4.app.LoaderManager;\nimport android.support.v4.content.Loader;\n\nimport com.ess.filepicker.model.EssFile;\n\nimport java.lang.ref.WeakReference;\nimport java.util.List;\n\n/**\n * 按照文件类型查找\n */\npublic class EssMimeTypeCollection implements LoaderManager.LoaderCallbacks<Cursor> {\n    public static final int LOADER_ID = 3;\n    private WeakReference<Context> mContext;\n    private static final String ARGS_EXTENSION = \"args_extension\";\n    private static final String ARGS_SORT_TYPE = \"args_sort_type\";\n    private LoaderManager mLoaderManager;\n    private EssMimeTypeCallbacks mCallbacks;\n\n    @Override\n    public Loader<Cursor> onCreateLoader(int id, Bundle args) {\n        Context context = mContext.get();\n        if (context == null) {\n            return null;\n        }\n\n        String extension = args.getString(ARGS_EXTENSION);\n        int sortType = args.getInt(ARGS_SORT_TYPE);\n\n        return EssMimeTypeLoader.newInstance(context, extension, sortType);\n    }\n\n    @Override\n    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {\n        Context context = mContext.get();\n        if (context == null) {\n            return;\n        }\n        mCallbacks.onFileLoad(((EssMimeTypeLoader)loader).getEssFileList());\n    }\n\n    @Override\n    public void onLoaderReset(Loader<Cursor> loader) {\n        Context context = mContext.get();\n        if (context == null) {\n            return;\n        }\n        if(mCallbacks!=null){\n            mCallbacks.onFileReset();\n        }\n    }\n\n    public void onCreate(@NonNull FragmentActivity context, @NonNull EssMimeTypeCallbacks callbacks) {\n        mContext = new WeakReference<Context>(context);\n        mLoaderManager = context.getSupportLoaderManager();\n        mCallbacks = callbacks;\n    }\n\n    public void onDestroy() {\n        mLoaderManager.destroyLoader(LOADER_ID);\n        mCallbacks = null;\n    }\n\n    public void load(String extension, int sortType,int loaderId) {\n        Bundle args = new Bundle();\n        args.putString(ARGS_EXTENSION,extension);\n        args.putInt(ARGS_SORT_TYPE,sortType);\n        if(mContext.get() == null){\n            mLoaderManager.initLoader(loaderId, args, this);\n        }else {\n            mLoaderManager.restartLoader(loaderId,args,this);\n        }\n    }\n\n    public interface EssMimeTypeCallbacks {\n\n        void onFileLoad(List<EssFile> essFileList);\n\n        void onFileReset();\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/loader/EssMimeTypeLoader.java",
    "content": "package com.ess.filepicker.loader;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.net.Uri;\nimport android.provider.MediaStore;\nimport android.support.v4.content.CursorLoader;\nimport android.webkit.MimeTypeMap;\n\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.util.Const;\nimport com.ess.filepicker.util.FileUtils;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * 按照文件类型查找\n */\n\npublic class EssMimeTypeLoader extends CursorLoader {\n\n    private static final Uri QUERY_URI = MediaStore.Files.getContentUri(\"external\");\n\n    private static final String[] PROJECTION = new String[]{\n            MediaStore.Images.Media._ID,\n            MediaStore.Images.Media.DATA,\n            MediaStore.Files.FileColumns.MIME_TYPE,\n            MediaStore.Files.FileColumns.SIZE,\n            MediaStore.Images.Media.DATE_ADDED,\n            MediaStore.Files.FileColumns.TITLE,\n            MediaStore.Files.FileColumns.DATE_MODIFIED};\n\n    private List<EssFile> essFileList;\n\n    public EssMimeTypeLoader(Context context, String selection, String[] selectionArgs, String sortOrder) {\n        //默认按照创建时间降序排列\n        super(context, QUERY_URI, PROJECTION, selection, selectionArgs, sortOrder);\n    }\n\n    public static CursorLoader newInstance(Context context, String extension, int mSortType) {\n        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);\n        String selection = MediaStore.Files.FileColumns.MIME_TYPE + \"='\" + mimeType + \"'\";\n        String[] selectionArgs = null;\n        if (extension == null) {\n            extension = \"\";\n        }\n        if (extension.equalsIgnoreCase(\"doc\") || extension.equalsIgnoreCase(\"docx\")) {\n            selection = MediaStore.Files.FileColumns.MIME_TYPE + \" in(?,?) \";\n            selectionArgs = new String[]{Const.mimeTypeMap.get(\"doc\"), Const.mimeTypeMap.get(\"docx\")};\n        }\n        if (extension.equalsIgnoreCase(\"xls\") || extension.equalsIgnoreCase(\"xlsx\")) {\n            selection = MediaStore.Files.FileColumns.MIME_TYPE + \" in(?,?) \";\n            selectionArgs = new String[]{Const.mimeTypeMap.get(\"xls\"), Const.mimeTypeMap.get(\"xlsx\")};\n        }\n        if (extension.equalsIgnoreCase(\"ppt\") || extension.equalsIgnoreCase(\"pptx\")) {\n            selection = MediaStore.Files.FileColumns.MIME_TYPE + \" in(?,?) \";\n            selectionArgs = new String[]{Const.mimeTypeMap.get(\"ppt\"), Const.mimeTypeMap.get(\"pptx\")};\n        }\n        if (extension.equalsIgnoreCase(\"png\") || extension.equalsIgnoreCase(\"jpg\") || extension.equalsIgnoreCase(\"jpeg\")) {\n            selection = MediaStore.Files.FileColumns.MIME_TYPE + \" in(?,?,?) \";\n            selectionArgs = new String[]{Const.mimeTypeMap.get(\"png\"), Const.mimeTypeMap.get(\"jpg\"), Const.mimeTypeMap.get(\"jpeg\")};\n            //不扫描有.nomedia文件的文件夹下的多媒体文件，带有.nomedia文件的文件夹下的多媒体文件的media_type都被置为了0\n            selection = selection + \" and \" + MediaStore.Files.FileColumns.MEDIA_TYPE + \" != \" + MediaStore.Files.FileColumns.MEDIA_TYPE_NONE;\n        }\n        if (extension.equalsIgnoreCase(\"apk\")) {\n            selection = MediaStore.Files.FileColumns.DATA + \" LIKE '%.apk' \";\n        }\n\n        selection = selection + \" and \" + MediaStore.Files.FileColumns.SIZE + \" >0 \" ;\n\n\n        String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + \" DESC \";\n        if (mSortType == FileUtils.BY_NAME_ASC) {\n            sortOrder = MediaStore.Files.FileColumns.DATA + \" ASC \";\n        } else if (mSortType == FileUtils.BY_NAME_DESC) {\n            sortOrder = MediaStore.Files.FileColumns.DATA + \" DESC \";\n        } else if (mSortType == FileUtils.BY_TIME_ASC) {\n            sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + \" ASC \";\n        } else if (mSortType == FileUtils.BY_TIME_DESC) {\n            sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + \" DESC \";\n        } else if (mSortType == FileUtils.BY_SIZE_ASC) {\n            sortOrder = MediaStore.Files.FileColumns.SIZE + \" ASC \";\n        } else if (mSortType == FileUtils.BY_SIZE_DESC) {\n            sortOrder = MediaStore.Files.FileColumns.SIZE + \" DESC \";\n        }\n        return new EssMimeTypeLoader(context, selection, selectionArgs, sortOrder);\n    }\n\n    public List<EssFile> getEssFileList() {\n        return essFileList;\n    }\n\n    @Override\n    public Cursor loadInBackground() {\n        Cursor data = super.loadInBackground();\n        essFileList = new ArrayList<>();\n        if (data != null) {\n            while (data.moveToNext()){\n                EssFile essFile = new EssFile(data.getString(data.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)));\n                if(essFile.isExits()){\n                    essFileList.add(essFile);\n                }\n            }\n            data.moveToFirst();\n        }\n\n        return data;\n    }\n\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/Album.java",
    "content": "/*\n * Copyright (C) 2014 nohana, Inc.\n * Copyright 2017 Zhihu Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.ess.filepicker.model;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport android.provider.MediaStore;\nimport android.support.annotation.Nullable;\n\nimport com.ess.filepicker.loader.EssAlbumLoader;\n\npublic class Album implements Parcelable {\n    public static final Creator<Album> CREATOR = new Creator<Album>() {\n        @Nullable\n        @Override\n        public Album createFromParcel(Parcel source) {\n            return new Album(source);\n        }\n\n        @Override\n        public Album[] newArray(int size) {\n            return new Album[size];\n        }\n    };\n    public static final String ALBUM_ID_ALL = String.valueOf(-1);\n    public static final String ALBUM_NAME_ALL = \"All\";\n\n    private final String mId;\n    private final String mCoverPath;\n    private final String mDisplayName;\n    private long mCount;\n\n    Album(String id, String coverPath, String albumName, long count) {\n        mId = id;\n        mCoverPath = coverPath;\n        mDisplayName = albumName;\n        mCount = count;\n    }\n\n    Album(Parcel source) {\n        mId = source.readString();\n        mCoverPath = source.readString();\n        mDisplayName = source.readString();\n        mCount = source.readLong();\n    }\n\n    /**\n     * Constructs a new {@link Album} entity from the {@link Cursor}.\n     * This method is not responsible for managing cursor resource, such as close, iterate, and so on.\n     */\n    public static Album valueOf(Cursor cursor) {\n        return new Album(\n                cursor.getString(cursor.getColumnIndex(\"bucket_id\")),\n                cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.DATA)),\n                cursor.getString(cursor.getColumnIndex(\"bucket_display_name\")),\n                cursor.getLong(cursor.getColumnIndex(EssAlbumLoader.COLUMN_COUNT)));\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n        dest.writeString(mId);\n        dest.writeString(mCoverPath);\n        dest.writeString(mDisplayName);\n        dest.writeLong(mCount);\n    }\n\n    public String getId() {\n        return mId;\n    }\n\n    public String getCoverPath() {\n        return mCoverPath;\n    }\n\n    public long getCount() {\n        return mCount;\n    }\n\n    public void addCaptureCount() {\n        mCount++;\n    }\n\n    public String getDisplayName(Context context) {\n        if (isAll()) {\n            return \"全部\";\n        }\n        return mDisplayName;\n    }\n\n    public boolean isAll() {\n        return ALBUM_ID_ALL.equals(mId);\n    }\n\n    public boolean isEmpty() {\n        return mCount == 0;\n    }\n\n}"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/BreadModel.java",
    "content": "package com.ess.filepicker.model;\n\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * BreadModel\n * Created by 李波 on 2018/2/5.\n */\n\npublic class BreadModel {\n\n    /*当前Path*/\n    private String mCurPath;\n\n    /*之前的浏览位置，默认0*/\n    private int mPrePosition = 0;\n\n    /*当前面包屑的名称*/\n    private String mCurName;\n\n    public String getCurName() {\n        return mCurName;\n    }\n\n    public void setCurName(String mCurName) {\n        this.mCurName = mCurName;\n    }\n\n    public int getPrePosition() {\n        return mPrePosition;\n    }\n\n    public void setPrePosition(int mPrePosition) {\n        this.mPrePosition = mPrePosition;\n    }\n\n    public String getCurPath() {\n        return mCurPath;\n    }\n\n    public void setmCurPath(String mCurPath) {\n        this.mCurPath = mCurPath;\n    }\n\n    /**\n     * 获取需要添加的路径列表\n     * @param oldList\n     * @param newList\n     * @return\n     */\n    public static List<BreadModel> getNewBreadModel(List<BreadModel> oldList, List<BreadModel> newList) {\n        List<BreadModel> newModelList = new ArrayList<>();\n        if (oldList == null || newList == null) {\n            return newModelList;\n        }\n        if (oldList.size() >= newList.size()) {\n            return newModelList;\n        }\n        for (int i = 0; i < newList.size(); i++) {\n            if (i < oldList.size()) {\n                continue;\n            }\n            newModelList.add(newList.get(i));\n        }\n        return newModelList;\n    }\n\n    /**\n     * 获取路径List需要裁剪的位置\n     * @param oldList\n     * @param newList\n     * @return\n     */\n    public static int getRemovedBreadModel(List<BreadModel> oldList, List<BreadModel> newList) {\n        int removeFirstPosition = 0;\n        if (oldList == null || newList == null) {\n            return removeFirstPosition;\n        }\n        if (oldList.size() <= newList.size()) {\n            return removeFirstPosition;\n        }\n        for (int i = 0; i < oldList.size(); i++) {\n            if (i == newList.size()) {\n                return i;\n            }\n        }\n        return removeFirstPosition;\n    }\n\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/CaptureStrategy.java",
    "content": "/*\n * Copyright 2017 Zhihu Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.ess.filepicker.model;\n\npublic class CaptureStrategy {\n\n    public final boolean isPublic;\n    public final String authority;\n\n    public CaptureStrategy(boolean isPublic, String authority) {\n        this.isPublic = isPublic;\n        this.authority = authority;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/EssFile.java",
    "content": "package com.ess.filepicker.model;\n\nimport android.content.ContentUris;\nimport android.content.Context;\nimport android.net.Uri;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport android.provider.MediaStore;\n\nimport com.ess.filepicker.util.FileUtils;\nimport com.ess.filepicker.util.MimeType;\nimport com.ess.filepicker.util.PathUtils;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * EssFile\n * Created by 李波 on 2018/2/5.\n */\n\npublic class EssFile implements Parcelable {\n\n    public static final int CAPTURE = 0;\n    public static final int MEDIA = 1;\n\n    private String mFilePath;\n    private String mimeType;\n    private String childFolderCount = \"加载中\";\n    private String childFileCount = \"加载中\";\n    private boolean isChecked = false;\n    private boolean isExits = false;\n    private boolean isDirectory = false;\n    private boolean isFile = false;\n    private String mFileName;\n    private Uri uri;\n\n    private int itemType = MEDIA;\n\n    protected EssFile(Parcel in) {\n        mFilePath = in.readString();\n        mimeType = in.readString();\n        childFolderCount = in.readString();\n        childFileCount = in.readString();\n        isChecked = in.readByte() != 0;\n        isExits = in.readByte() != 0;\n        isDirectory = in.readByte() != 0;\n        isFile = in.readByte() != 0;\n        mFileName = in.readString();\n        uri = in.readParcelable(Uri.class.getClassLoader());\n        itemType = in.readInt();\n    }\n\n    public static final Creator<EssFile> CREATOR = new Creator<EssFile>() {\n        @Override\n        public EssFile createFromParcel(Parcel in) {\n            return new EssFile(in);\n        }\n\n        @Override\n        public EssFile[] newArray(int size) {\n            return new EssFile[size];\n        }\n    };\n\n    public boolean isChecked() {\n        return isChecked;\n    }\n\n    public void setChecked(boolean checked) {\n        isChecked = checked;\n    }\n\n    public EssFile(String path) {\n        mFilePath = path;\n        File file = new File(mFilePath);\n        if (file.exists()) {\n            isExits = true;\n            isDirectory = file.isDirectory();\n            isFile = file.isFile();\n            mFileName = file.getName();\n        }\n        mimeType = FileUtils.getMimeType(mFilePath);\n    }\n\n    public EssFile(File file) {\n        mFilePath = file.getAbsolutePath();\n        if (file.exists()) {\n            isExits = true;\n            isDirectory = file.isDirectory();\n            isFile = file.isFile();\n        }\n        mimeType = FileUtils.getMimeType(file.getAbsolutePath());\n    }\n\n    public EssFile(long id, String mimeType) {\n        this.mimeType = mimeType;\n        Uri contentUri;\n        if (isImage()) {\n            contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;\n        } else if (isVideo()) {\n            contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;\n        } else {\n            // ?\n            contentUri = MediaStore.Files.getContentUri(\"external\");\n        }\n        this.uri = ContentUris.withAppendedId(contentUri, id);\n    }\n\n    public Uri getUri() {\n        return uri;\n    }\n\n    public boolean isExits() {\n        return isExits;\n    }\n\n    public String getMimeType() {\n        return mimeType;\n    }\n\n    public void setMimeType(String mimeType) {\n        this.mimeType = mimeType;\n    }\n\n    public String getChildFolderCount() {\n        return childFolderCount;\n    }\n\n    public void setChildFolderCount(String childFolderCount) {\n        this.childFolderCount = childFolderCount;\n    }\n\n    public String getChildFileCount() {\n        return childFileCount;\n    }\n\n    public void setChildFileCount(String childFileCount) {\n        this.childFileCount = childFileCount;\n    }\n\n    public void setChildCounts(String childFileCount, String childFolderCount) {\n        this.childFileCount = childFileCount;\n        this.childFolderCount = childFolderCount;\n    }\n\n\n    public File getFile() {\n        return new File(mFilePath);\n    }\n\n    public String getName() {\n        return new File(mFilePath).getName();\n    }\n\n    public boolean isDirectory() {\n        return isDirectory;\n    }\n\n    public boolean isFile() {\n        return isFile;\n    }\n\n    public String getAbsolutePath() {\n        return mFilePath;\n    }\n\n    public static List<EssFile> getEssFileList(List<File> files) {\n        List<EssFile> essFileList = new ArrayList<>();\n        for (File file :\n                files) {\n            essFileList.add(new EssFile(file));\n        }\n        return essFileList;\n    }\n\n    public static ArrayList<EssFile> getEssFileList(Context context, Set<EssFile> essFileSet) {\n        ArrayList<EssFile> essFileArrayList = new ArrayList<>();\n        for (EssFile ess_file :\n                essFileSet) {\n            ess_file.mFilePath = PathUtils.getPath(context, ess_file.uri);\n            essFileArrayList.add(ess_file);\n        }\n        return essFileArrayList;\n    }\n\n    public static ArrayList<String> getFilePathList(ArrayList<EssFile> essFileArrayList){\n        ArrayList<String> resultList = new ArrayList<>();\n        for (EssFile essFile:essFileArrayList) {\n            resultList.add(essFile.getAbsolutePath());\n        }\n        return resultList;\n    }\n\n\n    @Override\n    public String toString() {\n        return \"EssFile{\" +\n                \"mFilePath='\" + mFilePath + '\\'' +\n                \", mimeType='\" + mimeType + '\\'' +\n                \", mFileName='\" + mFileName + '\\'' +\n                '}';\n    }\n\n    public boolean isImage() {\n        if (mimeType == null) return false;\n        return mimeType.equals(MimeType.JPEG.toString())\n                || mimeType.equals(MimeType.PNG.toString())\n                || mimeType.equals(MimeType.GIF.toString())\n                || mimeType.equals(MimeType.BMP.toString())\n                || mimeType.equals(MimeType.WEBP.toString());\n    }\n\n    public boolean isGif() {\n        if (mimeType == null) return false;\n        return mimeType.equals(MimeType.GIF.toString());\n    }\n\n    public boolean isVideo() {\n        if (mimeType == null) return false;\n        return mimeType.equals(MimeType.MPEG.toString())\n                || mimeType.equals(MimeType.MP4.toString())\n                || mimeType.equals(MimeType.QUICKTIME.toString())\n                || mimeType.equals(MimeType.THREEGPP.toString())\n                || mimeType.equals(MimeType.THREEGPP2.toString())\n                || mimeType.equals(MimeType.MKV.toString())\n                || mimeType.equals(MimeType.WEBM.toString())\n                || mimeType.equals(MimeType.TS.toString())\n                || mimeType.equals(MimeType.AVI.toString());\n    }\n\n    public void setItemType(int itemType) {\n        this.itemType = itemType;\n    }\n\n    public int getItemType() {\n        return itemType;\n    }\n\n    @Override\n    public int describeContents() {\n        return 0;\n    }\n\n    @Override\n    public void writeToParcel(Parcel dest, int flags) {\n        dest.writeString(mFilePath);\n        dest.writeString(mimeType);\n        dest.writeString(childFolderCount);\n        dest.writeString(childFileCount);\n        dest.writeByte((byte) (isChecked ? 1 : 0));\n        dest.writeByte((byte) (isExits ? 1 : 0));\n        dest.writeByte((byte) (isDirectory ? 1 : 0));\n        dest.writeByte((byte) (isFile ? 1 : 0));\n        dest.writeString(mFileName);\n        dest.writeParcelable(uri, flags);\n        dest.writeInt(itemType);\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (!(obj instanceof EssFile)) {\n            return false;\n        }\n\n        EssFile other = (EssFile) obj;\n        if (uri == null) {\n            return mFilePath.equalsIgnoreCase(other.getAbsolutePath());\n        } else {\n            return uri.equals(other.getUri());\n        }\n    }\n\n    @Override\n    public int hashCode() {\n        int result = mFilePath != null ? mFilePath.hashCode() : 0;\n        result = 31 * result + (uri != null ? uri.hashCode() : 0);\n        result = 31 * result + itemType;\n        return result;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/EssFileCountCallBack.java",
    "content": "package com.ess.filepicker.model;\n\n/**\n * EssFileCountCallBack\n * Created by 李波 on 2018/3/5.\n */\n\npublic interface EssFileCountCallBack {\n    void onFindChildFileAndFolderCount(int position, String childFileCount, String childFolderCount);\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/EssFileFilter.java",
    "content": "package com.ess.filepicker.model;\n\nimport java.io.File;\nimport java.io.FileFilter;\n\n/**\n * EssFileFilter\n * 不显示隐藏文件、文件夹\n */\npublic class EssFileFilter implements FileFilter {\n    private String[] mTypes;\n\n    public EssFileFilter(String[] types) {\n        this.mTypes = types;\n    }\n\n    @Override\n    public boolean accept(File file) {\n        if (file.isDirectory() && !file.isHidden()) {\n            return true;\n        }\n        if (mTypes != null && mTypes.length > 0) {\n            for (String mType : mTypes) {\n                if ((file.getName().endsWith(mType.toLowerCase()) || file.getName().endsWith(mType.toUpperCase())) && !file.isHidden()) {\n//                if (FileUtils.getMimeType(file.getAbsolutePath()).equalsIgnoreCase(MimeTypeMap.getSingleton().getMimeTypeFromExtension(mType))) {\n                    return true;\n                }\n            }\n        }else {\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/EssFileListCallBack.java",
    "content": "package com.ess.filepicker.model;\n\nimport java.util.List;\n\n/**\n * EssFileListCallBack\n * Created by 李波 on 2018/3/5.\n */\n\npublic interface EssFileListCallBack {\n    void onFindFileList(String queryPath, List<EssFile> essFileList);\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/EssFileProvider.java",
    "content": "package com.ess.filepicker.model;\n\nimport android.support.v4.content.FileProvider;\n\n/**\n * EssFileProvider\n * Created by 李波 on 2018/2/23.\n */\n\npublic class EssFileProvider extends FileProvider {\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/FileScanActEvent.java",
    "content": "package com.ess.filepicker.model;\n\n/**\n * FileScanActEvent\n * Created by 李波 on 2018/2/23.\n */\n\npublic class FileScanActEvent {\n    private int canSelectMaxCount;\n\n    public FileScanActEvent(int canSelectMaxCount) {\n        this.canSelectMaxCount = canSelectMaxCount;\n    }\n\n    public int getCanSelectMaxCount() {\n        return canSelectMaxCount;\n    }\n\n    public void setCanSelectMaxCount(int canSelectMaxCount) {\n        this.canSelectMaxCount = canSelectMaxCount;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/FileScanFragEvent.java",
    "content": "package com.ess.filepicker.model;\n\n\n/**\n * FileScanFragEvent\n * Created by 李波 on 2018/2/23.\n */\n\npublic class FileScanFragEvent {\n\n    private EssFile selectedFile;\n    private boolean isAdd;\n\n    public FileScanFragEvent(EssFile selectedFile, boolean isAdd) {\n        this.selectedFile = selectedFile;\n        this.isAdd = isAdd;\n    }\n\n    public EssFile getSelectedFile() {\n        return selectedFile;\n    }\n\n    public void setSelectedFile(EssFile selectedFile) {\n        this.selectedFile = selectedFile;\n    }\n\n    public boolean isAdd() {\n        return isAdd;\n    }\n\n    public void setAdd(boolean add) {\n        isAdd = add;\n    }\n\n    public EssFile getSelectedFileList() {\n        return selectedFile;\n    }\n\n    public void setSelectedFileList(EssFile selectedFileList) {\n        this.selectedFile = selectedFileList;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/model/FileScanSortChangedEvent.java",
    "content": "package com.ess.filepicker.model;\n\n/**\n * FileScanSortChangedEvent\n * Created by 李波 on 2018/2/26.\n */\n\npublic class FileScanSortChangedEvent {\n    private int sortType;\n    private int currentItem;\n\n    public FileScanSortChangedEvent(int sortType, int currentItem) {\n        this.sortType = sortType;\n        this.currentItem = currentItem;\n    }\n\n    public int getCurrentItem() {\n        return currentItem;\n    }\n\n    public void setCurrentItem(int currentItem) {\n        this.currentItem = currentItem;\n    }\n\n    public FileScanSortChangedEvent(int sortType) {\n        this.sortType = sortType;\n    }\n\n    public int getSortType() {\n        return sortType;\n    }\n\n    public void setSortType(int sortType) {\n        this.sortType = sortType;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/task/EssFileCountTask.java",
    "content": "package com.ess.filepicker.task;\n\nimport android.os.AsyncTask;\n\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.model.EssFileCountCallBack;\nimport com.ess.filepicker.model.EssFileFilter;\n\nimport java.io.File;\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * EssFileCountTask\n * Created by 李波 on 2018/3/5.\n */\n\npublic class EssFileCountTask extends AsyncTask<Void,Void,Void>{\n\n    private int position;\n    private String queryPath;\n    private String[] types;\n    private EssFileCountCallBack countCallBack;\n    private int childFileCount = 0;\n    private int childFolderCount = 0;\n\n    public EssFileCountTask(int position, String queryPath, String[] types, EssFileCountCallBack countCallBack) {\n        this.position = position;\n        this.queryPath = queryPath;\n        this.types = types;\n        this.countCallBack = countCallBack;\n    }\n\n    @Override\n    protected Void doInBackground(Void... voids) {\n        File file = new File(queryPath);\n        File[] files = file.listFiles(new EssFileFilter(types));\n        if(files == null){\n            return null;\n        }\n        List<EssFile> fileList = EssFile.getEssFileList(Arrays.asList(files));\n        for (EssFile essFile :\n                fileList) {\n            if(essFile.isDirectory()){\n                childFolderCount++;\n            }else {\n                childFileCount++;\n            }\n        }\n        return null;\n    }\n\n    @Override\n    protected void onPostExecute(Void aVoid) {\n        if(countCallBack!=null){\n            countCallBack.onFindChildFileAndFolderCount(position,String.valueOf(childFileCount),String.valueOf(childFolderCount));\n        }\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/task/EssFileListTask.java",
    "content": "package com.ess.filepicker.task;\n\nimport android.os.AsyncTask;\n\nimport com.ess.filepicker.model.EssFile;\nimport com.ess.filepicker.model.EssFileFilter;\nimport com.ess.filepicker.model.EssFileListCallBack;\nimport com.ess.filepicker.util.FileUtils;\n\nimport java.io.File;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * EssFileListTask\n * Created by 李波 on 2018/3/5.\n */\n\npublic class EssFileListTask extends AsyncTask<Void,Void,List<EssFile>> {\n\n    private List<EssFile> mSelectedFileList;\n    private String queryPath;\n    private String[] types;\n    private int mSortType;\n    private EssFileListCallBack callBack;\n\n    public EssFileListTask(List<EssFile> mSelectedFileList, String queryPath, String[] types, int mSortType, EssFileListCallBack fileCallBack) {\n        this.mSelectedFileList = mSelectedFileList;\n        this.queryPath = queryPath;\n        this.types = types;\n        this.mSortType = mSortType;\n        this.callBack = fileCallBack;\n    }\n\n    @Override\n    protected List<EssFile> doInBackground(Void... voids) {\n        File file = new File(queryPath);\n        File[] files = file.listFiles(new EssFileFilter(types));\n        if(files == null){\n            return new ArrayList<>();\n        }\n        List<File> fileList = Arrays.asList(files);\n        if(mSortType == FileUtils.BY_NAME_ASC){\n            Collections.sort(fileList, new FileUtils.SortByName());\n        }else if(mSortType == FileUtils.BY_NAME_DESC){\n            Collections.sort(fileList, new FileUtils.SortByName());\n            Collections.reverse(fileList);\n        }else if(mSortType == FileUtils.BY_TIME_ASC){\n            Collections.sort(fileList,new FileUtils.SortByTime());\n        }else if(mSortType == FileUtils.BY_TIME_DESC){\n            Collections.sort(fileList,new FileUtils.SortByTime());\n            Collections.reverse(fileList);\n        }else if(mSortType == FileUtils.BY_SIZE_ASC){\n            Collections.sort(fileList,new FileUtils.SortBySize());\n        }else if(mSortType == FileUtils.BY_SIZE_DESC){\n            Collections.sort(fileList,new FileUtils.SortBySize());\n            Collections.reverse(fileList);\n        }else if(mSortType == FileUtils.BY_EXTENSION_ASC){\n            Collections.sort(fileList,new FileUtils.SortByExtension());\n        }else if(mSortType == FileUtils.BY_EXTENSION_DESC){\n            Collections.sort(fileList,new FileUtils.SortByExtension());\n            Collections.reverse(fileList);\n        }\n        List<EssFile> tempFileList = EssFile.getEssFileList(fileList);\n        for (EssFile selectedFile :\n                mSelectedFileList) {\n            for (int i = 0; i < tempFileList.size(); i++) {\n                if (selectedFile.getAbsolutePath().equals(tempFileList.get(i).getAbsolutePath())) {\n                    tempFileList.get(i).setChecked(true);\n                    break;\n                }\n            }\n        }\n        return tempFileList;\n    }\n\n    @Override\n    protected void onPreExecute() {\n        super.onPreExecute();\n    }\n\n    @Override\n    protected void onPostExecute(List<EssFile> essFileList) {\n        if(callBack!=null){\n            callBack.onFindFileList(queryPath,essFileList);\n        }\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/Const.java",
    "content": "package com.ess.filepicker.util;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Const\n * Created by 李波 on 2018/2/22.\n */\n\npublic class Const {\n\n    public static Map<String,String> mimeTypeMap = null;\n\n    static {\n        mimeTypeMap = new HashMap<>();\n        mimeTypeMap.put(\"apk\",\"application/vnd.android.package-archive\");\n        mimeTypeMap.put(\"asf\", \"video/x-ms-asf\");\n        mimeTypeMap.put(\"avi\", \"video/x-msvideo\");\n        mimeTypeMap.put(\"bin\", \"application/octet-stream\");\n        mimeTypeMap.put(\"bmp\", \"image/bmp\");\n        mimeTypeMap.put(\"c\", \"text/plain\");\n        mimeTypeMap.put(\"class\", \"application/octet-stream\");\n        mimeTypeMap.put(\"conf\", \"text/plain\");\n        mimeTypeMap.put(\"cpp\", \"text/plain\");\n        mimeTypeMap.put(\"doc\", \"application/msword\");\n        mimeTypeMap.put(\"docx\", \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\");\n        mimeTypeMap.put(\"xls\", \"application/vnd.ms-excel\");\n        mimeTypeMap.put(\"xlsx\", \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\");\n        mimeTypeMap.put(\"exe\", \"application/octet-stream\");\n        mimeTypeMap.put(\"gif\", \"image/gif\");\n        mimeTypeMap.put(\"gtar\", \"application/x-gtar\");\n        mimeTypeMap.put(\"gz\", \"application/x-gzip\");\n        mimeTypeMap.put(\"h\", \"text/plain\");\n        mimeTypeMap.put(\"htm\", \"text/html\");\n        mimeTypeMap.put(\"html\", \"text/html\");\n        mimeTypeMap.put(\"jar\", \"application/java-archive\");\n        mimeTypeMap.put(\"java\", \"text/plain\");\n        mimeTypeMap.put(\"jpeg\", \"image/jpeg\");\n        mimeTypeMap.put(\"jpg\", \"image/jpeg\");\n        mimeTypeMap.put(\"js\", \"application/x-javascript\");\n        mimeTypeMap.put(\"log\", \"text/plain\");\n        mimeTypeMap.put(\"m3u\", \"audio/x-mpegurl\");\n        mimeTypeMap.put(\"m4a\", \"audio/mp4a-latm\");\n        mimeTypeMap.put(\"m4b\", \"audio/mp4a-latm\");\n        mimeTypeMap.put(\"m4p\", \"audio/mp4a-latm\");\n        mimeTypeMap.put(\"m4u\", \"video/vnd.mpegurl\");\n        mimeTypeMap.put(\"m4v\", \"video/x-m4v\");\n        mimeTypeMap.put(\"mov\", \"video/quicktime\");\n        mimeTypeMap.put(\"mp2\", \"audio/x-mpeg\");\n        mimeTypeMap.put(\"mp3\", \"audio/mpeg\");\n        mimeTypeMap.put(\"mp4\", \"video/mp4\");\n        mimeTypeMap.put(\"mpc\", \"application/vnd.mpohun.certificate\");\n        mimeTypeMap.put(\"mpe\", \"video/mpeg\");\n        mimeTypeMap.put(\"mpeg\", \"video/mpeg\");\n        mimeTypeMap.put(\"mpg\", \"video/mpeg\");\n        mimeTypeMap.put(\"mpg4\", \"video/mp4\");\n        mimeTypeMap.put(\"mpga\", \"audio/mpeg\");\n        mimeTypeMap.put(\"msg\", \"application/vnd.ms-outlook\");\n        mimeTypeMap.put(\"ogg\", \"audio/ogg\");\n        mimeTypeMap.put(\"pdf\", \"application/pdf\");\n        mimeTypeMap.put(\"png\", \"image/png\");\n        mimeTypeMap.put(\"pps\", \"application/vnd.ms-powerpoint\");\n        mimeTypeMap.put(\"ppt\", \"application/vnd.ms-powerpoint\");\n        mimeTypeMap.put(\"pptx\", \"application/vnd.openxmlformats-officedocument.presentationml.presentation\");\n        mimeTypeMap.put(\"prop\", \"text/plain\");\n        mimeTypeMap.put(\"rc\", \"text/plain\");\n        mimeTypeMap.put(\"rmvb\", \"audio/x-pn-realaudio\");\n        mimeTypeMap.put(\"rtf\", \"application/rtf\");\n        mimeTypeMap.put(\"sh\", \"text/plain\");\n        mimeTypeMap.put(\"tar\", \"application/x-tar\");\n        mimeTypeMap.put(\"tgz\", \"application/x-compressed\");\n        mimeTypeMap.put(\"txt\", \"text/plain\");\n        mimeTypeMap.put(\"wav\", \"audio/x-wav\");\n        mimeTypeMap.put(\"wma\", \"audio/x-ms-wma\");\n        mimeTypeMap.put(\"wmv\", \"audio/x-ms-wmv\");\n        mimeTypeMap.put(\"wps\", \"application/vnd.ms-works\");\n        mimeTypeMap.put(\"xml\", \"text/plain\");\n        mimeTypeMap.put(\"z\", \"application/x-compress\");\n        mimeTypeMap.put(\"zip\", \"application/x-zip-compressed\");\n        mimeTypeMap.put(\"\", \"*/*\");\n    }\n\n    /*文件类型*/\n    public static final String EXTRA_KEY_FILE_TYPE = \"EXTRA_KEY_FILE_TYPE\";\n    /*排序类型*/\n    public static final String EXTRA_KEY_SORT_TYPE = \"EXTRA_KEY_SORT_TYPE\";\n    /*是否多选*/\n    public static final String EXTRA_KEY_IS_SINGLE = \"EXTRA_KEY_IS_SINGLE\";\n    /*最大可选择数量*/\n    public static final String EXTRA_KEY_MAX_COUNT = \"EXTRA_KEY_MAX_COUNT\";\n    public static final String EXTRA_KEY_OnSelectFileListener = \"EXTRA_KEY_OnSelectFileListener\";\n\n    public static final String EXTRA_RESULT_SELECTION = \"extra_result_selection\";\n\n\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/ConvertUtils.java",
    "content": "package com.ess.filepicker.util;\n\nimport android.annotation.TargetApi;\nimport android.content.ContentUris;\nimport android.content.Context;\nimport android.content.res.ColorStateList;\nimport android.content.res.Resources;\nimport android.database.Cursor;\nimport android.graphics.Bitmap;\nimport android.graphics.BitmapFactory;\nimport android.graphics.Canvas;\nimport android.graphics.Color;\nimport android.graphics.drawable.BitmapDrawable;\nimport android.graphics.drawable.ColorDrawable;\nimport android.graphics.drawable.Drawable;\nimport android.graphics.drawable.NinePatchDrawable;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.Environment;\nimport android.provider.DocumentsContract;\nimport android.provider.MediaStore;\nimport android.support.annotation.ColorInt;\nimport android.support.annotation.FloatRange;\nimport android.text.TextUtils;\nimport android.view.View;\nimport android.widget.ListView;\nimport android.widget.ScrollView;\n\nimport java.io.BufferedReader;\nimport java.io.ByteArrayOutputStream;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.UnsupportedEncodingException;\nimport java.nio.ByteBuffer;\nimport java.text.DecimalFormat;\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.Locale;\n\n/**\n * 数据类型转换、单位转换\n *\n * @author 李玉江[QQ:1023694760]\n * @since 2014-4-18\n */\npublic class ConvertUtils {\n    public static final long GB = 1073741824;\n    public static final long MB = 1048576;\n    public static final long KB = 1024;\n\n    public static int toInt(Object obj) {\n        try {\n            return Integer.parseInt(obj.toString());\n        } catch (NumberFormatException e) {\n            return -1;\n        }\n    }\n\n    public static int toInt(byte[] bytes) {\n        int result = 0;\n        byte abyte;\n        for (int i = 0; i < bytes.length; i++) {\n            abyte = bytes[i];\n            result += (abyte & 0xFF) << (8 * i);\n        }\n        return result;\n    }\n\n    public static int toShort(byte first, byte second) {\n        return (first << 8) + (second & 0xFF);\n    }\n\n    public static long toLong(Object obj) {\n        try {\n            return Long.parseLong(obj.toString());\n        } catch (NumberFormatException e) {\n            return -1L;\n        }\n    }\n\n    public static float toFloat(Object obj) {\n        try {\n            return Float.parseFloat(obj.toString());\n        } catch (NumberFormatException e) {\n            return -1f;\n        }\n    }\n\n    /**\n     * int占4字节\n     *\n     * @param i the\n     * @return byte [ ]\n     */\n    public static byte[] toByteArray(int i) {\n        // byte[] bytes = new byte[4];\n        // bytes[0] = (byte) (0xff & i);\n        // bytes[1] = (byte) ((0xff00 & i) >> 8);\n        // bytes[2] = (byte) ((0xff0000 & i) >> 16);\n        // bytes[3] = (byte) ((0xff000000 & i) >> 24);\n        // return bytes;\n        return ByteBuffer.allocate(4).putInt(i).array();\n    }\n\n    public static byte[] toByteArray(String hexData, boolean isHex) {\n        if (hexData == null || hexData.equals(\"\")) {\n            return null;\n        }\n        if (!isHex) {\n            return hexData.getBytes();\n        }\n        hexData = hexData.replaceAll(\"\\\\s+\", \"\");\n        String hexDigits = \"0123456789ABCDEF\";\n        ByteArrayOutputStream baos = new ByteArrayOutputStream(\n                hexData.length() / 2);\n        // 将每2位16进制整数组装成一个字节\n        for (int i = 0; i < hexData.length(); i += 2) {\n            baos.write((hexDigits.indexOf(hexData.charAt(i)) << 4 | hexDigits\n                    .indexOf(hexData.charAt(i + 1))));\n        }\n        byte[] bytes = baos.toByteArray();\n        try {\n            baos.close();\n        } catch (IOException e) {\n            LogUtils.warn(e);\n        }\n        return bytes;\n    }\n\n    public static String toHexString(String str) {\n        if (TextUtils.isEmpty(str))\n            return \"\";\n        StringBuilder builder = new StringBuilder();\n        byte[] bytes = str.getBytes();\n        for (byte aByte : bytes) {\n            builder.append(Integer.toHexString(0xFF & aByte));\n            builder.append(\" \");\n        }\n        return builder.toString();\n    }\n\n    /**\n     * To hex string string.\n     *\n     * @param bytes the bytes\n     * @return the string\n     */\n    public static String toHexString(byte... bytes) {\n        char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6',\n                '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};\n        // 参见：http://www.oschina.net/code/snippet_116768_9019\n        char[] buffer = new char[bytes.length * 2];\n        for (int i = 0, j = 0; i < bytes.length; ++i) {\n            int u = bytes[i] < 0 ? bytes[i] + 256 : bytes[i];//转无符号整型\n            buffer[j++] = DIGITS[u >>> 4];\n            buffer[j++] = DIGITS[u & 0xf];\n        }\n        return new String(buffer);\n    }\n\n    /**\n     * To hex string string.\n     *\n     * @param num the num\n     * @return the string\n     */\n    public static String toHexString(int num) {\n        String hexString = Integer.toHexString(num);\n        LogUtils.verbose(String.format(Locale.CHINA, \"%d to hex string is %s\", num, hexString));\n        return hexString;\n    }\n\n    /**\n     * To binary string string.\n     *\n     * @param bytes the bytes\n     * @return the string\n     */\n    public static String toBinaryString(byte... bytes) {\n        char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6',\n                '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};\n        // 参见：http://www.oschina.net/code/snippet_116768_9019\n        char[] buffer = new char[bytes.length * 8];\n        for (int i = 0, j = 0; i < bytes.length; ++i) {\n            int u = bytes[i] < 0 ? bytes[i] + 256 : bytes[i];//转无符号整型\n            buffer[j++] = DIGITS[(u >>> 7) & 0x1];\n            buffer[j++] = DIGITS[(u >>> 6) & 0x1];\n            buffer[j++] = DIGITS[(u >>> 5) & 0x1];\n            buffer[j++] = DIGITS[(u >>> 4) & 0x1];\n            buffer[j++] = DIGITS[(u >>> 3) & 0x1];\n            buffer[j++] = DIGITS[(u >>> 2) & 0x1];\n            buffer[j++] = DIGITS[(u >>> 1) & 0x1];\n            buffer[j++] = DIGITS[u & 0x1];\n        }\n        return new String(buffer);\n    }\n\n    /**\n     * To binary string string.\n     *\n     * @param num the num\n     * @return the string\n     */\n    public static String toBinaryString(int num) {\n        String binaryString = Integer.toBinaryString(num);\n        LogUtils.verbose(String.format(Locale.CHINA, \"%d to binary string is %s\", num, binaryString));\n        return binaryString;\n    }\n\n    public static String toSlashString(String str) {\n        String result = \"\";\n        char[] chars = str.toCharArray();\n        for (char chr : chars) {\n            if (chr == '\"' || chr == '\\'' || chr == '\\\\') {\n                result += \"\\\\\";//符合“\"”“'”“\\”这三个符号的前面加一个“\\”\n            }\n            result += chr;\n        }\n        return result;\n    }\n\n    public static <T> T[] toArray(List<T> list) {\n        //noinspection unchecked\n        return (T[]) list.toArray();\n    }\n\n    public static <T> List<T> toList(T[] array) {\n        return Arrays.asList(array);\n    }\n\n    public static String toString(Object[] objects) {\n        return Arrays.deepToString(objects);\n    }\n\n    public static String toString(Object[] objects, String tag) {\n        StringBuilder sb = new StringBuilder();\n        for (Object object : objects) {\n            sb.append(object);\n            sb.append(tag);\n        }\n        return sb.toString();\n    }\n\n    public static byte[] toByteArray(InputStream is) {\n        if (is == null) {\n            return null;\n        }\n        try {\n            ByteArrayOutputStream os = new ByteArrayOutputStream();\n            byte[] buff = new byte[100];\n            while (true) {\n                int len = is.read(buff, 0, 100);\n                if (len == -1) {\n                    break;\n                } else {\n                    os.write(buff, 0, len);\n                }\n            }\n            byte[] bytes = os.toByteArray();\n            os.close();\n            is.close();\n            return bytes;\n        } catch (IOException e) {\n            LogUtils.warn(e);\n        }\n        return null;\n    }\n\n    public static byte[] toByteArray(Bitmap bitmap) {\n        if (bitmap == null) {\n            return null;\n        }\n        ByteArrayOutputStream os = new ByteArrayOutputStream();\n        // 将Bitmap压缩成PNG编码，质量为100%存储，除了PNG还有很多常见格式，如jpeg等。\n        bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);\n        byte[] bytes = os.toByteArray();\n        try {\n            os.close();\n        } catch (IOException e) {\n            LogUtils.warn(e);\n        }\n        return bytes;\n    }\n\n    public static Bitmap toBitmap(byte[] bytes, int width, int height) {\n        Bitmap bitmap = null;\n        if (bytes.length != 0) {\n            try {\n                BitmapFactory.Options options = new BitmapFactory.Options();\n                // 不进行图片抖动处理\n                options.inDither = false;\n                // 设置让解码器以最佳方式解码\n                options.inPreferredConfig = null;\n                if (width > 0 && height > 0) {\n                    options.outWidth = width;\n                    options.outHeight = height;\n                }\n                bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);\n                bitmap.setDensity(96);// 96 dpi\n            } catch (Exception e) {\n                LogUtils.error(e);\n            }\n        }\n        return bitmap;\n    }\n\n    public static Bitmap toBitmap(byte[] bytes) {\n        return toBitmap(bytes, -1, -1);\n    }\n\n    /**\n     * 将Drawable转换为Bitmap\n     * 参考：http://kylines.iteye.com/blog/1660184\n     */\n    public static Bitmap toBitmap(Drawable drawable) {\n        if (drawable instanceof BitmapDrawable) {\n            return ((BitmapDrawable) drawable).getBitmap();\n        } else if (drawable instanceof ColorDrawable) {\n            //color\n            Bitmap bitmap = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888);\n            Canvas canvas = new Canvas(bitmap);\n            canvas.drawColor(((ColorDrawable) drawable).getColor());\n            return bitmap;\n        } else if (drawable instanceof NinePatchDrawable) {\n            //.9.png\n            Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),\n                    drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);\n            Canvas canvas = new Canvas(bitmap);\n            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());\n            drawable.draw(canvas);\n            return bitmap;\n        }\n        return null;\n    }\n\n    /**\n     * 从第三方文件选择器获取路径。\n     * 参见：http://blog.csdn.net/zbjdsbj/article/details/42387551\n     */\n    @TargetApi(Build.VERSION_CODES.KITKAT)\n    public static String toPath(Context context, Uri uri) {\n        if (uri == null) {\n            LogUtils.verbose(\"uri is null\");\n            return \"\";\n        }\n        LogUtils.verbose(\"uri: \" + uri.toString());\n        String path = uri.getPath();\n        String scheme = uri.getScheme();\n        String authority = uri.getAuthority();\n        //是否是4.4及以上版本\n        boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;\n        // DocumentProvider\n        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {\n            String docId = DocumentsContract.getDocumentId(uri);\n            String[] split = docId.split(\":\");\n            String type = split[0];\n            Uri contentUri = null;\n            switch (authority) {\n                // ExternalStorageProvider\n                case \"com.android.externalstorage.documents\":\n                    if (\"primary\".equalsIgnoreCase(type)) {\n                        return Environment.getExternalStorageDirectory() + \"/\" + split[1];\n                    }\n                    break;\n                // DownloadsProvider\n                case \"com.android.providers.downloads.documents\":\n                    contentUri = ContentUris.withAppendedId(\n                            Uri.parse(\"content://downloads/public_downloads\"), Long.valueOf(docId));\n                    return _queryPathFromMediaStore(context, contentUri, null, null);\n                // MediaProvider\n                case \"com.android.providers.media.documents\":\n                    if (\"image\".equals(type)) {\n                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;\n                    } else if (\"video\".equals(type)) {\n                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;\n                    } else if (\"audio\".equals(type)) {\n                        contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;\n                    }\n                    String selection = \"_id=?\";\n                    String[] selectionArgs = new String[]{split[1]};\n                    return _queryPathFromMediaStore(context, contentUri, selection, selectionArgs);\n            }\n        }\n        // MediaStore (and general)\n        else {\n            if (\"content\".equalsIgnoreCase(scheme)) {\n                // Return the remote address\n                if (authority.equals(\"com.google.android.apps.photos.content\")) {\n                    return uri.getLastPathSegment();\n                }\n                return _queryPathFromMediaStore(context, uri, null, null);\n            }\n            // File\n            else if (\"file\".equalsIgnoreCase(scheme)) {\n                return uri.getPath();\n            }\n        }\n        LogUtils.verbose(\"uri to path: \" + path);\n        return path;\n    }\n\n    private static String _queryPathFromMediaStore(Context context, Uri uri, String selection, String[] selectionArgs) {\n        String filePath = null;\n        try {\n            String[] projection = {MediaStore.Images.Media.DATA};\n            Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);\n            if (cursor != null) {\n                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);\n                cursor.moveToFirst();\n                filePath = cursor.getString(column_index);\n                cursor.close();\n            }\n        } catch (IllegalArgumentException e) {\n            LogUtils.error(e);\n        }\n        return filePath;\n    }\n\n    /**\n     * 把view转化为bitmap（截图）\n     * 参见：http://www.cnblogs.com/lee0oo0/p/3355468.html\n     */\n    public static Bitmap toBitmap(View view) {\n        int width = view.getWidth();\n        int height = view.getHeight();\n        if (view instanceof ListView) {\n            height = 0;\n            // 获取listView实际高度\n            ListView listView = (ListView) view;\n            for (int i = 0; i < listView.getChildCount(); i++) {\n                height += listView.getChildAt(i).getHeight();\n            }\n        } else if (view instanceof ScrollView) {\n            height = 0;\n            // 获取scrollView实际高度\n            ScrollView scrollView = (ScrollView) view;\n            for (int i = 0; i < scrollView.getChildCount(); i++) {\n                height += scrollView.getChildAt(i).getHeight();\n            }\n        }\n        view.setDrawingCacheEnabled(true);\n        view.clearFocus();\n        view.setPressed(false);\n        boolean willNotCache = view.willNotCacheDrawing();\n        view.setWillNotCacheDrawing(false);\n        // Reset the drawing cache background color to fully transparent for the duration of this operation\n        int color = view.getDrawingCacheBackgroundColor();\n        view.setDrawingCacheBackgroundColor(Color.WHITE);//截图去黑色背景(透明像素)\n        if (color != Color.WHITE) {\n            view.destroyDrawingCache();\n        }\n        view.buildDrawingCache();\n        Bitmap cacheBitmap = view.getDrawingCache();\n        if (cacheBitmap == null) {\n            return null;\n        }\n        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);\n        Canvas canvas = new Canvas(bitmap);\n        canvas.drawBitmap(cacheBitmap, 0, 0, null);\n        canvas.save(Canvas.ALL_SAVE_FLAG);\n        canvas.restore();\n        if (!bitmap.isRecycled()) {\n            LogUtils.verbose(\"recycle bitmap: \" + bitmap.toString());\n            bitmap.recycle();\n        }\n        // Restore the view\n        view.destroyDrawingCache();\n        view.setWillNotCacheDrawing(willNotCache);\n        view.setDrawingCacheBackgroundColor(color);\n        return bitmap;\n    }\n\n    public static Drawable toDrawable(Bitmap bitmap) {\n        return bitmap == null ? null : new BitmapDrawable(Resources.getSystem(), bitmap);\n    }\n\n    public static byte[] toByteArray(Drawable drawable) {\n        return toByteArray(toBitmap(drawable));\n    }\n\n    public static Drawable toDrawable(byte[] bytes) {\n        return toDrawable(toBitmap(bytes));\n    }\n\n    /**\n     * dp转换为px\n     */\n    public static int toPx(Context context, float dpValue) {\n        final float scale = context.getResources().getDisplayMetrics().density;\n        int pxValue = (int) (dpValue * scale + 0.5f);\n        LogUtils.verbose(dpValue + \" dp == \" + pxValue + \" px\");\n        return pxValue;\n    }\n\n    /**\n     * px转换为dp\n     */\n    public static int toDp(Context context, float pxValue) {\n        final float scale = context.getResources().getDisplayMetrics().density;\n        int dpValue = (int) (pxValue / scale + 0.5f);\n        LogUtils.verbose(pxValue + \" px == \" + dpValue + \" dp\");\n        return dpValue;\n    }\n\n    /**\n     * px转换为sp\n     */\n    public static int toSp(Context context, float pxValue) {\n        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;\n        int spValue = (int) (pxValue / fontScale + 0.5f);\n        LogUtils.verbose(pxValue + \" px == \" + spValue + \" sp\");\n        return spValue;\n    }\n\n    public static String toGbk(String str) {\n        try {\n            return new String(str.getBytes(\"utf-8\"), \"gbk\");\n        } catch (UnsupportedEncodingException e) {\n            LogUtils.warn(e);\n            return str;\n        }\n    }\n\n    public static String toFileSizeString(long fileSize) {\n        DecimalFormat df = new DecimalFormat(\"0.00\");\n        String fileSizeString;\n        if (fileSize < KB) {\n            fileSizeString = fileSize + \"B\";\n        } else if (fileSize < MB) {\n            fileSizeString = df.format((double) fileSize / KB) + \"K\";\n        } else if (fileSize < GB) {\n            fileSizeString = df.format((double) fileSize / MB) + \"M\";\n        } else {\n            fileSizeString = df.format((double) fileSize / GB) + \"G\";\n        }\n        return fileSizeString;\n    }\n\n    public static String toString(InputStream is, String charset) {\n        StringBuilder sb = new StringBuilder();\n        try {\n            BufferedReader reader = new BufferedReader(new InputStreamReader(is, charset));\n            while (true) {\n                String line = reader.readLine();\n                if (line == null) {\n                    break;\n                } else {\n                    sb.append(line).append(\"\\n\");\n                }\n            }\n            reader.close();\n            is.close();\n        } catch (IOException e) {\n            LogUtils.error(e);\n        }\n        return sb.toString();\n    }\n\n    public static String toString(InputStream is) {\n        return toString(is, \"utf-8\");\n    }\n\n    public static int toDarkenColor(@ColorInt int color) {\n        return toDarkenColor(color, 0.8f);\n    }\n\n    public static int toDarkenColor(@ColorInt int color, @FloatRange(from = 0f, to = 1f) float value) {\n        float[] hsv = new float[3];\n        Color.colorToHSV(color, hsv);\n        hsv[2] *= value;//HSV指Hue、Saturation、Value，即色调、饱和度和亮度，此处表示修改亮度\n        return Color.HSVToColor(hsv);\n    }\n\n    /**\n     * 转换为6位十六进制颜色代码，不含“#”\n     */\n    public static String toColorString(@ColorInt int color) {\n        return toColorString(color, false);\n    }\n\n    /**\n     * 转换为6位十六进制颜色代码，不含“#”\n     */\n    public static String toColorString(@ColorInt int color, boolean includeAlpha) {\n        String alpha = Integer.toHexString(Color.alpha(color));\n        String red = Integer.toHexString(Color.red(color));\n        String green = Integer.toHexString(Color.green(color));\n        String blue = Integer.toHexString(Color.blue(color));\n        if (alpha.length() == 1) {\n            alpha = \"0\" + alpha;\n        }\n        if (red.length() == 1) {\n            red = \"0\" + red;\n        }\n        if (green.length() == 1) {\n            green = \"0\" + green;\n        }\n        if (blue.length() == 1) {\n            blue = \"0\" + blue;\n        }\n        String colorString;\n        if (includeAlpha) {\n            colorString = alpha + red + green + blue;\n            LogUtils.verbose(String.format(Locale.CHINA, \"%d to color string is %s\", color, colorString));\n        } else {\n            colorString = red + green + blue;\n            LogUtils.verbose(String.format(Locale.CHINA, \"%d to color string is %s%s%s%s, exclude alpha is %s\", color, alpha, red, green, blue, colorString));\n        }\n        return colorString;\n    }\n\n    /**\n     * 对TextView、Button等设置不同状态时其文字颜色。\n     * 参见：http://blog.csdn.net/sodino/article/details/6797821\n     * Modified by liyujiang at 2015.08.13\n     */\n    public static ColorStateList toColorStateList(@ColorInt int normalColor, @ColorInt int pressedColor,\n                                                  @ColorInt int focusedColor, @ColorInt int unableColor) {\n        int[] colors = new int[]{pressedColor, focusedColor, normalColor, focusedColor, unableColor, normalColor};\n        int[][] states = new int[6][];\n        states[0] = new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled};\n        states[1] = new int[]{android.R.attr.state_enabled, android.R.attr.state_focused};\n        states[2] = new int[]{android.R.attr.state_enabled};\n        states[3] = new int[]{android.R.attr.state_focused};\n        states[4] = new int[]{android.R.attr.state_window_focused};\n        states[5] = new int[]{};\n        return new ColorStateList(states, colors);\n    }\n\n    public static ColorStateList toColorStateList(@ColorInt int normalColor, @ColorInt int pressedColor) {\n        return toColorStateList(normalColor, pressedColor, pressedColor, normalColor);\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/DateUtils.java",
    "content": "package com.ess.filepicker.util;\n\nimport android.support.annotation.IntDef;\nimport android.support.annotation.NonNull;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Arrays;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Locale;\n\n/**\n * 日期时间工具类\n *\n * @author 李玉江[QQ:1023694760]\n * @since 2015/8/5\n */\npublic class DateUtils extends android.text.format.DateUtils {\n    public static final int Second = 0;\n    public static final int Minute = 1;\n    public static final int Hour = 2;\n    public static final int Day = 3;\n\n    @IntDef(value = {Second, Minute, Hour, Day})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface DifferenceMode {\n    }\n\n    public static long calculateDifferentSecond(Date startDate, Date endDate) {\n        return calculateDifference(startDate, endDate, Second);\n    }\n\n    public static long calculateDifferentMinute(Date startDate, Date endDate) {\n        return calculateDifference(startDate, endDate, Minute);\n    }\n\n    public static long calculateDifferentHour(Date startDate, Date endDate) {\n        return calculateDifference(startDate, endDate, Hour);\n    }\n\n    public static long calculateDifferentDay(Date startDate, Date endDate) {\n        return calculateDifference(startDate, endDate, Day);\n    }\n\n    public static long calculateDifferentSecond(long startTimeMillis, long endTimeMillis) {\n        return calculateDifference(startTimeMillis, endTimeMillis, Second);\n    }\n\n    public static long calculateDifferentMinute(long startTimeMillis, long endTimeMillis) {\n        return calculateDifference(startTimeMillis, endTimeMillis, Minute);\n    }\n\n    public static long calculateDifferentHour(long startTimeMillis, long endTimeMillis) {\n        return calculateDifference(startTimeMillis, endTimeMillis, Hour);\n    }\n\n    public static long calculateDifferentDay(long startTimeMillis, long endTimeMillis) {\n        return calculateDifference(startTimeMillis, endTimeMillis, Day);\n    }\n\n    /**\n     * 计算两个时间戳之间相差的时间戳数\n     */\n    public static long calculateDifference(long startTimeMillis, long endTimeMillis, @DifferenceMode int mode) {\n        return calculateDifference(new Date(startTimeMillis), new Date(endTimeMillis), mode);\n    }\n\n    /**\n     * 计算两个日期之间相差的时间戳数\n     */\n    public static long calculateDifference(Date startDate, Date endDate, @DifferenceMode int mode) {\n        long[] different = calculateDifference(startDate, endDate);\n        if (mode == Minute) {\n            return different[2];\n        } else if (mode == Hour) {\n            return different[1];\n        } else if (mode == Day) {\n            return different[0];\n        } else {\n            return different[3];\n        }\n    }\n\n    private static long[] calculateDifference(Date startDate, Date endDate) {\n        return calculateDifference(endDate.getTime() - startDate.getTime());\n    }\n\n    private static long[] calculateDifference(long differentMilliSeconds) {\n        long secondsInMilli = 1000;//1s==1000ms\n        long minutesInMilli = secondsInMilli * 60;\n        long hoursInMilli = minutesInMilli * 60;\n        long daysInMilli = hoursInMilli * 24;\n        long elapsedDays = differentMilliSeconds / daysInMilli;\n        differentMilliSeconds = differentMilliSeconds % daysInMilli;\n        long elapsedHours = differentMilliSeconds / hoursInMilli;\n        differentMilliSeconds = differentMilliSeconds % hoursInMilli;\n        long elapsedMinutes = differentMilliSeconds / minutesInMilli;\n        differentMilliSeconds = differentMilliSeconds % minutesInMilli;\n        long elapsedSeconds = differentMilliSeconds / secondsInMilli;\n        LogUtils.verbose(String.format(Locale.CHINA, \"different: %d ms, %d days, %d hours, %d minutes, %d seconds\",\n                differentMilliSeconds, elapsedDays, elapsedHours, elapsedMinutes, elapsedSeconds));\n        return new long[]{elapsedDays, elapsedHours, elapsedMinutes, elapsedSeconds};\n    }\n\n    /**\n     * 计算每月的天数\n     */\n    public static int calculateDaysInMonth(int month) {\n        return calculateDaysInMonth(0, month);\n    }\n\n    /**\n     * 根据年份及月份计算每月的天数\n     */\n    public static int calculateDaysInMonth(int year, int month) {\n        // 添加大小月月份并将其转换为list,方便之后的判断\n        String[] bigMonths = {\"1\", \"3\", \"5\", \"7\", \"8\", \"10\", \"12\"};\n        String[] littleMonths = {\"4\", \"6\", \"9\", \"11\"};\n        List<String> bigList = Arrays.asList(bigMonths);\n        List<String> littleList = Arrays.asList(littleMonths);\n        // 判断大小月及是否闰年,用来确定\"日\"的数据\n        if (bigList.contains(String.valueOf(month))) {\n            return 31;\n        } else if (littleList.contains(String.valueOf(month))) {\n            return 30;\n        } else {\n            if (year <= 0) {\n                return 29;\n            }\n            // 是否闰年\n            if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {\n                return 29;\n            } else {\n                return 28;\n            }\n        }\n    }\n\n    /**\n     * 月日时分秒，0-9前补0\n     */\n    @NonNull\n    public static String fillZero(int number) {\n        return number < 10 ? \"0\" + number : \"\" + number;\n    }\n\n    /**\n     * 截取掉前缀0以便转换为整数\n     *\n     * @see #fillZero(int)\n     */\n    public static int trimZero(@NonNull String text) {\n        try {\n            if (text.startsWith(\"0\")) {\n                text = text.substring(1);\n            }\n            return Integer.parseInt(text);\n        } catch (NumberFormatException e) {\n            LogUtils.warn(e);\n            return 0;\n        }\n    }\n\n    /**\n     * 功能：判断日期是否和当前date对象在同一天。\n     * 参见：http://www.cnblogs.com/myzhijie/p/3330970.html\n     *\n     * @param date 比较的日期\n     * @return boolean 如果在返回true，否则返回false。\n     */\n    public static boolean isSameDay(Date date) {\n        if (date == null) {\n            throw new IllegalArgumentException(\"date is null\");\n        }\n        Calendar nowCalendar = Calendar.getInstance();\n        Calendar newCalendar = Calendar.getInstance();\n        newCalendar.setTime(date);\n        return (nowCalendar.get(Calendar.ERA) == newCalendar.get(Calendar.ERA) &&\n                nowCalendar.get(Calendar.YEAR) == newCalendar.get(Calendar.YEAR) &&\n                nowCalendar.get(Calendar.DAY_OF_YEAR) == newCalendar.get(Calendar.DAY_OF_YEAR));\n    }\n\n    /**\n     * 将yyyy-MM-dd HH:mm:ss字符串转换成日期<br/>\n     *\n     * @param dateStr    时间字符串\n     * @param dataFormat 当前时间字符串的格式。\n     * @return Date 日期 ,转换异常时返回null。\n     */\n    public static Date parseDate(String dateStr, String dataFormat) {\n        try {\n            SimpleDateFormat dateFormat = new SimpleDateFormat(dataFormat, Locale.PRC);\n            Date date = dateFormat.parse(dateStr);\n            return new Date(date.getTime());\n        } catch (ParseException e) {\n            LogUtils.warn(e);\n            return null;\n        }\n    }\n\n    /**\n     * 将yyyy-MM-dd HH:mm:ss字符串转换成日期<br/>\n     *\n     * @param dateStr yyyy-MM-dd HH:mm:ss字符串\n     * @return Date 日期 ,转换异常时返回null。\n     */\n    public static Date parseDate(String dateStr) {\n        return parseDate(dateStr, \"yyyy-MM-dd HH:mm:ss\");\n    }\n\n    public static String getFileLastModifyTime(long time) {\n        SimpleDateFormat formatter = new SimpleDateFormat(\"yyyy-MM-dd HH:mm\", Locale.CHINA);\n        return formatter.format(time);\n    }\n\n    /**\n     * 将指定的日期转换为一定格式的字符串\n     */\n    public static String formatDate(Date date, String format) {\n        SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.PRC);\n        return sdf.format(date);\n    }\n\n    /**\n     * 将当前日期转换为一定格式的字符串\n     */\n    public static String formatDate(String format) {\n        return formatDate(Calendar.getInstance(Locale.CHINA).getTime(), format);\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/DialogUtil.java",
    "content": "package com.ess.filepicker.util;\n\nimport android.app.Activity;\nimport android.content.DialogInterface;\nimport android.content.Intent;\nimport android.provider.Settings;\nimport android.support.v7.app.AlertDialog;\n\n/**\n * DialogUtil\n * Created by 李波 on 2018/2/27.\n */\n\npublic class DialogUtil {\n\n    /***\n     * 显示权限拒绝提醒对话框\n     */\n    public static void showPermissionDialog(final Activity mActivity, String permission) {\n        AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);\n        builder\n                .setMessage(\"您未授权 \" + permission + \" 权限, 请在权限管理中开启此权限。\")\n                .setTitle(\"提示\")\n                .setPositiveButton(\"确认\", new DialogInterface.OnClickListener() {\n                    @Override\n                    public void onClick(DialogInterface dialog, int which) {\n                        Intent intent = new Intent(Settings.ACTION_SETTINGS);\n                        mActivity.startActivity(intent);\n                    }\n                })\n                .setNegativeButton(\"取消\", new DialogInterface.OnClickListener() {\n                    @Override\n                    public void onClick(DialogInterface dialog, int which) {\n                        dialog.dismiss();\n                    }\n                });\n        builder.create().show();\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/FileSizeUtil.java",
    "content": "package com.ess.filepicker.util;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.text.DecimalFormat;\n\n/**\n * FileSizeUtil 计算文件大小，自动转换为b,kb,mb等\n * Created by 李波 on 2018/2/7.\n */\n\npublic class FileSizeUtil {\n    private static final String TAG = FileSizeUtil.class.getSimpleName();\n\n    public static final int SIZETYPE_B = 1;//获取文件大小单位为B的double值\n    public static final int SIZETYPE_KB = 2;//获取文件大小单位为KB的double值\n    public static final int SIZETYPE_MB = 3;//获取文件大小单位为MB的double值\n    public static final int SIZETYPE_GB = 4;//获取文件大小单位为GB的double值\n\n    /**\n     * 获取文件指定文件的指定单位的大小\n     *\n     * @param filePath 文件路径\n     * @param sizeType 获取大小的类型1为B、2为KB、3为MB、4为GB\n     * @return double值的大小\n     */\n    public static double getFileOrFilesSize(String filePath, int sizeType) {\n        File file = new File(filePath);\n        long blockSize = 0;\n        try {\n            if (file.isDirectory()) {\n                blockSize = getFileSizes(file);\n            } else {\n                blockSize = getFileSize(file);\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return FormetFileSize(blockSize, sizeType);\n    }\n\n    /**\n     * 调用此方法自动计算指定文件或指定文件夹的大小\n     *\n     * @return 计算好的带B、KB、MB、GB的字符串\n     */\n    public static String getAutoFileOrFilesSize(File file) {\n        long blockSize = 0;\n        try {\n            if (file.isDirectory()) {\n                blockSize = getFileSizes(file);\n            } else {\n                blockSize = file.length();\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return FormetFileSize(blockSize);\n    }\n\n    /**\n     * 获取指定文件大小\n     *\n     * @param file\n     * @return\n     * @throws Exception\n     */\n    private static long getFileSize(File file) throws Exception {\n        long size = 0;\n        if (file.exists()) {\n            FileInputStream fis = null;\n            fis = new FileInputStream(file);\n            size = fis.available();\n        } else {\n            file.createNewFile();\n        }\n        return size;\n    }\n\n    /**\n     * 获取指定文件夹\n     *\n     * @param f\n     * @return\n     * @throws Exception\n     */\n    private static long getFileSizes(File f) throws Exception {\n        long size = 0;\n        File flist[] = f.listFiles();\n        for (int i = 0; i < flist.length; i++) {\n            if (flist[i].isDirectory()) {\n                size = size + getFileSizes(flist[i]);\n            } else {\n                size = size + getFileSize(flist[i]);\n            }\n        }\n        return size;\n    }\n\n    /**\n     * 转换文件大小\n     *\n     * @param fileS\n     * @return\n     */\n    private static String FormetFileSize(long fileS) {\n        DecimalFormat df = new DecimalFormat(\"#.00\");\n        String fileSizeString = \"\";\n        String wrongSize = \"0B\";\n        if (fileS == 0) {\n            return wrongSize;\n        }\n        if (fileS < 1024) {\n            fileSizeString = df.format((double) fileS) + \"B\";\n        } else if (fileS < 1048576) {\n            fileSizeString = df.format((double) fileS / 1024) + \"KB\";\n        } else if (fileS < 1073741824) {\n            fileSizeString = df.format((double) fileS / 1048576) + \"MB\";\n        } else {\n            fileSizeString = df.format((double) fileS / 1073741824) + \"GB\";\n        }\n        return fileSizeString;\n    }\n\n    /**\n     * 转换文件大小,指定转换的类型\n     *\n     * @param fileS\n     * @param sizeType\n     * @return\n     */\n    private static double FormetFileSize(long fileS, int sizeType) {\n        DecimalFormat df = new DecimalFormat(\"#.00\");\n        double fileSizeLong = 0;\n        switch (sizeType) {\n            case SIZETYPE_B:\n                fileSizeLong = Double.valueOf(df.format((double) fileS));\n                break;\n            case SIZETYPE_KB:\n                fileSizeLong = Double.valueOf(df.format((double) fileS / 1024));\n                break;\n            case SIZETYPE_MB:\n                fileSizeLong = Double.valueOf(df.format((double) fileS / 1048576));\n                break;\n            case SIZETYPE_GB:\n                fileSizeLong = Double.valueOf(df.format((double) fileS / 1073741824));\n                break;\n            default:\n                break;\n        }\n        return fileSizeLong;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/FileUtils.java",
    "content": "package com.ess.filepicker.util;\n\nimport android.content.Context;\nimport android.os.Environment;\nimport android.os.storage.StorageManager;\nimport android.support.annotation.IntDef;\nimport android.text.TextUtils;\nimport android.webkit.MimeTypeMap;\n\nimport com.ess.filepicker.model.BreadModel;\n\nimport java.io.BufferedInputStream;\nimport java.io.BufferedOutputStream;\nimport java.io.ByteArrayOutputStream;\nimport java.io.Closeable;\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.FileWriter;\nimport java.io.FilenameFilter;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStream;\nimport java.io.UnsupportedEncodingException;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Calendar;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.List;\nimport java.util.regex.Pattern;\n\n/**\n * 文件处理\n * <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n * <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n *\n * @author 李玉江[QQ:1023694760]\n * @since 2014-4-18\n */\npublic final class FileUtils {\n    public static final int BY_NAME_ASC = 0;\n    public static final int BY_NAME_DESC = 1;\n    public static final int BY_TIME_ASC = 2;\n    public static final int BY_TIME_DESC = 3;\n    public static final int BY_SIZE_ASC = 4;\n    public static final int BY_SIZE_DESC = 5;\n    public static final int BY_EXTENSION_ASC = 6;\n    public static final int BY_EXTENSION_DESC = 7;\n\n    @IntDef(value = {\n            BY_NAME_ASC,//按名称\n            BY_NAME_DESC,\n            BY_TIME_ASC,//按最后修改时间\n            BY_TIME_DESC,\n            BY_SIZE_ASC,//按大小\n            BY_SIZE_DESC,\n            BY_EXTENSION_ASC,//按文件扩展名\n            BY_EXTENSION_DESC\n    })\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface SortType {\n    }\n\n    /**\n     * 将目录分隔符统一为平台默认的分隔符，并为目录结尾添加分隔符\n     */\n    public static String separator(String path) {\n        String separator = File.separator;\n        path = path.replace(\"\\\\\", separator);\n        if (!path.endsWith(separator)) {\n            path += separator;\n        }\n        return path;\n    }\n\n    /**\n     * 从路径名中获取面包屑导航列表\n     *\n     * @param mSdCardList mSdCardList\n     * @param path        路径名\n     * @return 面包屑导航列表\n     */\n    public static List<BreadModel> getBreadModeListFromPath(List<String> mSdCardList, String path) {\n        List<String> pathList = new ArrayList<>();\n        for (int i = 0; i < mSdCardList.size(); i++) {\n            if (i == 0) {\n                //内部存储设备\n                path = path.replace(mSdCardList.get(i), \"/内部存储设备\");\n            } else {\n                path = path.replace(mSdCardList.get(i), \"/SD卡\" + i);\n            }\n        }\n        if (!TextUtils.isEmpty(path)) {\n            String[] a = path.substring(1, path.length()).split(\"/\");\n            pathList = Arrays.asList(a);\n        }\n        List<BreadModel> breadModelList = new ArrayList<>();\n        for (String str :\n                pathList) {\n            BreadModel breadModel = new BreadModel();\n            breadModel.setCurName(str);\n            breadModelList.add(breadModel);\n        }\n        return breadModelList;\n    }\n\n    /**\n     * 点击某个位置的面包屑导航，获取到面包屑导航列表\n     *\n     * @param mSdCardList    mSdCardList\n     * @param breadModelList 原列表\n     * @param position       点击位置\n     * @return 新列表\n     */\n    public static String getBreadModelListByPosition(List<String> mSdCardList, List<BreadModel> breadModelList, int position) {\n        StringBuilder result = new StringBuilder(\"/\");\n        for (int i = 0; i < breadModelList.size(); i++) {\n            if (position >= i) {\n                result.append(breadModelList.get(i).getCurName()).append(File.separator);\n            } else {\n                break;\n            }\n        }\n        String resultStr = result.toString();\n        if (resultStr.startsWith(\"/内部存储设备\")) {\n            resultStr = resultStr.replace(\"/内部存储设备\", mSdCardList.get(0));\n        } else if (resultStr.startsWith(\"/SD卡\")) {\n            resultStr = resultStr.replace(\"/SD卡\" + String.valueOf(resultStr.charAt(4)), mSdCardList.get(Integer.valueOf(String.valueOf(resultStr.charAt(4)))));\n        }\n        return resultStr;\n    }\n\n    /**\n     * 切换SD卡路径\n     * @param sdCardName\n     * @param mSdCardList\n     * @return\n     */\n    public static String getChangeSdCard(String sdCardName,List<String> mSdCardList){\n        if(TextUtils.isEmpty(sdCardName)){\n            return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;\n        }\n        if(sdCardName.startsWith(\"内部存储设备\")){\n            return mSdCardList.get(0) + File.separator;\n        }\n        if(sdCardName.startsWith(\"SD卡\")){\n            return mSdCardList.get(Integer.valueOf(String.valueOf(sdCardName.charAt(3)))) + File.separator;\n        }\n        return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator;\n    }\n\n    /**\n     * 判断是否可以返回上一级目录,true可以返回上级目录，false不可以返回，直接finish\n     */\n    public static boolean canBackParent(String curFolder, List<String> sdCardList) {\n        for (String sdcard :\n                sdCardList) {\n            if (curFolder.equals(sdcard + File.separator)) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n\n    public static void closeSilently(Closeable c) {\n        if (c == null) {\n            return;\n        }\n        try {\n            c.close();\n        } catch (IOException e) {\n            // do nothing\n        }\n    }\n\n    /**\n     * 列出指定目录下的所有子目录\n     */\n    public static File[] listDirs(String startDirPath, String[] excludeDirs, @SortType int sortType) {\n        ArrayList<File> dirList = new ArrayList<File>();\n        File startDir = new File(startDirPath);\n        if (!startDir.isDirectory()) {\n            return new File[0];\n        }\n        File[] dirs = startDir.listFiles(new FileFilter() {\n            public boolean accept(File f) {\n                if (f == null) {\n                    return false;\n                }\n                //noinspection RedundantIfStatement\n                if (f.isDirectory()) {\n                    return true;\n                }\n                return false;\n            }\n        });\n        if (dirs == null) {\n            return new File[0];\n        }\n        if (excludeDirs == null) {\n            excludeDirs = new String[0];\n        }\n        for (File dir : dirs) {\n            File file = dir.getAbsoluteFile();\n            if (!ConvertUtils.toString(excludeDirs).contains(file.getName())) {\n                dirList.add(file);\n            }\n        }\n        if (sortType == BY_NAME_ASC) {\n            Collections.sort(dirList, new SortByName());\n        } else if (sortType == BY_NAME_DESC) {\n            Collections.sort(dirList, new SortByName());\n            Collections.reverse(dirList);\n        } else if (sortType == BY_TIME_ASC) {\n            Collections.sort(dirList, new SortByTime());\n        } else if (sortType == BY_TIME_DESC) {\n            Collections.sort(dirList, new SortByTime());\n            Collections.reverse(dirList);\n        } else if (sortType == BY_SIZE_ASC) {\n            Collections.sort(dirList, new SortBySize());\n        } else if (sortType == BY_SIZE_DESC) {\n            Collections.sort(dirList, new SortBySize());\n            Collections.reverse(dirList);\n        } else if (sortType == BY_EXTENSION_ASC) {\n            Collections.sort(dirList, new SortByExtension());\n        } else if (sortType == BY_EXTENSION_DESC) {\n            Collections.sort(dirList, new SortByExtension());\n            Collections.reverse(dirList);\n        }\n        return dirList.toArray(new File[dirList.size()]);\n    }\n\n    /**\n     * 列出指定目录下的所有子目录\n     */\n    public static File[] listDirs(String startDirPath, String[] excludeDirs) {\n        return listDirs(startDirPath, excludeDirs, BY_NAME_ASC);\n    }\n\n    /**\n     * 列出指定目录下的所有子目录\n     */\n    public static File[] listDirs(String startDirPath) {\n        return listDirs(startDirPath, null, BY_NAME_ASC);\n    }\n\n    /**\n     * 列出指定目录下的所有子目录及所有文件\n     */\n    public static File[] listDirsAndFiles(String startDirPath, String[] allowExtensions) {\n        File[] dirs, files, dirsAndFiles;\n        dirs = listDirs(startDirPath);\n        if (allowExtensions == null) {\n            files = listFiles(startDirPath);\n        } else {\n            files = listFiles(startDirPath, allowExtensions);\n        }\n        if (dirs == null || files == null) {\n            return null;\n        }\n        dirsAndFiles = new File[dirs.length + files.length];\n        System.arraycopy(dirs, 0, dirsAndFiles, 0, dirs.length);\n        System.arraycopy(files, 0, dirsAndFiles, dirs.length, files.length);\n        return dirsAndFiles;\n    }\n\n    /**\n     * 列出指定目录下的所有子目录及所有文件\n     */\n    public static File[] listDirsAndFiles(String startDirPath) {\n        return listDirsAndFiles(startDirPath, null);\n    }\n\n    /**\n     * 列出指定目录下的所有文件\n     */\n    public static File[] listFiles(String startDirPath, final Pattern filterPattern, @SortType int sortType) {\n        LogUtils.verbose(String.format(\"list file %s\", startDirPath));\n        ArrayList<File> fileList = new ArrayList<File>();\n        File f = new File(startDirPath);\n        if (!f.isDirectory()) {\n            return new File[0];\n        }\n        File[] files = f.listFiles(new FileFilter() {\n            public boolean accept(File f) {\n                if (f == null) {\n                    return false;\n                }\n                if (f.isDirectory()) {\n                    return false;\n                }\n                //noinspection SimplifiableIfStatement\n                if (filterPattern == null) {\n                    return true;\n                }\n                return filterPattern.matcher(f.getName()).find();\n            }\n        });\n        if (files == null) {\n            return new File[0];\n        }\n        for (File file : files) {\n            fileList.add(file.getAbsoluteFile());\n        }\n        if (sortType == BY_NAME_ASC) {\n            Collections.sort(fileList, new SortByName());\n        } else if (sortType == BY_NAME_DESC) {\n            Collections.sort(fileList, new SortByName());\n            Collections.reverse(fileList);\n        } else if (sortType == BY_TIME_ASC) {\n            Collections.sort(fileList, new SortByTime());\n        } else if (sortType == BY_TIME_DESC) {\n            Collections.sort(fileList, new SortByTime());\n            Collections.reverse(fileList);\n        } else if (sortType == BY_SIZE_ASC) {\n            Collections.sort(fileList, new SortBySize());\n        } else if (sortType == BY_SIZE_DESC) {\n            Collections.sort(fileList, new SortBySize());\n            Collections.reverse(fileList);\n        } else if (sortType == BY_EXTENSION_ASC) {\n            Collections.sort(fileList, new SortByExtension());\n        } else if (sortType == BY_EXTENSION_DESC) {\n            Collections.sort(fileList, new SortByExtension());\n            Collections.reverse(fileList);\n        }\n        return fileList.toArray(new File[fileList.size()]);\n    }\n\n    /**\n     * 列出指定目录下的所有文件\n     */\n    public static File[] listFiles(String startDirPath, Pattern filterPattern) {\n        return listFiles(startDirPath, filterPattern, BY_NAME_ASC);\n    }\n\n    /**\n     * 列出指定目录下的所有文件\n     */\n    public static File[] listFiles(String startDirPath) {\n        return listFiles(startDirPath, null, BY_NAME_ASC);\n    }\n\n    /**\n     * 列出指定目录下的所有文件\n     */\n    public static File[] listFiles(String startDirPath, final String[] allowExtensions) {\n        LogUtils.verbose(String.format(\"list file %s\", startDirPath));\n        File file = new File(startDirPath);\n        return file.listFiles(new FilenameFilter() {\n\n            @Override\n            public boolean accept(File dir, String name) {\n                //返回当前目录所有以某些扩展名结尾的文件\n                String extension = FileUtils.getExtension(name);\n                return ConvertUtils.toString(allowExtensions).contains(extension);\n            }\n\n        });\n    }\n\n    /**\n     * 列出指定目录下的所有文件\n     */\n    public static File[] listFiles(String startDirPath, String allowExtension) {\n        return listFiles(startDirPath, new String[]{allowExtension});\n    }\n\n    /**\n     * 判断文件或目录是否存在\n     */\n    public static boolean exist(String path) {\n        File file = new File(path);\n        return file.exists();\n    }\n\n    /**\n     * 删除文件或目录\n     */\n    public static boolean delete(File file, boolean deleteRootDir) {\n        LogUtils.verbose(String.format(\"delete file %s\", file.getAbsolutePath()));\n        boolean result = false;\n        if (file.isFile()) {\n            //是文件\n            result = deleteResolveEBUSY(file);\n        } else {\n            //是目录\n            File[] files = file.listFiles();\n            if (files == null) {\n                return false;\n            }\n            if (files.length == 0) {\n                result = deleteRootDir && deleteResolveEBUSY(file);\n            } else {\n                for (File f : files) {\n                    delete(f, deleteRootDir);\n                    result = deleteResolveEBUSY(f);\n                }\n            }\n            if (deleteRootDir) {\n                result = deleteResolveEBUSY(file);\n            }\n        }\n        return result;\n    }\n\n    /**\n     * bug: open failed: EBUSY (Device or resource busy)\n     * fix: http://stackoverflow.com/questions/11539657/open-failed-ebusy-device-or-resource-busy\n     */\n    private static boolean deleteResolveEBUSY(File file) {\n        // Before you delete a Directory or File: rename it!\n        final File to = new File(file.getAbsolutePath() + System.currentTimeMillis());\n        //noinspection ResultOfMethodCallIgnored\n        file.renameTo(to);\n        return to.delete();\n    }\n\n    /**\n     * 删除文件或目录\n     */\n    public static boolean delete(String path, boolean deleteRootDir) {\n        File file = new File(path);\n        //noinspection SimplifiableIfStatement\n        if (file.exists()) {\n            return delete(file, deleteRootDir);\n        }\n        return false;\n    }\n\n    /**\n     * 删除文件或目录, 不删除最顶层目录\n     */\n    public static boolean delete(String path) {\n        return delete(path, false);\n    }\n\n    /**\n     * 删除文件或目录, 不删除最顶层目录\n     */\n    public static boolean delete(File file) {\n        return delete(file, false);\n    }\n\n    /**\n     * 复制文件为另一个文件，或复制某目录下的所有文件及目录到另一个目录下\n     */\n    public static boolean copy(String src, String tar) {\n        File srcFile = new File(src);\n        return srcFile.exists() && copy(srcFile, new File(tar));\n    }\n\n    /**\n     * 复制文件或目录\n     */\n    public static boolean copy(File src, File tar) {\n        try {\n            LogUtils.verbose(String.format(\"copy %s to %s\", src.getAbsolutePath(), tar.getAbsolutePath()));\n            if (src.isFile()) {\n                InputStream is = new FileInputStream(src);\n                OutputStream op = new FileOutputStream(tar);\n                BufferedInputStream bis = new BufferedInputStream(is);\n                BufferedOutputStream bos = new BufferedOutputStream(op);\n                byte[] bt = new byte[1024 * 8];\n                while (true) {\n                    int len = bis.read(bt);\n                    if (len == -1) {\n                        break;\n                    } else {\n                        bos.write(bt, 0, len);\n                    }\n                }\n                bis.close();\n                bos.close();\n            } else if (src.isDirectory()) {\n                File[] files = src.listFiles();\n                //noinspection ResultOfMethodCallIgnored\n                tar.mkdirs();\n                for (File file : files) {\n                    copy(file.getAbsoluteFile(), new File(tar.getAbsoluteFile(), file.getName()));\n                }\n            }\n            return true;\n        } catch (Exception e) {\n            LogUtils.error(e);\n            return false;\n        }\n    }\n\n    /**\n     * 移动文件或目录\n     */\n    public static boolean move(String src, String tar) {\n        return move(new File(src), new File(tar));\n    }\n\n    /**\n     * 移动文件或目录\n     */\n    public static boolean move(File src, File tar) {\n        return rename(src, tar);\n    }\n\n    /**\n     * 文件重命名\n     */\n    public static boolean rename(String oldPath, String newPath) {\n        return rename(new File(oldPath), new File(newPath));\n    }\n\n    /**\n     * 文件重命名\n     */\n    public static boolean rename(File src, File tar) {\n        LogUtils.verbose(String.format(\"rename %s to %s\", src.getAbsolutePath(), tar.getAbsolutePath()));\n        return src.renameTo(tar);\n    }\n\n    /**\n     * 读取文本文件, 失败将返回空串\n     */\n    public static String readText(String filepath, String charset) {\n        LogUtils.verbose(String.format(\"read %s use %s\", filepath, charset));\n        try {\n            byte[] data = readBytes(filepath);\n            if (data != null) {\n                return new String(data, charset).trim();\n            }\n        } catch (UnsupportedEncodingException e) {\n            LogUtils.warn(e);\n        }\n        return \"\";\n    }\n\n    /**\n     * 读取文本文件, 失败将返回空串\n     */\n    public static String readText(String filepath) {\n        return readText(filepath, \"utf-8\");\n    }\n\n    /**\n     * 读取文件内容, 失败将返回空串\n     */\n    public static byte[] readBytes(String filepath) {\n        LogUtils.verbose(String.format(\"read %s\", filepath));\n        FileInputStream fis = null;\n        try {\n            fis = new FileInputStream(filepath);\n            ByteArrayOutputStream baos = new ByteArrayOutputStream();\n            byte[] buffer = new byte[1024];\n            while (true) {\n                int len = fis.read(buffer, 0, buffer.length);\n                if (len == -1) {\n                    break;\n                } else {\n                    baos.write(buffer, 0, len);\n                }\n            }\n            byte[] data = baos.toByteArray();\n            baos.close();\n            return data;\n        } catch (IOException e) {\n            LogUtils.warn(e);\n            return null;\n        } finally {\n            closeSilently(fis);\n        }\n    }\n\n    /**\n     * 保存文本内容\n     */\n    public static boolean writeText(String filepath, String content, String charset) {\n        try {\n            writeBytes(filepath, content.getBytes(charset));\n            return true;\n        } catch (UnsupportedEncodingException e) {\n            LogUtils.warn(e);\n            return false;\n        }\n    }\n\n    /**\n     * 保存文本内容\n     */\n    public static boolean writeText(String filepath, String content) {\n        return writeText(filepath, content, \"utf-8\");\n    }\n\n    /**\n     * 保存文件内容\n     */\n    public static boolean writeBytes(String filepath, byte[] data) {\n        LogUtils.verbose(String.format(\"write %s\", filepath));\n        File file = new File(filepath);\n        FileOutputStream fos = null;\n        try {\n            if (!file.exists()) {\n                //noinspection ResultOfMethodCallIgnored\n                file.getParentFile().mkdirs();\n                //noinspection ResultOfMethodCallIgnored\n                file.createNewFile();\n            }\n            fos = new FileOutputStream(filepath);\n            fos.write(data);\n            return true;\n        } catch (IOException e) {\n            LogUtils.warn(e);\n            return false;\n        } finally {\n            closeSilently(fos);\n        }\n    }\n\n    /**\n     * 追加文本内容\n     */\n    public static boolean appendText(String path, String content) {\n        LogUtils.verbose(String.format(\"append %s\", path));\n        File file = new File(path);\n        FileWriter writer = null;\n        try {\n            if (!file.exists()) {\n                //noinspection ResultOfMethodCallIgnored\n                file.createNewFile();\n            }\n            writer = new FileWriter(file, true);\n            writer.write(content);\n            return true;\n        } catch (IOException e) {\n            LogUtils.warn(e);\n            return false;\n        } finally {\n            closeSilently(writer);\n        }\n    }\n\n    /**\n     * 获取文件大小\n     */\n    public static long getLength(String path) {\n        File file = new File(path);\n        if (!file.isFile() || !file.exists()) {\n            return 0;\n        }\n        return file.length();\n    }\n\n    /**\n     * 获取文件或网址的名称（包括后缀）\n     */\n    public static String getName(String pathOrUrl) {\n        if (pathOrUrl == null) {\n            return \"\";\n        }\n        int pos = pathOrUrl.lastIndexOf('/');\n        if (0 <= pos) {\n            return pathOrUrl.substring(pos + 1);\n        } else {\n            return String.valueOf(System.currentTimeMillis()) + \".\" + getExtension(pathOrUrl);\n        }\n    }\n\n    /**\n     * 获取文件名（不包括扩展名）\n     */\n    public static String getNameExcludeExtension(String path) {\n        try {\n            String fileName = (new File(path)).getName();\n            int lastIndexOf = fileName.lastIndexOf(\".\");\n            if (lastIndexOf != -1) {\n                fileName = fileName.substring(0, lastIndexOf);\n            }\n            return fileName;\n        } catch (Exception e) {\n            LogUtils.warn(e);\n            return \"\";\n        }\n    }\n\n    /**\n     * 获取格式化后的文件大小\n     */\n    public static String getSize(String path) {\n        long fileSize = getLength(path);\n        return ConvertUtils.toFileSizeString(fileSize);\n    }\n\n    /**\n     * 获取文件后缀,不包括“.”\n     */\n    public static String getExtension(String pathOrUrl) {\n        int dotPos = pathOrUrl.lastIndexOf('.');\n        if (0 <= dotPos) {\n            return pathOrUrl.substring(dotPos + 1);\n        } else {\n            return \"ext\";\n        }\n    }\n\n    /**\n     * 获取文件的MIME类型\n     */\n    public static String getMimeType(String pathOrUrl) {\n        String ext = getExtension(pathOrUrl);\n        MimeTypeMap map = MimeTypeMap.getSingleton();\n        String mimeType;\n        if (map.hasExtension(ext)) {\n            mimeType = map.getMimeTypeFromExtension(ext);\n        } else {\n            mimeType = \"*/*\";\n        }\n        return mimeType;\n    }\n\n    /**\n     * 获取格式化后的文件/目录创建或最后修改时间\n     */\n    public static String getDateTime(String path) {\n        return getDateTime(path, \"yyyy-MM-dd HH:mm\");\n    }\n\n    /**\n     * 获取格式化后的文件/目录创建或最后修改时间\n     */\n    public static String getDateTime(String path, String format) {\n        File file = new File(path);\n        return getDateTime(file, format);\n    }\n\n    /**\n     * 获取格式化后的文件/目录创建或最后修改时间\n     */\n    public static String getDateTime(File file, String format) {\n        Calendar cal = Calendar.getInstance();\n        cal.setTimeInMillis(file.lastModified());\n        return DateUtils.formatDate(cal.getTime(), format);\n    }\n\n    /**\n     * 比较两个文件的最后修改时间\n     */\n    public static int compareLastModified(String path1, String path2) {\n        long stamp1 = (new File(path1)).lastModified();\n        long stamp2 = (new File(path2)).lastModified();\n        if (stamp1 > stamp2) {\n            return 1;\n        } else if (stamp1 < stamp2) {\n            return -1;\n        } else {\n            return 0;\n        }\n    }\n\n    /**\n     * 创建多级别的目录\n     */\n    public static boolean makeDirs(String path) {\n        return makeDirs(new File(path));\n    }\n\n    /**\n     * 创建多级别的目录\n     */\n    public static boolean makeDirs(File file) {\n        return file.mkdirs();\n    }\n\n    public static class SortByExtension implements Comparator<File> {\n\n        public SortByExtension() {\n            super();\n        }\n\n        public int compare(File f1, File f2) {\n            if (f1 == null || f2 == null) {\n                if (f1 == null) {\n                    return -1;\n                } else {\n                    return 1;\n                }\n            } else {\n                if (f1.isDirectory() && f2.isFile()) {\n                    return -1;\n                } else if (f1.isFile() && f2.isDirectory()) {\n                    return 1;\n                } else {\n                    return f1.getName().compareToIgnoreCase(f2.getName());\n                }\n            }\n        }\n\n    }\n\n    public static class SortByName implements Comparator<File> {\n        private boolean caseSensitive;\n\n        public SortByName(boolean caseSensitive) {\n            this.caseSensitive = caseSensitive;\n        }\n\n        public SortByName() {\n            this.caseSensitive = false;\n        }\n\n        public int compare(File f1, File f2) {\n            if (f1 == null || f2 == null) {\n                if (f1 == null) {\n                    return -1;\n                } else {\n                    return 1;\n                }\n            } else {\n                if (f1.isDirectory() && f2.isFile()) {\n                    return -1;\n                } else if (f1.isFile() && f2.isDirectory()) {\n                    return 1;\n                } else {\n                    String s1 = f1.getName();\n                    String s2 = f2.getName();\n                    if (caseSensitive) {\n                        return s1.compareTo(s2);\n                    } else {\n                        return s1.compareToIgnoreCase(s2);\n                    }\n                }\n            }\n        }\n\n    }\n\n    public static class SortBySize implements Comparator<File> {\n\n        public SortBySize() {\n            super();\n        }\n\n        public int compare(File f1, File f2) {\n            if (f1 == null || f2 == null) {\n                if (f1 == null) {\n                    return -1;\n                } else {\n                    return 1;\n                }\n            } else {\n                if (f1.isDirectory() && f2.isFile()) {\n                    return -1;\n                } else if (f1.isFile() && f2.isDirectory()) {\n                    return 1;\n                } else {\n                    if (f1.length() < f2.length()) {\n                        return -1;\n                    } else {\n                        return 1;\n                    }\n                }\n            }\n        }\n\n    }\n\n    public static class SortByTime implements Comparator<File> {\n\n        public SortByTime() {\n            super();\n        }\n\n        public int compare(File f1, File f2) {\n            if (f1 == null || f2 == null) {\n                if (f1 == null) {\n                    return -1;\n                } else {\n                    return 1;\n                }\n            } else {\n                if (f1.isDirectory() && f2.isFile()) {\n                    return -1;\n                } else if (f1.isFile() && f2.isDirectory()) {\n                    return 1;\n                } else {\n                    if (f1.lastModified() > f2.lastModified()) {\n                        return -1;\n                    } else {\n                        return 1;\n                    }\n                }\n            }\n        }\n\n    }\n\n    /**\n     * 得到所有的存储路径（内部存储+外部存储）\n     *\n     * @param context context\n     * @return 路径列表\n     */\n    public static List<String> getAllSdPaths(Context context) {\n        Method mMethodGetPaths = null;\n        String[] paths = null;\n        //通过调用类的实例mStorageManager的getClass()获取StorageManager类对应的Class对象\n        //getMethod(\"getVolumePaths\")返回StorageManager类对应的Class对象的getVolumePaths方法，这里不带参数\n        StorageManager mStorageManager = (StorageManager) context\n                .getSystemService(context.STORAGE_SERVICE);//storage\n        try {\n            mMethodGetPaths = mStorageManager.getClass().getMethod(\"getVolumePaths\");\n            paths = (String[]) mMethodGetPaths.invoke(mStorageManager);\n        } catch (Exception e) {\n            // TODO Auto-generated catch block\n            e.printStackTrace();\n        }\n        if (paths != null) {\n            return Arrays.asList(paths);\n        }\n        return new ArrayList<String>();\n    }\n\n    /**\n     * 获取用于显示的Sd卡列表\n     * @param sdCardList sdCardList\n     * @return List\n     */\n    public static List<String> getAllSdCardList(List<String> sdCardList) {\n        List<String> resultList = new ArrayList<>();\n        for (int i = 0; i < sdCardList.size(); i++) {\n            if (i == 0) {\n                //内部存储设备\n                resultList.add(\"内部存储设备\");\n            } else {\n                resultList.add(\"SD卡\"+i);\n            }\n        }\n        return resultList;\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/LogUtils.java",
    "content": "package com.ess.filepicker.util;\n\nimport android.os.Debug;\nimport android.os.Environment;\nimport android.util.Log;\n\nimport com.ess.filepicker.BuildConfig;\n\nimport java.io.File;\nimport java.io.PrintWriter;\nimport java.io.StringWriter;\n\n\n/**\n * 将信息记录到控制台的LogCat，显示调用方法及所在的文件、行号，方便开发时调试查错。\n * 注意：在Debug状态下开启，在Release状态下关闭，敏感信息不宜打印，否则被非法之徒抓取贻害无穷。\n *\n * @author 李玉江[QQ:1023694760]\n * @since 2013/11/2\n */\npublic final class LogUtils {\n    private static final int MIN_STACK_OFFSET = 3;// starts at this class after two native calls\n    private static final int MAX_STACK_TRACE_SIZE = 131071; //128 KB - 1\n    private static final int METHOD_COUNT = 2; // show method count in trace\n    private static boolean isDebug = BuildConfig.DEBUG;// 是否调试模式\n    private static String debugTag = \"FilePicker\";// LogCat的标记\n\n    public static void setIsDebug(boolean isDebug) {\n        LogUtils.isDebug = isDebug;\n    }\n\n    public static boolean isDebug() {\n        return isDebug;\n    }\n\n    public static void setDebugTag(String debugTag) {\n        LogUtils.debugTag = debugTag;\n    }\n\n    public static String getDebugTag() {\n        return debugTag;\n    }\n\n    /**\n     * Verbose.\n     *\n     * @param message the message\n     */\n    public static void verbose(String message) {\n        verbose(\"\", message);\n    }\n\n    /**\n     * Verbose.\n     *\n     * @param object  the object\n     * @param message the message\n     */\n    public static void verbose(Object object, String message) {\n        verbose(object.getClass().getSimpleName(), message);\n    }\n\n    /**\n     * 记录“verbose”级别的信息\n     *\n     * @param tag the tag\n     * @param msg the msg\n     */\n    public static void verbose(String tag, String msg) {\n        if (isDebug) {\n            tag = debugTag + ((tag == null || tag.trim().length() == 0) ? \"\" : \"-\") + tag;\n            msg = msg + getTraceElement();\n            Log.v(tag, msg);\n        }\n    }\n\n    /**\n     * Debug.\n     *\n     * @param message the message\n     */\n    public static void debug(String message) {\n        debug(\"\", message);\n    }\n\n    /**\n     * Debug.\n     *\n     * @param object  the object\n     * @param message the message\n     */\n    public static void debug(Object object, String message) {\n        debug(object.getClass().getSimpleName(), message);\n    }\n\n    /**\n     * 记录“debug”级别的信息\n     *\n     * @param tag the tag\n     * @param msg the msg\n     */\n    public static void debug(String tag, String msg) {\n        if (isDebug) {\n            tag = debugTag + ((tag == null || tag.trim().length() == 0) ? \"\" : \"-\") + tag;\n            msg = msg + getTraceElement();\n            Log.d(tag, msg);\n        }\n    }\n\n    /**\n     * Warn.\n     *\n     * @param e the e\n     */\n    public static void warn(Throwable e) {\n        warn(toStackTraceString(e));\n    }\n\n    /**\n     * Warn.\n     *\n     * @param message the message\n     */\n    public static void warn(String message) {\n        warn(\"\", message);\n    }\n\n    /**\n     * Warn.\n     *\n     * @param object  the object\n     * @param message the message\n     */\n    public static void warn(Object object, String message) {\n        warn(object.getClass().getSimpleName(), message);\n    }\n\n    /**\n     * Warn.\n     *\n     * @param object the object\n     * @param e      the e\n     */\n    public static void warn(Object object, Throwable e) {\n        warn(object.getClass().getSimpleName(), toStackTraceString(e));\n    }\n\n    /**\n     * 记录“warn”级别的信息\n     *\n     * @param tag the tag\n     * @param msg the msg\n     */\n    public static void warn(String tag, String msg) {\n        if (isDebug) {\n            tag = debugTag + ((tag == null || tag.trim().length() == 0) ? \"\" : \"-\") + tag;\n            msg = msg + getTraceElement();\n            Log.w(tag, msg);\n        }\n    }\n\n    /**\n     * Error.\n     *\n     * @param e the e\n     */\n    public static void error(Throwable e) {\n        error(toStackTraceString(e));\n    }\n\n    /**\n     * Error.\n     *\n     * @param message the message\n     */\n    public static void error(String message) {\n        error(\"\", message);\n    }\n\n    /**\n     * Error.\n     *\n     * @param object  the object\n     * @param message the message\n     */\n    public static void error(Object object, String message) {\n        error(object.getClass().getSimpleName(), message);\n    }\n\n    /**\n     * Error.\n     *\n     * @param object the object\n     * @param e      the e\n     */\n    public static void error(Object object, Throwable e) {\n        error(object.getClass().getSimpleName(), toStackTraceString(e));\n    }\n\n    /**\n     * 记录“error”级别的信息\n     *\n     * @param tag the tag\n     * @param msg the msg\n     */\n    public static void error(String tag, String msg) {\n        if (isDebug) {\n            tag = debugTag + ((tag == null || tag.trim().length() == 0) ? \"\" : \"-\") + tag;\n            msg = msg + getTraceElement();\n            Log.e(tag, msg);\n        }\n    }\n\n    /**\n     * 在某个方法中调用生成.trace文件。然后拿到电脑上用DDMS工具打开分析\n     *\n     * @see #stopMethodTracing()\n     */\n    public static void startMethodTracing() {\n        if (isDebug) {\n            Debug.startMethodTracing(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + debugTag + \".trace\");\n        }\n    }\n\n    /**\n     * Stop method tracing.\n     */\n    public static void stopMethodTracing() {\n        if (isDebug) {\n            Debug.stopMethodTracing();\n        }\n    }\n\n    /**\n     * To stack trace string string.\n     * <p>\n     * 此方法参见：https://github.com/Ereza/CustomActivityOnCrash\n     *\n     * @param throwable the throwable\n     * @return the string\n     */\n    public static String toStackTraceString(Throwable throwable) {\n        StringWriter sw = new StringWriter();\n        PrintWriter pw = new PrintWriter(sw);\n        throwable.printStackTrace(pw);\n        String stackTraceString = sw.toString();\n        //Reduce data to 128KB so we don't get a TransactionTooLargeException when sending the intent.\n        //The limit is 1MB on Android but some devices seem to have it lower.\n        //See: http://developer.android.com/reference/android/os/TransactionTooLargeException.html\n        //And: http://stackoverflow.com/questions/11451393/what-to-do-on-transactiontoolargeexception#comment46697371_12809171\n        if (stackTraceString.length() > MAX_STACK_TRACE_SIZE) {\n            String disclaimer = \" [stack trace too large]\";\n            stackTraceString = stackTraceString.substring(0, MAX_STACK_TRACE_SIZE - disclaimer.length()) + disclaimer;\n        }\n        pw.close();\n        return stackTraceString;\n    }\n\n    /**\n     * 可显示调用方法所在的文件行号，在AndroidStudio的logcat处可点击定位。\n     * 此方法参考：https://github.com/orhanobut/logger\n     */\n    private static String getTraceElement() {\n        try {\n            int methodCount = METHOD_COUNT;\n            StackTraceElement[] trace = Thread.currentThread().getStackTrace();\n            int stackOffset = _getStackOffset(trace);\n\n            //corresponding method count with the current stack may exceeds the stack trace. Trims the count\n            if (methodCount + stackOffset > trace.length) {\n                methodCount = trace.length - stackOffset - 1;\n            }\n\n            String level = \"    \";\n            StringBuilder builder = new StringBuilder();\n            for (int i = methodCount; i > 0; i--) {\n                int stackIndex = i + stackOffset;\n                if (stackIndex >= trace.length) {\n                    continue;\n                }\n                builder.append(\"\\n\")\n                        .append(level)\n                        .append(_getSimpleClassName(trace[stackIndex].getClassName()))\n                        .append(\".\")\n                        .append(trace[stackIndex].getMethodName())\n                        .append(\" \")\n                        .append(\"(\")\n                        .append(trace[stackIndex].getFileName())\n                        .append(\":\")\n                        .append(trace[stackIndex].getLineNumber())\n                        .append(\")\");\n                level += \"    \";\n            }\n            return builder.toString();\n        } catch (Exception e) {\n            Log.w(debugTag, e);\n            return \"\";\n        }\n    }\n\n    /**\n     * Determines the starting index of the stack trace, after method calls made by this class.\n     *\n     * @param trace the stack trace\n     * @return the stack offset\n     */\n    private static int _getStackOffset(StackTraceElement[] trace) {\n        for (int i = MIN_STACK_OFFSET; i < trace.length; i++) {\n            StackTraceElement e = trace[i];\n            String name = e.getClassName();\n            if (!name.equals(LogUtils.class.getName())) {\n                return --i;\n            }\n        }\n        return -1;\n    }\n\n    private static String _getSimpleClassName(String name) {\n        int lastIndex = name.lastIndexOf(\".\");\n        return name.substring(lastIndex + 1);\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/MediaStoreCompat.java",
    "content": "/*\n * Copyright 2017 Zhihu Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.ess.filepicker.util;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.pm.PackageManager;\nimport android.content.pm.ResolveInfo;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.Environment;\nimport android.provider.MediaStore;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.content.FileProvider;\nimport android.support.v4.os.EnvironmentCompat;\n\n\nimport com.ess.filepicker.model.CaptureStrategy;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.lang.ref.WeakReference;\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Locale;\n\npublic class MediaStoreCompat {\n\n    private final WeakReference<Activity> mContext;\n    private final WeakReference<Fragment> mFragment;\n    private CaptureStrategy mCaptureStrategy;\n    private       Uri                     mCurrentPhotoUri;\n    private       String                  mCurrentPhotoPath;\n\n    public MediaStoreCompat(Activity activity) {\n        mContext = new WeakReference<>(activity);\n        mFragment = null;\n    }\n\n    public MediaStoreCompat(Activity activity, Fragment fragment) {\n        mContext = new WeakReference<>(activity);\n        mFragment = new WeakReference<>(fragment);\n    }\n\n    /**\n     * Checks whether the device has a camera feature or not.\n     *\n     * @param context a context to check for camera feature.\n     * @return true if the device has a camera feature. false otherwise.\n     */\n    public static boolean hasCameraFeature(Context context) {\n        PackageManager pm = context.getApplicationContext().getPackageManager();\n        return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);\n    }\n\n    public void setCaptureStrategy(CaptureStrategy strategy) {\n        mCaptureStrategy = strategy;\n    }\n\n    public void dispatchCaptureIntent(Context context, int requestCode) {\n        Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);\n        if (captureIntent.resolveActivity(context.getPackageManager()) != null) {\n            File photoFile = null;\n            try {\n                photoFile = createImageFile();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n\n            if (photoFile != null) {\n                mCurrentPhotoPath = photoFile.getAbsolutePath();\n                mCurrentPhotoUri = FileProvider.getUriForFile(mContext.get(),\n                        mCaptureStrategy.authority, photoFile);\n                captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCurrentPhotoUri);\n                captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);\n                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {\n                    List<ResolveInfo> resInfoList = context.getPackageManager()\n                            .queryIntentActivities(captureIntent, PackageManager.MATCH_DEFAULT_ONLY);\n                    for (ResolveInfo resolveInfo : resInfoList) {\n                        String packageName = resolveInfo.activityInfo.packageName;\n                        context.grantUriPermission(packageName, mCurrentPhotoUri,\n                                Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);\n                    }\n                }\n                if (mFragment != null) {\n                    mFragment.get().startActivityForResult(captureIntent, requestCode);\n                } else {\n                    mContext.get().startActivityForResult(captureIntent, requestCode);\n                }\n            }\n        }\n    }\n\n    private File createImageFile() throws IOException {\n        // Create an image file name\n        String timeStamp =\n                new SimpleDateFormat(\"yyyyMMdd_HHmmss\", Locale.getDefault()).format(new Date());\n        String imageFileName = String.format(\"JPEG_%s.jpg\", timeStamp);\n        File storageDir;\n        if (mCaptureStrategy.isPublic) {\n            storageDir = Environment.getExternalStoragePublicDirectory(\n                    Environment.DIRECTORY_PICTURES);\n        } else {\n            storageDir = mContext.get().getExternalFilesDir(Environment.DIRECTORY_PICTURES);\n        }\n\n        // Avoid joining path components manually\n        File tempFile = new File(storageDir, imageFileName);\n\n        // Handle the situation that user's external storage is not ready\n        if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) {\n            return null;\n        }\n\n        return tempFile;\n    }\n\n    public Uri getCurrentPhotoUri() {\n        return mCurrentPhotoUri;\n    }\n\n    public String getCurrentPhotoPath() {\n        return mCurrentPhotoPath;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/MimeType.java",
    "content": "/*\n * Copyright (C) 2014 nohana, Inc.\n * Copyright 2017 Zhihu Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.ess.filepicker.util;\n\nimport android.content.ContentResolver;\nimport android.net.Uri;\nimport android.support.v4.util.ArraySet;\nimport android.text.TextUtils;\nimport android.webkit.MimeTypeMap;\n\n\nimport java.util.Arrays;\nimport java.util.EnumSet;\nimport java.util.Locale;\nimport java.util.Set;\n\n/**\n * MIME Type enumeration to restrict selectable media on the selection activity. Matisse only supports images and\n * videos.\n * <p>\n * Good example of mime types Android supports:\n * https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/MediaFile.java\n */\n@SuppressWarnings(\"unused\")\npublic enum MimeType {\n\n    // ============== images ==============\n    JPEG(\"image/jpeg\", arraySetOf(\n            \"jpg\",\n            \"jpeg\"\n    )),\n    PNG(\"image/png\", arraySetOf(\n            \"png\"\n    )),\n    GIF(\"image/gif\", arraySetOf(\n            \"gif\"\n    )),\n    BMP(\"image/x-ms-bmp\", arraySetOf(\n            \"bmp\"\n    )),\n    WEBP(\"image/webp\", arraySetOf(\n            \"webp\"\n    )),\n\n    // ============== videos ==============\n    MPEG(\"video/mpeg\", arraySetOf(\n            \"mpeg\",\n            \"mpg\"\n    )),\n    MP4(\"video/mp4\", arraySetOf(\n            \"mp4\",\n            \"m4v\"\n    )),\n    QUICKTIME(\"video/quicktime\", arraySetOf(\n            \"mov\"\n    )),\n    THREEGPP(\"video/3gpp\", arraySetOf(\n            \"3gp\",\n            \"3gpp\"\n    )),\n    THREEGPP2(\"video/3gpp2\", arraySetOf(\n            \"3g2\",\n            \"3gpp2\"\n    )),\n    MKV(\"video/x-matroska\", arraySetOf(\n            \"mkv\"\n    )),\n    WEBM(\"video/webm\", arraySetOf(\n            \"webm\"\n    )),\n    TS(\"video/mp2ts\", arraySetOf(\n            \"ts\"\n    )),\n    AVI(\"video/avi\", arraySetOf(\n            \"avi\"\n    ));\n\n    private final String mMimeTypeName;\n    private final Set<String> mExtensions;\n\n    MimeType(String mimeTypeName, Set<String> extensions) {\n        mMimeTypeName = mimeTypeName;\n        mExtensions = extensions;\n    }\n\n    public static Set<MimeType> ofAll() {\n        return EnumSet.allOf(MimeType.class);\n    }\n\n    public static Set<MimeType> of(MimeType type, MimeType... rest) {\n        return EnumSet.of(type, rest);\n    }\n\n    public static Set<MimeType> ofImage() {\n        return EnumSet.of(JPEG, PNG, GIF, BMP, WEBP);\n    }\n\n    public static Set<MimeType> ofVideo() {\n        return EnumSet.of(MPEG, MP4, QUICKTIME, THREEGPP, THREEGPP2, MKV, WEBM, TS, AVI);\n    }\n\n    private static Set<String> arraySetOf(String... suffixes) {\n        return new ArraySet<>(Arrays.asList(suffixes));\n    }\n\n    @Override\n    public String toString() {\n        return mMimeTypeName;\n    }\n\n    public boolean checkType(ContentResolver resolver, Uri uri) {\n        MimeTypeMap map = MimeTypeMap.getSingleton();\n        if (uri == null) {\n            return false;\n        }\n        String type = map.getExtensionFromMimeType(resolver.getType(uri));\n        String path = null;\n        // lazy load the path and prevent resolve for multiple times\n        boolean pathParsed = false;\n        for (String extension : mExtensions) {\n            if (extension.equals(type)) {\n                return true;\n            }\n            if (!pathParsed) {\n                // we only resolve the path for one time\n                path = PhotoMetadataUtils.getPath(resolver, uri);\n                if (!TextUtils.isEmpty(path)) {\n                    path = path.toLowerCase(Locale.US);\n                }\n                pathParsed = true;\n            }\n            if (path != null && path.endsWith(extension)) {\n                return true;\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/PathUtils.java",
    "content": "package com.ess.filepicker.util;\n\nimport android.annotation.TargetApi;\nimport android.content.ContentUris;\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.net.Uri;\nimport android.os.Build;\nimport android.os.Environment;\nimport android.provider.DocumentsContract;\nimport android.provider.MediaStore;\n\n/**\n * http://stackoverflow.com/a/27271131/4739220\n */\n\npublic class PathUtils {\n    /**\n     * Get a file path from a Uri. This will get the the path for Storage Access\n     * Framework Documents, as well as the _data field for the MediaStore and\n     * other file-based ContentProviders.\n     *\n     * @param context The context.\n     * @param uri     The Uri to query.\n     * @author paulburke\n     */\n    @TargetApi(Build.VERSION_CODES.KITKAT)\n    public static String getPath(final Context context, final Uri uri) {\n        // DocumentProvider\n        if (Platform.hasKitKat() && DocumentsContract.isDocumentUri(context, uri)) {\n            // ExternalStorageProvider\n            if (isExternalStorageDocument(uri)) {\n                final String docId = DocumentsContract.getDocumentId(uri);\n                final String[] split = docId.split(\":\");\n                final String type = split[0];\n\n                if (\"primary\".equalsIgnoreCase(type)) {\n                    return Environment.getExternalStorageDirectory() + \"/\" + split[1];\n                }\n\n                // TODO handle non-primary volumes\n            } else if (isDownloadsDocument(uri)) { // DownloadsProvider\n\n                final String id = DocumentsContract.getDocumentId(uri);\n                final Uri contentUri = ContentUris.withAppendedId(\n                        Uri.parse(\"content://downloads/public_downloads\"), Long.valueOf(id));\n\n                return getDataColumn(context, contentUri, null, null);\n            } else if (isMediaDocument(uri)) { // MediaProvider\n                final String docId = DocumentsContract.getDocumentId(uri);\n                final String[] split = docId.split(\":\");\n                final String type = split[0];\n\n                Uri contentUri = null;\n                if (\"image\".equals(type)) {\n                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;\n                } else if (\"video\".equals(type)) {\n                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;\n                } else if (\"audio\".equals(type)) {\n                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;\n                }\n\n                final String selection = \"_id=?\";\n                final String[] selectionArgs = new String[]{\n                        split[1]\n                };\n\n                return getDataColumn(context, contentUri, selection, selectionArgs);\n            }\n        } else if (\"content\".equalsIgnoreCase(uri.getScheme())) { // MediaStore (and general)\n            return getDataColumn(context, uri, null, null);\n        } else if (\"file\".equalsIgnoreCase(uri.getScheme())) { // File\n            return uri.getPath();\n        }\n\n        return null;\n    }\n\n    /**\n     * Get the value of the data column for this Uri. This is useful for\n     * MediaStore Uris, and other file-based ContentProviders.\n     *\n     * @param context       The context.\n     * @param uri           The Uri to query.\n     * @param selection     (Optional) Filter used in the query.\n     * @param selectionArgs (Optional) Selection arguments used in the query.\n     * @return The value of the _data column, which is typically a file path.\n     */\n    public static String getDataColumn(Context context, Uri uri, String selection,\n                                       String[] selectionArgs) {\n\n        Cursor cursor = null;\n        final String column = \"_data\";\n        final String[] projection = {\n                column\n        };\n\n        try {\n            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);\n            if (cursor != null && cursor.moveToFirst()) {\n                final int columnIndex = cursor.getColumnIndexOrThrow(column);\n                return cursor.getString(columnIndex);\n            }\n        } finally {\n            if (cursor != null)\n                cursor.close();\n        }\n        return null;\n    }\n\n\n    /**\n     * @param uri The Uri to check.\n     * @return Whether the Uri authority is ExternalStorageProvider.\n     */\n    public static boolean isExternalStorageDocument(Uri uri) {\n        return \"com.android.externalstorage.documents\".equals(uri.getAuthority());\n    }\n\n    /**\n     * @param uri The Uri to check.\n     * @return Whether the Uri authority is DownloadsProvider.\n     */\n    public static boolean isDownloadsDocument(Uri uri) {\n        return \"com.android.providers.downloads.documents\".equals(uri.getAuthority());\n    }\n\n    /**\n     * @param uri The Uri to check.\n     * @return Whether the Uri authority is MediaProvider.\n     */\n    public static boolean isMediaDocument(Uri uri) {\n        return \"com.android.providers.media.documents\".equals(uri.getAuthority());\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/PhotoMetadataUtils.java",
    "content": "/*\n * Copyright (C) 2014 nohana, Inc.\n * Copyright 2017 Zhihu Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.ess.filepicker.util;\n\nimport android.content.ContentResolver;\nimport android.database.Cursor;\nimport android.graphics.BitmapFactory;\nimport android.graphics.Point;\nimport android.net.Uri;\nimport android.provider.MediaStore;\n\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.text.DecimalFormat;\n\npublic final class PhotoMetadataUtils {\n    private static final String TAG = PhotoMetadataUtils.class.getSimpleName();\n    private static final int MAX_WIDTH = 1600;\n    private static final String SCHEME_CONTENT = \"content\";\n\n    private PhotoMetadataUtils() {\n        throw new AssertionError(\"oops! the utility class is about to be instantiated...\");\n    }\n\n    public static int getPixelsCount(ContentResolver resolver, Uri uri) {\n        Point size = getBitmapBound(resolver, uri);\n        return size.x * size.y;\n    }\n\n    public static Point getBitmapBound(ContentResolver resolver, Uri uri) {\n        InputStream is = null;\n        try {\n            BitmapFactory.Options options = new BitmapFactory.Options();\n            options.inJustDecodeBounds = true;\n            is = resolver.openInputStream(uri);\n            BitmapFactory.decodeStream(is, null, options);\n            int width = options.outWidth;\n            int height = options.outHeight;\n            return new Point(width, height);\n        } catch (FileNotFoundException e) {\n            return new Point(0, 0);\n        } finally {\n            if (is != null) {\n                try {\n                    is.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n    }\n\n    public static String getPath(ContentResolver resolver, Uri uri) {\n        if (uri == null) {\n            return null;\n        }\n\n        if (SCHEME_CONTENT.equals(uri.getScheme())) {\n            Cursor cursor = null;\n            try {\n                cursor = resolver.query(uri, new String[]{MediaStore.Images.ImageColumns.DATA},\n                        null, null, null);\n                if (cursor == null || !cursor.moveToFirst()) {\n                    return null;\n                }\n                return cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA));\n            } finally {\n                if (cursor != null) {\n                    cursor.close();\n                }\n            }\n        }\n        return uri.getPath();\n    }\n\n    public static float getSizeInMB(long sizeInBytes) {\n        return Float.valueOf(new DecimalFormat(\"0.0\").format((float) sizeInBytes / 1024 / 1024));\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/Platform.java",
    "content": "package com.ess.filepicker.util;\n\nimport android.os.Build;\n\n/**\n * @author JoongWon Baik\n */\npublic class Platform {\n    public static boolean hasICS() {\n        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;\n    }\n\n    public static boolean hasKitKat() {\n        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;\n    }\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/util/UiUtils.java",
    "content": "package com.ess.filepicker.util;\n\nimport android.content.Context;\nimport android.support.v7.widget.GridLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.util.DisplayMetrics;\nimport android.util.TypedValue;\n\n/**\n * UiUtils\n * Created by 李波 on 2018/2/8.\n */\n\npublic class UiUtils {\n\n    /***\n     * DP 转 PX\n     * @param c\n     * @param dipValue\n     * @return\n     */\n    public static int dpToPx(Context c, float dipValue) {\n        DisplayMetrics metrics = c.getResources().getDisplayMetrics();\n        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics);\n    }\n\n    public static int getImageResize(Context context,RecyclerView recyclerView) {\n        int mImageResize;\n        RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();\n        int spanCount = ((GridLayoutManager) lm).getSpanCount();\n        int screenWidth = context.getResources().getDisplayMetrics().widthPixels;\n        mImageResize = screenWidth / spanCount;\n        return mImageResize;\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/widget/MediaItemDecoration.java",
    "content": "package com.ess.filepicker.widget;\n\nimport android.graphics.Rect;\nimport android.support.v7.widget.GridLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.support.v7.widget.StaggeredGridLayoutManager;\nimport android.view.View;\n\nimport com.ess.filepicker.util.UiUtils;\n\n/**\n * MediaItemDecoration\n * Created by 李波 on 2018/3/2.\n */\n\npublic class MediaItemDecoration extends RecyclerView.ItemDecoration {\n\n    private int getSpanCount(RecyclerView parent) {\n        // 列数\n        int spanCount = -1;\n        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();\n        if (layoutManager instanceof GridLayoutManager) {\n\n            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();\n        } else if (layoutManager instanceof StaggeredGridLayoutManager) {\n            spanCount = ((StaggeredGridLayoutManager) layoutManager)\n                    .getSpanCount();\n        }\n        return spanCount;\n    }\n\n    @Override\n    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {\n        int itemPosition = parent.getChildAdapterPosition(view);\n        int divider = UiUtils.dpToPx(parent.getContext(), 4);\n        int spanCount = getSpanCount(parent);\n        int childCount = parent.getAdapter().getItemCount();\n        if (isLastRaw(parent, itemPosition, spanCount, childCount)) {\n            outRect.set(0, 0, divider, 0);\n        } else if (isLastColum(parent, itemPosition, spanCount, childCount)) {\n            outRect.set(0, 0, 0, divider);\n        } else {\n            outRect.set(0, 0, divider, divider);\n        }\n\n    }\n\n    private boolean isLastColum(RecyclerView parent, int pos, int spanCount,\n                                int childCount) {\n        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();\n        if (layoutManager instanceof GridLayoutManager) {\n            if ((pos + 1) % spanCount == 0)// 如果是最后一列，则不需要绘制右边\n            {\n                return true;\n            }\n        } else if (layoutManager instanceof StaggeredGridLayoutManager) {\n            int orientation = ((StaggeredGridLayoutManager) layoutManager)\n                    .getOrientation();\n            if (orientation == StaggeredGridLayoutManager.VERTICAL) {\n                if ((pos + 1) % spanCount == 0)// 如果是最后一列，则不需要绘制右边\n                {\n                    return true;\n                }\n            } else {\n                childCount = childCount - childCount % spanCount;\n                if (pos >= childCount)// 如果是最后一列，则不需要绘制右边\n                    return true;\n            }\n        }\n        return false;\n    }\n\n    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,\n                              int childCount) {\n        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();\n        if (layoutManager instanceof GridLayoutManager) {\n            childCount = childCount - childCount % spanCount;\n            if (pos >= childCount)// 如果是最后一行，则不需要绘制底部\n                return true;\n        } else if (layoutManager instanceof StaggeredGridLayoutManager) {\n            int orientation = ((StaggeredGridLayoutManager) layoutManager)\n                    .getOrientation();\n            // StaggeredGridLayoutManager 且纵向滚动\n            if (orientation == StaggeredGridLayoutManager.VERTICAL) {\n                childCount = childCount - childCount % spanCount;\n                // 如果是最后一行，则不需要绘制底部\n                if (pos >= childCount)\n                    return true;\n            } else\n            // StaggeredGridLayoutManager 且横向滚动\n            {\n                // 如果是最后一行，则不需要绘制底部\n                if ((pos + 1) % spanCount == 0) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/java/com/ess/filepicker/widget/ToolbarSpinner.java",
    "content": "/*\n * Copyright 2017 Zhihu Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npackage com.ess.filepicker.widget;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.database.Cursor;\nimport android.graphics.PorterDuff;\nimport android.graphics.drawable.Drawable;\nimport android.support.annotation.NonNull;\nimport android.support.v7.widget.ListPopupWindow;\nimport android.view.View;\nimport android.widget.AdapterView;\nimport android.widget.CursorAdapter;\nimport android.widget.TextView;\n\nimport com.ess.filepicker.R;\nimport com.ess.filepicker.model.Album;\nimport com.ess.filepicker.util.Platform;\n\npublic class ToolbarSpinner {\n\n    private static final int MAX_SHOWN_COUNT = 6;\n    private CursorAdapter mAdapter;\n    private TextView mSelected;\n    private ListPopupWindow mListPopupWindow;\n    private AdapterView.OnItemSelectedListener mOnItemSelectedListener;\n\n    public ToolbarSpinner(@NonNull Context context) {\n        mListPopupWindow = new ListPopupWindow(context, null, R.attr.listPopupWindowStyle);\n        mListPopupWindow.setModal(true);\n        float density = context.getResources().getDisplayMetrics().density;\n        mListPopupWindow.setContentWidth((int) (216 * density));\n        mListPopupWindow.setHorizontalOffset((int) (16 * density));\n        mListPopupWindow.setVerticalOffset((int) (-48 * density));\n\n        mListPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {\n\n            @Override\n            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {\n                ToolbarSpinner.this.onItemSelected(parent.getContext(), position);\n                if (mOnItemSelectedListener != null) {\n                    mOnItemSelectedListener.onItemSelected(parent, view, position, id);\n                }\n            }\n        });\n    }\n\n    public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {\n        mOnItemSelectedListener = listener;\n    }\n\n    public void setSelection(Context context, int position) {\n        mListPopupWindow.setSelection(position);\n        onItemSelected(context, position);\n    }\n\n    private void onItemSelected(Context context, int position) {\n        mListPopupWindow.dismiss();\n        Cursor cursor = mAdapter.getCursor();\n        cursor.moveToPosition(position);\n        Album album = Album.valueOf(cursor);\n        String displayName = album.getDisplayName(context);\n        if (mSelected.getVisibility() == View.VISIBLE) {\n            mSelected.setText(displayName);\n        } else {\n            if (Platform.hasICS()) {\n                mSelected.setAlpha(0.0f);\n                mSelected.setVisibility(View.VISIBLE);\n                mSelected.setText(displayName);\n                mSelected.animate().alpha(1.0f).setDuration(context.getResources().getInteger(\n                        android.R.integer.config_longAnimTime)).start();\n            } else {\n                mSelected.setVisibility(View.VISIBLE);\n                mSelected.setText(displayName);\n            }\n\n        }\n    }\n\n    public void setAdapter(CursorAdapter adapter) {\n        mListPopupWindow.setAdapter(adapter);\n        mAdapter = adapter;\n    }\n\n    public void setSelectedTextView(TextView textView) {\n        mSelected = textView;\n        // tint dropdown arrow icon\n        Drawable[] drawables = mSelected.getCompoundDrawables();\n        Drawable right = drawables[2];\n        TypedArray ta = mSelected.getContext().getTheme().obtainStyledAttributes(\n                new int[]{R.attr.album_element_color});\n        int color = ta.getColor(0, 0);\n        ta.recycle();\n        right.setColorFilter(color, PorterDuff.Mode.SRC_IN);\n\n        mSelected.setVisibility(View.VISIBLE);\n        mSelected.setOnClickListener(new View.OnClickListener() {\n\n            @Override\n            public void onClick(View v) {\n                int itemHeight = v.getResources().getDimensionPixelSize(R.dimen.album_item_height);\n                mListPopupWindow.setHeight(\n                        mAdapter.getCount() > MAX_SHOWN_COUNT ? itemHeight * MAX_SHOWN_COUNT\n                                : itemHeight * mAdapter.getCount());\n                mListPopupWindow.show();\n            }\n        });\n        mSelected.setOnTouchListener(mListPopupWindow.createDragToOpenListener(mSelected));\n    }\n\n    public void setPopupAnchorView(View view) {\n        mListPopupWindow.setAnchorView(view);\n    }\n\n}\n"
  },
  {
    "path": "filepicker/src/main/res/color/dracula_bottom_toolbar_apply.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:color=\"@color/dracula_bottom_toolbar_apply_text_disable\"\n          android:state_enabled=\"false\"/>\n    <item android:color=\"@color/dracula_bottom_toolbar_apply_text\"/>\n</selector>"
  },
  {
    "path": "filepicker/src/main/res/color/dracula_bottom_toolbar_preview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:color=\"@color/dracula_bottom_toolbar_preview_text_disable\"\n          android:state_enabled=\"false\"/>\n    <item android:color=\"@color/dracula_bottom_toolbar_preview_text\"/>\n</selector>"
  },
  {
    "path": "filepicker/src/main/res/color/dracula_preview_bottom_toolbar_apply.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:color=\"@color/dracula_preview_bottom_toolbar_apply_text_disable\"\n          android:state_enabled=\"false\"/>\n    <item android:color=\"@color/dracula_preview_bottom_toolbar_apply_text\"/>\n</selector>"
  },
  {
    "path": "filepicker/src/main/res/color/elec_bottom_toolbar_apply.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:color=\"@color/elec_bottom_toolbar_apply_text_disable\"\n          android:state_enabled=\"false\"/>\n    <item android:color=\"@color/elec_bottom_toolbar_apply_text\"/>\n</selector>"
  },
  {
    "path": "filepicker/src/main/res/color/elec_bottom_toolbar_preview.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:color=\"@color/elec_bottom_toolbar_preview_text_disable\"\n          android:state_enabled=\"false\"/>\n    <item android:color=\"@color/elec_bottom_toolbar_preview_text\"/>\n</selector>"
  },
  {
    "path": "filepicker/src/main/res/color/elec_preview_bottom_toolbar_apply.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:color=\"@color/elec_preview_bottom_toolbar_apply_text_disable\"\n          android:state_enabled=\"false\"/>\n    <item android:color=\"@color/elec_preview_bottom_toolbar_apply_text\"/>\n</selector>\n"
  },
  {
    "path": "filepicker/src/main/res/drawable/bg_bottom_line_gray.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item>\n        <shape>\n            <solid android:color=\"#D3DFDE\"/>\n        </shape>\n    </item>\n    <item\n        android:bottom=\"1px\">\n        <shape>\n            <solid android:color=\"#FFFFFF\"/>\n        </shape>\n    </item>\n</layer-list>"
  },
  {
    "path": "filepicker/src/main/res/layout/activity_pictures_detail.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\"com.ess.filepicker.activity.PicturesViewActivity\">\n\n</android.support.constraint.ConstraintLayout>\n"
  },
  {
    "path": "filepicker/src/main/res/layout/activity_select_file.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/coordinator_layout\"\n    tools:context=\".activity.SelectFileByBrowserActivity\">\n\n    <android.support.design.widget.AppBarLayout\n        android:layout_height=\"wrap_content\"\n        android:layout_width=\"match_parent\"\n        android:theme=\"@style/AppTheme.AppBarOverlay\"\n        android:background=\"?attr/colorPrimary\">\n\n        <android.support.v7.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"?attr/actionBarSize\"\n            app:popupTheme=\"@style/AppTheme.PopupOverlay\"\n            app:layout_scrollFlags=\"scroll|enterAlways\"/>\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"36dp\"\n            android:orientation=\"horizontal\"\n            >\n            <ImageView\n                android:visibility=\"gone\"\n                android:id=\"@+id/imb_select_sdcard\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_width=\"36dp\"\n                android:layout_height=\"36dp\"\n                android:rotation=\"90\"\n                android:scaleType=\"centerInside\"\n                android:src=\"@drawable/ic_chevron_right_white_24dp\"\n                android:background=\"?android:attr/selectableItemBackground\"\n                />\n            <android.support.v7.widget.RecyclerView\n                android:id=\"@+id/breadcrumbs_view\"\n                android:layout_width=\"match_parent\"\n                android:paddingRight=\"10dp\"\n                android:layout_height=\"?attr/actionBarSize\"\n                />\n        </LinearLayout>\n\n\n    </android.support.design.widget.AppBarLayout>\n\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/rcv_file_list\"\n        android:layout_width=\"match_parent\"\n        android:scrollbars=\"vertical\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n        />\n\n</android.support.design.widget.CoordinatorLayout>\n"
  },
  {
    "path": "filepicker/src/main/res/layout/activity_select_file_by_scan.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/coordinator_layout\"\n    tools:context=\".activity.SelectFileByBrowserActivity\">\n\n    <android.support.design.widget.AppBarLayout\n        android:layout_height=\"wrap_content\"\n        android:layout_width=\"match_parent\"\n        android:theme=\"@style/AppTheme.AppBarOverlay\"\n        android:background=\"?attr/colorPrimary\">\n\n        <android.support.v7.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"?attr/actionBarSize\"\n            app:popupTheme=\"@style/AppTheme.PopupOverlay\"\n            />\n        <!--app:layout_scrollFlags=\"scroll|enterAlways\"-->\n\n        <android.support.design.widget.TabLayout\n            android:id=\"@+id/tabl_select_file_scan\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"36dp\">\n\n        </android.support.design.widget.TabLayout>\n\n\n    </android.support.design.widget.AppBarLayout>\n\n    <android.support.v4.view.ViewPager\n        android:id=\"@+id/vp_select_file_scan\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n        />\n\n</android.support.design.widget.CoordinatorLayout>\n"
  },
  {
    "path": "filepicker/src/main/res/layout/activity_select_picture.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/coordinator_layout\"\n    tools:context=\".activity.SelectFileByBrowserActivity\">\n\n    <android.support.design.widget.AppBarLayout\n        android:layout_height=\"wrap_content\"\n        android:layout_width=\"match_parent\"\n        android:theme=\"@style/AppTheme.AppBarOverlay\"\n        android:background=\"?attr/colorPrimary\">\n\n        <android.support.v7.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"?attr/actionBarSize\"\n            app:popupTheme=\"@style/AppTheme.PopupOverlay\"\n            >\n            <TextView\n                android:id=\"@+id/selected_folder\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"?actionBarSize\"\n                android:drawableRight=\"@drawable/ic_arrow_drop_down_white_24dp\"\n                android:foreground=\"?selectableItemBackground\"\n                android:gravity=\"center\"\n                android:text=\"全部\"\n                android:textColor=\"?attr/album.element.color\"\n                android:textSize=\"20sp\"/>\n        </android.support.v7.widget.Toolbar>\n\n    </android.support.design.widget.AppBarLayout>\n\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/rcv_file_picture_list\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n        />\n\n\n</android.support.design.widget.CoordinatorLayout>\n"
  },
  {
    "path": "filepicker/src/main/res/layout/bread_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"36dp\"\n    android:orientation=\"horizontal\"\n    android:gravity=\"center_vertical\"\n    android:background=\"@android:color/transparent\"\n    android:paddingLeft=\"10dp\"\n    >\n\n    <Button\n        android:id=\"@+id/btn_bread\"\n        android:minWidth=\"36dp\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"match_parent\"\n        android:background=\"?android:attr/selectableItemBackground\"\n        android:elevation=\"0dp\"\n        android:textAlignment=\"center\"\n        android:gravity=\"center_vertical\"\n        android:textAppearance=\"?android:attr/textAppearanceSmall\"\n        android:textColor=\"?android:attr/textColorPrimary\" />\n\n    <ImageButton\n        android:id=\"@+id/imb_bread\"\n        android:layout_width=\"36dp\"\n        android:layout_height=\"36dp\"\n        android:src=\"@drawable/ic_chevron_right_white_24dp\"\n        android:background=\"?android:attr/selectableItemBackground\"\n        />\n\n</LinearLayout>"
  },
  {
    "path": "filepicker/src/main/res/layout/buket_list_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"@dimen/album_item_height\">\n\n    <ImageView\n        android:id=\"@+id/album_cover\"\n        android:layout_width=\"40dp\"\n        android:layout_height=\"40dp\"\n        android:layout_centerVertical=\"true\"\n        android:layout_marginStart=\"16dp\"\n        android:layout_marginLeft=\"16dp\" />\n\n    <TextView\n        android:id=\"@+id/album_name\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignTop=\"@id/album_cover\"\n        android:layout_marginStart=\"8dp\"\n        android:layout_toEndOf=\"@id/album_cover\"\n        android:ellipsize=\"end\"\n        android:maxLines=\"1\"\n        android:textColor=\"?attr/album.dropdown.title.color\"\n        android:textSize=\"16sp\"\n        android:layout_marginLeft=\"8dp\"\n        android:layout_toRightOf=\"@id/album_cover\" />\n\n    <TextView\n        android:id=\"@+id/album_media_count\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_alignStart=\"@id/album_name\"\n        android:layout_below=\"@id/album_name\"\n        android:layout_marginTop=\"4dp\"\n        android:layout_toEndOf=\"@id/album_cover\"\n        android:ellipsize=\"end\"\n        android:maxLines=\"1\"\n        android:textColor=\"?album.dropdown.count.color\"\n        android:textSize=\"14sp\"\n        android:layout_alignLeft=\"@id/album_name\"\n        android:layout_toRightOf=\"@id/album_cover\" />\n</RelativeLayout>"
  },
  {
    "path": "filepicker/src/main/res/layout/empty_file_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    >\n\n    <TextView\n        android:id=\"@+id/textView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_centerVertical=\"true\"\n        android:text=\"空\" />\n</RelativeLayout>"
  },
  {
    "path": "filepicker/src/main/res/layout/ess_media_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?><!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    >\n\n    <FrameLayout\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:id=\"@+id/media\"\n        >\n        <ImageView\n            android:id=\"@+id/media_thumbnail\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:scaleType=\"centerCrop\"\n            />\n\n        <android.support.v7.widget.AppCompatCheckBox\n            android:id=\"@+id/check_view\"\n            android:theme=\"@style/checkbox\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentStart=\"true\"\n            android:layout_alignParentTop=\"true\"\n            android:layout_gravity=\"top|right\" />\n\n        <ImageView\n            android:id=\"@+id/gif\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"right|bottom\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginRight=\"8dp\"\n            android:src=\"@drawable/ic_gif\"\n            android:visibility=\"gone\" />\n\n        <TextView\n            android:id=\"@+id/video_duration\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"right|bottom\"\n            android:layout_marginBottom=\"8dp\"\n            android:layout_marginRight=\"8dp\"\n            android:textColor=\"@android:color/white\"\n            android:textSize=\"12sp\"\n            android:visibility=\"gone\" />\n    </FrameLayout>\n\n    <FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:id=\"@+id/capture\"\n        android:visibility=\"gone\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"#EAEEF4\"\n        android:foreground=\"?android:selectableItemBackground\"\n        >\n\n        <TextView\n            android:id=\"@+id/hint\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:drawablePadding=\"8dp\"\n            android:drawableTop=\"@drawable/ic_photo_camera_white_24dp\"\n            android:gravity=\"center\"\n            android:text=\"拍一张\"\n            android:textSize=\"14sp\"\n            />\n\n\n    </FrameLayout>\n\n\n</FrameLayout>"
  },
  {
    "path": "filepicker/src/main/res/layout/fragment_file_type_list.xml",
    "content": "<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\"com.ess.filepicker.activity.FileTypeListFragment\">\n\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/rcv_file_list_scan\"\n        android:scrollbars=\"vertical\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"/>\n\n</FrameLayout>\n"
  },
  {
    "path": "filepicker/src/main/res/layout/item_capture.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"?selectableItemBackground\"\n    >\n\n\n    <TextView\n        android:id=\"@+id/hint\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:drawablePadding=\"8dp\"\n        android:drawableTop=\"@drawable/ic_photo_camera_white_24dp\"\n        android:gravity=\"center\"\n        android:text=\"拍一张\"\n        android:textSize=\"14sp\"\n        />\n\n\n</FrameLayout>"
  },
  {
    "path": "filepicker/src/main/res/layout/item_file_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"54dp\"\n    android:gravity=\"center_vertical\"\n    android:orientation=\"horizontal\"\n    android:paddingLeft=\"10dp\"\n    android:background=\"#fff\"\n    >\n\n    <ImageView\n        android:id=\"@+id/iv_item_file_select_left\"\n        android:layout_width=\"36dp\"\n        android:layout_height=\"42dp\"\n        android:src=\"@mipmap/apk\" />\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:orientation=\"horizontal\"\n        android:layout_marginLeft=\"15dp\"\n        android:paddingRight=\"10dp\"\n        android:gravity=\"center_vertical\"\n        android:background=\"@drawable/bg_bottom_line_gray\"\n        >\n\n        <LinearLayout\n            android:layout_width=\"0dp\"\n            android:layout_weight=\"1\"\n            android:layout_height=\"match_parent\"\n            android:orientation=\"vertical\"\n            android:gravity=\"center_vertical\"\n            >\n            <TextView\n                android:id=\"@+id/tv_item_file_list\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"22dp\"\n                android:gravity=\"center_vertical\"\n                android:maxLines=\"1\"\n                android:ellipsize=\"end\"\n                android:text=\"风控.apk\"\n                android:textColor=\"#333\"\n                android:textSize=\"14sp\" />\n\n            <TextView\n                android:id=\"@+id/tv_item_file_list_desc\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"22dp\"\n                android:maxLines=\"1\"\n                android:gravity=\"center_vertical\"\n                android:ellipsize=\"end\"\n                android:text=\"文件： 文件夹：\"\n                android:textColor=\"@android:color/darker_gray\"\n                android:textSize=\"12sp\" />\n        </LinearLayout>\n\n        <android.support.v7.widget.AppCompatCheckBox\n            android:id=\"@+id/checkbox_item_file_list\"\n            android:checked=\"true\"\n            android:enabled=\"false\"\n            android:layout_width=\"32dp\"\n            android:layout_height=\"32dp\"\n            />\n\n        <ImageView\n            android:id=\"@+id/iv_item_file_select_right\"\n            android:layout_width=\"16dp\"\n            android:layout_height=\"wrap_content\"\n            android:src=\"@mipmap/right\"\n            />\n\n    </LinearLayout>\n\n\n\n</LinearLayout>"
  },
  {
    "path": "filepicker/src/main/res/layout/item_select_sdcard.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<TextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:background=\"@drawable/bg_bottom_line_gray\"\n    android:textAppearance=\"?android:attr/textAppearanceSmallPopupMenu\"\n    android:layout_marginLeft=\"15dp\"\n    android:id=\"@+id/tv_item_select_sdcard\"\n    android:gravity=\"center_vertical\"\n    android:layout_height=\"54dp\"\n    />\n"
  },
  {
    "path": "filepicker/src/main/res/layout/loading_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.constraint.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <ProgressBar\n        android:id=\"@+id/progressBar\"\n        style=\"?android:attr/progressBarStyleSmall\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_marginBottom=\"7dp\"\n        android:layout_marginTop=\"27dp\"\n        app:layout_constraintBottom_toTopOf=\"@+id/textView\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\"\n        app:layout_constraintVertical_chainStyle=\"packed\" />\n\n    <TextView\n        android:id=\"@+id/textView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"正在加载\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintEnd_toEndOf=\"parent\"\n        app:layout_constraintStart_toStartOf=\"parent\"\n        app:layout_constraintTop_toBottomOf=\"@+id/progressBar\" />\n\n</android.support.constraint.ConstraintLayout>"
  },
  {
    "path": "filepicker/src/main/res/layout/pop_select_sdcard.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<android.support.v7.widget.RecyclerView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/rcv_pop_select_sdcard\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:background=\"#fff\" />\n"
  },
  {
    "path": "filepicker/src/main/res/layout-v21/activity_select_file.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/coordinator_layout\"\n    tools:context=\".activity.SelectFileByBrowserActivity\">\n\n    <android.support.design.widget.AppBarLayout\n        android:layout_height=\"wrap_content\"\n        android:layout_width=\"match_parent\"\n        android:theme=\"@style/AppTheme.AppBarOverlay\"\n        android:background=\"?attr/colorPrimary\">\n\n        <android.support.v7.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"?attr/actionBarSize\"\n            app:popupTheme=\"@style/AppTheme.PopupOverlay\"\n            app:layout_scrollFlags=\"scroll|enterAlways\"/>\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"36dp\"\n            android:orientation=\"horizontal\"\n            >\n            <ImageView\n                android:visibility=\"gone\"\n                android:id=\"@+id/imb_select_sdcard\"\n                android:layout_gravity=\"center_vertical\"\n                android:layout_width=\"36dp\"\n                android:layout_height=\"36dp\"\n                android:rotation=\"90\"\n                android:scaleType=\"centerInside\"\n                android:src=\"@drawable/ic_chevron_right_white_24dp\"\n                android:background=\"?android:attr/selectableItemBackgroundBorderless\"\n                />\n            <android.support.v7.widget.RecyclerView\n                android:id=\"@+id/breadcrumbs_view\"\n                android:layout_width=\"match_parent\"\n                android:paddingRight=\"10dp\"\n                android:layout_height=\"?attr/actionBarSize\"\n                />\n        </LinearLayout>\n\n\n    </android.support.design.widget.AppBarLayout>\n\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/rcv_file_list\"\n        android:layout_width=\"match_parent\"\n        android:scrollbars=\"vertical\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n        />\n\n</android.support.design.widget.CoordinatorLayout>\n"
  },
  {
    "path": "filepicker/src/main/res/layout-v21/bread_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"36dp\"\n    android:orientation=\"horizontal\"\n    android:gravity=\"center_vertical\"\n    android:background=\"@android:color/transparent\"\n    android:paddingLeft=\"10dp\"\n    >\n\n    <Button\n        android:id=\"@+id/btn_bread\"\n        android:minWidth=\"36dp\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"match_parent\"\n        android:background=\"?android:attr/selectableItemBackgroundBorderless\"\n        android:elevation=\"0dp\"\n        android:textAlignment=\"center\"\n        android:gravity=\"center_vertical\"\n        android:textAppearance=\"?android:attr/textAppearanceSmall\"\n        android:textColor=\"?android:attr/textColorPrimary\" />\n\n    <ImageButton\n        android:id=\"@+id/imb_bread\"\n        android:layout_width=\"36dp\"\n        android:layout_height=\"36dp\"\n        android:src=\"@drawable/ic_chevron_right_white_24dp\"\n        android:background=\"?android:attr/selectableItemBackgroundBorderless\"\n        />\n\n</LinearLayout>"
  },
  {
    "path": "filepicker/src/main/res/menu/browse_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/browser_select_count\"\n        android:orderInCategory=\"100\"\n        android:title=\"选中(0)\"\n        app:showAsAction=\"always\"/>\n\n    <item\n        android:id=\"@+id/browser_sort\"\n        android:orderInCategory=\"100\"\n        android:title=\"排序\"\n        app:showAsAction=\"always\"\n        android:icon=\"@drawable/ic_sort_white_24dp\"\n        />\n\n</menu>"
  },
  {
    "path": "filepicker/src/main/res/menu/media_menu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/browser_select_count\"\n        android:orderInCategory=\"100\"\n        android:title=\"选中(0)\"\n        app:showAsAction=\"always\"/>\n\n</menu>"
  },
  {
    "path": "filepicker/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<resources>\n    <attr name=\"toolbar\" format=\"reference\"/>\n    <attr name=\"album.dropdown.title.color\" format=\"reference|color\"/>\n    <attr name=\"album.dropdown.count.color\" format=\"reference|color\"/>\n    <attr name=\"album.element.color\" format=\"reference|color\"/>\n    <attr name=\"album.thumbnail.placeholder\" format=\"reference|color\"/>\n    <attr name=\"album.emptyView\" format=\"reference\"/>\n    <attr name=\"album.emptyView.textColor\" format=\"reference|color\"/>\n    <attr name=\"listPopupWindowStyle\" format=\"reference\"/>\n    <attr name=\"page.bg\" format=\"reference|color\"/>\n    <attr name=\"bottomToolbar.bg\" format=\"reference|color\"/>\n    <attr name=\"bottomToolbar.preview.textColor\" format=\"reference|color\"/>\n    <attr name=\"bottomToolbar.apply.textColor\" format=\"reference|color\"/>\n    <attr name=\"preview.bottomToolbar.back.textColor\" format=\"reference|color\"/>\n    <attr name=\"preview.bottomToolbar.apply.textColor\" format=\"reference|color\"/>\n    <attr name=\"item.placeholder\" format=\"reference|color\"/>\n    <attr name=\"item.checkCircle.backgroundColor\" format=\"reference|color\"/>\n    <attr name=\"item.checkCircle.borderColor\" format=\"reference|color\"/>\n    <attr name=\"capture.textColor\" format=\"reference|color\"/>\n</resources>"
  },
  {
    "path": "filepicker/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<resources>\n\n    <color name=\"preview_bottom_toolbar_bg\">#CC000000</color>\n    <color name=\"preview_bottom_size\">#61FFFFFF</color>\n\n</resources>"
  },
  {
    "path": "filepicker/src/main/res/values/colors_dracula.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<resources>\n    <color name=\"dracula_primary\">#263237</color>\n    <color name=\"dracula_primary_dark\">#1D282C</color>\n\n    <color name=\"dracula_album_popup_bg\">#34474E</color>\n    <color name=\"dracula_album_dropdown_title_text\">#DEFFFFFF</color>\n    <color name=\"dracula_album_dropdown_count_text\">#89FFFFFF</color>\n    <color name=\"dracula_album_dropdown_thumbnail_placeholder\">#455A64</color>\n    <color name=\"dracula_album_empty_view\">#4DFFFFFF</color>\n\n    <color name=\"dracula_item_placeholder\">#37474F</color>\n    <color name=\"dracula_item_checkCircle_backgroundColor\">#263237</color>\n    <color name=\"dracula_item_checkCircle_borderColor\">#FFFFFF</color>\n    <color name=\"dracula_capture\">#FFFFFF</color>\n\n    <color name=\"dracula_page_bg\">#232E32</color>\n    <color name=\"dracula_bottom_toolbar_bg\">#34474E</color>\n\n    <color name=\"dracula_bottom_toolbar_preview_text\">#DEFFFFFF</color>\n    <color name=\"dracula_bottom_toolbar_preview_text_disable\">#4DFFFFFF</color>\n    <color name=\"dracula_bottom_toolbar_apply_text\">#03A9F4</color>\n    <color name=\"dracula_bottom_toolbar_apply_text_disable\">#4D03A9F4</color>\n\n    <color name=\"dracula_preview_bottom_toolbar_back_text\">#FFFFFF</color>\n    <color name=\"dracula_preview_bottom_toolbar_apply_text\">#03A9F4</color>\n    <color name=\"dracula_preview_bottom_toolbar_apply_text_disable\">#4D03A9F4</color>\n</resources>"
  },
  {
    "path": "filepicker/src/main/res/values/colors_zhihu.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 elec Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<resources>\n    <color name=\"elec_primary\">#1bbc9b</color>\n    <color name=\"elec_primary_dark\">#1bbc9b</color>\n\n    <color name=\"elec_album_popup_bg\">#FFFFFF</color>\n    <color name=\"elec_album_dropdown_title_text\">#DE000000</color>\n    <color name=\"elec_album_dropdown_count_text\">#999999</color>\n    <color name=\"elec_album_dropdown_thumbnail_placeholder\">#EAEEF4</color>\n    <color name=\"elec_album_empty_view\">#4D000000</color>\n\n    <color name=\"elec_item_placeholder\">#EAEEF4</color>\n    <color name=\"elec_item_checkCircle_backgroundColor\">#1bbc9b</color>\n    <color name=\"elec_item_checkCircle_borderColor\">#FFFFFF</color>\n    <color name=\"elec_capture\">#424242</color>\n\n    <color name=\"elec_page_bg\">#FFFFFF</color>\n    <color name=\"elec_bottom_toolbar_bg\">#FFFFFF</color>\n\n    <color name=\"elec_bottom_toolbar_preview_text\">#000000</color>\n    <color name=\"elec_bottom_toolbar_preview_text_disable\">#000000</color>\n    <color name=\"elec_bottom_toolbar_apply_text\">#1bbc9b</color>\n    <color name=\"elec_bottom_toolbar_apply_text_disable\">#1bbc9b</color>\n\n    <color name=\"elec_preview_bottom_toolbar_back_text\">#FFFFFF</color>\n    <color name=\"elec_preview_bottom_toolbar_apply_text\">#1bbc9b</color>\n    <color name=\"elec_preview_bottom_toolbar_apply_text_disable\">#4D0077D9</color>\n</resources>"
  },
  {
    "path": "filepicker/src/main/res/values/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  Copyright 2017 Zhihu Inc.\n\n  Licensed under the Apache License, Version 2.0 (the \"License\");\n  you may not use this file except in compliance with the License.\n  You may obtain a copy of the License at\n\n  http://www.apache.org/licenses/LICENSE-2.0\n\n  Unless required by applicable law or agreed to in writing, software\n  distributed under the License is distributed on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  See the License for the specific language governing permissions and\n  limitations under the License.\n  -->\n<resources>\n    <dimen name=\"media_grid_size\">48dp</dimen>\n    <dimen name=\"media_grid_spacing\">4dp</dimen>\n\n    <dimen name=\"album_item_height\">72dp</dimen>\n</resources>"
  },
  {
    "path": "filepicker/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">FilePicker</string>\n    <string name=\"folder_desc\">文件:%1$s&#160;&#160;|&#160;&#160;文件夹:%2$s</string>\n    <string name=\"file_desc\">%1$s&#160;&#160;|&#160;&#160;%2$s</string>\n    <string name=\"selected_file_count\">选中(%1$s/%2$s)</string>\n    <string-array name=\"sort_list\">\n        <item>按名称</item>\n        <item>按时间</item>\n        <item>按大小</item>\n        <item>按类型</item>\n    </string-array>\n    <string-array name=\"sort_list_scan\">\n        <item>按名称</item>\n        <item>按时间</item>\n        <item>按大小</item>\n    </string-array>\n\n    <!-- TODO: Remove or change this placeholder text -->\n    <string name=\"hello_blank_fragment\">Hello blank fragment</string>\n</resources>\n"
  },
  {
    "path": "filepicker/src/main/res/values/styles.xml",
    "content": "<resources xmlns:tools=\"http://schemas.android.com/tools\">\n\n\t<style name=\"OverflowButtonStyle\" parent=\"android:Widget.ActionButton.Overflow\">\n\t\t<item name=\"android:src\">@drawable/ic_sort_white_24dp</item>\n\t</style>\n\n\t<style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\"/>\n\n\t<style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\"/>\n\n\n\t//====================================== Theme Electricity ===========================================\n\n\t<style name=\"FilePicker.Elec\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n\t\t<item name=\"colorPrimary\">@color/elec_primary</item>\n\t\t<item name=\"colorPrimaryDark\">@color/elec_primary_dark</item>\n\t\t<item name=\"toolbar\">@style/Toolbar.elec</item>\n\t\t<item name=\"album.dropdown.title.color\">@color/elec_album_dropdown_title_text</item>\n\t\t<item name=\"album.dropdown.count.color\">@color/elec_album_dropdown_count_text</item>\n\t\t<item name=\"album.element.color\">@android:color/white</item>\n\t\t<item name=\"album.thumbnail.placeholder\">@color/elec_album_dropdown_thumbnail_placeholder</item>\n\t\t<item name=\"album.emptyView\">@drawable/ic_empty_elec</item>\n\t\t<item name=\"album.emptyView.textColor\">@color/elec_album_empty_view</item>\n\t\t<item name=\"item.placeholder\">@color/elec_item_placeholder</item>\n\t\t<item name=\"item.checkCircle.backgroundColor\">@color/elec_item_checkCircle_backgroundColor</item>\n\t\t<item name=\"item.checkCircle.borderColor\">@color/elec_item_checkCircle_borderColor</item>\n\t\t<item name=\"page.bg\">@color/elec_page_bg</item>\n\t\t<item name=\"bottomToolbar.bg\">@color/elec_bottom_toolbar_bg</item>\n\t\t<item name=\"bottomToolbar.preview.textColor\">@color/elec_bottom_toolbar_preview</item>\n\t\t<item name=\"bottomToolbar.apply.textColor\">@color/elec_bottom_toolbar_apply</item>\n\t\t<item name=\"preview.bottomToolbar.back.textColor\">@color/elec_preview_bottom_toolbar_back_text</item>\n\t\t<item name=\"preview.bottomToolbar.apply.textColor\">@color/elec_preview_bottom_toolbar_apply</item>\n\t\t<item name=\"listPopupWindowStyle\">@style/Popup.elec</item>\n\t\t<item name=\"capture.textColor\">@color/elec_capture</item>\n\t</style>\n\n\t<style name=\"Toolbar.elec\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\">\n\n\t</style>\n\n\t<style name=\"Popup.elec\" parent=\"Widget.AppCompat.Light.ListPopupWindow\">\n\t\t<item name=\"android:popupBackground\">@color/elec_album_popup_bg</item>\n\t</style>\n\n\t//===================================== Theme Dracula ==========================================\n\n\t<style name=\"FilePicker.Dracula\" parent=\"Theme.AppCompat.NoActionBar\">\n\t\t<item name=\"colorPrimary\">@color/dracula_primary</item>\n\t\t<item name=\"colorPrimaryDark\">@color/dracula_primary_dark</item>\n\t\t<item name=\"toolbar\">@style/Toolbar.Dracula</item>\n\t\t<item name=\"album.dropdown.title.color\">@color/dracula_album_dropdown_title_text</item>\n\t\t<item name=\"album.dropdown.count.color\">@color/dracula_album_dropdown_count_text</item>\n\t\t<item name=\"album.element.color\">@android:color/white</item>\n\t\t<item name=\"album.thumbnail.placeholder\">@color/dracula_album_dropdown_thumbnail_placeholder</item>\n\t\t<item name=\"album.emptyView\">@drawable/ic_empty_dracula</item>\n\t\t<item name=\"album.emptyView.textColor\">@color/dracula_album_empty_view</item>\n\t\t<item name=\"item.placeholder\">@color/dracula_item_placeholder</item>\n\t\t<item name=\"item.checkCircle.backgroundColor\">@color/dracula_item_checkCircle_backgroundColor</item>\n\t\t<item name=\"item.checkCircle.borderColor\">@color/dracula_item_checkCircle_borderColor</item>\n\t\t<item name=\"page.bg\">@color/dracula_page_bg</item>\n\t\t<item name=\"bottomToolbar.bg\">@color/dracula_bottom_toolbar_bg</item>\n\t\t<item name=\"bottomToolbar.preview.textColor\">@color/dracula_bottom_toolbar_preview</item>\n\t\t<item name=\"bottomToolbar.apply.textColor\">@color/dracula_bottom_toolbar_apply</item>\n\t\t<item name=\"preview.bottomToolbar.back.textColor\">@color/dracula_preview_bottom_toolbar_back_text</item>\n\t\t<item name=\"preview.bottomToolbar.apply.textColor\">@color/dracula_preview_bottom_toolbar_apply</item>\n\t\t<item name=\"android:listPopupWindowStyle\">@style/Popup.Dracula</item>\n\t\t<item name=\"listPopupWindowStyle\">@style/Popup.Dracula</item>\n\t\t<item name=\"capture.textColor\">@color/dracula_capture</item>\n\t</style>\n\n\t<style name=\"Toolbar.Dracula\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\">\n\n\t</style>\n\n\t<style name=\"Popup.Dracula\" parent=\"Widget.AppCompat.ListPopupWindow\">\n\t\t<item name=\"android:popupBackground\">@color/dracula_album_popup_bg</item>\n\t</style>\n\n</resources>\n"
  },
  {
    "path": "filepicker/src/main/res/values-v21/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"checkbox\" parent=\"Widget.AppCompat.CompoundButton.CheckBox\">\n        <item name=\"android:colorControlNormal\">@color/elec_album_dropdown_count_text</item>\n        <item name=\"android:colorControlActivated\">@color/elec_primary</item>\n    </style>\n</resources>"
  },
  {
    "path": "filepicker/src/main/res/xml/provider_paths.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <external-path name=\"external_files\" path=\".\"/>\n</paths>"
  },
  {
    "path": "filepicker/src/test/java/com/ess/filepicker/ExampleUnitTest.java",
    "content": "package com.ess.filepicker;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Apr 16 15:31:49 CST 2018\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-4.4-all.zip\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app', ':filepicker'\n"
  }
]