├── .gitignore
├── .gradle
└── 2.4
│ └── taskArtifacts
│ ├── cache.properties
│ ├── cache.properties.lock
│ ├── fileHashes.bin
│ ├── fileSnapshots.bin
│ ├── outputFileStates.bin
│ └── taskArtifacts.bin
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── lizhiyun.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
├── vcs.xml
└── workspace.xml
├── README.md
├── app
├── app.iml
├── build.gradle
├── libs
│ └── gson-2.0.jar
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ ├── a.gif
│ ├── anim.gif
│ ├── c.gif
│ ├── d.gif
│ ├── e.gif
│ ├── f.gif
│ ├── g.gif
│ └── h.gif
│ ├── java
│ ├── com
│ │ ├── example
│ │ │ └── ui
│ │ │ │ ├── App.java
│ │ │ │ ├── AppEntry.java
│ │ │ │ ├── CrashHandler.java
│ │ │ │ ├── FileDownloadActivity.java
│ │ │ │ ├── ImageloaderActivity.java
│ │ │ │ └── MyUtils.java
│ │ └── litesuits
│ │ │ └── go
│ │ │ ├── OverloadPolicy.java
│ │ │ ├── PriorityRunnable.java
│ │ │ ├── SchedulePolicy.java
│ │ │ ├── SmartExecutor.java
│ │ │ └── utils
│ │ │ └── GoUtil.java
│ └── download
│ │ ├── http
│ │ ├── core
│ │ │ ├── Http.java
│ │ │ ├── HttpManager.java
│ │ │ └── HttpTask.java
│ │ ├── entity
│ │ │ ├── CustomJsonReader.java
│ │ │ ├── FileEntity.java
│ │ │ ├── ResultData.java
│ │ │ ├── SimpleJsonReader.java
│ │ │ └── User.java
│ │ ├── exception
│ │ │ ├── AppException.java
│ │ │ └── IfNeedLoginGlobalException.java
│ │ ├── listener
│ │ │ ├── AbsCallback.java
│ │ │ ├── CustomJsonReaderCallback.java
│ │ │ ├── FileCallback.java
│ │ │ ├── ICallback.java
│ │ │ ├── JsonCallback.java
│ │ │ ├── JsonListCallback.java
│ │ │ ├── JsonReaderCallback.java
│ │ │ ├── JsonReaderListCallback.java
│ │ │ ├── OnGlobalExceptionListener.java
│ │ │ ├── OnProgressDownloadListener.java
│ │ │ ├── OnProgressUpdateListener.java
│ │ │ └── StringCallback.java
│ │ ├── request
│ │ │ ├── Request.java
│ │ │ └── RequestBuilder.java
│ │ └── util
│ │ │ ├── HttpUrlConnectionUtil.java
│ │ │ └── UploadUtil.java
│ │ ├── imageLoader
│ │ ├── cache
│ │ │ ├── BitmapCache.java
│ │ │ └── DiskLruCache.java
│ │ ├── config
│ │ │ ├── FailedDrawable.java
│ │ │ ├── ImageConfig.java
│ │ │ ├── LoadOrder.java
│ │ │ └── LoadingDrawable.java
│ │ ├── core
│ │ │ ├── BmManager.java
│ │ │ ├── Image.java
│ │ │ ├── ImageLoader.java
│ │ │ ├── LoadTask.java
│ │ │ └── RunningTasksManager.java
│ │ ├── listener
│ │ │ ├── CustomDisplayMethod.java
│ │ │ └── OnProgressUpdatedListener.java
│ │ ├── loader
│ │ │ ├── AssetsLoader.java
│ │ │ ├── DrawableLoader.java
│ │ │ ├── FileLoader.java
│ │ │ ├── HttpLoader.java
│ │ │ ├── Load.java
│ │ │ └── LoadInterface.java
│ │ ├── request
│ │ │ ├── BitmapRequest.java
│ │ │ └── BitmapRequestBuilder.java
│ │ ├── util
│ │ │ ├── BitmapOperate.java
│ │ │ ├── FaceCropper.java
│ │ │ ├── GaussianBlur.java
│ │ │ └── ImageSizeUtil.java
│ │ └── view
│ │ │ └── PowerImageView.java
│ │ ├── otherFileLoader
│ │ ├── core
│ │ │ ├── ConnectRunnable.java
│ │ │ ├── ConnectionChangeReceiver.java
│ │ │ ├── Constants.java
│ │ │ ├── DownloadService.java
│ │ │ ├── DownloadTask.java
│ │ │ └── DownloadThread.java
│ │ ├── db
│ │ │ ├── DLDBHelper.java
│ │ │ ├── DLDBManager.java
│ │ │ └── DownFileManager.java
│ │ ├── listener
│ │ │ └── DownloadListener.java
│ │ ├── request
│ │ │ └── DownFile.java
│ │ └── util
│ │ │ └── ToastUtils.java
│ │ └── utils
│ │ └── Util.java
│ ├── res
│ ├── drawable-hdpi
│ │ ├── anim.gif
│ │ ├── face.jpg
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ │ └── ic_launcher.png
│ ├── layout
│ │ ├── activity_applist_item.xml
│ │ ├── activity_filedownload.xml
│ │ ├── activity_imageloader.xml
│ │ └── image_list_item.xml
│ ├── raw
│ │ └── anim.gif
│ └── values
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── resources
│ └── download
│ └── imageLoader
│ └── config
│ └── image
│ ├── loadfailed.png
│ └── loading.png
├── build.gradle
├── down.gif
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── import-summary.txt
├── lib_download.iml
├── local.properties
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Java class files
2 | *.class
3 |
4 | # Local configuration file (sdk path, etc)
5 | local.properties
6 |
7 | #IntelliJ IDEA
8 | .idea
9 | *.iml
10 |
11 | #Gradle
12 | .gradle
13 | build
14 |
15 | signing.properties
16 | CMakeLists.txt
17 | src/main/obj
18 | src/main/libs
--------------------------------------------------------------------------------
/.gradle/2.4/taskArtifacts/cache.properties:
--------------------------------------------------------------------------------
1 | #Wed May 18 16:31:46 CST 2016
2 |
--------------------------------------------------------------------------------
/.gradle/2.4/taskArtifacts/cache.properties.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/.gradle/2.4/taskArtifacts/cache.properties.lock
--------------------------------------------------------------------------------
/.gradle/2.4/taskArtifacts/fileHashes.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/.gradle/2.4/taskArtifacts/fileHashes.bin
--------------------------------------------------------------------------------
/.gradle/2.4/taskArtifacts/fileSnapshots.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/.gradle/2.4/taskArtifacts/fileSnapshots.bin
--------------------------------------------------------------------------------
/.gradle/2.4/taskArtifacts/outputFileStates.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/.gradle/2.4/taskArtifacts/outputFileStates.bin
--------------------------------------------------------------------------------
/.gradle/2.4/taskArtifacts/taskArtifacts.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/.gradle/2.4/taskArtifacts/taskArtifacts.bin
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | lib_download
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/lizhiyun.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # lib_download
2 | ## 效果图
3 |
4 |
5 | 这是一个处理异步下载的库,包含图片加载,多文件多线程断点下载,http和ormgo(马天宇的开源),特点如下:
6 |
7 | 全局公用一个线程池
8 |
9 | 非ImageView的view也支持哦
10 |
11 | 支持预加载:
12 | ```java
13 | BmLoader.preLoad(uri);
14 | ```
15 |
16 | 支持本地和网络图片,径格式示例为:
17 | ```xml
18 | "http://img.blog.csdn.net/20160114230048304",
19 | "assets://anim.gif",
20 | "drawable://"+R.drawable.anim,
21 | "file:///mnt/sdcard/paint.png",
22 | ```
23 | 优化了listview等快速滑动时的图片加载
24 |
25 | 圆角图采用了性能最优的方案
26 |
27 | 可设置模糊效果和头像识别自动剪裁功能
28 |
29 | 通过各种手段保障gridview等在有圆角和大量gif的情况下快速滑动时也能依旧极度流畅。
30 |
31 | 通过自定义的方式确保默认的加载中和加载失败的图片在任何形状的view中都能显示完整并且大小适当。
32 |
33 | 如果view使用或者继承download.imageLoader.view.GifMovieView这个类的话支持gif图,否则只能用回调自己自定义view实现。
34 |
35 | 设置自定义显示方法这样就可以实现各种功能如给textviw设置上下左右的图,给子view设置网络图片,给remoteview设置网络图片等等。
36 | ```java
37 | Image.with(this).load("http://img.my.csdn.net/uploads/201407/26/1406383265_8550.jpg")
38 | .size(130, 130).blur(false)
39 | .customDisplay(new CustomDisplayMethod() {
40 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
41 | @Override
42 | public void display(Drawable bitmap, Movie movie) {
43 | mTv.setCompoundDrawablesRelativeWithIntrinsicBounds(bitmap, null, null, null);
44 | }
45 | }).into(mTv);
46 | ```
47 |
48 | 如果使用类download.imageLoader.view.GifMovieView,调用方法更简单了:
49 | ```java
50 | view.rectangle().face(true).blur(false).setBorder(Color.BLUE, 15f).bind(uri);
51 | view.circle().blur(false).setBorder(Color.BLACK, 0f).bind(uri);
52 | view.round(50).blur(false).setBorder(Color.GREEN, 0f).bind(uri);
53 | view.bind(uri)
54 |
55 | ```
56 |
57 | 断点下载 :可多界面监听同一下载,恢复网络时自动恢复之前失败的下载,可指定各自的下载目录,带md5校验
58 | ```java
59 | DownFileManager.getInstance(FileDownloadActivity.this).download(entry.url,new DownloadListener() {
60 | @Override
61 | public void success(String path) {
62 |
63 | }
64 |
65 | @Override
66 | public void progress(int currentLen, int totalLen) {
67 |
68 | }
69 |
70 | @Override
71 | public void error(String errror) {
72 |
73 | }
74 |
75 | @Override
76 | public void pause() {
77 |
78 | }
79 |
80 | @Override
81 | public void cancel() {
82 |
83 | }
84 | });
85 |
86 | ```
87 |
88 | HTTP模块:
89 | ```java
90 | Http.with(this).url(url).progressDownload(new OnProgressDownloadListener() {
91 | @Override
92 | public void onProgressDownload(int curLength, int totalLength) {
93 |
94 | }
95 | }).progressUpdate(new OnProgressUpdateListener() {
96 | @Override
97 | public void onProgressUpdate(int curLength, int totalLength) {
98 |
99 | }
100 | }).callback(new JsonReaderListCallback("data") {
101 | @Override
102 | public void onSuccess(ArrayList result) {
103 | Log.e("test",""+result.size());
104 | for (int i = 0;i
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | android {
3 | compileSdkVersion 19
4 | buildToolsVersion "23.0.3"
5 |
6 | defaultConfig {
7 | applicationId "com.example.ui"
8 | minSdkVersion 8
9 | targetSdkVersion 17
10 | }
11 |
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
16 | }
17 | }
18 | }
19 |
20 | dependencies {
21 | compile files('libs/gson-2.0.jar')
22 | }
--------------------------------------------------------------------------------
/app/libs/gson-2.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/libs/gson-2.0.jar
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/assets/a.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/assets/a.gif
--------------------------------------------------------------------------------
/app/src/main/assets/anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/assets/anim.gif
--------------------------------------------------------------------------------
/app/src/main/assets/c.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/assets/c.gif
--------------------------------------------------------------------------------
/app/src/main/assets/d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/assets/d.gif
--------------------------------------------------------------------------------
/app/src/main/assets/e.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/assets/e.gif
--------------------------------------------------------------------------------
/app/src/main/assets/f.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/assets/f.gif
--------------------------------------------------------------------------------
/app/src/main/assets/g.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/assets/g.gif
--------------------------------------------------------------------------------
/app/src/main/assets/h.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/assets/h.gif
--------------------------------------------------------------------------------
/app/src/main/java/com/example/ui/App.java:
--------------------------------------------------------------------------------
1 | package com.example.ui;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Activity;
5 | import android.app.Application;
6 | import android.content.ComponentCallbacks;
7 | import android.content.res.Configuration;
8 | import android.os.Build;
9 | import android.os.Bundle;
10 |
11 | /**
12 | * Created by lizhiyun on 16/6/15.
13 | */
14 | public class App extends Application {
15 | @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
16 | @Override
17 | public void onCreate() {
18 | super.onCreate();
19 |
20 |
21 | //在这里为应用设置异常处理程序,然后我们的程序才能捕获未处理的异常
22 | CrashHandler crashHandler = CrashHandler.getInstance();
23 | crashHandler.init(this);
24 | this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
25 | @Override
26 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
27 |
28 | }
29 |
30 | @Override
31 | public void onActivityStarted(Activity activity) {
32 |
33 | }
34 |
35 | @Override
36 | public void onActivityResumed(Activity activity) {
37 |
38 | }
39 |
40 | @Override
41 | public void onActivityPaused(Activity activity) {
42 |
43 | }
44 |
45 | @Override
46 | public void onActivityStopped(Activity activity) {
47 |
48 | }
49 |
50 | @Override
51 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
52 |
53 | }
54 |
55 | @Override
56 | public void onActivityDestroyed(Activity activity) {
57 |
58 | }
59 | });
60 | this.registerComponentCallbacks(new ComponentCallbacks() {
61 | @Override
62 | public void onConfigurationChanged(Configuration newConfig) {
63 |
64 | }
65 |
66 | @Override
67 | public void onLowMemory() {
68 |
69 | }
70 | });
71 |
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/ui/AppEntry.java:
--------------------------------------------------------------------------------
1 | package com.example.ui;
2 |
3 | import java.io.Serializable;
4 |
5 | import download.http.entity.SimpleJsonReader;
6 | import download.otherFileLoader.request.DownFile;
7 |
8 | /**
9 | * Created by Stay on 18/8/15.
10 | * Powered by www.stay4it.com
11 | */
12 | public class AppEntry extends SimpleJsonReader implements Serializable {
13 | public String name;
14 | public String icon;
15 | public String size;
16 | public String desc;
17 | public String url;
18 | public DownFile.DownloadStatus state = DownFile.DownloadStatus.IDLE;
19 | public int downLength;
20 | public int totalLength;
21 |
22 |
23 | @Override
24 | public String toString() {
25 | return name + "-----" + desc + "-----" + url;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/ui/CrashHandler.java:
--------------------------------------------------------------------------------
1 | package com.example.ui;
2 |
3 | import java.io.BufferedWriter;
4 | import java.io.File;
5 | import java.io.FileWriter;
6 | import java.io.IOException;
7 | import java.io.PrintWriter;
8 | import java.lang.Thread.UncaughtExceptionHandler;
9 | import java.text.SimpleDateFormat;
10 | import java.util.Date;
11 |
12 | import android.content.Context;
13 | import android.content.pm.PackageInfo;
14 | import android.content.pm.PackageManager;
15 | import android.content.pm.PackageManager.NameNotFoundException;
16 | import android.os.Build;
17 | import android.os.Environment;
18 | import android.os.Process;
19 | import android.util.Log;
20 |
21 | public class CrashHandler implements UncaughtExceptionHandler {
22 | private static final String TAG = "CrashHandler";
23 | private static final boolean DEBUG = true;
24 |
25 | private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/CrashTest/log/";
26 | private static final String FILE_NAME = "crash";
27 | private static final String FILE_NAME_SUFFIX = ".trace";
28 |
29 | private static CrashHandler sInstance = new CrashHandler();
30 | private UncaughtExceptionHandler mDefaultCrashHandler;
31 | private Context mContext;
32 |
33 | private CrashHandler() {
34 | }
35 |
36 | public static CrashHandler getInstance() {
37 | return sInstance;
38 | }
39 |
40 | public void init(Context context) {
41 | mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
42 | Thread.setDefaultUncaughtExceptionHandler(this);
43 | mContext = context.getApplicationContext();
44 | }
45 |
46 | /**
47 | * 这个是最关键的函数,当程序中有未被捕获的异常,系统将会自动调用#uncaughtException方法
48 | * thread为出现未捕获异常的线程,ex为未捕获的异常,有了这个ex,我们就可以得到异常信息。
49 | */
50 | @Override
51 | public void uncaughtException(Thread thread, Throwable ex) {
52 | try {
53 | //导出异常信息到SD卡中
54 | dumpExceptionToSDCard(ex);
55 | uploadExceptionToServer();
56 | //这里可以通过网络上传异常信息到服务器,便于开发人员分析日志从而解决bug
57 | } catch (IOException e) {
58 | e.printStackTrace();
59 | }
60 |
61 | ex.printStackTrace();
62 |
63 | //如果系统提供了默认的异常处理器,则交给系统去结束我们的程序,否则就由我们自己结束自己
64 | if (mDefaultCrashHandler != null) {
65 | mDefaultCrashHandler.uncaughtException(thread, ex);
66 | } else {
67 | Process.killProcess(Process.myPid());
68 | }
69 |
70 | }
71 |
72 | private void dumpExceptionToSDCard(Throwable ex) throws IOException {
73 | //如果SD卡不存在或无法使用,则无法把异常信息写入SD卡
74 | if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
75 | if (DEBUG) {
76 | Log.w(TAG, "sdcard unmounted,skip dump exception");
77 | return;
78 | }
79 | }
80 |
81 | File dir = new File(PATH);
82 | if (!dir.exists()) {
83 | dir.mkdirs();
84 | }
85 | long current = System.currentTimeMillis();
86 | String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));
87 | File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
88 |
89 | try {
90 | PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
91 | pw.println(time);
92 | dumpPhoneInfo(pw);
93 | pw.println();
94 | ex.printStackTrace(pw);
95 | pw.close();
96 | } catch (Exception e) {
97 | Log.e(TAG, "dump crash info failed");
98 | }
99 | }
100 |
101 | private void dumpPhoneInfo(PrintWriter pw) throws NameNotFoundException {
102 | PackageManager pm = mContext.getPackageManager();
103 | PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
104 | pw.print("App Version: ");
105 | pw.print(pi.versionName);
106 | pw.print('_');
107 | pw.println(pi.versionCode);
108 |
109 | //android版本号
110 | pw.print("OS Version: ");
111 | pw.print(Build.VERSION.RELEASE);
112 | pw.print("_");
113 | pw.println(Build.VERSION.SDK_INT);
114 |
115 | //手机制造商
116 | pw.print("Vendor: ");
117 | pw.println(Build.MANUFACTURER);
118 |
119 | //手机型号
120 | pw.print("Model: ");
121 | pw.println(Build.MODEL);
122 |
123 | //cpu架构
124 | pw.print("CPU ABI: ");
125 | pw.println(Build.CPU_ABI);
126 | }
127 |
128 | private void uploadExceptionToServer() {
129 | //TODO Upload Exception Message To Your Web Server
130 | }
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/ui/FileDownloadActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.ui;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.text.format.Formatter;
6 | import android.util.Log;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.AdapterView;
11 | import android.widget.BaseAdapter;
12 | import android.widget.Button;
13 | import android.widget.ListView;
14 | import android.widget.TextView;
15 | import java.util.ArrayList;
16 | import download.http.core.Http;
17 | import download.http.listener.JsonReaderListCallback;
18 | import download.otherFileLoader.db.DownFileManager;
19 | import download.otherFileLoader.listener.DownloadListener;
20 | import download.otherFileLoader.request.DownFile;
21 | import download.otherFileLoader.util.ToastUtils;
22 |
23 | public class FileDownloadActivity extends Activity implements View.OnClickListener{
24 |
25 |
26 | DownFileManager mDownloadManager;
27 |
28 | Button pauseall;
29 |
30 |
31 | private ListView mDownloadLsv;
32 | private DownloadAdapter adapter;
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 |
38 | setContentView(R.layout.activity_filedownload);
39 | mDownloadManager = DownFileManager.getInstance(this);
40 |
41 | pauseall = (Button) findViewById(R.id.pauseall);
42 | pauseall.setOnClickListener(this);
43 |
44 | mDownloadLsv = (ListView) findViewById(R.id.mDownloadLsv);
45 | mDownloadLsv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
46 | @Override
47 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
48 |
49 | }
50 | });
51 |
52 | String url = "http://api.stay4it.com/v1/public/core/?service=downloader.applist";
53 | Http.with(this).url(url).callback(new JsonReaderListCallback("data") {
54 | @Override
55 | public ArrayList onPost(ArrayList appEntries) {
56 | for (int i = 0; i < appEntries.size(); i++) {
57 |
58 | DownFile downFile = DownFileManager.getInstance(FileDownloadActivity.this).initData
59 | (appEntries.get(i).url, null);
60 | if (downFile != null){
61 | appEntries.get(i).downLength = downFile.downLength;
62 | appEntries.get(i).totalLength = downFile.totalLength;
63 | appEntries.get(i).state = downFile.state;
64 | }
65 | }
66 | return super.onPost(appEntries);
67 | }
68 |
69 | @Override
70 | public void onSuccess(ArrayList result) {
71 | Log.e("test", "" + result.size());
72 |
73 | adapter = new DownloadAdapter(result);
74 | mDownloadLsv.setAdapter(adapter);
75 |
76 | for (final AppEntry entry:result
77 | ) {
78 | if (entry.state == DownFile.DownloadStatus.DOWNLOADING || entry.state == DownFile.DownloadStatus.WAITING || entry.state == DownFile.DownloadStatus.ERROR){
79 | DownFileManager.getInstance(FileDownloadActivity.this).download(entry.url,getDownloadListener(entry));
80 | }
81 | }
82 | }
83 | }).get();
84 | }
85 | Boolean isVisiable = false;
86 |
87 | @Override
88 | protected void onPause() {
89 | super.onPause();
90 | isVisiable = false;
91 | }
92 |
93 | @Override
94 | protected void onResume() {
95 | super.onResume();
96 | isVisiable = true;
97 | }
98 |
99 |
100 | @Override
101 | public void onClick(View v) {
102 | switch (v.getId()){
103 | case R.id.pauseall:
104 | if (pauseall.getText().equals("pauseall")){
105 | pauseall.setText("recoverall");
106 | mDownloadManager.pauseAll();
107 | }else {
108 | pauseall.setText("pauseall");
109 | mDownloadManager.recoverAll();
110 | }
111 | break;
112 | }
113 |
114 | }
115 | class DownloadAdapter extends BaseAdapter {
116 |
117 | public ArrayList applist;
118 | public DownloadAdapter(ArrayList list){
119 | this.applist = list;
120 | }
121 |
122 | private ViewHolder holder;
123 |
124 | @Override
125 | public int getCount() {
126 | return applist != null ? applist.size() : 0;
127 | }
128 |
129 | @Override
130 | public Object getItem(int position) {
131 | return applist.get(position);
132 | }
133 |
134 | @Override
135 | public long getItemId(int position) {
136 | return position;
137 | }
138 |
139 | @Override
140 | public View getView(int position, View convertView, ViewGroup parent) {
141 | if (convertView == null || convertView.getTag() == null) {
142 | convertView = LayoutInflater.from(FileDownloadActivity.this).inflate(R.layout.activity_applist_item, null);
143 | holder = new ViewHolder();
144 | holder.mDownloadBtn = (Button) convertView.findViewById(R.id.mDownloadBtn);
145 | holder.mDownloadLabel = (TextView) convertView.findViewById(R.id.mDownloadLabel);
146 | holder.mDownloadStatusLabel = (TextView) convertView.findViewById(R.id.mDownloadStatusLabel);
147 | convertView.setTag(holder);
148 | } else {
149 | holder = (ViewHolder) convertView.getTag();
150 | }
151 | final AppEntry entry = applist.get(position);
152 |
153 |
154 |
155 | holder.mDownloadLabel.setText(entry.name + " " + entry.size + "\n" + entry.desc);
156 |
157 | holder.mDownloadStatusLabel.setText(entry.state + "\n"
158 | + Formatter.formatShortFileSize(getApplicationContext(), entry.downLength)
159 | + "/" + Formatter.formatShortFileSize(getApplicationContext(), entry.totalLength));
160 | holder.mDownloadBtn.setOnClickListener(new View.OnClickListener() {
161 | @Override
162 | public void onClick(View v) {
163 | if (entry.state != DownFile.DownloadStatus.DOWNLOADING && entry.state != DownFile.DownloadStatus.FINISH && entry.state != DownFile.DownloadStatus.WAITING) {
164 | DownFileManager.getInstance(FileDownloadActivity.this).download(entry.url,getDownloadListener(entry));
165 | } else if (entry.state == DownFile.DownloadStatus.FINISH) {
166 | //完成
167 | } else if (entry.state == DownFile.DownloadStatus.DOWNLOADING || entry.state == DownFile.DownloadStatus.WAITING) {
168 | DownFileManager.getInstance(FileDownloadActivity.this).pause(entry.url);
169 | }
170 | }
171 | });
172 | return convertView;
173 | }
174 | }
175 | public DownloadListener getDownloadListener(final AppEntry entry){
176 |
177 | return new DownloadListener() {
178 | @Override
179 | public void success(String path) {
180 | entry.state = DownFile.DownloadStatus.FINISH;
181 | adapter.notifyDataSetChanged();
182 | ToastUtils.showToast(FileDownloadActivity.this,"已完成"+path);
183 | }
184 |
185 | @Override
186 | public void progress(int currentLen, int totalLen) {
187 | if (!isVisiable){
188 | return;
189 | }
190 | entry.downLength = currentLen;
191 | entry.totalLength = totalLen;
192 | entry.state = DownFile.DownloadStatus.DOWNLOADING;
193 | adapter.notifyDataSetChanged();
194 | }
195 |
196 | @Override
197 | public void error() {
198 | entry.state = DownFile.DownloadStatus.ERROR;
199 | adapter.notifyDataSetChanged();
200 | }
201 |
202 | @Override
203 | public void waiting() {
204 | entry.state = DownFile.DownloadStatus.WAITING;
205 | adapter.notifyDataSetChanged();
206 | }
207 |
208 | @Override
209 | public void pause() {
210 | entry.state = DownFile.DownloadStatus.PAUSE;
211 | adapter.notifyDataSetChanged();
212 | }
213 |
214 | @Override
215 | public void cancel() {
216 | entry.state = DownFile.DownloadStatus.CANCEL;
217 | adapter.notifyDataSetChanged();
218 | }
219 | };
220 | }
221 |
222 | static class ViewHolder {
223 | TextView mDownloadLabel;
224 | TextView mDownloadStatusLabel;
225 | Button mDownloadBtn;
226 | }
227 |
228 | }
229 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/ui/MyUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.ui;
2 |
3 | import java.io.Closeable;
4 | import java.io.IOException;
5 | import java.util.List;
6 |
7 | import android.app.ActivityManager;
8 | import android.app.ActivityManager.RunningAppProcessInfo;
9 | import android.content.Context;
10 | import android.content.res.TypedArray;
11 | import android.net.ConnectivityManager;
12 | import android.net.NetworkInfo;
13 | import android.util.DisplayMetrics;
14 | import android.util.TypedValue;
15 | import android.view.WindowManager;
16 |
17 | public class MyUtils {
18 |
19 | public static String getProcessName(Context cxt, int pid) {
20 | ActivityManager am = (ActivityManager) cxt
21 | .getSystemService(Context.ACTIVITY_SERVICE);
22 | List runningApps = am.getRunningAppProcesses();
23 | if (runningApps == null) {
24 | return null;
25 | }
26 | for (RunningAppProcessInfo procInfo : runningApps) {
27 | if (procInfo.pid == pid) {
28 | return procInfo.processName;
29 | }
30 | }
31 | return null;
32 | }
33 |
34 | public static void close(Closeable closeable) {
35 | try {
36 | if (closeable != null) {
37 | closeable.close();
38 | }
39 | } catch (IOException e) {
40 | e.printStackTrace();
41 | }
42 | }
43 |
44 | public static DisplayMetrics getScreenMetrics(Context context) {
45 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
46 | DisplayMetrics dm = new DisplayMetrics();
47 | wm.getDefaultDisplay().getMetrics(dm);
48 | return dm;
49 | }
50 |
51 | public static float dp2px(Context context, float dp) {
52 | return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
53 | context.getResources().getDisplayMetrics());
54 | }
55 |
56 | public static boolean isWifi(Context context) {
57 | ConnectivityManager connectivityManager = (ConnectivityManager) context
58 | .getSystemService(Context.CONNECTIVITY_SERVICE);
59 | NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
60 | if (activeNetInfo != null
61 | && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {
62 | return true;
63 | }
64 | return false;
65 | }
66 |
67 | public static void executeInThread(Runnable runnable) {
68 | new Thread(runnable).start();
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/litesuits/go/OverloadPolicy.java:
--------------------------------------------------------------------------------
1 | package com.litesuits.go;
2 |
3 |
4 | /**
5 | * Policy of thread-pool-executor overload.
6 | *
7 | * @author MaTianyu
8 | * @date 2015-04-23
9 | */
10 | public enum OverloadPolicy {
11 | DiscardNewTaskInQueue,
12 | DiscardOldTaskInQueue,
13 | DiscardCurrentTask,
14 | CallerRuns,
15 | ThrowExecption
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/litesuits/go/PriorityRunnable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 litesuits.com
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.litesuits.go;
17 |
18 | /**
19 | * @author MaTianyu
20 | * @date 2015-04-23
21 | */
22 | public abstract class PriorityRunnable implements Runnable {
23 |
24 | int priority;
25 |
26 | protected PriorityRunnable(int priority) {
27 | this.priority = priority;
28 | }
29 |
30 | public int getPriority() {
31 | return priority;
32 | }
33 |
34 | public void setPriority(int priority) {
35 | this.priority = priority;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/litesuits/go/SchedulePolicy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 litesuits.com
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.litesuits.go;
17 |
18 | /**
19 | * @author MaTianyu
20 | * @date 2015-04-23
21 | */
22 | public enum SchedulePolicy {
23 | LastInFirstRun,
24 | FirstInFistRun
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/litesuits/go/utils/GoUtil.java:
--------------------------------------------------------------------------------
1 | package com.litesuits.go.utils;
2 |
3 | import android.app.AlertDialog;
4 | import android.app.Dialog;
5 | import android.content.Context;
6 | import android.content.DialogInterface;
7 | import android.util.Log;
8 |
9 | import java.io.File;
10 | import java.io.FileFilter;
11 | import java.text.SimpleDateFormat;
12 | import java.util.Date;
13 | import java.util.regex.Pattern;
14 |
15 | /**
16 | * @author MaTianyu
17 | * @date 2015-04-21
18 | */
19 | public class GoUtil {
20 | private static final String TAG = GoUtil.class.getSimpleName();
21 |
22 | private static final String PATH_CPU = "/sys/devices/system/cpu/";
23 | private static final String CPU_FILTER = "cpu[0-9]+";
24 | private static int CPU_CORES = 0;
25 |
26 | public static String formatDate(long millis) {
27 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
28 | return format.format(new Date(millis));
29 | }
30 |
31 | /**
32 | * Get available processors.
33 | */
34 | public static int getProcessorsCount() {
35 | return Runtime.getRuntime().availableProcessors();
36 | }
37 |
38 | /**
39 | * Gets the number of cores available in this device, across all processors.
40 | * Requires: Ability to peruse the filesystem at "/sys/devices/system/cpu"
41 | *
42 | * @return The number of cores, or available processors if failed to get result
43 | */
44 | public static int getCoresNumbers() {
45 | if (CPU_CORES > 0) {
46 | return CPU_CORES;
47 | }
48 | //Private Class to display only CPU devices in the directory listing
49 | class CpuFilter implements FileFilter {
50 | @Override
51 | public boolean accept(File pathname) {
52 | //Check if filename is "cpu", followed by a single digit number
53 | if (Pattern.matches(CPU_FILTER, pathname.getName())) {
54 | return true;
55 | }
56 | return false;
57 | }
58 | }
59 | try {
60 | //Get directory containing CPU info
61 | File dir = new File(PATH_CPU);
62 | //Filter to only list the devices we care about
63 | File[] files = dir.listFiles(new CpuFilter());
64 | //Return the number of cores (virtual CPU devices)
65 | CPU_CORES = files.length;
66 | } catch (Exception e) {
67 | e.printStackTrace();
68 | }
69 | if (CPU_CORES < 1) {
70 | CPU_CORES = Runtime.getRuntime().availableProcessors();
71 | }
72 | if (CPU_CORES < 1) {
73 | CPU_CORES = 1;
74 | }
75 | Log.i(TAG, "CPU cores: " + CPU_CORES);
76 | return CPU_CORES;
77 | }
78 |
79 | public static AlertDialog.Builder dialogBuilder(Context context, String title, String msg) {
80 | AlertDialog.Builder builder = new AlertDialog.Builder(context);
81 | if (msg != null) {
82 | builder.setMessage(msg);
83 | }
84 | if (title != null) {
85 | builder.setTitle(title);
86 | }
87 | return builder;
88 | }
89 |
90 |
91 | public static Dialog showTips(Context context, String title, String des) {
92 | return showTips(context, title, des, null, null);
93 | }
94 |
95 | public static Dialog showTips(Context context, String title, String des, String btn,
96 | DialogInterface.OnDismissListener dismissListener) {
97 | AlertDialog.Builder builder = dialogBuilder(context, title, des);
98 | builder.setCancelable(true);
99 | builder.setPositiveButton(btn, null);
100 | Dialog dialog = builder.show();
101 | dialog.setCanceledOnTouchOutside(true);
102 | dialog.setOnDismissListener(dismissListener);
103 | return dialog;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/core/Http.java:
--------------------------------------------------------------------------------
1 | package download.http.core;
2 |
3 | import android.content.Context;
4 |
5 | import download.http.request.RequestBuilder;
6 | import download.utils.Util;
7 |
8 | /**
9 | * Created by lizhiyun on 16/6/7.
10 | */
11 | public class Http {
12 | public static String tempFileRootPath;
13 | public static RequestBuilder with(Context context){
14 | if (tempFileRootPath == null){
15 | tempFileRootPath = Util.getDiskCacheDir(context,"temp").getAbsolutePath();
16 | }
17 | return new RequestBuilder(context);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/core/HttpManager.java:
--------------------------------------------------------------------------------
1 | package download.http.core;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.os.Build;
6 |
7 | import com.litesuits.go.OverloadPolicy;
8 | import com.litesuits.go.SchedulePolicy;
9 | import com.litesuits.go.SmartExecutor;
10 |
11 | import download.http.request.Request;
12 | import download.http.request.RequestBuilder;
13 |
14 | public class HttpManager {
15 | private SmartExecutor executor;
16 | private static class InstanceHoler {
17 | private static final HttpManager instance = new HttpManager();
18 | }
19 | public static HttpManager getInstance() {
20 | return InstanceHoler.instance;
21 | }
22 |
23 | private final int threadCount = 3;
24 |
25 | private HttpManager() {
26 | executor = new SmartExecutor(threadCount, 200);
27 | executor.setSchedulePolicy(SchedulePolicy.FirstInFistRun);
28 | executor.setOverloadPolicy(OverloadPolicy.DiscardOldTaskInQueue);
29 | executor.setDebug(false);
30 | }
31 |
32 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
33 | public void request(final Request request) {
34 | executor.execute(new HttpTask(request));
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/download/http/core/HttpTask.java:
--------------------------------------------------------------------------------
1 | package download.http.core;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 | import android.os.Message;
6 | import android.util.Log;
7 |
8 | import java.net.HttpURLConnection;
9 |
10 | import download.http.exception.AppException;
11 | import download.http.listener.OnProgressDownloadListener;
12 | import download.http.request.Request;
13 | import download.http.util.HttpUrlConnectionUtil;
14 | import download.imageLoader.listener.OnProgressUpdatedListener;
15 |
16 | /**
17 | * Created by lizhiyun on 16/5/23.
18 | */
19 | public class HttpTask implements Runnable {
20 | public final static int UPDATEPROGRESS = 0;
21 | public final static int DOWNLOADPROGRESS = 1;
22 | public final static int RESULT = 2;
23 | public Request mRequest;
24 | int retryTime;
25 | private HttpTask(){}
26 | public HttpTask(Request request){
27 | super();
28 | this.mRequest = request;
29 | }
30 |
31 | @Override
32 | public void run() {
33 | notifyFinish(request(retryTime));
34 | }
35 |
36 | private Object request(int retryTime) {
37 | try {
38 | HttpURLConnection connection = HttpUrlConnectionUtil.execute(mRequest, new OnProgressUpdatedListener() {
39 | @Override
40 | public void onProgressUpdated(int curLen, int totalLen) {
41 | if (mRequest.onProgressUpdatedListener != null){
42 | updateProgress(curLen,totalLen);
43 | }
44 | }
45 | });
46 | if (mRequest.onProgressDownloadListener != null){
47 | return mRequest.getCallback().parse(mRequest, connection, new OnProgressDownloadListener() {
48 | @Override
49 | public void onProgressDownload(int curLength, int totalLength) {
50 | downloadProgress(curLength, totalLength);
51 | }
52 | });
53 | }else {
54 | return mRequest.getCallback().parse(mRequest, connection, null);
55 | }
56 | } catch (AppException e) {
57 | if (e.errorType == AppException.ErrorType.IO){
58 | if (retryTime < mRequest.getMaxRetryTime()){
59 | retryTime++;
60 | return request(retryTime);
61 | }
62 | }
63 | return e;
64 | }
65 | }
66 |
67 | private void updateProgress(int curLength, int totalLength) {
68 | Message message = Message.obtain();
69 | message.what = UPDATEPROGRESS;
70 | message.obj = mRequest;
71 | message.arg1 = curLength;
72 | message.arg2 = totalLength;
73 | if (sUIHandler != null){
74 | sUIHandler.sendMessage(message);
75 | }
76 | }
77 | private void downloadProgress(int curLength, int totalLength) {
78 | Message message = Message.obtain();
79 | message.what = DOWNLOADPROGRESS;
80 | message.obj = mRequest;
81 | message.arg1 = curLength;
82 | message.arg2 = totalLength;
83 | if (sUIHandler != null){
84 | sUIHandler.sendMessage(message);
85 | }
86 | }
87 |
88 | private void notifyFinish(Object object) {
89 | Message message = Message.obtain();
90 | message.what = RESULT;
91 | mRequest.setReturnObject(object);
92 | message.obj = mRequest;
93 | if (sUIHandler != null){
94 | sUIHandler.sendMessage(message);
95 | }
96 | }
97 | private static Handler sUIHandler = new Handler(Looper.getMainLooper()) {
98 | public void handleMessage(Message msg) {
99 | final Request request = (Request) msg.obj;
100 | switch (msg.what) {
101 | case HttpTask.UPDATEPROGRESS:
102 | request.onProgressUpdatedListener.onProgressUpdate(msg.arg1, msg.arg2);
103 | break;
104 | case HttpTask.DOWNLOADPROGRESS:
105 | request.onProgressDownloadListener.onProgressDownload(msg.arg1, msg.arg2);
106 | break;
107 | case HttpTask.RESULT:
108 | if (request.getReturnObject() instanceof AppException){
109 | if (request.isCanceled()){
110 | request.getCallback().onCancel();
111 | return;
112 | }
113 | if (request.getGlobalExceptionListener() != null){
114 | if (!request.getGlobalExceptionListener().handleException((AppException) request.getReturnObject())){
115 | request.getCallback().onFailure((AppException) request.getReturnObject());
116 | }
117 | }
118 | }else {
119 | request.getCallback().onSuccess(request.getReturnObject());
120 | }
121 | break;
122 |
123 | default:
124 | break;
125 | }
126 |
127 | }
128 |
129 | };
130 |
131 | }
--------------------------------------------------------------------------------
/app/src/main/java/download/http/entity/CustomJsonReader.java:
--------------------------------------------------------------------------------
1 | package download.http.entity;
2 |
3 | import com.google.gson.stream.JsonReader;
4 |
5 | import download.http.exception.AppException;
6 |
7 | /**
8 | * Created by lizhiyun on 16/6/10.
9 | */
10 | public interface CustomJsonReader {
11 | public abstract void readJsonReader(JsonReader jsonReader) throws AppException;
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/entity/FileEntity.java:
--------------------------------------------------------------------------------
1 | package download.http.entity;
2 |
3 | /**
4 | * @author Stay
5 | * @version create time:Mar 11, 2014 9:06:17 PM
6 | */
7 | public class FileEntity {
8 |
9 | private String fileName;
10 | private String fileType;
11 | private String filePath;
12 |
13 | public String getFileName() {
14 | return fileName;
15 | }
16 |
17 | public void setFileName(String fileName) {
18 | this.fileName = fileName;
19 | }
20 |
21 | public String getFileType() {
22 | return fileType;
23 | }
24 |
25 | public void setFileType(String fileType) {
26 | this.fileType = fileType;
27 | }
28 |
29 | public String getFilePath() {
30 | return filePath;
31 | }
32 |
33 | public void setFilePath(String filePath) {
34 | this.filePath = filePath;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/entity/ResultData.java:
--------------------------------------------------------------------------------
1 | package download.http.entity;
2 |
3 | /**
4 | * Created by lizhiyun on 16/6/6.
5 | */
6 | public class ResultData extends SimpleJsonReader {
7 | public int ret;
8 | public User data;
9 | public String msg;
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/entity/SimpleJsonReader.java:
--------------------------------------------------------------------------------
1 | package download.http.entity;
2 |
3 |
4 | import com.google.gson.stream.JsonReader;
5 |
6 | import java.io.IOException;
7 | import java.lang.reflect.Field;
8 |
9 | import download.http.exception.AppException;
10 |
11 | /**
12 | * Created by lizhiyun on 16/6/10.
13 | */
14 | public class SimpleJsonReader {
15 | Field[] fields = null;
16 | public void readFromJsonReader(JsonReader reader) throws AppException{
17 | try {
18 | reader.beginObject();
19 | String node;
20 | while (reader.hasNext()){
21 | node = reader.nextName();
22 | Boolean isReaded = false;
23 | if (fields == null){
24 | fields = this.getClass().getDeclaredFields();
25 | }
26 | for (Field field: fields
27 | ) {
28 | if (field.getName().equals(node)){
29 | field.setAccessible(true);
30 | Class field_class = field.getType();
31 | if (field_class == Integer.TYPE){
32 | field.set(this, reader.nextInt());
33 | isReaded = true;
34 | }else if (field_class == Long.TYPE){
35 | field.set(this, reader.nextLong());
36 | isReaded = true;
37 | }else if (field_class == Boolean.TYPE){
38 | field.set(this, reader.nextBoolean());
39 | isReaded = true;
40 | }else if (field_class == String.class){
41 | field.set(this, reader.nextString());
42 | isReaded = true;
43 | }else if (field_class == Double.TYPE){
44 | field.set(this, reader.nextDouble());
45 | isReaded = true;
46 | }
47 | else if (field_class.getSuperclass() == SimpleJsonReader.class){
48 | SimpleJsonReader baseJsonReader = (SimpleJsonReader) field_class.newInstance();
49 | baseJsonReader.readFromJsonReader(reader);
50 | field.set(this, baseJsonReader);
51 | isReaded = true;
52 | }
53 | }
54 | }
55 | if (!isReaded){
56 | reader.skipValue();
57 | }
58 | }
59 | reader.endObject();
60 | }catch (IOException e){
61 | throw new AppException(AppException.ErrorType.JSON,e.getMessage());
62 | } catch (IllegalAccessException e) {
63 | throw new AppException(AppException.ErrorType.JSON,e.getMessage());
64 | }
65 | catch (InstantiationException e) {
66 | throw new AppException(AppException.ErrorType.JSON,e.getMessage());
67 | }
68 | };
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/entity/User.java:
--------------------------------------------------------------------------------
1 | package download.http.entity;
2 |
3 |
4 | /**
5 | * Created by lizhiyun on 16/6/3.
6 | */
7 | public class User extends SimpleJsonReader {
8 | public String id;
9 | public String account;
10 | public String email;
11 | public String username;
12 | public String token;
13 |
14 | @Override
15 | public String toString() {
16 | return username+" "+email;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/exception/AppException.java:
--------------------------------------------------------------------------------
1 | package download.http.exception;
2 |
3 | /**
4 | * Created by lizhiyun on 16/6/5.
5 | */
6 | public class AppException extends Exception {
7 |
8 | public int statusCode;
9 | public String responseMessage;
10 | public enum ErrorType{TIMEOUT,SERVER,JSON,IO,FILENOTFOUND, UPLOAD, MANUAL, CANCEL}
11 |
12 | public ErrorType errorType;
13 | public AppException(int statusCode, String responseMessage){
14 | super();
15 | this.statusCode = statusCode;
16 | this.responseMessage = responseMessage;
17 | this.errorType = ErrorType.SERVER;
18 | }
19 | public AppException(ErrorType errorType, String responseMessage){
20 | super(responseMessage);
21 | this.errorType = errorType;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/exception/IfNeedLoginGlobalException.java:
--------------------------------------------------------------------------------
1 | package download.http.exception;
2 |
3 |
4 | import download.http.listener.OnGlobalExceptionListener;
5 |
6 | /**
7 | * Created by lizhiyun on 16/6/7.
8 | */
9 | public class IfNeedLoginGlobalException implements OnGlobalExceptionListener{
10 | @Override
11 | public boolean handleException(AppException e) {
12 | if (e.statusCode == 403){
13 | //TODO ...
14 |
15 | return true;
16 | }
17 | return false;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/AbsCallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 | import org.apache.http.HttpStatus;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.FileOutputStream;
8 | import java.io.InputStream;
9 | import java.io.InputStreamReader;
10 | import java.io.OutputStream;
11 | import java.net.HttpURLConnection;
12 | import java.util.zip.GZIPInputStream;
13 | import java.util.zip.InflaterInputStream;
14 |
15 | import download.http.exception.AppException;
16 | import download.http.request.Request;
17 | import download.utils.Util;
18 |
19 | /**
20 | * Created by lizhiyun on 16/6/3.
21 | */
22 | public abstract class AbsCallback implements ICallback {
23 |
24 | public void onCancel(){}
25 | public T onPost(T t){return t;}
26 |
27 | public void onFailure(AppException exception){}
28 |
29 | private String path;
30 |
31 | @Override
32 | public T parse(Request request,HttpURLConnection connection, download.http.listener.OnProgressDownloadListener listener) throws AppException {
33 | try {
34 | request.checkIfCancelled();
35 | int status = connection.getResponseCode();
36 | InputStream is = null;
37 | BufferedReader reader = null;
38 | String encode = connection.getContentEncoding();
39 | if (encode != null && "gzip".equalsIgnoreCase(encode)){
40 | is = new GZIPInputStream(connection.getInputStream());
41 | }else if (encode != null && "deflate".equalsIgnoreCase(encode)){
42 | is = new InflaterInputStream(connection.getInputStream());
43 | }else {
44 | reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
45 | }
46 | OutputStream out;
47 | if (status == HttpStatus.SC_OK){
48 | if (path == null){
49 | out = new ByteArrayOutputStream();
50 | }else {
51 | out = new FileOutputStream(path);
52 | }
53 | int totalLength = connection.getContentLength();
54 | int curLength = 0;
55 | if (reader == null){
56 | byte[] buffer = new byte[2048];
57 | int len;
58 | while ((len = is.read(buffer)) != -1){
59 | request.checkIfCancelled();
60 | out.write(buffer, 0, len);
61 | curLength += len;
62 | if (listener != null){
63 | listener.onProgressDownload(curLength, totalLength);
64 | }
65 | }
66 | }else {
67 | String s;
68 | while ((s = reader.readLine()) != null){
69 | request.checkIfCancelled();
70 | byte[] bytes = s.getBytes();
71 | out.write(bytes,0,bytes.length);
72 | curLength += bytes.length;
73 | if (listener != null){
74 | listener.onProgressDownload(curLength, totalLength);
75 | }
76 | }
77 | }
78 | if (is != null){
79 | is.close();
80 | }
81 | if (out != null){
82 | out.flush();
83 | out.close();
84 | }
85 | if (reader != null){
86 | reader.close();
87 | }
88 | if (path == null){
89 | String result = new String(((ByteArrayOutputStream)out).toByteArray()).trim();
90 | return onPost(parseData(result));
91 | }else {
92 | return onPost(parseData(path));
93 | }
94 |
95 | }else {
96 | throw new AppException(AppException.ErrorType.SERVER,connection.getResponseMessage());
97 | }
98 | }catch (Exception e){
99 | throw new AppException(AppException.ErrorType.IO,e.getMessage());
100 | }
101 | }
102 |
103 |
104 | protected abstract T parseData(String result) throws AppException;
105 |
106 | public ICallback setCachePath(String path){
107 | this.path = path;
108 | return this;
109 | };
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/CustomJsonReaderCallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 |
4 | import android.annotation.TargetApi;
5 | import android.os.Build;
6 |
7 | import com.google.gson.stream.JsonReader;
8 |
9 | import java.io.File;
10 | import java.io.FileReader;
11 | import java.lang.reflect.ParameterizedType;
12 | import java.lang.reflect.Type;
13 | import java.util.UUID;
14 |
15 | import download.http.core.Http;
16 | import download.http.entity.CustomJsonReader;
17 | import download.http.exception.AppException;
18 |
19 |
20 | /**
21 | * 数据很多的时自己处理数据以防oom
22 | * Created by lizhiyun on 16/6/3.
23 | */
24 | public abstract class CustomJsonReaderCallback extends download.http.listener.AbsCallback {
25 | public CustomJsonReaderCallback(){
26 | setCachePath(Http.tempFileRootPath + File.separator + UUID.randomUUID());
27 | }
28 |
29 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
30 | @Override
31 | protected T parseData(String result) throws AppException{
32 | try{
33 | ParameterizedType p = (ParameterizedType) this.getClass().getGenericSuperclass();
34 | Type type = p.getActualTypeArguments()[0];
35 | Class clazz = (Class) type;
36 | T t = clazz.newInstance();
37 | FileReader in = new FileReader(result);
38 | JsonReader reader = new JsonReader(in);
39 | t.readJsonReader(reader);
40 | return t;
41 | }catch (Exception e){
42 | throw new AppException(AppException.ErrorType.JSON,e.getMessage());
43 | }finally {
44 | File file = new File(result);
45 | if (file != null && file.exists()){
46 | file.delete();
47 | }
48 | }
49 |
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/FileCallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 |
4 |
5 | /**
6 | * Created by lizhiyun on 16/6/3.
7 | */
8 | public abstract class FileCallback extends AbsCallback {
9 |
10 | @Override
11 | protected String parseData(String result) {
12 | return result;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/ICallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 |
4 | import java.net.HttpURLConnection;
5 |
6 | import download.http.exception.AppException;
7 | import download.http.request.Request;
8 |
9 | /**
10 | * Created by lizhiyun on 16/6/3.
11 | */
12 | public interface ICallback {
13 |
14 | /**
15 | * 获取数据后的耗时预处理,在子线程
16 | * @param t
17 | * @return
18 | */
19 | T onPost(T t);
20 | void onSuccess(T result);
21 | void onFailure(AppException exception);
22 | void onCancel();
23 | T parse(Request request, HttpURLConnection connection, OnProgressDownloadListener listener) throws AppException;
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/JsonCallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 |
4 | import com.google.gson.Gson;
5 |
6 | import java.lang.reflect.ParameterizedType;
7 |
8 |
9 | /**
10 | * Created by lizhiyun on 16/6/3.
11 | */
12 | public abstract class JsonCallback extends AbsCallback {
13 |
14 | @Override
15 | protected T parseData(String result) {
16 | ParameterizedType p = (ParameterizedType) this.getClass().getGenericSuperclass();
17 | Class c = (Class) p.getActualTypeArguments()[0];
18 | return (T) new Gson().fromJson(result, c);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/JsonListCallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 |
4 | import android.annotation.TargetApi;
5 | import android.os.Build;
6 |
7 | import com.google.gson.Gson;
8 | import com.google.gson.stream.JsonReader;
9 |
10 | import org.json.JSONArray;
11 | import org.json.JSONObject;
12 |
13 | import java.io.File;
14 | import java.io.FileReader;
15 | import java.lang.reflect.ParameterizedType;
16 | import java.lang.reflect.Type;
17 | import java.util.ArrayList;
18 | import java.util.UUID;
19 |
20 | import download.http.core.Http;
21 | import download.http.entity.SimpleJsonReader;
22 | import download.http.exception.AppException;
23 |
24 | /**
25 | * Created by lizhiyun on 16/6/3.
26 | */
27 | public abstract class JsonListCallback extends AbsCallback> {
28 | String key="";
29 | public JsonListCallback(String key){
30 | this.key = key;
31 | }
32 |
33 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
34 | @Override
35 | protected ArrayList parseData(String result) throws AppException{
36 | ParameterizedType p = (ParameterizedType) this.getClass().getGenericSuperclass();
37 | Class c = (Class) p.getActualTypeArguments()[0];
38 | ArrayList ts = new ArrayList();
39 |
40 | T t;
41 | try{
42 | JSONObject jsonObject = new JSONObject(result);
43 | JSONArray jsonArray = jsonObject.getJSONArray(key);
44 | if (jsonArray.length() > 0){
45 | for (int i = 0;i < jsonArray.length();i++){
46 | JSONObject object = jsonArray.getJSONObject(i);
47 | t = (T) new Gson().fromJson(object.toString(), c);
48 | ts.add(t);
49 | }
50 | }
51 | return ts;
52 | }catch (Exception e){
53 | throw new AppException(AppException.ErrorType.JSON,e.getMessage());
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/JsonReaderCallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 |
4 |
5 | import android.annotation.TargetApi;
6 | import android.os.Build;
7 | import com.google.gson.stream.JsonReader;
8 |
9 | import java.io.File;
10 | import java.io.FileReader;
11 | import java.lang.reflect.ParameterizedType;
12 | import java.lang.reflect.Type;
13 | import java.util.UUID;
14 |
15 | import download.http.core.Http;
16 | import download.http.entity.SimpleJsonReader;
17 | import download.http.exception.AppException;
18 |
19 | /**
20 | * Created by lizhiyun on 16/6/3.
21 | */
22 | public abstract class JsonReaderCallback extends AbsCallback {
23 | public JsonReaderCallback(){
24 | setCachePath(Http.tempFileRootPath + File.separator + UUID.randomUUID());
25 | }
26 |
27 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
28 | @Override
29 | protected T parseData(String result) throws AppException{
30 | try{
31 | ParameterizedType p = (ParameterizedType) this.getClass().getGenericSuperclass();
32 | Type type = p.getActualTypeArguments()[0];
33 | Class clazz = (Class) type;
34 | T t = clazz.newInstance();
35 | FileReader in = new FileReader(result);
36 | JsonReader reader = new JsonReader(in);
37 | t.readFromJsonReader(reader);
38 | return t;
39 | }catch (Exception e){
40 | throw new AppException(AppException.ErrorType.JSON,e.getMessage());
41 | }finally {
42 | File file = new File(result);
43 | if (file != null && file.exists()){
44 | file.delete();
45 | }
46 | }
47 |
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/JsonReaderListCallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 |
4 | import android.annotation.TargetApi;
5 | import android.os.Build;
6 |
7 | import com.google.gson.stream.JsonReader;
8 |
9 | import java.io.File;
10 | import java.io.FileReader;
11 | import java.lang.reflect.ParameterizedType;
12 | import java.lang.reflect.Type;
13 | import java.util.ArrayList;
14 | import java.util.UUID;
15 |
16 | import download.http.core.Http;
17 | import download.http.entity.SimpleJsonReader;
18 | import download.http.exception.AppException;
19 |
20 | /**
21 | * Created by lizhiyun on 16/6/3.
22 | */
23 | public abstract class JsonReaderListCallback extends AbsCallback> {
24 | String key="data";
25 | public JsonReaderListCallback(String key){
26 | this.key = key;
27 | setCachePath(Http.tempFileRootPath + File.separator + UUID.randomUUID());
28 | }
29 |
30 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
31 | @Override
32 | protected ArrayList parseData(String result) throws AppException{
33 | ArrayList ts = new ArrayList();
34 | T t;
35 | try{
36 | ParameterizedType p = (ParameterizedType) this.getClass().getGenericSuperclass();
37 | Type type = p.getActualTypeArguments()[0];
38 | Class clazz = (Class) type;
39 | FileReader in = new FileReader(result);
40 | JsonReader reader = new JsonReader(in);
41 | String node = "";
42 | reader.beginObject();
43 | while (reader.hasNext()){
44 | node = reader.nextName();
45 | if (node.equals(key)){
46 | reader.beginArray();
47 | while (reader.hasNext()){
48 | t = clazz.newInstance();
49 | t.readFromJsonReader(reader);
50 | ts.add(t);
51 | }
52 | reader.endArray();
53 | }else {
54 | reader.skipValue();
55 | }
56 | }
57 | reader.endObject();
58 | return ts;
59 | }catch (Exception e){
60 | throw new AppException(AppException.ErrorType.JSON,e.getMessage());
61 | }finally {
62 | try {
63 | File file = new File(result);
64 | if (file != null && file.exists()){
65 | file.delete();
66 | }
67 | }catch (Exception e){
68 | e.printStackTrace();
69 | }
70 | }
71 |
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/OnGlobalExceptionListener.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 | import download.http.exception.AppException;
4 |
5 | /**
6 | * Created by lizhiyun on 16/6/5.
7 | */
8 | public interface OnGlobalExceptionListener {
9 | boolean handleException(AppException e);
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/OnProgressDownloadListener.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 | /**
4 | * Created by lizhiyun on 16/6/4.
5 | */
6 | public interface OnProgressDownloadListener {
7 | void onProgressDownload(int curLength, int totalLength);
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/OnProgressUpdateListener.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 | /**
4 | * Created by lizhiyun on 16/6/4.
5 | */
6 | public interface OnProgressUpdateListener {
7 | void onProgressUpdate(int curLength, int totalLength);
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/listener/StringCallback.java:
--------------------------------------------------------------------------------
1 | package download.http.listener;
2 |
3 |
4 |
5 | /**
6 | * Created by lizhiyun on 16/6/3.
7 | */
8 | public abstract class StringCallback extends AbsCallback {
9 |
10 | @Override
11 | protected String parseData(String result) {
12 | return result;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/request/Request.java:
--------------------------------------------------------------------------------
1 | package download.http.request;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Map;
5 |
6 | import download.http.entity.FileEntity;
7 | import download.http.exception.AppException;
8 | import download.http.listener.ICallback;
9 | import download.http.listener.OnGlobalExceptionListener;
10 | import download.http.listener.OnProgressDownloadListener;
11 | import download.http.listener.OnProgressUpdateListener;
12 |
13 | import static download.http.request.RequestBuilder.*;
14 |
15 | /**
16 | * Created by lizhiyun on 16/6/3.
17 | */
18 | public class Request {
19 |
20 | private Object returnObject;
21 | private String tag;
22 | private ICallback callback;
23 | public OnProgressUpdateListener onProgressUpdatedListener;
24 | public OnProgressDownloadListener onProgressDownloadListener;
25 | private int maxRetryTime = 0;
26 | private volatile boolean isCanceled = false;
27 | public String filePath;
28 | public ArrayList fileEntities;
29 |
30 | private OnGlobalExceptionListener globalExceptionListener;
31 |
32 |
33 | public void checkIfCancelled() throws AppException {
34 | if (isCanceled){
35 | throw new AppException(AppException.ErrorType.CANCEL,"canceled");
36 | }
37 | }
38 |
39 | public void cancel() {
40 | isCanceled = true;
41 | }
42 |
43 | private RequestMethod method;
44 |
45 | private String url;
46 | private Map headers;
47 | private String content;
48 |
49 | public Request(){
50 | }
51 |
52 | public Object getReturnObject() {
53 | return returnObject;
54 | }
55 |
56 | public void setReturnObject(Object returnObject) {
57 | this.returnObject = returnObject;
58 | }
59 |
60 | public String getTag() {
61 | return tag;
62 | }
63 |
64 | public void setTag(String tag) {
65 | this.tag = tag;
66 | }
67 |
68 | public ICallback getCallback() {
69 | return callback;
70 | }
71 |
72 | protected void setCallback(ICallback callback) {
73 | this.callback = callback;
74 | }
75 |
76 | public int getMaxRetryTime() {
77 | return maxRetryTime;
78 | }
79 |
80 | public void setMaxRetryTime(int maxRetryTime) {
81 | this.maxRetryTime = maxRetryTime;
82 | }
83 |
84 | public boolean isCanceled() {
85 | return isCanceled;
86 | }
87 |
88 | public void setIsCanceled(boolean isCanceled) {
89 | this.isCanceled = isCanceled;
90 | }
91 |
92 | public OnGlobalExceptionListener getGlobalExceptionListener() {
93 | return globalExceptionListener;
94 | }
95 |
96 | protected void setGlobalExceptionListener(OnGlobalExceptionListener globalExceptionListener) {
97 | this.globalExceptionListener = globalExceptionListener;
98 | }
99 |
100 | public String getFilePath() {
101 | return filePath;
102 | }
103 |
104 | public void setFilePath(String filePath) {
105 | this.filePath = filePath;
106 | }
107 |
108 | public ArrayList getFileEntities() {
109 | return fileEntities;
110 | }
111 |
112 | public void setFileEntities(ArrayList fileEntities) {
113 | this.fileEntities = fileEntities;
114 | }
115 |
116 | public RequestMethod getMethod() {
117 | return method;
118 | }
119 |
120 | protected void setMethod(RequestMethod method) {
121 | this.method = method;
122 | }
123 |
124 | public String getUrl() {
125 | return url;
126 | }
127 |
128 | protected void setUrl(String url) {
129 | this.url = url;
130 | }
131 |
132 | public Map getHeaders() {
133 | return headers;
134 | }
135 |
136 | protected void setHeaders(Map headers) {
137 | this.headers = headers;
138 | }
139 |
140 | public String getContent() {
141 | return content;
142 | }
143 |
144 | protected void setContent(String content) {
145 | this.content = content;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/request/RequestBuilder.java:
--------------------------------------------------------------------------------
1 | package download.http.request;
2 |
3 | import android.content.Context;
4 |
5 | import java.util.ArrayList;
6 | import java.util.Map;
7 |
8 | import download.http.core.HttpManager;
9 | import download.http.entity.FileEntity;
10 | import download.http.listener.ICallback;
11 | import download.http.listener.OnGlobalExceptionListener;
12 | import download.http.listener.OnProgressDownloadListener;
13 | import download.http.listener.OnProgressUpdateListener;
14 |
15 | /**
16 | * Created by lizhiyun on 16/6/3.
17 | */
18 | public class RequestBuilder {
19 | private ICallback callback;
20 | public OnProgressUpdateListener onProgressUpdatedListener;
21 | public OnProgressDownloadListener onProgressDownloadListener;
22 | private int maxRetryTime = 3;
23 | private OnGlobalExceptionListener globalExceptionListener;
24 | public enum RequestMethod{GET,POST,PUT,DELETE}
25 | private RequestMethod method;
26 | public String filePath;
27 | public ArrayList fileEntities;
28 |
29 | private String url;
30 | private Map headers;
31 | private String content;
32 |
33 |
34 | public RequestBuilder(Context context){
35 | this.method = RequestMethod.GET;
36 | this.maxRetryTime = 2;
37 | }
38 | public RequestBuilder url(String url){
39 | this.url = url;
40 | return this;
41 | }
42 | public RequestBuilder method(RequestMethod method){
43 | this.method = method;
44 | return this;
45 | }
46 | public RequestBuilder content(String content){
47 | this.content = content;
48 | return this;
49 | }
50 | public RequestBuilder headers(Map headers){
51 | this.headers = headers;
52 | return this;
53 | }
54 |
55 | public RequestBuilder maxRetryTime(int maxRetryTime){
56 | this.maxRetryTime = maxRetryTime;
57 | return this;
58 | }
59 | public RequestBuilder callback(ICallback callback){
60 | this.callback = callback;
61 | return this;
62 | }
63 |
64 | public RequestBuilder globalException(OnGlobalExceptionListener globalExceptionListener){
65 | this.globalExceptionListener = globalExceptionListener;
66 | return this;
67 | }
68 |
69 |
70 | public void post(){
71 | this.method = RequestMethod.POST;
72 | execute();
73 | }
74 | public void get(){
75 | this.method = RequestMethod.GET;
76 | execute();
77 | }
78 | public void delete(){
79 | this.method = RequestMethod.DELETE;
80 | execute();
81 | }
82 | public void put(){
83 | this.method = RequestMethod.PUT;
84 | put();
85 | }
86 |
87 | public RequestBuilder progressUpdate(OnProgressUpdateListener listener){
88 | this.onProgressUpdatedListener = listener;
89 | return this;
90 | }
91 | public RequestBuilder progressDownload(OnProgressDownloadListener listener){
92 | this.onProgressDownloadListener = listener;
93 | return this;
94 | }
95 | public RequestBuilder filePath(String filePath){
96 | this.filePath = filePath;
97 | return this;
98 | }
99 |
100 |
101 | public RequestBuilder fileEntities(ArrayList fileEntities){
102 | this.fileEntities = fileEntities;
103 | return this;
104 | }
105 | private void execute(){
106 | Request request = new Request();
107 | request.setUrl(url);
108 | request.setCallback(callback);
109 | request.setContent(content);
110 | request.setHeaders(headers);
111 | request.setMethod(method);
112 | request.setGlobalExceptionListener(globalExceptionListener);
113 | request.setMaxRetryTime(maxRetryTime);
114 | request.onProgressDownloadListener = onProgressDownloadListener;
115 | request.onProgressUpdatedListener = onProgressUpdatedListener;
116 | request.setFilePath(filePath);
117 | request.setFileEntities(fileEntities);
118 | HttpManager.getInstance().request(request);
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/util/HttpUrlConnectionUtil.java:
--------------------------------------------------------------------------------
1 | package download.http.util;
2 |
3 | import android.webkit.URLUtil;
4 |
5 | import java.io.IOException;
6 | import java.io.InterruptedIOException;
7 | import java.io.OutputStream;
8 | import java.net.HttpURLConnection;
9 | import java.net.URL;
10 | import java.util.Map;
11 |
12 | import download.http.exception.AppException;
13 | import download.http.request.Request;
14 | import download.imageLoader.listener.OnProgressUpdatedListener;
15 |
16 | /**
17 | * Created by lizhiyun on 16/6/3.
18 | */
19 | public class HttpUrlConnectionUtil {
20 | public static HttpURLConnection execute(Request request,OnProgressUpdatedListener listener) throws AppException {
21 | if (!URLUtil.isNetworkUrl(request.getUrl())){
22 | throw new AppException(AppException.ErrorType.IO,"the url :"+request.getUrl() + "is not valid");
23 | }
24 | switch (request.getMethod()){
25 | case GET:
26 | case DELETE:
27 | return get(request);
28 | case POST:
29 | case PUT:
30 | return post(request,listener);
31 |
32 | }
33 | return null;
34 |
35 | }
36 | private static HttpURLConnection get(Request request) throws AppException {
37 | try {
38 | request.checkIfCancelled();
39 | HttpURLConnection connection = (HttpURLConnection) new URL(request.getUrl()).openConnection();
40 | connection.setRequestMethod(request.getMethod().name());
41 | connection.setConnectTimeout(15 * 1000);
42 | connection.setReadTimeout(10 * 1000);
43 | addHeader(connection, request.getHeaders());
44 | request.checkIfCancelled();
45 | return connection;
46 |
47 | }
48 | catch(InterruptedIOException e) {
49 | throw new AppException(AppException.ErrorType.TIMEOUT,e.getMessage());
50 | }
51 | catch(IOException e){
52 | throw new AppException(AppException.ErrorType.IO,e.getMessage());
53 | }
54 |
55 | }
56 |
57 | private static HttpURLConnection post(Request request,OnProgressUpdatedListener listener) throws AppException {
58 | OutputStream os = null;
59 | try {
60 | request.checkIfCancelled();
61 | HttpURLConnection connection = (HttpURLConnection) new URL(request.getUrl()).openConnection();
62 | connection.setRequestMethod(request.getMethod().name());
63 | connection.setConnectTimeout(15 * 1000);
64 | connection.setReadTimeout(10 * 1000);
65 | connection.setDoOutput(true);
66 | addHeader(connection, request.getHeaders());
67 | request.checkIfCancelled();
68 | os = connection.getOutputStream();
69 | if (request.filePath != null){
70 | UploadUtil.upload(os, request.filePath);
71 | }else if (request.fileEntities != null){
72 | UploadUtil.upload(os, request.getContent(), request.getFileEntities(), listener);
73 | }else if (request.getContent() != null){
74 | os.write(request.getContent().getBytes());
75 | }else {
76 | throw new AppException(AppException.ErrorType.MANUAL,"the post request has no post content");
77 | }
78 | os.write(request.getContent().getBytes());
79 | request.checkIfCancelled();
80 | return connection;
81 | }
82 | catch(InterruptedIOException e) {
83 | throw new AppException(AppException.ErrorType.TIMEOUT,e.getMessage());
84 | }catch (IOException e) {
85 | throw new AppException(AppException.ErrorType.IO,e.getMessage());
86 | }finally {
87 | try {
88 | if (os != null){
89 | os.flush();
90 | os.close();
91 | }
92 | }catch (IOException e){
93 | throw new AppException(AppException.ErrorType.IO,"the post outputstream cannot close");
94 | }
95 | }
96 | }
97 | private static void addHeader(HttpURLConnection connection, Map headers) {
98 | if (headers == null || headers.size() == 0)
99 | return;
100 | for (Map.Entry entry: headers.entrySet()){
101 | connection.addRequestProperty(entry.getKey(),entry.getValue());
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/download/http/util/UploadUtil.java:
--------------------------------------------------------------------------------
1 | package download.http.util;
2 |
3 |
4 |
5 | import java.io.DataOutputStream;
6 | import java.io.File;
7 | import java.io.FileInputStream;
8 | import java.io.InputStream;
9 | import java.io.OutputStream;
10 | import java.util.ArrayList;
11 |
12 | import download.http.entity.FileEntity;
13 | import download.http.exception.AppException;
14 | import download.imageLoader.listener.OnProgressUpdatedListener;
15 |
16 |
17 | /**
18 | * @author Stay
19 | * @version create time:Mar 11, 2014 9:01:28 PM
20 | */
21 | public class UploadUtil {
22 | /**
23 | * @param out
24 | * @param filePath
25 | * @throws AppException
26 | */
27 | public static void upload(OutputStream out, String filePath) throws AppException {
28 | String BOUNDARY = "7d4a6d158c9"; // 数据分隔线
29 | DataOutputStream outStream = new DataOutputStream(out);
30 | try {
31 | outStream.writeBytes("--" + BOUNDARY + "\r\n");
32 | outStream.writeBytes("Content-Disposition: form-data; name=\"file0\"; filename=\""
33 | + filePath.substring(filePath.lastIndexOf("/") + 1) + "\"" + "\r\n");
34 | outStream.writeBytes("\r\n");
35 | byte[] buffer = new byte[1024];
36 | FileInputStream fis = new FileInputStream(filePath);
37 | while (fis.read(buffer, 0, 1024) != -1) {
38 | outStream.write(buffer, 0, buffer.length);
39 | }
40 | fis.close();
41 | outStream.write("\r\n".getBytes());
42 | byte[] end_data = ("--" + BOUNDARY + "--\r\n").getBytes();// 数据结束标志
43 | outStream.write(end_data);
44 | outStream.flush();
45 | } catch (Exception e) {
46 | throw new AppException(AppException.ErrorType.UPLOAD, e.getMessage());
47 | }
48 | }
49 |
50 | /**
51 | * @param out
52 | * @param postContent
53 | * @param entities
54 | */
55 | public static void upload(OutputStream out, String postContent, ArrayList entities) throws AppException {
56 | String BOUNDARY = "7d4a6d158c9"; // 数据分隔线
57 | String PREFIX = "--", LINEND = "\r\n";
58 | String CHARSET = "UTF-8";
59 | DataOutputStream outStream = new DataOutputStream(out);
60 | try {
61 | StringBuilder sb = new StringBuilder();
62 | sb.append(PREFIX);
63 | sb.append(BOUNDARY);
64 | sb.append(LINEND);
65 | sb.append("Content-Disposition: form-data; name=\"" + "data" + "\"" + LINEND);
66 | sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
67 | sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
68 | sb.append(LINEND);
69 | // post content
70 | sb.append(postContent);
71 | sb.append(LINEND);
72 | outStream.write(sb.toString().getBytes());
73 | int i = 0;
74 | for (FileEntity entity : entities) {
75 | StringBuilder sb1 = new StringBuilder();
76 | sb1.append(PREFIX);
77 | sb1.append(BOUNDARY);
78 | sb1.append(LINEND);
79 | sb1.append("Content-Disposition: form-data; name=\"file" + (i++) + "\"; filename=\"" + entity.getFileName() + "\""
80 | + LINEND);
81 | sb1.append("Content-Type: " + entity.getFileType() + LINEND);
82 | sb1.append(LINEND);
83 | outStream.write(sb1.toString().getBytes());
84 |
85 | InputStream is = new FileInputStream(entity.getFilePath());
86 | byte[] buffer = new byte[1024];
87 | int len = 0;
88 | while ((len = is.read(buffer)) != -1) {
89 |
90 | outStream.write(buffer, 0, len);
91 | }
92 |
93 | is.close();
94 | outStream.write(LINEND.getBytes());
95 | }
96 | byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
97 | outStream.write(end_data);
98 | outStream.flush();
99 | } catch (Exception e) {
100 | throw new AppException(AppException.ErrorType.UPLOAD, e.getMessage());
101 | }
102 | }
103 |
104 | /**
105 | * @param out
106 | * @param postContent
107 | * @param entities
108 | */
109 | public static void upload(OutputStream out, String postContent, ArrayList entities, OnProgressUpdatedListener listener) throws AppException {
110 | String BOUNDARY = "7d4a6d158c9"; // 数据分隔线
111 | String PREFIX = "--", LINEND = "\r\n";
112 | String CHARSET = "UTF-8";
113 | DataOutputStream outStream = new DataOutputStream(out);
114 | try {
115 | StringBuilder sb = new StringBuilder();
116 | sb.append(PREFIX);
117 | sb.append(BOUNDARY);
118 | sb.append(LINEND);
119 | sb.append("Content-Disposition: form-data; name=\"" + "data" + "\"" + LINEND);
120 | sb.append("Content-Type: text/plain; charset=" + CHARSET + LINEND);
121 | sb.append("Content-Transfer-Encoding: 8bit" + LINEND);
122 | sb.append(LINEND);
123 | // post content
124 | sb.append(postContent);
125 | sb.append(LINEND);
126 | outStream.write(sb.toString().getBytes());
127 | int i = 0;
128 | int totalLen = 0;
129 | int percent = 0;
130 | if (listener != null) {
131 | // TODO compute total file length
132 | File file = null;
133 | for (FileEntity entity : entities) {
134 | file = new File(entity.getFilePath());
135 | if (file.length() > 0) {
136 | totalLen += file.length();
137 | }
138 | }
139 | }
140 | for (FileEntity entity : entities) {
141 | StringBuilder sb1 = new StringBuilder();
142 | sb1.append(PREFIX);
143 | sb1.append(BOUNDARY);
144 | sb1.append(LINEND);
145 | sb1.append("Content-Disposition: form-data; name=\"file" + (i++) + "\"; filename=\"" + entity.getFileName() + "\""
146 | + LINEND);
147 | sb1.append("Content-Type: " + entity.getFileType() + LINEND);
148 | sb1.append(LINEND);
149 | outStream.write(sb1.toString().getBytes());
150 |
151 | InputStream is = new FileInputStream(entity.getFilePath());
152 | byte[] buffer = new byte[1024];
153 | int len = 0;
154 | int curLen = 0;
155 | while ((len = is.read(buffer)) != -1) {
156 | outStream.write(buffer, 0, len);
157 | if (listener != null){
158 | curLen += len;
159 | if (curLen * 100l / totalLen > percent) {
160 | listener.onProgressUpdated(curLen, totalLen);
161 | percent = (int) (curLen * 100l / totalLen);
162 | }
163 | }
164 | }
165 |
166 | is.close();
167 | outStream.write(LINEND.getBytes());
168 | }
169 | byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();
170 | outStream.write(end_data);
171 | outStream.flush();
172 | } catch (Exception e) {
173 | throw new AppException(AppException.ErrorType.UPLOAD, e.getMessage());
174 | }
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/cache/BitmapCache.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.cache;
2 |
3 |
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.IOException;
7 | import java.util.HashMap;
8 |
9 | import download.imageLoader.request.BitmapRequest;
10 | import download.imageLoader.util.ImageSizeUtil;
11 | import download.utils.Util;
12 |
13 | import android.annotation.SuppressLint;
14 | import android.annotation.TargetApi;
15 | import android.content.Context;
16 | import android.graphics.Bitmap;
17 | import android.graphics.BitmapFactory;
18 | import android.graphics.Movie;
19 | import android.graphics.drawable.BitmapDrawable;
20 | import android.os.Build;
21 | import android.os.StatFs;
22 | import android.os.Build.VERSION_CODES;
23 | import android.util.LruCache;
24 |
25 |
26 | @SuppressLint("NewApi")
27 | public class BitmapCache {
28 | private LruCache mMemoryBitmapLruCache;
29 | private LruCache mMemoryMovieLruCache;
30 | private DiskLruCache mDiskLruCache = null;
31 | private static final long DISK_CACHE_SIZE = 1024 * 1024 * 60;
32 | private class Size{
33 | public int width;
34 | public int height;
35 | public Size(int w,int h){
36 | this.width = w;
37 | this.height = h;
38 | }
39 | }
40 | private HashMap mHistoryMaxSize = new HashMap();
41 |
42 |
43 |
44 | @SuppressLint("NewApi")
45 | public BitmapCache() {
46 | super();
47 | // 获取我们应用的最大可用内存
48 | int maxMemory = Math.min(
49 | (int) Runtime.getRuntime().maxMemory() / 8, 30 * 1024 * 1024);
50 | mMemoryBitmapLruCache = new LruCache(maxMemory) {
51 | @Override
52 | protected int sizeOf(String key, Bitmap value) {
53 | return getBitmapByteSize(value);
54 | }
55 | };
56 | mMemoryMovieLruCache = new LruCache(10){
57 | @Override
58 | protected int sizeOf(String key, Movie value) {
59 | return 1;
60 | }
61 | };
62 | }
63 |
64 | private Boolean isSetted = false;
65 | private File diskCacheDir;
66 |
67 | public void setDiskLruCache(Context context) {
68 | if (isSetted) {
69 | isSetted = true;
70 | return;
71 | }
72 | if (mDiskLruCache == null) {
73 | try {
74 | diskCacheDir = Util.getDiskCacheDir(context, "bitmap");
75 | if (!diskCacheDir.exists()) {
76 | diskCacheDir.mkdirs();
77 | }
78 | if (getUsableSpace(diskCacheDir) > DISK_CACHE_SIZE) {
79 | mDiskLruCache = DiskLruCache.open(diskCacheDir,
80 | 1, 1, DISK_CACHE_SIZE);
81 | }
82 | } catch (IOException e) {
83 | e.printStackTrace();
84 | }
85 | }
86 | }
87 |
88 | @SuppressWarnings("deprecation")
89 | @TargetApi(VERSION_CODES.GINGERBREAD)
90 | private long getUsableSpace(File path) {
91 | if (Build.VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
92 | return path.getUsableSpace();
93 | }
94 | final StatFs stats = new StatFs(path.getPath());
95 | return (long) stats.getBlockSize() * (long) stats.getAvailableBlocks();
96 | }
97 |
98 | public void addMemoryBitmap(BitmapRequest request) {
99 | String key = Util.md5(request.path);
100 | if (request.bitmap != null){
101 | //保存使用过的尽可能的最大值
102 | Size oldSize = mHistoryMaxSize.get(request.path);
103 | Size newSize = new Size(request.width,request.height);
104 | if (oldSize == null || ( newSize.width * newSize.height > oldSize.width * oldSize.height )){
105 | mHistoryMaxSize.put(request.path,newSize);
106 | }
107 | mMemoryBitmapLruCache.put(request.getKey(), request.bitmap);
108 | }
109 | if (request.movie != null){
110 | mMemoryMovieLruCache.put(key,request.movie);
111 | }
112 | }
113 |
114 |
115 | public void getMemoryCache(BitmapRequest request) {
116 | String key = Util.md5(request.path);
117 | ImageSizeUtil.getImageViewSize(request);
118 | request.movie = mMemoryMovieLruCache.get(key);
119 | if (request.checkIfNeedAsyncLoad()){
120 | request.bitmap = mMemoryBitmapLruCache.get(request.getKey());
121 |
122 | Size oldSize = mHistoryMaxSize.get(request.path);
123 | if (oldSize != null && request.view != null && request.bitmap != null && (request.width > oldSize.width || request.height > oldSize.height)) {
124 | request.bitmap = null;
125 | }
126 | }
127 |
128 | }
129 |
130 | public DiskLruCache getmDiskLruCacheBitmap() {
131 | return mDiskLruCache;
132 | }
133 |
134 |
135 | public void getDiskCacheBitmap(BitmapRequest request) {
136 | if (mDiskLruCache == null) {
137 | return ;
138 | }
139 | String key = Util.md5(request.path);
140 | try {
141 | DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
142 | if (snapShot != null) {
143 | loadImageFromLocal(diskCacheDir.getAbsolutePath()
144 | + File.separator + key + ".0", request);
145 |
146 | }
147 | } catch (IOException e) {
148 | e.printStackTrace();
149 | }
150 | }
151 |
152 | private void loadImageFromLocal(String path, BitmapRequest request) {
153 | if (request.view == null || request.view.get() == null){
154 | return;
155 | }
156 | if (!new File(path).exists()) {
157 | return ;
158 | }
159 | ImageSizeUtil.getImageViewSize(request);
160 | BitmapFactory.Options options = new BitmapFactory.Options();
161 | options.inJustDecodeBounds = true;
162 | BitmapFactory.decodeFile(path, options);
163 | options.inSampleSize = ImageSizeUtil.caculateInSampleSize(options,
164 | request.width, request.height);
165 | options.inJustDecodeBounds = false;
166 | try{
167 | request.movie = Movie.decodeStream(new FileInputStream(new File(path)));
168 | }catch (Exception e){
169 |
170 | }
171 | if (request.checkIfNeedAsyncLoad()){
172 | request.bitmap = BitmapFactory.decodeFile(path, options);
173 | }
174 |
175 | }
176 |
177 | public Boolean hasDiskBm(String path) {
178 | String key = Util.md5(path);
179 | File file = new File(diskCacheDir.getAbsolutePath()+ File.separator + key + ".0");
180 | return file.exists() && file.length() > 0;
181 | }
182 |
183 | public void clearMemory(){
184 | mMemoryBitmapLruCache.evictAll();
185 | mMemoryMovieLruCache.evictAll();
186 | }
187 | public void clearDiskMemory(){
188 | try {
189 | if (mDiskLruCache != null){
190 | mDiskLruCache.delete();
191 | }
192 | }catch (Exception e){
193 | e.printStackTrace();
194 | }
195 | }
196 | private int getBitmapByteSize(Bitmap bitmap) {
197 | // The return value of getAllocationByteCount silently changes for recycled bitmaps from the
198 | // internal buffer size to row bytes * height. To avoid random inconsistencies in caches, we
199 | // instead assert here.
200 | if (bitmap.isRecycled()) {
201 | throw new IllegalStateException("Cannot obtain size for recycled Bitmap: " + bitmap
202 | + "[" + bitmap.getWidth() + "x" + bitmap.getHeight() + "] " + bitmap.getConfig());
203 | }
204 | if (Build.VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
205 | // Workaround for KitKat initial release NPE in Bitmap, fixed in MR1. See issue #148.
206 | try {
207 | return bitmap.getAllocationByteCount();
208 | } catch (NullPointerException e) {
209 | // Do nothing.
210 | }
211 | }
212 | return bitmap.getHeight() * bitmap.getRowBytes();
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/config/FailedDrawable.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.config;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.ColorFilter;
6 | import android.graphics.Paint;
7 | import android.graphics.PixelFormat;
8 | import android.graphics.Rect;
9 | import android.graphics.drawable.Drawable;
10 |
11 | public class FailedDrawable extends Drawable {
12 | private Paint mPaint;
13 | private int txsize;
14 | private int txcolor;
15 |
16 | public FailedDrawable(int color) {
17 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
18 | this.txcolor = color;
19 | }
20 |
21 | @Override
22 | public void draw(Canvas canvas) {
23 | final Rect r = getBounds();
24 | float cx = r.exactCenterX();
25 | float cy = r.exactCenterY();
26 | txsize = (int) Math.min((cx/2/2),cy * 0.8);
27 | mPaint.setTextSize(txsize);
28 | mPaint.setColor(txcolor);
29 | canvas.drawText("加载失败", cx - mPaint.measureText("加载失败") / 2, cy + txsize / 2, mPaint);
30 | }
31 |
32 | @Override
33 | public void setAlpha(int alpha) {
34 | mPaint.setAlpha(alpha);
35 | invalidateSelf();
36 |
37 | }
38 |
39 | @Override
40 | public void setColorFilter(ColorFilter cf) {
41 | mPaint.setColorFilter(cf);
42 | invalidateSelf();
43 | }
44 |
45 | @Override
46 | public int getOpacity() {
47 | // not sure, so be safe
48 | return PixelFormat.TRANSLUCENT;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/config/ImageConfig.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.config;
2 |
3 | import java.io.InputStream;
4 |
5 | import download.imageLoader.cache.BitmapCache;
6 | import android.annotation.SuppressLint;
7 | import android.content.Context;
8 | import android.content.res.Resources;
9 | import android.graphics.Bitmap;
10 | import android.graphics.BitmapFactory;
11 | import android.graphics.Color;
12 | import android.graphics.drawable.BitmapDrawable;
13 | import android.graphics.drawable.Drawable;
14 |
15 |
16 | @SuppressLint("NewApi")
17 | public class ImageConfig {
18 | public BitmapCache cache;
19 | private Drawable loadingBm = null;
20 | private Drawable failedBm;
21 | /**
22 | *只在wifi下下载
23 | */
24 | private Boolean onlyWifiMode = false;
25 | /**
26 | * 仅使用内存缓存模式,针对图片名不变图片经常变动的商城项目这样的需求。
27 | */
28 | private Boolean onlyMemoryMode = false;
29 |
30 | public void setOnlyWifiMode(Boolean b){
31 | this.onlyWifiMode = b;
32 | }
33 |
34 | public void setOnlyMemoryMode(Boolean b){
35 | this.onlyMemoryMode = b;
36 | }
37 |
38 | public Boolean getOnlyWifiMode(){
39 | return onlyWifiMode;
40 | }
41 |
42 | public Boolean getOnlyMemoryMode(){
43 | return onlyMemoryMode;
44 | }
45 |
46 | public void setFailedIdAndLoadingId(Resources res,int failedId,int loadingId) {
47 | ifIint = true;
48 | this.failedBm = new BitmapDrawable(res,BitmapFactory.decodeResource(res, failedId));
49 | this.loadingBm = new BitmapDrawable(res,BitmapFactory.decodeResource(res, loadingId));
50 | }
51 |
52 |
53 | private Boolean ifIint = false;
54 | public void initDefault(Context context){
55 | if (!ifIint){
56 | ifIint = true;
57 | loadingBm = new LoadingDrawable();
58 | failedBm = new FailedDrawable(Color.RED);
59 | }
60 | }
61 | public Drawable getLoadingBm() {
62 | return loadingBm;
63 | }
64 |
65 | public Drawable getFailedBm() {
66 | return failedBm;
67 | }
68 |
69 |
70 | public ImageConfig() {
71 | super();
72 | cache = new BitmapCache();
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/config/LoadOrder.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.config;
2 |
3 | public enum LoadOrder {
4 | FIFO, LIFO;
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/config/LoadingDrawable.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.config;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.Canvas;
6 | import android.graphics.ColorFilter;
7 | import android.graphics.Paint;
8 | import android.graphics.PixelFormat;
9 | import android.graphics.Rect;
10 | import android.graphics.RectF;
11 | import android.graphics.drawable.Drawable;
12 |
13 |
14 | import java.io.InputStream;
15 |
16 | public class LoadingDrawable extends Drawable {
17 | private Paint mPaint;
18 | private int txsize;
19 | private Bitmap bitmap;
20 |
21 | final Rect r = null;
22 | float cx;
23 | float cy;
24 | int size;
25 | Rect src;
26 | RectF dst;
27 |
28 | public LoadingDrawable() {
29 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
30 | bitmap = getBitmapFormSrc("image/loading.png");
31 | }
32 |
33 | @Override
34 | public void draw(Canvas canvas) {
35 | Rect r = getBounds();
36 | cx = r.exactCenterX();
37 | cy = r.exactCenterY();
38 | size = (int) Math.min(cx,cy);
39 | src = new Rect(0,0, bitmap.getWidth(),bitmap.getHeight());
40 | dst = new RectF(cx - size / 2, cy - size / 2,cx + size / 2, cy + size / 2);
41 | canvas.drawBitmap(bitmap,src,dst,mPaint);
42 | }
43 |
44 | @Override
45 | public void setAlpha(int alpha) {
46 | mPaint.setAlpha(alpha);
47 | invalidateSelf();
48 |
49 | }
50 |
51 | @Override
52 | public void setColorFilter(ColorFilter cf) {
53 | mPaint.setColorFilter(cf);
54 | invalidateSelf();
55 | }
56 |
57 | @Override
58 | public int getOpacity() {
59 | // not sure, so be safe
60 | return PixelFormat.TRANSLUCENT;
61 | }
62 | public static Bitmap getBitmapFormSrc(String src){
63 | Bitmap bit = null;
64 | try {
65 | InputStream is = ImageConfig.class.getResourceAsStream(src);
66 | bit = BitmapFactory.decodeStream(is);
67 | } catch (Exception e) {
68 | }
69 | return bit;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/core/BmManager.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.core;
2 |
3 | import android.graphics.Bitmap;
4 | import android.util.Log;
5 |
6 | import download.imageLoader.util.FaceCropper;
7 |
8 | /**
9 | * 为了调用更简单添加此门面
10 | * path示例:"http://img.blog.csdn.net/20160114230048304",//gif图
11 | * "assets//:test.png",
12 | * "drawable//:"+R.drawable.common_logo,
13 | * "file:///mnt/sdcard/paint.png",
14 | * @author lizhiyun
15 | *
16 | */
17 | public class BmManager {
18 |
19 | /**
20 | * preload
21 | *
22 | * @param path
23 | */
24 | public static void preLoad(String path) {
25 | download.imageLoader.core.ImageLoader.getInstance().preLoad(path);
26 | }
27 |
28 |
29 | /**
30 | * 设置是否仅wifi下下载模式
31 | * @param b
32 | */
33 | public static void setOnlyWifiMode(Boolean b){
34 | ImageLoader.getInstance().getConfig().setOnlyWifiMode(b);
35 | }
36 |
37 | /**
38 | * 设置是否仅使用缓存模式
39 | * @param b
40 | */
41 | public static void setOnlyMemoryMode(Boolean b){
42 | ImageLoader.getInstance().getConfig().setOnlyMemoryMode(b);
43 | }
44 |
45 | /**
46 | * clear all memory
47 | */
48 | public static void clearAllMemory(){
49 | ImageLoader.getInstance().getConfig().cache.clearMemory();
50 | ImageLoader.getInstance().getConfig().cache.clearDiskMemory();
51 | }
52 |
53 |
54 | static FaceCropper fc = null;
55 | public static synchronized Bitmap face(Bitmap bitmap){
56 | try{
57 | if (fc == null){
58 | fc = new FaceCropper();
59 | fc.setDebug(false);
60 | }
61 | Log.e("test", "face");
62 | Bitmap faceBitmap = fc.cropFace(bitmap);
63 | return faceBitmap;
64 | }catch (Exception e){
65 | Log.e("test","face exception "+e.getMessage());
66 | return null;
67 | }
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/core/Image.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.core;
2 |
3 | import android.content.Context;
4 |
5 | import download.imageLoader.request.BitmapRequestBuilder;
6 |
7 | /**
8 | * Created by lizhiyun on 16/6/7.
9 | */
10 | public class Image {
11 | public static BitmapRequestBuilder with(){
12 | return new BitmapRequestBuilder();
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/core/ImageLoader.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.core;
2 |
3 | import com.litesuits.go.OverloadPolicy;
4 | import com.litesuits.go.SchedulePolicy;
5 | import com.litesuits.go.SmartExecutor;
6 | import download.imageLoader.config.ImageConfig;
7 | import download.imageLoader.request.BitmapRequest;
8 | import download.imageLoader.view.PowerImageView;
9 |
10 | import android.annotation.TargetApi;
11 | import android.content.Context;
12 | import android.os.Build;
13 | import android.os.Looper;
14 | import android.util.Log;
15 |
16 | public class ImageLoader {
17 | private SmartExecutor executor;
18 |
19 |
20 | private static class InstanceHoler {
21 | private static final ImageLoader instance = new ImageLoader();
22 | }
23 | public static ImageLoader getInstance() {
24 | return InstanceHoler.instance;
25 | }
26 |
27 | private RunningTasksManager mRunningTasksManager;
28 | private ImageConfig config = null;
29 | private final int threadCount = 3;
30 |
31 | public RunningTasksManager getmRunningTasksManager(){
32 | if (mRunningTasksManager == null)
33 | mRunningTasksManager = new RunningTasksManager(threadCount);
34 | return mRunningTasksManager;
35 | }
36 | public ImageConfig getConfig(){
37 | return config;
38 | }
39 | private ImageLoader() {
40 | mRunningTasksManager = new RunningTasksManager(threadCount);
41 | executor = new SmartExecutor(threadCount, 400);
42 | executor.setSchedulePolicy(SchedulePolicy.FirstInFistRun);
43 | executor.setOverloadPolicy(OverloadPolicy.DiscardOldTaskInQueue);
44 | config = new ImageConfig();
45 | }
46 |
47 | protected void setLoadingAndFailedId(Context context, int loadingId,
48 | int failedId) {
49 | config.setFailedIdAndLoadingId(context.getResources(), failedId,
50 | loadingId);
51 | }
52 |
53 |
54 | protected void preLoad(String path) {
55 | BitmapRequest request = new BitmapRequest();
56 | request.path = path;
57 | loadImage(request);
58 | }
59 |
60 | public void cancelOldTask(PowerImageView powerImageView) {
61 | executor.remove(powerImageView);
62 | }
63 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
64 | public void loadImage(final BitmapRequest request) {
65 | if (Looper.myLooper() == Looper.getMainLooper()) {
66 | if (request.view == null || request.view.get() == null){
67 | final LoadTask task = new LoadTask(request, ImageLoader.this);
68 | executor.execute(task);
69 | }else {
70 | getInstance();
71 | config.cache.setDiskLruCache(request.view.get().getContext()
72 | .getApplicationContext());
73 | config.initDefault(request.view.get().getContext());
74 | config.cache.getMemoryCache(request);
75 | request.view.get().setTag(request.getKey());
76 | if (!request.checkIfNeedAsyncLoad()) {
77 | request.display();
78 | } else {
79 | executor.remove(request.view.get());
80 | final LoadTask task = new LoadTask(request, ImageLoader.this);
81 | request.displayLoading(config.getLoadingBm());
82 | executor.execute(task);
83 | }
84 | }
85 | } else {
86 | throw new RuntimeException("only run on ui thread");
87 | }
88 | }
89 |
90 | }
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/core/LoadTask.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.core;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.graphics.drawable.BitmapDrawable;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.os.Message;
9 | import android.util.Log;
10 |
11 |
12 | import com.example.ui.R;
13 |
14 | import java.lang.ref.WeakReference;
15 | import java.util.concurrent.atomic.AtomicBoolean;
16 |
17 | import download.imageLoader.loader.Load;
18 | import download.imageLoader.request.BitmapRequest;
19 | import download.imageLoader.util.FaceCropper;
20 | import download.imageLoader.util.GaussianBlur;
21 |
22 | /**
23 | * Created by lizhiyun on 16/5/23.
24 | */
25 | public class LoadTask implements Runnable {
26 | public final static int REFRESH = 1;
27 | public BitmapRequest mRequest;
28 | ImageLoader mImageLoader;
29 | private final AtomicBoolean mCancel = new AtomicBoolean();
30 | private LoadTask(){}
31 | public LoadTask(BitmapRequest request,ImageLoader loader){
32 | super();
33 | this.mRequest = request;
34 | this.mImageLoader = loader;
35 | this.mCancel.set(false);
36 | }
37 |
38 | public void cancel(){
39 | mCancel.set(true);
40 | }
41 |
42 | @Override
43 | public void run() {
44 | if (mCancel.get()){
45 | return;
46 | }
47 | while (mImageLoader.getmRunningTasksManager().hasDoingTask(mRequest)) {
48 | try {
49 | if (mCancel.get()){
50 | return;
51 | }
52 | Thread.sleep(50);
53 | } catch (InterruptedException e) {
54 | e.printStackTrace();
55 | }
56 | }
57 | mImageLoader.getmRunningTasksManager().addDoingTask(mRequest);
58 |
59 | mImageLoader.getConfig().cache.getMemoryCache(mRequest);
60 | if (mRequest.checkIfNeedAsyncLoad()){
61 | mImageLoader.getConfig().cache.getDiskCacheBitmap(mRequest);
62 | }
63 | if (mRequest.checkIfNeedAsyncLoad()) {
64 | Load.loadBitmap(mRequest, mImageLoader.getConfig());
65 | if (mRequest.checkIfNeedAsyncLoad()){
66 | mImageLoader.getConfig().cache.getDiskCacheBitmap(mRequest);
67 | }
68 |
69 | }
70 | if (mCancel.get()){
71 | return;
72 | }
73 | face();
74 | blur();
75 | if (mCancel.get()){
76 | return;
77 | }
78 | refreashBitmap();
79 | mImageLoader.getConfig().cache.addMemoryBitmap(mRequest);
80 | mImageLoader.getmRunningTasksManager().removeDoingTask(mRequest);
81 | }
82 |
83 | private void face() {
84 | if (mRequest.isFace && mRequest.movie == null && mRequest.bitmap != null) {
85 | Bitmap face = BmManager.face(mRequest.bitmap);
86 | if (face != null){
87 | mRequest.bitmap = face;
88 | }
89 | }
90 | }
91 |
92 | private void blur() {
93 | if (mRequest.isBlur && mRequest.movie == null && mRequest.bitmap != null) {
94 | Bitmap blurBitmap = new GaussianBlur().blur(mRequest.bitmap, 3);
95 | mRequest.bitmap = blurBitmap;
96 | }
97 | }
98 |
99 |
100 | private void refreashBitmap() {
101 | if (mCancel.get()){
102 | return;
103 | }
104 | //使用消息缓存
105 | Message message = Message.obtain();
106 | message.what = REFRESH;
107 | message.obj = mRequest;
108 | if (sUIHandler != null){
109 | sUIHandler.sendMessage(message);
110 | }
111 | }
112 | private static Handler sUIHandler = new Handler(Looper.getMainLooper()) {
113 | public void handleMessage(Message msg) {
114 | final BitmapRequest request = (BitmapRequest) msg.obj;
115 | switch (msg.what) {
116 | case LoadTask.REFRESH:
117 | if (!request.checkEffective()) {
118 | return;
119 | }
120 | if (request.view == null || request.view.get() == null){
121 | return;
122 | }
123 | request.display();
124 | break;
125 |
126 | default:
127 | break;
128 | }
129 |
130 | }
131 |
132 | };
133 |
134 | }
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/core/RunningTasksManager.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.core;
2 |
3 | import java.util.LinkedHashMap;
4 |
5 | import download.imageLoader.request.BitmapRequest;
6 |
7 | /**
8 | * 该类用于解决较近的2个相同uri下载造成的可能的bug。
9 | * Created by lizhiyun on 16/5/23.
10 | */
11 | public class RunningTasksManager {
12 |
13 | private LinkedHashMap doingMap = null;
14 | private RunningTasksManager(){}
15 | public RunningTasksManager(int threadCount){
16 | doingMap = new LinkedHashMap(
17 | threadCount);
18 | }
19 | public Boolean hasDoingTask(BitmapRequest request) {
20 | synchronized (doingMap) {
21 | if (!request.path.contains("http:") && !request.path.contains("https:")){
22 | return false;
23 | }
24 | return doingMap.containsKey(request.path);
25 | }
26 | }
27 |
28 | public void addDoingTask(BitmapRequest request) {
29 | synchronized (doingMap) {
30 | if (!request.path.contains("http:") && !request.path.contains("https:")){
31 | return ;
32 | }
33 | doingMap.put(request.path, request.path);
34 | }
35 | }
36 |
37 | public void removeDoingTask(BitmapRequest request) {
38 | synchronized (doingMap) {
39 | if (!request.path.contains("http:") && !request.path.contains("https:")){
40 | return ;
41 | }
42 | doingMap.remove(request.path);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/listener/CustomDisplayMethod.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.listener;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.Movie;
5 | import android.graphics.drawable.BitmapDrawable;
6 | import android.graphics.drawable.Drawable;
7 | import android.view.View;
8 |
9 | /**
10 | * Created by lizhiyun on 16/5/29.
11 | */
12 | public abstract class CustomDisplayMethod {
13 | public abstract void display(Bitmap bitmap,Movie movie);
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/listener/OnProgressUpdatedListener.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.listener;
2 |
3 | /**
4 | * Created by lizhiyun on 16/6/10.
5 | */
6 | public interface OnProgressUpdatedListener {
7 |
8 | void onProgressUpdated(int curLen, int totalLen);
9 | }
10 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/loader/AssetsLoader.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.loader;
2 |
3 | import android.graphics.BitmapFactory;
4 | import android.graphics.Movie;
5 | import android.graphics.drawable.BitmapDrawable;
6 |
7 |
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 |
11 | import download.imageLoader.config.ImageConfig;
12 | import download.imageLoader.request.BitmapRequest;
13 | import download.imageLoader.util.ImageSizeUtil;
14 |
15 | /**
16 | * Created by lizhiyun on 16/6/2.
17 | */
18 | public class AssetsLoader implements LoadInterface {
19 |
20 | @Override
21 | public void load(BitmapRequest request, ImageConfig config) {
22 | String name = request.path.substring(9);
23 | InputStream is = null;
24 | try {
25 | if (request.view == null || request.view.get() == null){
26 | return;
27 | }
28 | is = request.view.get().getContext().getAssets().open(name);
29 | } catch (IOException e) {
30 | e.printStackTrace();
31 | }
32 | if (is == null) {
33 | return;
34 | }
35 | ImageSizeUtil.getImageViewSize(request);
36 | request.movie = Movie.decodeStream(is);
37 | if (request.checkIfNeedAsyncLoad()){
38 | BitmapFactory.Options options = new BitmapFactory.Options();
39 | options.inJustDecodeBounds = true;
40 | BitmapFactory.decodeStream(is, null, options);
41 | options.inSampleSize = ImageSizeUtil.caculateInSampleSize(options,
42 | request.width, request.height);
43 | options.inJustDecodeBounds = false;
44 | request.bitmap = BitmapFactory.decodeStream(is, null, options);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/loader/DrawableLoader.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.loader;
2 |
3 | import android.graphics.BitmapFactory;
4 | import android.graphics.Movie;
5 | import android.graphics.drawable.BitmapDrawable;
6 |
7 |
8 | import download.imageLoader.config.ImageConfig;
9 | import download.imageLoader.request.BitmapRequest;
10 | import download.imageLoader.util.ImageSizeUtil;
11 |
12 | /**
13 | * Created by lizhiyun on 16/6/2.
14 | */
15 | public class DrawableLoader implements LoadInterface {
16 |
17 | @Override
18 | public void load(BitmapRequest request, ImageConfig config) {
19 | if (request.view == null || request.view.get() == null){
20 | return;
21 | }
22 | int id = 0;
23 | try {
24 | id = Integer.parseInt(request.path.substring(11));
25 | } catch (NumberFormatException e) {
26 | e.printStackTrace();
27 | }
28 | if (id == 0) {
29 | return;
30 | }
31 | ImageSizeUtil.getImageViewSize(request);
32 | BitmapFactory.Options options = new BitmapFactory.Options();
33 | options.inJustDecodeBounds = true;
34 |
35 | BitmapFactory.decodeResource(request.view.get().getResources(), id, options);
36 | options.inSampleSize = ImageSizeUtil.caculateInSampleSize(options,
37 | request.width, request.height);
38 | options.inJustDecodeBounds = false;
39 | try{
40 | request.movie = Movie.decodeStream(request.view.get().getResources().openRawResource(id));
41 | }catch (Exception e){
42 |
43 | }
44 | if (request.checkIfNeedAsyncLoad()){
45 | request.bitmap = BitmapFactory.decodeResource(request.view.get().getResources(), id, options);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/loader/FileLoader.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.loader;
2 |
3 | import android.graphics.BitmapFactory;
4 | import android.graphics.Movie;
5 | import android.graphics.drawable.BitmapDrawable;
6 |
7 |
8 | import java.io.File;
9 | import java.io.FileInputStream;
10 | import java.net.URI;
11 |
12 | import download.imageLoader.config.ImageConfig;
13 | import download.imageLoader.request.BitmapRequest;
14 | import download.imageLoader.util.ImageSizeUtil;
15 |
16 | /**
17 | * Created by lizhiyun on 16/6/2.
18 | */
19 | public class FileLoader implements download.imageLoader.loader.LoadInterface {
20 | @Override
21 | public void load(BitmapRequest request, ImageConfig config) {
22 |
23 | if (request.view == null || request.view.get() == null){
24 | return;
25 | }
26 | String path = new File(URI.create(request.path)).getAbsolutePath().substring(1);
27 | if (!new File(path).exists()) {
28 | return ;
29 | }
30 | ImageSizeUtil.getImageViewSize(request);
31 | BitmapFactory.Options options = new BitmapFactory.Options();
32 | options.inJustDecodeBounds = true;
33 | BitmapFactory.decodeFile(path, options);
34 | options.inSampleSize = ImageSizeUtil.caculateInSampleSize(options,
35 | request.width, request.height);
36 | options.inJustDecodeBounds = false;
37 |
38 | try{
39 | request.movie = Movie.decodeStream(new FileInputStream(new File(path)));
40 | }catch (Exception e){
41 |
42 | }
43 | if (request.checkIfNeedAsyncLoad()){
44 | request.bitmap = BitmapFactory.decodeFile(path, options);
45 | }
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/loader/HttpLoader.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.loader;
2 |
3 | import android.graphics.BitmapFactory;
4 | import android.graphics.Movie;
5 | import android.graphics.drawable.BitmapDrawable;
6 |
7 |
8 | import java.io.BufferedInputStream;
9 | import java.io.BufferedOutputStream;
10 | import java.io.FileOutputStream;
11 | import java.io.IOException;
12 | import java.io.InputStream;
13 | import java.io.OutputStream;
14 | import java.net.HttpURLConnection;
15 | import java.net.URL;
16 |
17 | import download.imageLoader.cache.DiskLruCache;
18 | import download.imageLoader.config.ImageConfig;
19 | import download.imageLoader.request.BitmapRequest;
20 | import download.imageLoader.util.ImageSizeUtil;
21 | import download.utils.Util;
22 |
23 | /**
24 | * Created by lizhiyun on 16/6/2.
25 | */
26 | public class HttpLoader implements LoadInterface {
27 |
28 | @Override
29 | public void load(BitmapRequest request, ImageConfig config) {
30 | request.isFirstDown = true;
31 | if (!config.getOnlyMemoryMode()){
32 | if (!config.getOnlyWifiMode()){
33 | downloadBitmapToDisk(request, config.cache.getmDiskLruCacheBitmap());
34 | }
35 | config.cache.getDiskCacheBitmap(request);
36 | }
37 | if (request.checkIfNeedAsyncLoad() && !config.getOnlyWifiMode()) {
38 | downloadImgByUrl(request);
39 | }
40 | }
41 | public void downloadBitmapToDisk(BitmapRequest request,
42 | DiskLruCache diskLruCache) {
43 | if (diskLruCache == null) {
44 | return ;
45 | }
46 | final String key = Util.md5(request.path);
47 | DiskLruCache.Editor editor;
48 | try {
49 | editor = diskLruCache.edit(key);
50 | if (editor != null) {
51 | OutputStream outputStream = editor.newOutputStream(0);
52 | BufferedOutputStream out = null;
53 | BufferedInputStream in = null;
54 | HttpURLConnection conn = null;
55 | try {
56 | URL url = new URL(request.path);
57 | conn = (HttpURLConnection) url.openConnection();
58 | conn.setConnectTimeout(10*1000);
59 | request.totalSize = conn.getContentLength();
60 | in = new BufferedInputStream(conn.getInputStream(), 8 * 1024);
61 | out = new BufferedOutputStream(outputStream, 8 * 1024);
62 | int b = 0;
63 | while ((b = in.read()) != -1) {
64 | out.write(b);
65 | }
66 | editor.commit();
67 | } catch (Exception e) {
68 | e.printStackTrace();
69 | editor.abort();
70 | } finally {
71 | Util.close(conn, out, in);
72 | }
73 | }
74 | } catch (IOException e1) {
75 | e1.printStackTrace();
76 | }
77 |
78 | try {
79 | diskLruCache.flush();
80 | } catch (IOException e) {
81 | e.printStackTrace();
82 | }
83 |
84 | }
85 |
86 |
87 | public static void downloadImgByUrl(BitmapRequest request) {
88 | FileOutputStream fos = null;
89 | InputStream is = null;
90 | HttpURLConnection conn = null;
91 | try {
92 | URL url = new URL(request.path);
93 | conn = (HttpURLConnection) url.openConnection();
94 | conn.setConnectTimeout(10*1000);
95 | is = new BufferedInputStream(conn.getInputStream());
96 | is.mark(is.available());
97 | BitmapFactory.Options options = new BitmapFactory.Options();
98 | options.inJustDecodeBounds = true;
99 | BitmapFactory.decodeStream(is, null, options);
100 | ImageSizeUtil.getImageViewSize(request);
101 | options.inSampleSize = ImageSizeUtil.caculateInSampleSize(options,
102 | request.width, request.height);
103 | options.inJustDecodeBounds = false;
104 | request.movie = Movie.decodeStream(is);
105 | if (request.checkIfNeedAsyncLoad()){
106 | request.bitmap = BitmapFactory.decodeStream(is, null, options);
107 | }
108 | } catch (Exception e) {
109 | e.printStackTrace();
110 | } finally {
111 | Util.close(conn, fos, is);
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/loader/Load.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.loader;
2 |
3 | // _ooOoo_
4 | // o8888888o
5 | // 88" . "88
6 | // (| -_- |)
7 | // O\ = /O
8 | // ____/`---'\____
9 | // . ' \\| |// `.
10 | // / \\||| : |||// \
11 | // / _||||| -:- |||||- \
12 | // | | \\\ - /// | |
13 | // | \_| ''\---/'' | |
14 | // \ .-\__ `-` ___/-. /
15 | // ___`. .' /--.--\ `. . __
16 | // ."" '< `.___\_<|>_/___.' >'"".
17 | // | | : `- \`.;`\ _ /`;.`/ - ` : | |
18 | // \ \ `-. \_ __\ /__ _/ .-` / /
19 | // ======`-.____`-.___\_____/___.-`____.-'======
20 | // `=---='
21 | //
22 | // .............................................
23 | // 佛祖镇楼 BUG辟易
24 | // 佛曰:
25 | // 写字楼里写字间,写字间里程序员;
26 | // 程序人员写程序,又拿程序换酒钱。
27 | // 酒醒只在网上坐,酒醉还来网下眠;
28 | // 酒醉酒醒日复日,网上网下年复年。
29 | // 但愿老死电脑间,不愿鞠躬老板前;
30 | // 奔驰宝马贵者趣,公交自行程序员。
31 | // 别人笑我忒疯癫,我笑自己命太贱;
32 | // 不见满街漂亮妹,哪个归得程序员?
33 |
34 |
35 | import java.util.HashMap;
36 | import java.util.Map;
37 |
38 | import download.imageLoader.config.ImageConfig;
39 | import download.imageLoader.request.BitmapRequest;
40 |
41 | /**
42 | * 图片加载器
43 | *
44 | * @author Administrator
45 | *
46 | */
47 | public class Load {
48 | private static HashMap map;
49 | private static HashMap classHashMap;
50 | static {
51 | classHashMap = new HashMap(4);
52 | classHashMap.put("http:",HttpLoader.class);
53 | classHashMap.put("https:",HttpLoader.class);
54 | classHashMap.put("assets:",AssetsLoader.class);
55 | classHashMap.put("drawable:",DrawableLoader.class);
56 | classHashMap.put("file:",FileLoader.class);
57 | map = new HashMap();
58 | }
59 | public static void loadBitmap(BitmapRequest request, ImageConfig config) {
60 | for (Map.Entry entry: classHashMap.entrySet()
61 | ) {
62 | if (request.path.contains(entry.getKey())){
63 | try {
64 | map.put(entry.getKey(),((LoadInterface) entry.getValue().newInstance()));
65 |
66 | } catch (InstantiationException e) {
67 | e.printStackTrace();
68 | } catch (IllegalAccessException e) {
69 | e.printStackTrace();
70 | }
71 | if (map.get(entry.getKey()) != null){
72 | map.get(entry.getKey()).load(request,config);
73 | }
74 | break;
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/loader/LoadInterface.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.loader;
2 |
3 | import download.imageLoader.config.ImageConfig;
4 | import download.imageLoader.request.BitmapRequest;
5 |
6 | /**
7 | * Created by lizhiyun on 16/6/2.
8 | */
9 | public interface LoadInterface {
10 | public abstract void load(BitmapRequest request, ImageConfig config);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/request/BitmapRequest.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.request;
2 |
3 | import download.imageLoader.core.ImageLoader;
4 | import download.imageLoader.core.LoadTask;
5 | import download.imageLoader.listener.CustomDisplayMethod;
6 | import download.imageLoader.view.PowerImageView;
7 | import download.utils.Util;
8 |
9 | import android.animation.ObjectAnimator;
10 | import android.annotation.TargetApi;
11 | import android.graphics.Bitmap;
12 | import android.graphics.Movie;
13 | import android.graphics.drawable.BitmapDrawable;
14 | import android.graphics.drawable.Drawable;
15 | import android.os.Build;
16 | import android.view.View;
17 | import android.widget.ImageSwitcher;
18 | import android.widget.ImageView;
19 |
20 | import java.lang.ref.WeakReference;
21 |
22 | public class BitmapRequest{
23 | public WeakReference view;
24 | public Bitmap bitmap;
25 | public Movie movie;
26 | public int width;
27 | public int height;
28 | public Boolean isFirstDown;
29 | public Boolean isBlur;
30 | public Boolean isFace;
31 | public String path;
32 | public long totalSize;
33 | public CustomDisplayMethod customDisplayMethod;
34 |
35 |
36 | public BitmapRequest(){
37 | isFirstDown = false;
38 | isBlur = false;
39 | }
40 | public String getKey(){
41 | return Util.md5(this.path) + this.isBlur + this.isFace;
42 | }
43 | /**
44 | * 检测是否需要异步获取
45 | * @return
46 | */
47 | public Boolean checkIfNeedAsyncLoad(){
48 | return isNoresult() || (bitmap == null && view.get() != null && !(view.get() instanceof PowerImageView)) ;
49 | }
50 |
51 | public Boolean isNoresult(){
52 | return (bitmap == null && movie == null);
53 | }
54 |
55 | /**
56 | * 检测是否能用于显示
57 | * @return
58 | */
59 | public Boolean checkEffective(){
60 | if (this.view.get() != null && ((String)this.view.get().getTag()).equals(getKey())){
61 | return true;
62 | }
63 | return false;
64 | }
65 | public Boolean isNetWork() {
66 | return path.contains("http:") || path.contains("https:");
67 | }
68 |
69 |
70 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
71 | public void displayLoading(Drawable b) {
72 | if (view == null || view.get() == null){
73 | return;
74 | }
75 | if (customDisplayMethod != null){
76 | customDisplayMethod.display(bitmap, movie);
77 | return;
78 | }
79 | if (view.get() instanceof PowerImageView){
80 | ((PowerImageView) view.get()).setImageDrawable(b);
81 | }else{
82 | setBitmap(view.get(), b);
83 | }
84 | }
85 |
86 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
87 | public void display() {
88 | if (view == null || view.get() == null){
89 | return;
90 | }
91 | if (customDisplayMethod != null){
92 | customDisplayMethod.display(bitmap,movie);
93 | return;
94 | }
95 | if (view.get() instanceof PowerImageView){
96 | if (movie != null){
97 | ((PowerImageView) view.get()).setMovie(movie);
98 | }else {
99 | if (bitmap != null){
100 | ((PowerImageView) view.get()).setImageBitmap(bitmap);
101 | }else {
102 | ((PowerImageView) view.get()).setImageDrawable(ImageLoader.getInstance().getConfig().getFailedBm());
103 | }
104 | }
105 | }else{
106 | if (bitmap != null){
107 | setBitmap(view.get(),bitmap);
108 | }else {
109 | setBitmap(view.get(),ImageLoader.getInstance().getConfig().getFailedBm());
110 | }
111 | }
112 | if (this != null && isFirstDown != null && isFirstDown && bitmap != null) {
113 | ObjectAnimator.ofFloat(view.get(),"alpha",0,1f).setDuration(500).start();
114 | }
115 | }
116 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
117 | public void setBitmap(View view,Drawable bitmap) {
118 | if (view == null) {
119 | return;
120 | }
121 | if (view instanceof ImageView) {
122 | ((ImageView) view).setImageDrawable(bitmap);
123 | } else if (view instanceof ImageSwitcher) {
124 | ((ImageSwitcher) view).setImageDrawable(bitmap);
125 | } else {// 对于其他view设置背景
126 | view.setBackground(bitmap);
127 | }
128 | }
129 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
130 | public void setBitmap(View view,Bitmap bitmap) {
131 | if (view == null) {
132 | return;
133 | }
134 | if (view instanceof ImageView) {
135 | ((ImageView) view).setImageBitmap(bitmap);
136 | } else if (view instanceof ImageSwitcher) {
137 | ((ImageSwitcher) view).setImageDrawable(new BitmapDrawable(bitmap));
138 | } else {// 对于其他view设置背景
139 | view.setBackground(new BitmapDrawable(bitmap));
140 | }
141 | }
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/request/BitmapRequestBuilder.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.request;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import java.lang.ref.WeakReference;
7 | import download.imageLoader.core.ImageLoader;
8 | import download.imageLoader.core.LoadTask;
9 | import download.imageLoader.listener.CustomDisplayMethod;
10 |
11 | /**
12 | * Created by lizhiyun on 16/6/3.
13 | */
14 | public class BitmapRequestBuilder {
15 | public WeakReference view;
16 | public int width;
17 | public int height;
18 | public String path;
19 | public CustomDisplayMethod customDisplayMethod;
20 | public Boolean isBlur;
21 | public Boolean isFace;
22 |
23 | public BitmapRequestBuilder(){
24 | this.isBlur = false;
25 | this.isFace = false;
26 | }
27 |
28 | public void into(View view){
29 | if (isBlur == null){
30 | isBlur = false;
31 | }
32 | BitmapRequest bitmapRequest = new BitmapRequest();
33 | bitmapRequest.path = path;
34 | bitmapRequest.width = width;
35 | bitmapRequest.height = height;
36 | bitmapRequest.customDisplayMethod = customDisplayMethod;
37 | bitmapRequest.view = new WeakReference(view);
38 | bitmapRequest.isBlur = isBlur;
39 | bitmapRequest.isFace = isFace;
40 | ImageLoader.getInstance().loadImage(bitmapRequest);
41 |
42 |
43 |
44 | }
45 | public BitmapRequestBuilder blur(Boolean b){
46 | this.isBlur = b;
47 | return this;
48 | }
49 | public BitmapRequestBuilder face(Boolean b){
50 | this.isFace = b;
51 | return this;
52 | }
53 |
54 | public BitmapRequestBuilder size(int width,int height){
55 | this.width = width;
56 | this.height = height;
57 | return this;
58 | }
59 | public BitmapRequestBuilder load(String path){
60 | this.path = path;
61 | return this;
62 | }
63 | public BitmapRequestBuilder customDisplay(CustomDisplayMethod customDisplayMethod){
64 | this.customDisplayMethod = customDisplayMethod;
65 | return this;
66 | }
67 |
68 |
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/util/BitmapOperate.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014, kymjs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package download.imageLoader.util;
17 |
18 | import android.graphics.Bitmap;
19 | import android.graphics.Canvas;
20 | import android.graphics.Color;
21 | import android.graphics.Paint;
22 |
23 | /**
24 | * 格式化图片的工具类
25 | *
26 | * @author kymjs (http://www.kymjs.com)
27 | *
28 | */
29 | final class BitmapOperate {
30 | /**
31 | * 格式化图片宽高,使之可以被识别
32 | *
33 | * @param bitmap
34 | * 待格式化的图片
35 | * @return
36 | */
37 | public static Bitmap formatBitmap(Bitmap bitmap) {
38 | Bitmap aimBitmap = null;
39 |
40 | int width = bitmap.getWidth();
41 | int height = bitmap.getHeight();
42 | boolean needChange = false;
43 | if (width % 2 == 1) {
44 | width++;
45 | needChange = true;
46 | }
47 | if (height % 2 == 1) {
48 | height++;
49 | needChange = true;
50 | }
51 | // 如果发生了改变,则做形变
52 | if (needChange) {
53 | aimBitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
54 | bitmap = null;
55 | } else {
56 | aimBitmap = bitmap;
57 | }
58 | return aimBitmap;
59 | }
60 |
61 | /**
62 | * 格式化图片为565格式,使之可以裁剪
63 | *
64 | * @param bitmap
65 | * 待处理的图片
66 | * @return
67 | */
68 | public static Bitmap formatBitmapTo565(Bitmap bitmap) {
69 | Bitmap aimBitmap = null;
70 | if (bitmap.getConfig() != Bitmap.Config.RGB_565) {
71 | aimBitmap = Bitmap.createBitmap(bitmap.getWidth(),
72 | bitmap.getHeight(), Bitmap.Config.RGB_565);
73 | // 将创建的565格式作为画布,把bitmap重新画到565画布上
74 | Paint paint = new Paint();
75 | Canvas canvas = new Canvas(aimBitmap);
76 | paint.setColor(Color.BLACK);
77 | canvas.drawBitmap(bitmap, 0, 0, paint);
78 | bitmap = null;
79 | }
80 | return aimBitmap;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/util/FaceCropper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014, kymjs
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package download.imageLoader.util;
17 |
18 | import android.content.Context;
19 | import android.graphics.Bitmap;
20 | import android.graphics.BitmapFactory;
21 | import android.graphics.Canvas;
22 | import android.graphics.Color;
23 | import android.graphics.Matrix;
24 | import android.graphics.Paint;
25 | import android.graphics.Point;
26 | import android.graphics.PointF;
27 | import android.media.FaceDetector;
28 | import android.util.Log;
29 |
30 | /**
31 | * 从Bitmap获取脸部位置的工具类.
32 | * 它支持多个人脸的识别并剪裁全部识别出来的脸(默认最多8个,效率问题)支持任何格式的图片
33 | *
34 | * @author kymjs (http://www.kymjs.com)
35 | */
36 | public final class FaceCropper {
37 |
38 | public enum SizeMode {
39 | FACE_MARGIN, EYE_MARGIN
40 | };
41 |
42 | // default constant
43 | private static final int MAX_FACES = 8; // 最多识别几张脸
44 | private static final int FACE_MARGIN_PX = 100; // 脸与脸间隔
45 | private static final float EYE_MARGIN_PX = 2F; // 双眼间距
46 | private static final int MIN_FACE_SIZE = 200; // 人脸最小直径
47 |
48 | // default value
49 | private int mFaceMinSize = MIN_FACE_SIZE;
50 | private int mMaxFaces = MAX_FACES;
51 | private int mFaceMarginPx = FACE_MARGIN_PX;
52 | private float mEyeMarginPx = EYE_MARGIN_PX;
53 | private SizeMode mSizeMode = SizeMode.EYE_MARGIN;
54 |
55 | private boolean mDebug = true;
56 | private Paint mDebugPainter; // 用作调试阶段显示人脸识别的圈
57 | private Paint mDebugAreaPainter; // 用作调试阶段显示人脸识别的圈
58 |
59 | public FaceCropper() {
60 | initPaints();
61 | }
62 |
63 | public FaceCropper(int faceMarginPx) {
64 | setFaceMarginPx(faceMarginPx);
65 | initPaints();
66 | }
67 |
68 | public FaceCropper(float eyesDistanceFactorMargin) {
69 | setEyeDistanceFactorMargin(eyesDistanceFactorMargin);
70 | initPaints();
71 | }
72 |
73 | private void initPaints() {
74 | mDebugPainter = new Paint();
75 | mDebugPainter.setColor(Color.RED);
76 | mDebugPainter.setAlpha(80);
77 |
78 | mDebugAreaPainter = new Paint();
79 | mDebugAreaPainter.setColor(Color.GREEN);
80 | mDebugAreaPainter.setAlpha(80);
81 | }
82 |
83 | /********************* core method **********************************/
84 |
85 | /**
86 | * 获取debug模式下的图片
87 | *
88 | * @param ctx
89 | * @param res
90 | * @return
91 | */
92 | public Bitmap getDebugImage(Context ctx, int res) {
93 | // 以565格式通过resId创建bitmap
94 | BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
95 | bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
96 | return getDebugImage(BitmapFactory.decodeResource(ctx.getResources(),
97 | res, bitmapOptions));
98 | }
99 |
100 | /**
101 | * 获取debug模式下的图片
102 | *
103 | * @param bitmap
104 | * @return
105 | */
106 | public Bitmap getDebugImage(Bitmap bitmap) {
107 | FaceResult result = cropFace(bitmap, true);
108 | Canvas canvas = new Canvas(result.getBitmap());
109 |
110 | canvas.drawBitmap(result.getBitmap(), new Matrix(), null);
111 | canvas.drawRect(result.getInit().x, result.getInit().y,
112 | result.getEnd().x, result.getEnd().y, mDebugAreaPainter);
113 |
114 | return result.getBitmap();
115 | }
116 |
117 | /**
118 | * 剪裁指定图片中的脸
119 | *
120 | * @param ctx
121 | * @param res
122 | * @return
123 | */
124 | public Bitmap cropFace(Context ctx, int res) {
125 | return getCroppedImage(ctx, res);
126 | }
127 |
128 | /**
129 | * 剪裁指定图片中的脸
130 | *
131 | * @param bitmap
132 | * @return
133 | */
134 | public Bitmap cropFace(Bitmap bitmap) {
135 | return getCroppedImage(bitmap);
136 | }
137 |
138 | /**
139 | * 获取裁剪以后的人脸
140 | *
141 | * @param ctx
142 | * @param res
143 | * @return
144 | */
145 | private Bitmap getCroppedImage(Context ctx, int res) {
146 | // 以565格式通过resId创建bitmap
147 | BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
148 | bitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
149 | return getCroppedImage(BitmapFactory.decodeResource(ctx.getResources(),
150 | res, bitmapOptions));
151 | }
152 |
153 | /**
154 | * 获取裁剪以后的人脸
155 | *
156 | * @param bitmap
157 | * @return
158 | */
159 | private Bitmap getCroppedImage(Bitmap bitmap) {
160 | FaceResult result = cropFace(bitmap, mDebug);
161 | Bitmap croppedBitmap = Bitmap.createBitmap(result.getBitmap(),
162 | result.getInit().x, result.getInit().y, result.getEnd().x
163 | - result.getInit().x,
164 | result.getEnd().y - result.getInit().y);
165 | if (result.getBitmap() != croppedBitmap) {
166 | result.getBitmap().recycle();
167 | }
168 | return croppedBitmap;
169 | }
170 |
171 | /**
172 | * 剪裁脸部的核心方法
173 | *
174 | * @param bitmap
175 | * 待识别的图片
176 | * @param debug
177 | * 是否开启调试模式
178 | * @return
179 | */
180 | private FaceResult cropFace(Bitmap bitmap, boolean debug) {
181 | Bitmap formatBitmap = BitmapOperate.formatBitmap(bitmap);
182 | formatBitmap = BitmapOperate.formatBitmapTo565(formatBitmap);
183 | Bitmap aimBitmap = formatBitmap.copy(Bitmap.Config.RGB_565, true);
184 | if (formatBitmap != aimBitmap) {
185 | formatBitmap.recycle();
186 | }
187 | // 创建一个人脸识别器
188 | FaceDetector faceDetector = new FaceDetector(aimBitmap.getWidth(),
189 | aimBitmap.getHeight(), mMaxFaces);
190 | // 人脸数组
191 | FaceDetector.Face[] faces = new FaceDetector.Face[mMaxFaces];
192 | // Bitmap必须是565格式
193 | int faceCount = faceDetector.findFaces(aimBitmap, faces);
194 |
195 | if (debug) {
196 | Log.d("kymjs", faceCount + "张脸被找到");
197 | }
198 |
199 | if (faceCount == 0) {
200 | return new FaceResult(aimBitmap);
201 | }
202 |
203 | int initX = aimBitmap.getWidth();
204 | int initY = aimBitmap.getHeight();
205 | int endX = 0;
206 | int endY = 0;
207 |
208 | PointF centerFace = new PointF();
209 |
210 | Canvas canvas = new Canvas(aimBitmap);
211 | canvas.drawBitmap(aimBitmap, new Matrix(), null);
212 |
213 | // 计算每张脸的最小外接圆
214 | for (int i = 0; i < faceCount; i++) {
215 | FaceDetector.Face face = faces[i];
216 | // 通常采用眼睛间距乘以三作为脸的外接圆直径
217 | int faceSize = (int) (face.eyesDistance() * 3);
218 | if (SizeMode.FACE_MARGIN.equals(mSizeMode)) {
219 | faceSize += mFaceMarginPx * 2;
220 | } else if (SizeMode.EYE_MARGIN.equals(mSizeMode)) {
221 | faceSize += face.eyesDistance() * mEyeMarginPx;
222 | }
223 | faceSize = Math.max(faceSize, mFaceMinSize);
224 | face.getMidPoint(centerFace);
225 |
226 | if (debug) { // 显示调试人脸识别圈
227 | canvas.drawPoint(centerFace.x, centerFace.y, mDebugPainter);
228 | canvas.drawCircle(centerFace.x, centerFace.y,
229 | face.eyesDistance() * 1.5f, mDebugPainter);
230 | }
231 |
232 | int tInitX = (int) (centerFace.x - faceSize / 2);
233 | int tInitY = (int) (centerFace.y - faceSize / 2);
234 | tInitX = Math.max(0, tInitX);
235 | tInitY = Math.max(0, tInitY);
236 |
237 | int tEndX = tInitX + faceSize;
238 | int tEndY = tInitY + faceSize;
239 | tEndX = Math.min(tEndX, aimBitmap.getWidth());
240 | tEndY = Math.min(tEndY, aimBitmap.getHeight());
241 |
242 | initX = Math.min(initX, tInitX);
243 | initY = Math.min(initY, tInitY);
244 | endX = Math.max(endX, tEndX);
245 | endY = Math.max(endY, tEndY);
246 | }
247 |
248 | int sizeX = endX - initX;
249 | int sizeY = endY - initY;
250 |
251 | if (sizeX + initX > aimBitmap.getWidth()) {
252 | sizeX = aimBitmap.getWidth() - initX;
253 | }
254 | if (sizeY + initY > aimBitmap.getHeight()) {
255 | sizeY = aimBitmap.getHeight() - initY;
256 | }
257 | Point init = new Point(initX, initY);
258 | Point end = new Point(initX + sizeX, initY + sizeY);
259 | return new FaceResult(aimBitmap, init, end);
260 | }
261 |
262 | /********************** config method *******************************/
263 |
264 | public int getMaxFaces() {
265 | return mMaxFaces;
266 | }
267 |
268 | public void setMaxFaces(int maxFaces) {
269 | this.mMaxFaces = maxFaces;
270 | }
271 |
272 | public int getFaceMinSize() {
273 | return mFaceMinSize;
274 | }
275 |
276 | public void setFaceMinSize(int faceMinSize) {
277 | mFaceMinSize = faceMinSize;
278 | }
279 |
280 | public int getFaceMarginPx() {
281 | return mFaceMarginPx;
282 | }
283 |
284 | public void setFaceMarginPx(int faceMarginPx) {
285 | mFaceMarginPx = faceMarginPx;
286 | mSizeMode = SizeMode.FACE_MARGIN;
287 | }
288 |
289 | public SizeMode getSizeMode() {
290 | return mSizeMode;
291 | }
292 |
293 | public float getEyeDistanceFactorMargin() {
294 | return mEyeMarginPx;
295 | }
296 |
297 | public void setEyeDistanceFactorMargin(float eyeDistanceFactorMargin) {
298 | mEyeMarginPx = eyeDistanceFactorMargin;
299 | mSizeMode = SizeMode.EYE_MARGIN;
300 | }
301 |
302 | public boolean isDebug() {
303 | return mDebug;
304 | }
305 |
306 | public void setDebug(boolean debug) {
307 | mDebug = debug;
308 | }
309 |
310 | private class FaceResult {
311 | Bitmap mBitmap;
312 | Point mInit;
313 | Point mEnd;
314 |
315 | public FaceResult(Bitmap bitmap, Point init, Point end) {
316 | mBitmap = bitmap;
317 | mInit = init;
318 | mEnd = end;
319 | }
320 |
321 | public FaceResult(Bitmap bitmap) {
322 | mBitmap = bitmap;
323 | mInit = new Point(0, 0);
324 | mEnd = new Point(bitmap.getWidth(), bitmap.getHeight());
325 | }
326 |
327 | public Bitmap getBitmap() {
328 | return mBitmap;
329 | }
330 |
331 | public Point getInit() {
332 | return mInit;
333 | }
334 |
335 | public Point getEnd() {
336 | return mEnd;
337 | }
338 | }
339 |
340 | }
341 |
--------------------------------------------------------------------------------
/app/src/main/java/download/imageLoader/util/ImageSizeUtil.java:
--------------------------------------------------------------------------------
1 | package download.imageLoader.util;
2 |
3 | import java.lang.reflect.Field;
4 |
5 | import download.imageLoader.request.BitmapRequest;
6 | import android.graphics.BitmapFactory.Options;
7 | import android.util.DisplayMetrics;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.view.ViewGroup.LayoutParams;
11 | import android.widget.ImageView;
12 |
13 | /**
14 | * http://blog.csdn.net/lmj623565791/article/details/41874561
15 | *
16 | * @author zhy
17 | *
18 | */
19 | public class ImageSizeUtil {
20 | /**
21 | * 根据需求的宽和高以及图片实际的宽和高计算SampleSize
22 | *
23 | */
24 | public static int caculateInSampleSize(Options options, int reqWidth,
25 | int reqHeight) {
26 | int width = options.outWidth;
27 | int height = options.outHeight;
28 |
29 | int inSampleSize = 1;
30 |
31 | if (width > reqWidth || height > reqHeight) {
32 | int widthRadio = Math.round(width * 1.0f / reqWidth);
33 | int heightRadio = Math.round(height * 1.0f / reqHeight);
34 |
35 | inSampleSize = Math.max(widthRadio, heightRadio);
36 | }
37 |
38 | return inSampleSize;
39 | }
40 |
41 | /**
42 | * 根据ImageView获适当的压缩的宽和高
43 | *
44 | */
45 | public static void getImageViewSize(BitmapRequest request) {
46 | if (request.width > 0 && request.height > 0) {
47 | return;
48 | }
49 | if (request.view == null || request.view.get() == null) {
50 | request.width = 300;
51 | request.height = 300;
52 | return;
53 | }
54 |
55 | LayoutParams lp = request.view.get().getLayoutParams();
56 |
57 | int width = request.view.get().getWidth() - request.view.get().getPaddingLeft() - request.view.get().getPaddingRight();// 获取imageview的实际宽度
58 | if (width <= 0) {
59 | width = lp.width - request.view.get().getPaddingLeft() - request.view.get().getPaddingRight();// 获取imageview在layout中声明的宽度
60 | }
61 | if (width <= 0) {
62 | // width = imageView.getMaxWidth();// 检查最大值
63 | width = getImageViewFieldValue(request.view, "mMaxWidth") - request.view.get().getPaddingTop() - request.view.get().getPaddingBottom();
64 | }
65 | if (width <= 0) {
66 | width = 300;
67 | }
68 |
69 | int height = request.view.get().getHeight() - request.view.get().getPaddingTop() - request.view.get().getPaddingBottom();// 获取imageview的实际高度
70 | if (height <= 0) {
71 | height = lp.height;// 获取imageview在layout中声明的宽度
72 | }
73 | if (height <= 0) {
74 | height = getImageViewFieldValue(request.view, "mMaxHeight") - request.view.get().getPaddingTop() - request.view.get().getPaddingBottom();// 检查最大值
75 | }
76 | if (height <= 0) {
77 | height = 300;
78 | }
79 | request.width = width;
80 | request.height = height;
81 |
82 | }
83 |
84 | public static class ImageSize {
85 | public int width;
86 | public int height;
87 | }
88 |
89 | /**
90 | * 通过反射获取imageview的某个属性值
91 | *
92 | * @param object
93 | * @param fieldName
94 | * @return
95 | */
96 | private static int getImageViewFieldValue(Object object, String fieldName) {
97 | int value = 0;
98 | try {
99 | Field field = ImageView.class.getDeclaredField(fieldName);
100 | field.setAccessible(true);
101 | int fieldValue = field.getInt(object);
102 | if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
103 | value = fieldValue;
104 | }
105 | } catch (Exception e) {
106 | }
107 | return value;
108 |
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/core/ConnectRunnable.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.core;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.net.HttpURLConnection;
6 | import java.net.URL;
7 |
8 | /**
9 | * Created by lizhiyun on 16/6/15.
10 | */
11 | public class ConnectRunnable implements Runnable {
12 | private String url;
13 | public ConnectRunnable(String url, ConnectListener listener){
14 | this.url = url;
15 | this.listener = listener;
16 | }
17 | private Boolean isRunning = false;
18 | ConnectListener listener;
19 | public Boolean isRunning (){
20 | return isRunning;
21 | }
22 |
23 | @Override
24 | public void run() {
25 | isRunning = true;
26 | HttpURLConnection connection = null;
27 | try {
28 | connection = (HttpURLConnection) new URL(url).openConnection();
29 | connection.setRequestMethod("GET");
30 | connection.setConnectTimeout(5 * 1000);
31 | connection.setReadTimeout(5*1000);
32 | int responseCode = connection.getResponseCode();
33 | int contentLength = connection.getContentLength();
34 | boolean isSupport = false;
35 | if (responseCode == HttpURLConnection.HTTP_OK){
36 | String ranges = connection.getHeaderField("Accept-Ranges");
37 | if ("bytes".equals(ranges)){
38 | isSupport = true;
39 | }
40 | listener.onConnected(contentLength,isSupport);
41 | String content_md5 = connection.getHeaderField("Content-MD5");
42 | if (TextUtils.isEmpty(content_md5)){
43 | listener.onGetContentMd5(content_md5);
44 | }
45 | }else {
46 | listener.onError("server error:"+responseCode);
47 | }
48 | isRunning = false;
49 | }catch (Exception e){
50 | isRunning = false;
51 | listener.onError(e.getMessage());
52 | e.printStackTrace();
53 | }finally {
54 | if (connection != null){
55 | connection.disconnect();
56 | }
57 | }
58 |
59 | }
60 | interface ConnectListener{
61 | void onConnected(int totalLength, Boolean isSupport);
62 | void onError(String message);
63 | void onGetContentMd5(String md5);
64 | }
65 | public void cancel(){
66 | Thread.currentThread().interrupt();
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/core/ConnectionChangeReceiver.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.core;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.net.ConnectivityManager;
7 | import android.net.NetworkInfo;
8 |
9 | import download.otherFileLoader.db.DownFileManager;
10 |
11 | /**
12 | * Created by lizhiyun on 16/7/6.
13 | */
14 | public class ConnectionChangeReceiver extends BroadcastReceiver {
15 | @Override
16 | public void onReceive(Context context, Intent intent) {
17 | ConnectivityManager connectivityManager=(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
18 | NetworkInfo mobNetInfo=connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
19 | NetworkInfo wifiNetInfo=connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
20 | if (!mobNetInfo.isConnected() && !wifiNetInfo.isConnected()) {
21 |
22 | }else {
23 | DownFileManager.getInstance().recoverAllNetError();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/core/Constants.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.core;
2 |
3 | /**
4 | * Created by lizhiyun on 16/6/12.
5 | */
6 | public class Constants {
7 |
8 | public static final int WHAT_DOWNLOADING = 10;
9 | public static final int WHAT_FINISH = 12;
10 | public static final int WHAT_ERROR = 13;
11 |
12 |
13 | public static final int CONNECT_TIME = 10000;
14 | public static final int READ_TIME = 10000;
15 | public static final int BLOB_COUNT = 3;
16 |
17 |
18 | public volatile static long lastNotifyTime;
19 |
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/core/DownloadService.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.core;
2 |
3 | import android.app.Service;
4 | import android.content.Intent;
5 | import android.content.IntentFilter;
6 | import android.net.ConnectivityManager;
7 | import android.os.IBinder;
8 |
9 | import download.otherFileLoader.db.DownFileManager;
10 | import download.otherFileLoader.request.DownFile;
11 |
12 | /**
13 | * Created by lizhiyun on 16/7/6.
14 | */
15 | public class DownloadService extends Service {
16 | private ConnectionChangeReceiver connectionChangeReceiver;
17 |
18 | @Override
19 | public void onCreate() {
20 | super.onCreate();
21 | connectionChangeReceiver = new ConnectionChangeReceiver();
22 | registerReceiver(connectionChangeReceiver,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
23 | }
24 |
25 | @Override
26 | public void onDestroy() {
27 | super.onDestroy();
28 | unregisterReceiver(connectionChangeReceiver);
29 | }
30 |
31 | @Override
32 | public IBinder onBind(Intent intent) {
33 | return null;
34 | }
35 |
36 | @Override
37 | public int onStartCommand(Intent intent, int flags, int startId) {
38 | String url = intent.getStringExtra("url");
39 | String path = intent.getStringExtra("path");
40 | DownFile downFile = new DownFile(url,path);
41 | DownFileManager.getInstance(this).addTask(downFile);
42 | return super.onStartCommand(intent, flags, startId);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/core/DownloadTask.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.core;
2 |
3 | import android.os.Bundle;
4 | import android.os.Handler;
5 | import android.os.Message;
6 | import android.text.TextUtils;
7 | import android.util.Log;
8 |
9 | import com.litesuits.go.SmartExecutor;
10 | import java.io.File;
11 | import java.util.HashMap;
12 |
13 | import download.otherFileLoader.db.DLDBManager;
14 | import download.otherFileLoader.db.DownFileManager;
15 | import download.otherFileLoader.request.DownFile;
16 | import download.utils.Util;
17 |
18 |
19 | public class DownloadTask implements DownloadThread.DownListener{
20 | public DownFile downFile;
21 | private ConnectRunnable mConnectThread;
22 | private DownloadThread[] mDownloadThreads;
23 | private DownFile.DownloadStatus[] mDownloadStatus;
24 | private long mLastStamp;
25 | private File destFile;
26 |
27 |
28 | public DownloadTask(DownFile entry) {
29 | this.downFile = entry;
30 | this.destFile = new File(entry.downPath,entry.name);
31 | }
32 |
33 | public void pause() {
34 | downFile.state = DownFile.DownloadStatus.PAUSE;
35 | if (mConnectThread != null && mConnectThread.isRunning()) {
36 | mConnectThread.cancel();
37 | }
38 | if (mDownloadThreads != null && mDownloadThreads.length > 0) {
39 | for (int i = 0; i < mDownloadThreads.length; i++) {
40 | if (mDownloadThreads[i] != null && mDownloadThreads[i].isRunning()) {
41 | if (downFile.isSuppurtRanger) {
42 | mDownloadThreads[i].pause();
43 | } else {
44 | mDownloadThreads[i].cancel();
45 | }
46 | }
47 | }
48 | }
49 | }
50 |
51 | public void error() {
52 | downFile.state = DownFile.DownloadStatus.ERROR;
53 | if (mConnectThread != null && mConnectThread.isRunning()) {
54 | mConnectThread.cancel();
55 | }
56 | if (mDownloadThreads != null && mDownloadThreads.length > 0) {
57 | for (int i = 0; i < mDownloadThreads.length; i++) {
58 | if (mDownloadThreads[i] != null && mDownloadThreads[i].isRunning()) {
59 | mDownloadThreads[i].error();
60 | }
61 | }
62 | }
63 | }
64 |
65 | public void cancel() {
66 | downFile.state = DownFile.DownloadStatus.CANCEL;
67 | if (mConnectThread != null && mConnectThread.isRunning()) {
68 | mConnectThread.cancel();
69 | }
70 | if (mDownloadThreads != null && mDownloadThreads.length > 0) {
71 | for (int i = 0; i < mDownloadThreads.length; i++) {
72 | if (mDownloadThreads[i] != null && mDownloadThreads[i].isRunning()) {
73 | mDownloadThreads[i].cancel();
74 | }
75 | }
76 | }
77 | }
78 |
79 | public void start() {
80 | downFile.isError = false;
81 | downFile.isCanceled = false;
82 | downFile.isPaused = false;
83 | if (downFile.totalLength == 0){
84 | DownFileManager.sExecutor.execute(new ConnectRunnable(downFile.url, new ConnectRunnable.ConnectListener() {
85 | @Override
86 | public void onConnected(int totalLength, Boolean isSupport) {
87 | downFile.totalLength = totalLength;
88 | downFile.isSuppurtRanger = isSupport;
89 | if (downFile.totalLength <= 0) {
90 | downFile.isSuppurtRanger = false;
91 | }
92 | startDownload();
93 |
94 | }
95 |
96 | @Override
97 | public void onError(String message) {
98 | downFile.isError = true;
99 | notifyUpdate(downFile, Constants.WHAT_ERROR);
100 | }
101 |
102 | @Override
103 | public void onGetContentMd5(String md5) {
104 | downFile.content_md5 = md5;
105 | }
106 | }));
107 | }else{
108 | startDownload();
109 | }
110 | }
111 |
112 |
113 | private void startDownload() {
114 | downFile.state = DownFile.DownloadStatus.DOWNLOADING;
115 | if (downFile.isSuppurtRanger) {
116 | startMultiDownload();
117 | } else {
118 | startSingleDownload();
119 | }
120 | }
121 |
122 | private void startMultiDownload() {
123 | int block = downFile.totalLength / Constants.BLOB_COUNT;
124 | int startPos = 0;
125 | int endPos = 0;
126 | if (downFile.ranges == null) {
127 | downFile.ranges = new HashMap();
128 | for (int i = 0; i < Constants.BLOB_COUNT; i++) {
129 | downFile.ranges.put(i, 0);
130 | }
131 | }
132 | mDownloadThreads = new DownloadThread[Constants.BLOB_COUNT];
133 | mDownloadStatus = new DownFile.DownloadStatus[Constants.BLOB_COUNT];
134 | for (int i = 0; i < Constants.BLOB_COUNT; i++) {
135 | startPos = i * block + downFile.ranges.get(i);
136 | if (i == Constants.BLOB_COUNT - 1) {
137 | endPos = downFile.totalLength;
138 | } else {
139 | endPos = (i + 1) * block - 1;
140 | }
141 | if (startPos < endPos) {
142 | mDownloadThreads[i] = new DownloadThread(downFile.url,destFile, i, startPos, endPos, this);
143 | mDownloadStatus[i] = DownFile.DownloadStatus.DOWNLOADING;
144 | DownFileManager.sExecutor.execute(mDownloadThreads[i]);
145 | }else {
146 | mDownloadStatus[i] = DownFile.DownloadStatus.FINISH;
147 | }
148 | }
149 | }
150 |
151 | private void startSingleDownload() {
152 | mDownloadThreads = new DownloadThread[1];
153 | mDownloadStatus = new DownFile.DownloadStatus[1];
154 | mDownloadStatus[0] = DownFile.DownloadStatus.DOWNLOADING;
155 | mDownloadThreads[0] = new DownloadThread(downFile.url,destFile, 0, 0, 0, this);
156 | DownFileManager.sExecutor.execute(mDownloadThreads[0]);
157 | }
158 |
159 | private void notifyUpdate(DownFile entry, int what) {
160 | if (what == Constants.WHAT_DOWNLOADING){
161 | if (System.currentTimeMillis() - Constants.lastNotifyTime > 1000 || downFile.downLength >= downFile.totalLength){
162 | Constants.lastNotifyTime = System.currentTimeMillis();
163 | }else {
164 | return;
165 | }
166 | }
167 | Message msg = DownFileManager.sHandler.obtainMessage();
168 | msg.what = what;
169 | msg.obj = entry;
170 | DownFileManager.sHandler.sendMessage(msg);
171 | if (what == Constants.WHAT_ERROR){
172 | DownFileManager.dldbManager.deleteTaskInfo(downFile);
173 | }else {
174 | DownFileManager.dldbManager.insertOrUpdate(downFile);
175 | }
176 | }
177 |
178 | @Override
179 | public void onProgressChanged(int index, int progress) {
180 | if (downFile.isSuppurtRanger) {
181 | int range = downFile.ranges.get(index) + progress;
182 | downFile.ranges.put(index, range);
183 | }
184 | downFile.downLength += progress;
185 | notifyUpdate(downFile, Constants.WHAT_DOWNLOADING);
186 | }
187 |
188 | @Override
189 | public void onDownloadCompleted(int index) {
190 | Log.e("test","onDownloadCompleted "+index);
191 | mDownloadStatus[index] = DownFile.DownloadStatus.FINISH;
192 | for (int i = 0; i < mDownloadStatus.length;i++){
193 | if (mDownloadStatus[i] != DownFile.DownloadStatus.FINISH){
194 | return;
195 | }
196 | }
197 | if (!TextUtils.isEmpty(downFile.content_md5)){
198 | if (!downFile.content_md5.equals(Util.md5sum(downFile.downPath))){
199 | downFile.state = DownFile.DownloadStatus.ERROR;
200 | notifyUpdate(downFile,Constants.WHAT_ERROR);
201 | return;
202 | }
203 | }
204 | downFile.state = DownFile.DownloadStatus.FINISH;
205 | Log.v("test","finish"+downFile.state.name+downFile.downLength+" "+downFile.totalLength);
206 | notifyUpdate(downFile, Constants.WHAT_FINISH);
207 | }
208 |
209 | @Override
210 | public void onDownloadError(int index, String message) {
211 | for (int i = 0; i < mDownloadStatus.length; i++) {
212 | if (mDownloadStatus[i] != DownFile.DownloadStatus.FINISH && mDownloadStatus[i] != DownFile.DownloadStatus.ERROR) {
213 | mDownloadThreads[i].error();
214 | }
215 | }
216 | downFile.isError = true;
217 | downFile.state = DownFile.DownloadStatus.ERROR;
218 | notifyUpdate(downFile, Constants.WHAT_ERROR);
219 | }
220 |
221 | }
222 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/core/DownloadThread.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.core;
2 |
3 | import android.util.Log;
4 |
5 | import java.io.BufferedInputStream;
6 | import java.io.BufferedOutputStream;
7 | import java.io.BufferedReader;
8 | import java.io.File;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.io.InputStreamReader;
13 | import java.io.RandomAccessFile;
14 | import java.net.HttpURLConnection;
15 | import java.net.URL;
16 |
17 | import download.otherFileLoader.listener.DownloadListener;
18 | import download.otherFileLoader.request.DownFile;
19 |
20 | /**
21 | * Created by Stay on 4/8/15.
22 | * Powered by www.stay4it.com
23 | */
24 | public class DownloadThread implements Runnable {
25 | private final String url;
26 | private final int startPos;
27 | private final int endPos;
28 | private final File destFile;
29 | private final DownListener listener;
30 | private final int index;
31 | private final boolean isSingleDownload;
32 | private volatile boolean isPaused;
33 | private volatile DownFile.DownloadStatus state = DownFile.DownloadStatus.IDLE;
34 |
35 | private volatile boolean isCancelled;
36 | private volatile boolean isError;
37 |
38 | public DownloadThread(String url, File destFile, int index, int startPos, int endPos, DownListener listener) {
39 | this.url = url;
40 | this.index = index;
41 | this.startPos = startPos;
42 | this.endPos = endPos;
43 | this.destFile = destFile;
44 | if (startPos == 0 && endPos == 0) {
45 | isSingleDownload = true;
46 | } else {
47 | isSingleDownload = false;
48 | }
49 |
50 | this.listener = listener;
51 | }
52 |
53 | @Override
54 | public void run() {
55 | state = DownFile.DownloadStatus.DOWNLOADING;
56 | HttpURLConnection connection = null;
57 | try {
58 | connection = (HttpURLConnection) new URL(url).openConnection();
59 | connection.setRequestMethod("GET");
60 | if (!isSingleDownload) {
61 | connection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);
62 | }
63 | connection.setConnectTimeout(Constants.CONNECT_TIME);
64 | connection.setReadTimeout(Constants.READ_TIME);
65 | int responseCode = connection.getResponseCode();
66 | int contentLength = connection.getContentLength();
67 | RandomAccessFile raf = null;
68 | BufferedOutputStream bos = null;
69 | BufferedInputStream is ;
70 | byte[] bytes;
71 | if (responseCode == HttpURLConnection.HTTP_PARTIAL) {
72 | raf = new RandomAccessFile(destFile, "rw");
73 | raf.seek(startPos);
74 | } else if (responseCode == HttpURLConnection.HTTP_OK) {
75 | bos = new BufferedOutputStream(new FileOutputStream(destFile));
76 | } else {
77 | state = DownFile.DownloadStatus.ERROR;
78 | listener.onDownloadError(index, "server error:" + responseCode);
79 | return;
80 | }
81 | String s;
82 | is = new BufferedInputStream(connection.getInputStream(),8 *1024);
83 | bytes = new byte[2048];
84 | int len;
85 | while ((len = is.read(bytes)) != -1) {
86 | if (isPaused || isCancelled || isError) {
87 | break;
88 | }
89 | if (raf != null){
90 | raf.write(bytes,0,len);
91 | }else {
92 | bos.write(bytes,0,len);
93 | }
94 | listener.onProgressChanged(index, len);
95 | }
96 | if (raf != null)
97 | raf.close();
98 | if (bos != null)
99 | bos.close();
100 | is.close();
101 |
102 | if (!isPaused && !isCancelled && !isError){
103 | listener.onDownloadCompleted(index);
104 | }
105 | } catch (IOException e) {
106 | e.printStackTrace();
107 | if (!isPaused && !isCancelled && !isError){
108 | listener.onDownloadError(index, e.getMessage());
109 | }
110 | } finally {
111 | if (connection != null) {
112 | connection.disconnect();
113 | }
114 | }
115 | }
116 |
117 | public boolean isRunning() {
118 | return state == DownFile.DownloadStatus.DOWNLOADING;
119 | }
120 |
121 | public void pause() {
122 | state = DownFile.DownloadStatus.PAUSE;
123 | isPaused = true;
124 | Thread.currentThread().interrupt();
125 | }
126 |
127 | public void cancel() {
128 | state = DownFile.DownloadStatus.CANCEL;
129 | isCancelled = true;
130 | Thread.currentThread().interrupt();
131 | }
132 |
133 | public void error() {
134 | state = DownFile.DownloadStatus.ERROR;
135 | isError = true;
136 | Thread.currentThread().interrupt();
137 | }
138 | interface DownListener {
139 | void onProgressChanged(int index, int progress);
140 |
141 | void onDownloadCompleted(int index);
142 |
143 | void onDownloadError(int index, String message);
144 |
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/db/DLDBHelper.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.db;
2 |
3 | import android.content.Context;
4 | import android.database.DatabaseErrorHandler;
5 | import android.database.sqlite.SQLiteDatabase;
6 | import android.database.sqlite.SQLiteOpenHelper;
7 |
8 | final class DLDBHelper extends SQLiteOpenHelper {
9 | private static final String DB_NAME = "df.db";
10 | private static final int DB_VERSION = 3;
11 | public static final String TABLENAME = "downloadfile";
12 | private static final String TB_CREATE =
13 | "CREATE TABLE "+
14 | TABLENAME+"(id INTEGER PRIMARY KEY AUTOINCREMENT, url CHAR, path CHAR NOT NULL," +
15 | " name CHAR,"+
16 | " issupportrange INTEGER, downlength INTEGER, totallength INTEGER, rangers CHAR, state INTEGER" +
17 | ")";
18 |
19 | public DLDBHelper(Context context) {
20 | super(context,DB_NAME,null,DB_VERSION);
21 | }
22 |
23 |
24 | @Override
25 | public void onCreate(SQLiteDatabase db) {
26 | db.execSQL(TB_CREATE);
27 | }
28 |
29 | @Override
30 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
31 | db.execSQL("DROP TABLE IF EXISTS "+TABLENAME);
32 | onCreate(db);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/db/DLDBManager.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.db;
2 |
3 | import android.content.ContentValues;
4 | import android.content.Context;
5 | import android.database.Cursor;
6 | import android.database.sqlite.SQLiteDatabase;
7 | import android.text.TextUtils;
8 |
9 | import java.util.HashMap;
10 | import java.util.List;
11 |
12 | import download.otherFileLoader.request.DownFile;
13 |
14 | public final class DLDBManager {
15 | private static DLDBManager sManager;
16 | private DLDBHelper helper;
17 | private Context context;
18 |
19 | private DLDBManager(Context context) {
20 | helper = new DLDBHelper(context);
21 | }
22 |
23 | static DLDBManager getInstance(Context context) {
24 | if (null == sManager) {
25 | sManager = new DLDBManager(context);
26 | }
27 | return sManager;
28 | }
29 |
30 | public synchronized void insertTaskInfo(DownFile info) {
31 | SQLiteDatabase db = helper.getWritableDatabase();
32 | ContentValues values = new ContentValues();
33 | values.put("url",info.url);
34 | values.put("path",info.downPath);
35 | values.put("name",info.name);
36 | values.put("downlength",info.downLength);
37 | values.put("totallength", info.totalLength);
38 | values.put("state",info.state.value);
39 |
40 | if (info.ranges != null && info.ranges.size() > 0){
41 | StringBuilder sb = new StringBuilder();
42 | for (int i = 0;i < info.ranges.size();i++){
43 | if (i > 0){
44 | sb.append(",");
45 | }
46 | sb.append(info.ranges.get(i));
47 | }
48 | values.put("rangers",sb.toString());
49 | }
50 | db.insert(DLDBHelper.TABLENAME,null,values);
51 | }
52 |
53 | public synchronized void insertOrUpdate(DownFile info){
54 | if (queryTaskInfo(info) == null){
55 | insertTaskInfo(info);
56 | }else {
57 | updateTaskInfo(info);
58 | }
59 | }
60 |
61 | public synchronized void deleteTaskInfo(DownFile info) {
62 | SQLiteDatabase db = helper.getWritableDatabase();
63 | db.delete(DLDBHelper.TABLENAME,"url=? and path=?",new String[]{info.url,info.downPath});
64 | db.close();
65 | }
66 |
67 | public synchronized void updateTaskInfo(DownFile info) {
68 | SQLiteDatabase db = helper.getWritableDatabase();
69 | ContentValues values = new ContentValues();
70 | values.put("url",info.url);
71 | values.put("path",info.downPath);
72 | values.put("name",info.name);
73 | values.put("downlength",info.downLength);
74 | values.put("totallength", info.totalLength);
75 | values.put("state",info.state.value);
76 | if (info.ranges != null && info.ranges.size() > 0){
77 | StringBuilder sb = new StringBuilder();
78 | if (info.ranges != null){
79 | for (int i = 0;i < info.ranges.size();i++){
80 | if (i > 0){
81 | sb.append(",");
82 | }
83 | sb.append(info.ranges.get(i));
84 | }
85 | }
86 | values.put("rangers",sb.toString());
87 | }
88 | db.update(DLDBHelper.TABLENAME,values,"url = ? and path = ?",new String[]{info.url,info.downPath});
89 | }
90 |
91 | public synchronized DownFile queryTaskInfo(DownFile info) {
92 | DownFile downFile = null;
93 | SQLiteDatabase db = helper.getReadableDatabase();
94 | Cursor cursor = db.query(DLDBHelper.TABLENAME,new String[]{"name,issupportrange,downlength,totallength,rangers,state"},"url = ? and path = ?",new String[]{info.url,info.downPath},null,null,"url desc","1,2");
95 |
96 | while (cursor.moveToNext()){
97 | if (downFile == null){
98 | downFile = new DownFile(info.url);
99 | downFile.downPath = info.downPath;
100 | }
101 | downFile.name = cursor.getString(0);
102 | downFile.isSuppurtRanger = cursor.getInt(1) > 0;
103 | downFile.downLength = cursor.getInt(2);
104 | downFile.totalLength = cursor.getInt(3);
105 | String rangers = cursor.getString(4);
106 | if (!TextUtils.isEmpty(rangers.trim())){
107 | String[] strings = rangers.split(",");
108 | if (strings.length > 0){
109 | downFile.ranges = new HashMap();
110 | }
111 | for (int i = 0;i ranges;
55 | public enum DownloadStatus{
56 | IDLE(0,"空闲"),DOWNLOADING(2,"下载中"),FINISH(1,"完成"),ERROR(3,"异常"),PAUSE(4,"暂停"),CANCEL(5,"取消"),WAITING(6,"等待");
57 | public int value;
58 | public String name;
59 | private DownloadStatus(int value,String name){
60 | this.name = name;
61 | this.value = value;
62 | }
63 | }
64 |
65 | @Override
66 | public boolean equals(Object o) {
67 | if (o == null){
68 | return false;
69 | }
70 | if (!(o instanceof DownFile)){
71 | return false;
72 | }
73 | DownFile other = (DownFile) o;
74 | return this.url.equals(other.url) && this.downPath.equals(other.downPath);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/download/otherFileLoader/util/ToastUtils.java:
--------------------------------------------------------------------------------
1 | package download.otherFileLoader.util;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.os.Build.VERSION;
6 | import android.util.Log;
7 | import android.view.Gravity;
8 | import android.view.View;
9 | import android.widget.TextView;
10 | import android.widget.Toast;
11 |
12 | public class ToastUtils {
13 |
14 | private static Toast toast;
15 |
16 | /**
17 | * 日记的输出方法
18 | *
19 | * @param msg
20 | */
21 | public static void log(Object msg) {
22 | Log.d("test", String.valueOf(msg));
23 | }
24 | private static int color = Color.parseColor("#3EA32B");
25 | /**
26 | * 显示常规的Toast
27 | *
28 | * @param context
29 | * 上下文对象
30 | * @param text
31 | * 显示的内容
32 | */
33 | public static void showToast(Context context, String text) {
34 | showMessage(context, text, 15,color);
35 | }
36 | public static void showToast(Context context, int text) {
37 | showMessage(context, context.getResources().getString(text), 15,color);
38 | }
39 | public static void showToast(Context context, String text,int size) {
40 | showMessage(context, text, size,color);
41 | }
42 | public static void showToast(Context context, String text,int size,int color) {
43 | showMessage(context, text, size,color);
44 | }
45 |
46 | /**
47 | * 根据方位显示toast
48 | *
49 | * @param context
50 | * 上下文对象
51 | * @param text
52 | * 显示的内容
53 | * @param gravity
54 | * 对齐方式
55 | */
56 | public static void makeToast(Context context, String text, int gravity) {
57 | Toast t = Toast.makeText(context, text, Toast.LENGTH_SHORT);
58 | t.setGravity(gravity, 0, 0);
59 | t.show();
60 |
61 | }
62 |
63 | /**
64 | * 自定义Toast的View的显示样式
65 | *
66 | * @param context
67 | * 上下文对象
68 | * @param view
69 | * 需要显示的布局视图
70 | */
71 | public static void makeToast(Context context, View view) {
72 | Toast t = Toast.makeText(context, "", Toast.LENGTH_SHORT);
73 | t.setView(view);
74 | t.setGravity(Gravity.CENTER, 0, 0);
75 | t.show();
76 | }
77 |
78 | public static void showMessage(Context context ,String text,int size,int color){
79 | if (toast == null) {
80 | toast=new Toast(context);
81 | }
82 | if (toast != null && VERSION.SDK_INT < 14) {
83 | toast.cancel();
84 | }
85 | toast.setDuration(Toast.LENGTH_SHORT);
86 | TextView textView = new TextView(context);
87 | textView.setText(text);
88 | textView.setTextSize(size);
89 | textView.setTextColor(color);
90 | textView.setGravity(Gravity.CENTER);
91 | textView.setBackgroundResource(android.R.drawable.toast_frame);
92 | toast.setView(textView);
93 | toast.setGravity(Gravity.CENTER, 0, 0);
94 | toast.show();
95 | }
96 | public static void showFailedToast(Context context) {
97 | showMessage(context, "获取数据失败", 15,Color.parseColor("#0000C0"));
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/app/src/main/java/download/utils/Util.java:
--------------------------------------------------------------------------------
1 | package download.utils;
2 |
3 | import android.content.Context;
4 | import android.content.pm.PackageInfo;
5 | import android.content.pm.PackageManager.NameNotFoundException;
6 | import android.graphics.drawable.BitmapDrawable;
7 | import android.os.Build;
8 | import android.os.Environment;
9 |
10 | import java.io.Closeable;
11 | import java.io.File;
12 | import java.io.FileInputStream;
13 | import java.io.InputStream;
14 | import java.net.HttpURLConnection;
15 | import java.security.MessageDigest;
16 | import java.security.NoSuchAlgorithmException;
17 |
18 | public class Util {
19 | /**
20 | * 利用签名辅助类,将字符串字节数组
21 | *
22 | * @param str
23 | * @return
24 | */
25 | public static String md5(String str) {
26 | byte[] digest = null;
27 | try {
28 | MessageDigest md = MessageDigest.getInstance("md5");
29 | digest = md.digest(str.getBytes());
30 | return bytes2hex02(digest);
31 |
32 | } catch (NoSuchAlgorithmException e) {
33 | e.printStackTrace();
34 | }
35 | return null;
36 | }
37 |
38 |
39 | /**
40 | * 方式二
41 | *
42 | * @param bytes
43 | * @return
44 | */
45 | public static String bytes2hex02(byte[] bytes) {
46 | StringBuilder sb = new StringBuilder();
47 | String tmp = null;
48 | for (byte b : bytes) {
49 | // 将每个字节与0xFF进行与运算,然后转化为10进制,然后借助于Integer再转化为16进制
50 | tmp = Integer.toHexString(0xFF & b);
51 | if (tmp.length() == 1)// 每个字节8为,转为16进制标志,2个16进制位
52 | {
53 | tmp = "0" + tmp;
54 | }
55 | sb.append(tmp);
56 | }
57 |
58 | return sb.toString();
59 |
60 | }
61 |
62 | public static File getDiskCacheDir(Context context, String uniqueName) {
63 | String cachePath = null;
64 | if (Environment.MEDIA_MOUNTED.equals(Environment
65 | .getExternalStorageState())) {
66 | File cacheDir = context.getExternalCacheDir();
67 | if (cacheDir != null) {
68 | cachePath = cacheDir.getPath();
69 | }
70 | } else {
71 | cachePath = context.getCacheDir().getPath();
72 | }
73 | if (cachePath == null) {
74 | cachePath = Environment.getExternalStorageDirectory().getAbsolutePath();
75 | }
76 | File file = new File(cachePath + File.separator + uniqueName);
77 | if (!file.exists()){
78 | file.mkdirs();
79 | }
80 | return file;
81 | }
82 | public static String getNameFromUrl(String url){
83 | return url.substring(url.lastIndexOf("/")+1);
84 | }
85 |
86 | public static int getAppVersion(Context context) {
87 | try {
88 | PackageInfo info = context.getPackageManager().getPackageInfo(
89 | context.getPackageName(), 0);
90 | return info.versionCode;
91 | } catch (NameNotFoundException e) {
92 | e.printStackTrace();
93 | }
94 | return 1;
95 | }
96 | public static String getFileSize(long size){
97 | if (size < 1024) {
98 | return size + "B";
99 | }else if (size < 1024*1024) {
100 | return new java.text.DecimalFormat("#.##").format(size / 1024.0f) + "KB";
101 | }else {
102 | return new java.text.DecimalFormat("#.##").format(size / (1024 * 1024.0f)) + "M";
103 | }
104 | }
105 |
106 | public static void close(Closeable c) {
107 | try {
108 | if (c != null) {
109 | c.close();
110 | }
111 | } catch (Exception e) {
112 | }
113 | }
114 |
115 | public static void close(HttpURLConnection c) {
116 | if (c != null) {
117 | c.disconnect();
118 | }
119 | }
120 |
121 | public static void close(HttpURLConnection conn, Closeable out, Closeable in) {
122 | close(conn);
123 | close(out);
124 | close(in);
125 | }
126 | private static final char HEX_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
127 | 'A', 'B', 'C', 'D', 'E', 'F' };
128 | public static String toHexString(byte[] b) {
129 | StringBuilder sb = new StringBuilder(b.length * 2);
130 | for (int i = 0; i < b.length; i++) {
131 | sb.append(HEX_DIGITS[(b[i] & 0xf0) >>> 4]);
132 | sb.append(HEX_DIGITS[b[i] & 0x0f]);
133 | }
134 | return sb.toString();
135 | }
136 |
137 | public static String md5sum(String filePath) {
138 | InputStream fis;
139 | byte[] buffer = new byte[1024];
140 | int numRead = 0;
141 | MessageDigest md5;
142 | try{
143 | fis = new FileInputStream(filePath);
144 | md5 = MessageDigest.getInstance("MD5");
145 | while((numRead=fis.read(buffer)) > 0) {
146 | md5.update(buffer,0,numRead);
147 | }
148 | fis.close();
149 | return toHexString(md5.digest());
150 | } catch (Exception e) {
151 | System.out.println("error");
152 | return "";
153 | }
154 | }
155 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/res/drawable-hdpi/anim.gif
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/face.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/res/drawable-hdpi/face.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_applist_item.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
13 |
18 |
19 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_filedownload.xml:
--------------------------------------------------------------------------------
1 |
8 |
13 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_imageloader.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
17 |
21 |
26 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/image_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/raw/anim.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/res/raw/anim.gif
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | lib_download
5 | Hello world!
6 | Settings
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/resources/download/imageLoader/config/image/loadfailed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/resources/download/imageLoader/config/image/loadfailed.png
--------------------------------------------------------------------------------
/app/src/main/resources/download/imageLoader/config/image/loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/app/src/main/resources/download/imageLoader/config/image/loading.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | }
6 | dependencies {
7 | classpath 'com.android.tools.build:gradle:1.3.0'
8 | }
9 | }
10 |
11 | allprojects {
12 | repositories {
13 | jcenter()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/down.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/down.gif
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangdanlizhiyun/lib_download/50a26a9e406221b85a4238de853a876e9e79ae6d/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/import-summary.txt:
--------------------------------------------------------------------------------
1 | ECLIPSE ANDROID PROJECT IMPORT SUMMARY
2 | ======================================
3 |
4 | Ignored Files:
5 | --------------
6 | The following files were *not* copied into the new Gradle project; you
7 | should evaluate whether these are still needed in your project and if
8 | so manually move them:
9 |
10 | * ic_launcher-web.png
11 | * proguard-project.txt
12 |
13 | Moved Files:
14 | ------------
15 | Android Gradle projects use a different directory structure than ADT
16 | Eclipse projects. Here's how the projects were restructured:
17 |
18 | * AndroidManifest.xml => app/src/main/AndroidManifest.xml
19 | * assets/ => app/src/main/assets
20 | * res/ => app/src/main/res/
21 | * src/ => app/src/main/java/
22 | * src/download/imageLoader/config/image/loadfailed.png => app/src/main/resources/download/imageLoader/config/image/loadfailed.png
23 | * src/download/imageLoader/config/image/loading.png => app/src/main/resources/download/imageLoader/config/image/loading.png
24 |
25 | Next Steps:
26 | -----------
27 | You can now build the project. The Gradle project needs network
28 | connectivity to download dependencies.
29 |
30 | Bugs:
31 | -----
32 | If for some reason your project does not build, and you determine that
33 | it is due to a bug or limitation of the Eclipse to Gradle importer,
34 | please file a bug at http://b.android.com with category
35 | Component-Tools.
36 |
37 | (This import summary is for your information only, and can be deleted
38 | after import once you are satisfied with the results.)
39 |
--------------------------------------------------------------------------------
/lib_download.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/local.properties:
--------------------------------------------------------------------------------
1 | ## This file is automatically generated by Android Studio.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 | #
7 | # Location of the SDK. This is only used by Gradle.
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | #Tue May 31 16:06:29 CST 2016
11 | ndk.dir=/Users/lizhiyun/android-sdk-macosx/ndk-bundle
12 | sdk.dir=/Users/lizhiyun/android-sdk-macosx
13 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':download_library', ':mylibrary'
2 |
--------------------------------------------------------------------------------