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