Browse Source

修改日志级别。添加断点续传用到的库

xulh 6 months ago
parent
commit
719668e824
26 changed files with 1421 additions and 8 deletions
  1. 2 2
      app/build.gradle
  2. 1 1
      app/src/main/java/com/hh/hhomc/keeplive/MyJobService.kt
  3. 9 4
      app/src/main/java/com/hh/hhomc/services/BackgroundService.java
  4. 58 0
      downloaderHelper/.gitignore
  5. 71 0
      downloaderHelper/build.gradle
  6. 25 0
      downloaderHelper/proguard-rules.pro
  7. 26 0
      downloaderHelper/src/androidTest/java/com/yaoxiaowen/download/ExampleInstrumentedTest.java
  8. 16 0
      downloaderHelper/src/main/AndroidManifest.xml
  9. 16 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/DownloadConstant.java
  10. 105 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/DownloadHelper.java
  11. 21 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/DownloadStatus.java
  12. 87 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/FileInfo.java
  13. 63 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/bean/DownloadInfo.java
  14. 50 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/bean/RequestInfo.java
  15. 36 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/config/InnerConstant.java
  16. 101 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/db/DbHolder.java
  17. 57 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/db/DbOpenHelper.java
  18. 43 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/execute/DownloadExecutor.java
  19. 246 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/execute/DownloadTask.java
  20. 137 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/service/DownloadService.java
  21. 43 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/utils/DebugUtils.java
  22. 161 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/utils/LogUtils.java
  23. 26 0
      downloaderHelper/src/main/java/com/yaoxiaowen/download/utils/ToastUtils.java
  24. 3 0
      downloaderHelper/src/main/res/values/strings.xml
  25. 17 0
      downloaderHelper/src/test/java/com/yaoxiaowen/download/ExampleUnitTest.java
  26. 1 1
      settings.gradle

+ 2 - 2
app/build.gradle

@@ -187,8 +187,8 @@ dependencies {
 
 
     // 断点下载
-    implementation 'com.yaoxiaowen:download:1.4.1'
-//    implementation project(path: ':downloaderHelper')
+//    implementation 'com.yaoxiaowen:download:1.4.1'
+    implementation project(path: ':downloaderHelper')
 
     implementation 'com.alibaba:fastjson:1.2.76'
 

+ 1 - 1
app/src/main/java/com/hh/hhomc/keeplive/MyJobService.kt

@@ -52,7 +52,7 @@ class MyJobService :JobService(){
     }
 
     override fun onStartJob(params: JobParameters?): Boolean {
-        AppLogUtils.e("开启job")
+        AppLogUtils.i("开启job")
 
         //如果7.0以上 轮训
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

+ 9 - 4
app/src/main/java/com/hh/hhomc/services/BackgroundService.java

@@ -350,7 +350,7 @@ public class BackgroundService extends Service {
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        AppLogUtils.e("onStartCommand");
+        AppLogUtils.i("onStartCommand");
 
 
         Looper looper = getMainLooper(); // 获取主线程的Looper对象
@@ -366,13 +366,13 @@ public class BackgroundService extends Service {
 
 
         } else {
-            AppLogUtils.e("服务 - 非首次");
+            AppLogUtils.i("服务 - 非首次");
 
             if (mWebSocketClient == null || !isWebsocketConnect) {
                 AppLogUtils.e("websocket重新连接");
                 restartWebsocket();
             } else {
-                AppLogUtils.e("websocket连接中");
+                AppLogUtils.i("websocket连接中");
             }
 
             // 点击图标时
@@ -538,11 +538,16 @@ public class BackgroundService extends Service {
 
     boolean isRegisterDownload;
 
+    /**
+     * 断点续传用到的库
+     * https://github.com/yaowen369/DownloadHelper
+     * 后台下载了,但没有进度条。查看服务端apk下载路径
+     */
     private void initDownloadApk() {
         AppLogUtils.e("initDownloadApk");
 
         mDownloadHelper = DownloadHelper.getInstance();
-//        mDownloadHelper.setDebug(true);
+        mDownloadHelper.setDebug(true);
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(FIRST_ACTION);

+ 58 - 0
downloaderHelper/.gitignore

@@ -0,0 +1,58 @@
+# Built application files
+*.apk
+*.ap_
+
+#OSX
+*.DS_Store
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+
+# Gradle files
+.gradle/
+build/
+
+app/
+
+# Local configuration file (sdk path, etc)
+/local.properties
+.local.properties
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# Intellij
+*.iml
+/.idea
+
+# Keystore files
+# *.jks
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+
+# Google Services (e.g. APIs or Firebase)
+google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json

+ 71 - 0
downloaderHelper/build.gradle

@@ -0,0 +1,71 @@
+apply plugin: 'com.android.library'
+apply plugin: 'com.novoda.bintray-release'
+
+android {
+    compileSdkVersion 30
+    buildToolsVersion "30.0.0"
+
+    defaultConfig {
+        minSdkVersion 15
+        targetSdkVersion 22
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+
+    lintOptions {
+        abortOnError false
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+//    implementation 'com.android.support:appcompat-v7:26.+'
+    testImplementation 'junit:junit:4.12'
+}
+
+
+
+// YaoWen(43194) modify  at 2017/12/23 10:48 
+// copy from utils
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        //在 as更新到2.3.3, 并且 com.android.tools.build:gradle 也更新到 2.3.3之后,
+        //在Win 7机器上, bintray-release 0.4.0 编译一直错误。类似gradle没有 相关方法的错误。
+        //当更改到 0.5.0之后,才ok
+        //目前尚不清楚 在mac下会怎么样。 等待更进一步的测试
+//        classpath 'com.novoda:bintray-release:0.4.0'
+
+        /**
+         * yaowen  (Wen.Yao2@geely.com) time:  18/7/14 14:52
+         *
+         * 这个地方还是可能存在风险的。 版本从  0.5.0 -> 0.8.0
+         */
+
+        classpath 'com.novoda:bintray-release:0.8.0'
+    }
+}
+
+
+publish {
+    userOrg = 'yaowen369'
+    groupId = 'com.yaoxiaowen'
+    artifactId = 'download'
+    publishVersion = '1.4.1'
+    desc = 'An Android download tool that supports multi-threading and breakpoint renewal'
+    website = 'https://github.com/yaowen369/DownloadHelper'
+}

+ 25 - 0
downloaderHelper/proguard-rules.pro

@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\Users\Administrator\AppData\Local\Android\Sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
downloaderHelper/src/androidTest/java/com/yaoxiaowen/download/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.yaoxiaowen.download;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.yaoxiaowen.download.test", appContext.getPackageName());
+    }
+}

+ 16 - 0
downloaderHelper/src/main/AndroidManifest.xml

@@ -0,0 +1,16 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+
+    package="com.yaoxiaowen.download">
+
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application android:allowBackup="false"
+        android:label="@string/app_name"
+        android:supportsRtl="true">
+
+        <!-- 注册service -->
+        <service android:name="com.yaoxiaowen.download.service.DownloadService" />
+
+    </application>
+
+</manifest>

+ 16 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/DownloadConstant.java

@@ -0,0 +1,16 @@
+package com.yaoxiaowen.download;
+
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/23 13:34
+ * @since 1.0.0
+ */
+public class DownloadConstant {
+    /**
+     * 下载过程会通过发送广播, 广播通过intent携带文件数据的 信息。
+     * intent 的key值就是该字段
+     * eg : FileInfo fileInfo = (FileInfo) intent.getSerializableExtra(DownloadConstant.EXTRA_INTENT_DOWNLOAD);
+     */
+    public static final String EXTRA_INTENT_DOWNLOAD = "yaoxiaowen_download_extra";
+}

+ 105 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/DownloadHelper.java

@@ -0,0 +1,105 @@
+package com.yaoxiaowen.download;
+
+import android.content.Context;
+import android.content.Intent;
+
+import com.yaoxiaowen.download.config.InnerConstant;
+import com.yaoxiaowen.download.bean.DownloadInfo;
+import com.yaoxiaowen.download.bean.RequestInfo;
+import com.yaoxiaowen.download.service.DownloadService;
+import com.yaoxiaowen.download.utils.LogUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/20 18:10
+ * @since 1.0.0
+ */
+public class DownloadHelper {
+    
+    public static final String TAG = "DownloadHelper";
+
+    private volatile static DownloadHelper SINGLETANCE;
+
+    private static ArrayList<RequestInfo> requests = new ArrayList<>();
+
+    private DownloadHelper(){
+    }
+
+    public static DownloadHelper getInstance(){
+        if (SINGLETANCE == null){
+            synchronized (DownloadHelper.class){
+                if (SINGLETANCE == null){
+                    SINGLETANCE = new DownloadHelper();
+                }
+            }
+        }
+        return SINGLETANCE;
+    }
+
+    /**
+     * 提交  下载/暂停  等任务.(提交就意味着开始执行生效)
+     * @param context
+     */
+    public synchronized void submit(Context context){
+        if (requests.isEmpty()){
+            LogUtils.w("没有下载任务可供执行");
+            return;
+        }
+        Intent intent = new Intent(context, DownloadService.class);
+        intent.putExtra(InnerConstant.Inner.SERVICE_INTENT_EXTRA, requests);
+        context.startService(intent);
+        requests.clear();
+    }// end of "submit(..."
+
+
+    /**
+     *  添加 新的下载任务
+     *
+     * @param url  下载的url
+     * @param file  存储在某个位置上的文件
+     * @param action  下载过程会发出广播信息.该参数是广播的action
+     * @return   DownloadHelper自身 (方便链式调用)
+     */
+    public DownloadHelper addTask(String url, File file, String action){
+        RequestInfo requestInfo = createRequest(url, file, action, InnerConstant.Request.loading);
+        LogUtils.i(TAG, "addTask() requestInfo=" + requestInfo);
+
+        requests.add(requestInfo);
+        return this;
+    }
+
+    /**
+     *  暂停某个下载任务
+     *
+     * @param url   下载的url
+     * @param file  存储在某个位置上的文件
+     * @param action  下载过程会发出广播信息.该参数是广播的action
+     * @return DownloadHelper自身 (方便链式调用)
+     */
+    public DownloadHelper pauseTask(String url, File file, String action){
+        RequestInfo requestInfo = createRequest(url, file, action, InnerConstant.Request.pause);
+        LogUtils.i(TAG, "pauseTask() -> requestInfo=" + requestInfo);
+        requests.add(requestInfo);
+        return this;
+    }
+
+    /**
+     * 设定该模块是否输出 debug信息
+     * Todo 要重构log模块, 对于我们的静态内部类,目前还不生效
+     */
+    public DownloadHelper setDebug(boolean isDebug){
+        LogUtils.setDebug(isDebug);
+        return this;
+    }
+
+
+    private RequestInfo createRequest(String url, File file, String action, int dictate){
+        RequestInfo request = new RequestInfo();
+        request.setDictate(dictate);
+        request.setDownloadInfo(new DownloadInfo(url, file, action));
+        return request;
+    }
+}

+ 21 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/DownloadStatus.java

@@ -0,0 +1,21 @@
+package com.yaoxiaowen.download;
+
+/**
+ *
+ * 标示着 下载过程中的状态
+ *
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/22 18:48
+ * @since 1.0.0
+ */
+public class DownloadStatus {
+
+    // Answer to the Ultimate Question of Life, The Universe, and Everything is 42
+
+    public static final int WAIT = 42;       //等待
+    public static final int PREPARE = 43;    //准备
+    public static final int LOADING = 44;    //下载中
+    public static final int PAUSE = 45;      //暂停Todo
+    public static final int COMPLETE = 46;   //完成
+    public static final int FAIL = 47;       //失败
+}

+ 87 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/FileInfo.java

@@ -0,0 +1,87 @@
+package com.yaoxiaowen.download;
+
+
+import com.yaoxiaowen.download.utils.DebugUtils;
+
+import java.io.Serializable;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/18 21:29
+ * @since 1.0.0
+ *
+ */
+public class FileInfo implements Serializable{
+    private String id;   //文件的唯一标识符 (url+文件存储路径)
+    private String downloadUrl;   //下载的url
+    private String filePath;  //文件存放的路径位置
+    private long size;   //文件的总尺寸
+    private long downloadLocation; // 下载的位置(就是当前已经下载过的size,也是断点的位置)
+
+    private int downloadStatus = DownloadStatus.PAUSE;   //下载的状态信息
+
+
+
+    public FileInfo() {
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getDownloadUrl() {
+        return downloadUrl;
+    }
+
+    public void setDownloadUrl(String downloadUrl) {
+        this.downloadUrl = downloadUrl;
+    }
+
+    public String getFilePath() {
+        return filePath;
+    }
+
+    public void setFilePath(String filePath) {
+        this.filePath = filePath;
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public void setSize(long size) {
+        this.size = size;
+    }
+
+    public long getDownloadLocation() {
+        return downloadLocation;
+    }
+
+    public void setDownloadLocation(long downloadLocation) {
+        this.downloadLocation = downloadLocation;
+    }
+
+    public int getDownloadStatus() {
+        return downloadStatus;
+    }
+
+    public void setDownloadStatus(int downloadStatus) {
+        this.downloadStatus = downloadStatus;
+    }
+
+    @Override
+    public String toString() {
+        return "FileInfo{" +
+                "id='" + id + '\'' +
+                ", downloadUrl='" + downloadUrl + '\'' +
+                ", filePath='" + filePath + '\'' +
+                ", size=" + size +
+                ", downloadLocation=" + downloadLocation +
+                ", downloadStatus=" + DebugUtils.getStatusDesc(downloadStatus) +
+                '}';
+    }
+}

+ 63 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/bean/DownloadInfo.java

@@ -0,0 +1,63 @@
+package com.yaoxiaowen.download.bean;
+
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/18 21:44
+ * @since 1.0.0
+ */
+public class DownloadInfo implements Serializable{
+    private String url;
+    private File file;
+    private String action; // 广播接受者的各种行为
+
+
+    public DownloadInfo(String url, File file, String action) {
+        this.url = url;
+        this.file = file;
+        this.action = action;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    public void setFile(File file) {
+        this.file = file;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+
+    @Override
+    public String toString() {
+        return "DownloadInfo{" +
+                "url='" + url + '\'' +
+                ", file=" + file +
+                ", action='" + action + '\'' +
+                '}';
+    }
+
+    public String getUniqueId(){
+        return url + file.getAbsolutePath();
+    }
+
+
+}

+ 50 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/bean/RequestInfo.java

@@ -0,0 +1,50 @@
+package com.yaoxiaowen.download.bean;
+
+
+
+import com.yaoxiaowen.download.config.InnerConstant;
+import com.yaoxiaowen.download.utils.DebugUtils;
+
+import java.io.Serializable;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/18 21:29
+ * @since 1.0.0
+ */
+public class RequestInfo implements Serializable{
+
+    private int dictate;   //下载的控制状态
+
+    private DownloadInfo downloadInfo;
+
+    public RequestInfo() {
+    }
+
+
+
+    public int getDictate() {
+        return dictate;
+    }
+
+    public void setDictate(int dictate) {
+        this.dictate = dictate;
+    }
+
+    public DownloadInfo getDownloadInfo() {
+        return downloadInfo;
+    }
+
+    public void setDownloadInfo(DownloadInfo downloadInfo) {
+        this.downloadInfo = downloadInfo;
+    }
+
+
+    @Override
+    public String toString() {
+        return "RequestInfo{" +
+                "dictate=" + DebugUtils.getRequestDictateDesc(dictate) +
+                ", downloadInfo=" + downloadInfo +
+                '}';
+    }
+}

+ 36 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/config/InnerConstant.java

@@ -0,0 +1,36 @@
+package com.yaoxiaowen.download.config;
+
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/18 21:23
+ * @since 1.0.0
+ */
+public class InnerConstant {
+
+    //Db 数据库中用到的字段
+    public static class Db {
+        public static final String id = "id";
+        public static final String downloadUrl = "downloadUrl";
+        public static final String filePath = "filePath";
+        public static final String size = "size";
+        public static final String downloadLocation = "downloadLocation";
+        public static final String downloadStatus = "downloadStatus";
+
+        public static final String NAME_TABALE = "download_info";
+        public static final String NAME_DB = "download.Db";
+    }
+
+    //请求参数中用到的信息
+    public static class Request{
+        public static final int loading = 10; //下载状态
+        public static final int pause = 11; //暂停状态
+    }
+
+    public static class Inner{
+        public static final String SERVICE_INTENT_EXTRA = "service_intent_extra";
+    }
+
+    //用于intent数据的传递
+//    public static final String EXTRA_INTENT_DOWNLOAD = "yaoxiaowen_download_extra";
+}

+ 101 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/db/DbHolder.java

@@ -0,0 +1,101 @@
+package com.yaoxiaowen.download.db;
+
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.text.TextUtils;
+
+import com.yaoxiaowen.download.config.InnerConstant;
+import com.yaoxiaowen.download.FileInfo;
+
+import java.io.File;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/19 19:15
+ * @since 1.0.0
+ */
+public class DbHolder {
+    private Context context;
+    private SQLiteDatabase mDb;
+
+    public DbHolder(Context context) {
+        this.context = context;
+        mDb = new DbOpenHelper(context).getWritableDatabase();
+    }
+
+    public void saveFile(FileInfo downloadFile){
+        if (null == downloadFile){
+            return;
+        }
+
+        ContentValues values = new ContentValues();
+        values.put(InnerConstant.Db.id, downloadFile.getId());
+        values.put(InnerConstant.Db.downloadUrl, downloadFile.getDownloadUrl());
+        values.put(InnerConstant.Db.filePath, downloadFile.getFilePath());
+        values.put(InnerConstant.Db.size, downloadFile.getSize());
+        values.put(InnerConstant.Db.downloadLocation, downloadFile.getDownloadLocation());
+        values.put(InnerConstant.Db.downloadStatus, downloadFile.getDownloadStatus());
+
+        if (has(downloadFile.getId())){
+            mDb.update(InnerConstant.Db.NAME_TABALE, values, InnerConstant.Db.id + " = ?", new String[]{downloadFile.getId()});
+        }else {
+            mDb.insert(InnerConstant.Db.NAME_TABALE, null, values);
+        }
+
+    }//end of "saveFile(..."
+
+
+    public void updateState(String id, int state){
+        if (TextUtils.isEmpty(id)){
+            return;
+        }
+
+        ContentValues values = new ContentValues();
+        values.put(InnerConstant.Db.downloadStatus, state);
+        mDb.update(InnerConstant.Db.NAME_TABALE, values, InnerConstant.Db.id + " = ?", new String[]{id});
+    }
+
+
+    public FileInfo getFileInfo(String id){
+        Cursor cursor = mDb.query(InnerConstant.Db.NAME_TABALE, null, " " + InnerConstant.Db.id + " = ? ", new String[]{id}, null, null, null);
+        FileInfo downloadFile = null;
+        while (cursor.moveToNext()){
+            downloadFile = new FileInfo();
+            downloadFile.setId( cursor.getString(cursor.getColumnIndex( InnerConstant.Db.id)) );
+            downloadFile.setDownloadUrl( cursor.getString(cursor.getColumnIndex( InnerConstant.Db.downloadUrl)) );
+            downloadFile.setFilePath( cursor.getString(cursor.getColumnIndex( InnerConstant.Db.filePath)) );
+            downloadFile.setSize( cursor.getLong( cursor.getColumnIndex(InnerConstant.Db.size)) );
+            downloadFile.setDownloadLocation( cursor.getLong( cursor.getColumnIndex(InnerConstant.Db.downloadLocation)));
+            downloadFile.setDownloadStatus( cursor.getInt(cursor.getColumnIndex(InnerConstant.Db.downloadStatus)) );
+
+            File file = new File(downloadFile.getFilePath());
+            if (!file.exists()){
+                deleteFileInfo(id);
+                return null;
+            }
+        }
+        cursor.close();
+        return downloadFile;
+    }
+
+
+    /**
+     * 根据id 来删除对应的文件信息
+     * @param id
+     */
+    public void deleteFileInfo(String id){
+        if (has(id)){
+            mDb.delete(InnerConstant.Db.NAME_TABALE, InnerConstant.Db.id + " = ?", new String[]{id});
+        }
+    }
+
+    private boolean has(String id){
+        Cursor cursor = mDb.query(InnerConstant.Db.NAME_TABALE, null,  " " + InnerConstant.Db.id + " = ? ", new String[]{id}, null, null, null);
+        boolean has = cursor.moveToNext();
+        cursor.close();
+        return has;
+    }
+}

+ 57 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/db/DbOpenHelper.java

@@ -0,0 +1,57 @@
+package com.yaoxiaowen.download.db;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+import com.yaoxiaowen.download.config.InnerConstant;
+import com.yaoxiaowen.download.utils.LogUtils;
+
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/19 19:15
+ * @since 1.0.0
+ */
+public class DbOpenHelper extends SQLiteOpenHelper{
+    public static final String TAG = "DbOpenHelper";
+
+    public DbOpenHelper(Context context) {
+        super(context, InnerConstant.Db.NAME_DB, null, getVersionCode(context));
+    }
+
+    private static int getVersionCode(Context context){
+        try {
+            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
+            return packageInfo.versionCode;
+        }catch (Exception e){
+            LogUtils.e(TAG, "创建数据库失败 ");
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        String info = "create table if not exists " + InnerConstant.Db.NAME_TABALE
+                + "(" +
+                InnerConstant.Db.id + " varchar(500)," +
+                InnerConstant.Db.downloadUrl + " varchar(100)," +
+                InnerConstant.Db.filePath + " varchar(100)," +
+                InnerConstant.Db.size + " integer," +
+                InnerConstant.Db.downloadLocation + " integer," +
+                InnerConstant.Db.downloadStatus + " integer)";
+
+        LogUtils.i(TAG, "onCreate() -> info=" + info);
+        db.execSQL(info);
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        //对于下载来讲,其实是不存在这种升级数据库的业务的.所以我们直接删除重新建表
+        db.execSQL("drop table if exists " + InnerConstant.Db.NAME_TABALE);
+        onCreate(db);
+    }
+}

+ 43 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/execute/DownloadExecutor.java

@@ -0,0 +1,43 @@
+package com.yaoxiaowen.download.execute;
+
+
+import android.content.Intent;
+
+import com.yaoxiaowen.download.DownloadConstant;
+import com.yaoxiaowen.download.DownloadStatus;
+import com.yaoxiaowen.download.utils.LogUtils;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/20 18:36
+ * @since 1.0.0
+ */
+public class DownloadExecutor extends ThreadPoolExecutor{
+    
+    public static final String TAG = "DownloadExecutor";
+    
+    public DownloadExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
+                            TimeUnit unit, BlockingQueue<Runnable> workQueue) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
+    }
+
+    public void executeTask(DownloadTask task){
+        int status = task.getStatus();
+        if (status== DownloadStatus.PAUSE || status== DownloadStatus.FAIL){
+            task.setFileStatus(DownloadStatus.WAIT);
+
+            Intent intent = new Intent();
+            intent.setAction(task.getDownLoadInfo().getAction());
+            intent.putExtra(DownloadConstant.EXTRA_INTENT_DOWNLOAD, task.getFileInfo());
+            task.sendBroadcast(intent);
+
+            execute(task);
+        }else {
+            LogUtils.w(TAG, "文件状态不正确, 不进行下载 FileInfo=" + task.getFileInfo());
+        }
+    }
+}

+ 246 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/execute/DownloadTask.java

@@ -0,0 +1,246 @@
+package com.yaoxiaowen.download.execute;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.yaoxiaowen.download.DownloadConstant;
+import com.yaoxiaowen.download.DownloadStatus;
+import com.yaoxiaowen.download.bean.DownloadInfo;
+import com.yaoxiaowen.download.FileInfo;
+import com.yaoxiaowen.download.db.DbHolder;
+import com.yaoxiaowen.download.utils.LogUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/19 19:12  
+ * @since 1.0.0
+ *
+ * Todo 这个地方可以改用 FutureTask来做
+ */
+public class DownloadTask implements Runnable{
+    
+    public static final String TAG = "DownloadTask";
+
+    private Context context;
+    private DownloadInfo info;
+    private FileInfo mFileInfo;
+    private DbHolder dbHolder;
+    private boolean isPause;
+
+    public DownloadTask(Context context, DownloadInfo info, DbHolder dbHolder) {
+        this.context = context;
+        this.info = info;
+        this.dbHolder = dbHolder;
+
+        //初始化下载文件信息
+        mFileInfo = new FileInfo();
+        mFileInfo.setId(info.getUniqueId());
+        mFileInfo.setDownloadUrl(info.getUrl());
+        mFileInfo.setFilePath(info.getFile().getAbsolutePath());
+
+        LogUtils.i(TAG, "构造函数 -> 初始化 mFileInfo=" + mFileInfo);
+
+        FileInfo fileInfoFromDb = dbHolder.getFileInfo(info.getUniqueId());
+        long location = 0;
+        long fileSize = 0;
+        if (null != fileInfoFromDb){
+            location = fileInfoFromDb.getDownloadLocation();
+            fileSize = fileInfoFromDb.getSize();
+
+            if (location == 0){
+                if (info.getFile().exists()){
+                    info.getFile().delete();
+                }
+            }else {
+                //因为未知的原因, 这个文件不存在了,(虽然数据库记录表明我们的确已经下载过了),所以我们要从头开始
+                if (!info.getFile().exists()){
+                    LogUtils.i(TAG, "file = " + info.getFile());
+                    Log.i(TAG, "数据库记录表明我们下载过该文件, 但是现在该文件不存在,所以从头开始");
+                    dbHolder.deleteFileInfo(info.getUniqueId());
+                    location = 0;
+                    fileSize = 0;
+                }
+            }
+        }else {
+            if (info.getFile().exists()){
+                info.getFile().delete();
+            }
+        }
+
+        mFileInfo.setSize(fileSize);
+        mFileInfo.setDownloadLocation(location);
+
+        LogUtils.i(TAG, "构造函数() -> 初始化完毕  mFileInfo=" + mFileInfo);
+    }
+
+    @Override
+    public void run() {
+        download();
+    }
+
+    public void pause(){
+        isPause = true;
+    }
+
+    public int getStatus(){
+        if (null != mFileInfo){
+            return mFileInfo.getDownloadStatus();
+        }
+        return DownloadStatus.FAIL;
+    }
+
+    public void setFileStatus(int status){
+        mFileInfo.setDownloadStatus(status);
+    }
+
+    public void sendBroadcast(Intent intent){
+        context.sendBroadcast(intent);
+    }
+
+    public DownloadInfo getDownLoadInfo(){
+        return info;
+    }
+
+    public FileInfo getFileInfo(){
+        return mFileInfo;
+    }
+
+    private void download(){
+        mFileInfo.setDownloadStatus(DownloadStatus.PREPARE);
+        LogUtils.i(TAG, "准备开始下载");
+
+        Intent intent = new Intent();
+        intent.setAction(info.getAction());
+        intent.putExtra(DownloadConstant.EXTRA_INTENT_DOWNLOAD, mFileInfo);
+        context.sendBroadcast(intent);
+
+        RandomAccessFile accessFile = null;
+        HttpURLConnection http = null;
+        InputStream inStream = null;
+
+        try {
+
+
+            String realUrl = getRedirectionUrl(info.getUrl());
+            URL sizeUrl = new URL(realUrl);
+            HttpURLConnection sizeHttp = (HttpURLConnection)sizeUrl.openConnection();
+            sizeHttp.setRequestMethod("GET");
+            sizeHttp.connect();
+
+            long totalSize = sizeHttp.getContentLength();
+            sizeHttp.disconnect();
+
+            if (totalSize <= 0){
+                if (info.getFile().exists()){
+                    info.getFile().delete();
+                }
+                dbHolder.deleteFileInfo(info.getUniqueId());
+                LogUtils.e(TAG, "文件大小 = " + totalSize + "\t, 终止下载过程");
+                return;
+            }
+
+            mFileInfo.setSize(totalSize);
+            accessFile = new RandomAccessFile(info.getFile(), "rwd");
+
+            URL url = new URL(realUrl);
+            http = (HttpURLConnection)url.openConnection();
+            http.setConnectTimeout(10000);
+            http.setRequestProperty("Connection", "Keep-Alive");
+            http.setReadTimeout(10000);
+            http.setRequestProperty("Range", "bytes=" + mFileInfo.getDownloadLocation() + "-");
+            http.connect();
+
+            inStream = http.getInputStream();
+            byte[] buffer = new byte[1024*8];
+            int offset;
+
+            accessFile.seek(mFileInfo.getDownloadLocation());
+            long  millis = SystemClock.uptimeMillis();
+            while ((offset = inStream.read(buffer)) != -1){
+                if (isPause){
+                    LogUtils.i(TAG, "下载过程 设置了 暂停");
+                    mFileInfo.setDownloadStatus(DownloadStatus.PAUSE);
+                    isPause = false;
+                    dbHolder.saveFile(mFileInfo);
+                    context.sendBroadcast(intent);
+
+                    http.disconnect();
+                    accessFile.close();
+                    inStream.close();
+                    return;
+                }
+                accessFile.write(buffer,0, offset);
+                mFileInfo.setDownloadLocation( mFileInfo.getDownloadLocation()+offset );
+                mFileInfo.setDownloadStatus(DownloadStatus.LOADING);
+
+                if (SystemClock.uptimeMillis()-millis >= 1000){
+                    millis = SystemClock.uptimeMillis();
+                    dbHolder.saveFile(mFileInfo);
+                    context.sendBroadcast(intent);
+                }
+            }// end of "while(..."
+
+            mFileInfo.setDownloadStatus(DownloadStatus.COMPLETE);
+            dbHolder.saveFile(mFileInfo);
+            context.sendBroadcast(intent);
+        } catch (Exception e){
+            LogUtils.e(TAG, "下载过程发生失败");
+            mFileInfo.setDownloadStatus(DownloadStatus.FAIL);
+            dbHolder.saveFile(mFileInfo);
+            context.sendBroadcast(intent);
+            e.printStackTrace();
+        } finally {
+            try {
+                if (accessFile != null){
+                    accessFile.close();
+                }
+                if (inStream != null){
+                    inStream.close();
+                }
+                if (http != null){
+                    http.disconnect();
+                }
+            }catch (IOException e){
+                LogUtils.e(TAG, "finally 块  关闭文件过程中 发生异常");
+                e.printStackTrace();
+            }
+        }
+
+
+
+    }//end of "download()"
+
+
+    private String getRedirectionUrl(String sourceUrl){
+
+        String redirUrl = sourceUrl;
+
+        try {
+            URL url = new URL(sourceUrl);
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            conn.setRequestMethod("GET");
+
+            conn.connect();
+            int responseCode = conn.getResponseCode();
+            if (responseCode == 302){
+                redirUrl = conn.getHeaderField("Location");
+                LogUtils.i(TAG, " 下载地址重定向为 = " + redirUrl);
+
+            }
+            conn.disconnect();
+
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+
+        return redirUrl;
+    }
+}

+ 137 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/service/DownloadService.java

@@ -0,0 +1,137 @@
+package com.yaoxiaowen.download.service;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.text.TextUtils;
+
+import com.yaoxiaowen.download.DownloadConstant;
+import com.yaoxiaowen.download.config.InnerConstant;
+import com.yaoxiaowen.download.DownloadStatus;
+import com.yaoxiaowen.download.bean.DownloadInfo;
+import com.yaoxiaowen.download.FileInfo;
+import com.yaoxiaowen.download.bean.RequestInfo;
+import com.yaoxiaowen.download.db.DbHolder;
+import com.yaoxiaowen.download.execute.DownloadExecutor;
+import com.yaoxiaowen.download.execute.DownloadTask;
+import com.yaoxiaowen.download.utils.LogUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/18 14:25
+ * @since 1.0.0
+ */
+public class DownloadService extends Service{
+
+    public static final String TAG = "DownloadService";
+
+    public static boolean canRequest = true;
+
+    //关于线程池的一些配置
+    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
+    private static final int CORE_POOL_SIZE = Math.max(3, CPU_COUNT/2);
+    private static final int MAX_POOL_SIZE =  CORE_POOL_SIZE * 2;
+    private static final long KEEP_ALIVE_TIME  = 0L;
+
+    private DownloadExecutor mExecutor = new DownloadExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE,
+            KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<Runnable>());
+
+    //存储任务
+    private HashMap<String, DownloadTask> mTasks = new HashMap<>();
+
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (canRequest){
+            LogUtils.i(TAG, "onStartCommand() -> 启动了service服务 intent=" + intent + "\t this=" + this);
+            canRequest = false;
+
+            if (null!=intent && intent.hasExtra(InnerConstant.Inner.SERVICE_INTENT_EXTRA)){
+                try {
+                    ArrayList<RequestInfo> requesetes =
+                            (ArrayList<RequestInfo>)intent.getSerializableExtra(InnerConstant.Inner.SERVICE_INTENT_EXTRA);
+                    if (null != requesetes && requesetes.size()>0){
+                        for (RequestInfo request : requesetes){
+                            executeDownload(request);
+                        }
+                    }
+                }catch (Exception e){
+                    LogUtils.i(TAG, "onStartCommand()-> 接受数据,启动线程中发生异常");
+                    e.printStackTrace();
+                }
+            }
+            canRequest = true;
+        }
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    //Todo  除了简单的synchronized, 是否有更好的方式来进行加锁呢
+    private synchronized void executeDownload(RequestInfo requestInfo){
+        DownloadInfo mDownloadInfo = requestInfo.getDownloadInfo();
+
+        //先看看在任务列表里,是否有这个任务
+        DownloadTask task = mTasks.get(mDownloadInfo.getUniqueId());
+        DbHolder dbHolder = new DbHolder(getBaseContext());
+        FileInfo mFileInfo = dbHolder.getFileInfo(mDownloadInfo.getUniqueId());
+
+        LogUtils.i(TAG, "executeDownload() -> task=" + task + "\t mFileInfo=" + mFileInfo);
+
+
+        if (null == task){ //之前没有类似任务
+            if (null != mFileInfo){
+                if (mFileInfo.getDownloadStatus()== DownloadStatus.LOADING
+                        || mFileInfo.getDownloadStatus()== DownloadStatus.PREPARE){
+                    //修正文件状态
+                    dbHolder.updateState(mFileInfo.getId(), DownloadStatus.PAUSE);
+                }else if (mFileInfo.getDownloadStatus() == DownloadStatus.COMPLETE){
+                    if (mDownloadInfo.getFile().exists()){
+                        if (!TextUtils.isEmpty(mDownloadInfo.getAction())){
+                            Intent intent = new Intent();
+                            intent.setAction(mDownloadInfo.getAction());
+                            intent.putExtra(DownloadConstant.EXTRA_INTENT_DOWNLOAD, mFileInfo);
+                            sendBroadcast(intent);
+                        }
+                        return;
+                    } else {
+                        dbHolder.deleteFileInfo(mDownloadInfo.getUniqueId());
+                    }
+                }
+            }//end of "  null != mFileInfo "
+
+            //创建一个下载任务
+            if (requestInfo.getDictate() == InnerConstant.Request.loading){
+                task = new DownloadTask(this, mDownloadInfo, dbHolder);
+                mTasks.put(mDownloadInfo.getUniqueId(), task);
+            }
+        }else {
+            // 什么情况下, 可能存在这种这种状态
+            if (task.getStatus()== DownloadStatus.COMPLETE || task.getStatus()== DownloadStatus.LOADING){
+                if (!mDownloadInfo.getFile().exists()){
+                    task.pause();
+                    mTasks.remove(mDownloadInfo.getUniqueId());
+                    LogUtils.i(TAG, " 状态标示完成,但是文件不存在,重新执行下载文件  ");
+                    executeDownload(requestInfo);
+                    return;
+                }
+            }
+        }
+
+        if (null != task){
+            if (requestInfo.getDictate() == InnerConstant.Request.loading){
+                mExecutor.executeTask(task);
+            }else {
+                task.pause();
+            }
+        }
+    }
+}

+ 43 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/utils/DebugUtils.java

@@ -0,0 +1,43 @@
+package com.yaoxiaowen.download.utils;
+
+
+
+import com.yaoxiaowen.download.config.InnerConstant;
+import com.yaoxiaowen.download.DownloadStatus;
+
+/**
+ * @author   www.yaoxiaowen.com
+ * time:  2017/12/19 19:50
+ * @since 1.0.0
+ */
+public class DebugUtils {
+    public static String getStatusDesc( int status){
+        switch (status){
+            case DownloadStatus.WAIT:
+                return " wait ";
+            case DownloadStatus.PREPARE:
+                return " prepare ";
+            case DownloadStatus.LOADING:
+                return " loading ";
+            case DownloadStatus.PAUSE:
+                return " pause ";
+            case DownloadStatus.COMPLETE:
+                return " complete ";
+            case DownloadStatus.FAIL:
+                return " fail ";
+            default:
+                return "  错误的未知状态 ";
+        }
+    }
+
+    public static String getRequestDictateDesc( int dictate){
+        switch (dictate){
+            case InnerConstant.Request.loading:
+                return " loading ";
+            case InnerConstant.Request.pause:
+                return " pause ";
+            default:
+                return " dictate描述错误  ";
+        }
+    }
+}

+ 161 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/utils/LogUtils.java

@@ -0,0 +1,161 @@
+package com.yaoxiaowen.download.utils;
+
+import android.util.Log;
+
+/**
+ * author:yaowen on 17/5/14 12:54
+ * email:yaoxiaowen88@gmail.com
+ * www.yaoxiaowen.com
+ *
+ * 在实际使用当中要注意,Log的TAG太长了,会输不出来.
+ * 官方要求是不超过23个字符的。
+ *  http://blog.csdn.net/voiceofnet/article/details/49866047
+ *
+ *  另外,使用Log工具不要使用v,d级别的,原因是因为部分型号手机会屏蔽掉 v,d等低级别的log,导致无法输出
+ *  因此v,d级别的log,本工具中使用了  Deprecated 标记
+ */
+
+public class LogUtils {
+
+    //Todo 这两个值,记得进行修改
+    public static final String PREFIX = "weny ";
+    private static boolean debug = false;
+
+    public static void setDebug(boolean b){
+        debug = b;
+    }
+
+    @Deprecated
+    public static void v(String msg) {
+        if (!debug){
+            return;
+        }
+
+        Log.v(getTAG(), msg);
+    }
+
+    @Deprecated
+    public static void v(String TAG, String msg) {
+        if (!debug){
+            return;
+        }
+        Log.v(PREFIX + TAG, msg);
+    }
+
+    @Deprecated
+    public static void d(String msg) {
+        if (!debug){
+            return;
+        }
+        Log.d(getTAG(), msg);
+    }
+
+
+    @Deprecated
+    public static void d(String TAG, String msg) {
+        if (!debug){
+            return;
+        }
+        String NewTAG = PREFIX + TAG;
+        Log.d(NewTAG, msg);
+    }
+
+    public static void i(String msg) {
+        if (!debug){
+            return;
+        }
+        Log.i(getTAG(), msg);
+    }
+
+    public static void i(String TAG, String msg) {
+        if (!debug){
+            return;
+        }
+        Log.i(PREFIX + TAG, msg);
+    }
+
+
+    public static void w(String msg) {
+        if (!debug){
+            return;
+        }
+        Log.w(getTAG(), msg);
+    }
+
+    public static void w(String TAG, String msg) {
+        if (!debug){
+            return;
+        }
+        Log.w(PREFIX + TAG, msg);
+    }
+
+    public static void e(String msg) {
+        if (!debug){
+            return;
+        }
+        Log.e(getTAG(), msg);
+    }
+
+    public static void e(String TAG, String msg) {
+        if (!debug){
+            return;
+        }
+        Log.e(PREFIX + TAG, msg);
+    }
+
+    public static void wtf(String msg){
+        if (!debug){
+            return;
+        }
+        Log.wtf(getTAG(), msg);
+    }
+
+    public static void wtf(String TAG, String msg){
+        if (!debug){
+            return;
+        }
+        Log.wtf(PREFIX + TAG, msg);
+    }
+
+    /**
+     *  返回值是我们默认的TAG, PREFIX + className + methodName() + lineNum;
+     *
+     * @return  eg : PREFIX MainActivity initData() 37
+     *          eg : PREFIX MainActivity onClick() 58
+     *          eg:  PREFIX MainActivity onClick() 69
+     */
+    private static String getTAG() {
+        StringBuilder sb = new StringBuilder();
+
+        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+        sb.append(PREFIX + " ");
+
+        StringBuilder classNameSb = new StringBuilder();
+
+        /**
+         * 我们在这里并没有使用 比较简单的方式来获取。
+         * StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+         * stackTrace[3].getClassName()
+         * stackTrace[3].getMethodName( )
+         *
+         * 原因是那样简单写,没办法 正确的得到 内部类的 一些信息。
+         * 所以我们遍历了调用栈,采用硬编码来判断
+         */
+        for (StackTraceElement element : stackTrace){
+            classNameSb.delete(0, classNameSb.length());
+            classNameSb.append(element.getClassName());
+            if (classNameSb.indexOf("com.yaoxiaowen.download")>=0
+                    && !classNameSb.toString().contains("LogUtils")){
+                int index = classNameSb.lastIndexOf(".");
+                sb.append(classNameSb.subSequence(index+1, classNameSb.length()));
+                sb.append(" ");
+                sb.append(element.getMethodName() + "()");
+                sb.append(" " + element.getLineNumber() + " ");
+                break;
+            }
+        }
+
+        return sb.toString();
+    }
+
+}

+ 26 - 0
downloaderHelper/src/main/java/com/yaoxiaowen/download/utils/ToastUtils.java

@@ -0,0 +1,26 @@
+package com.yaoxiaowen.download.utils;
+
+import android.content.Context;
+import android.widget.Toast;
+
+/**
+ * author:yaowen on 17/5/14 20:54
+ * email:yaowen369@gmail.com
+ * www.yaoxiaowen.com
+ */
+
+public class ToastUtils {
+
+    public static void showToast(Context context, String msg){
+        Toast.makeText(context, msg, Toast.LENGTH_SHORT)
+                .show();
+    }
+
+    public static void showToast(Context context, String msg, int time){
+        if (time <= 0){
+            time = Toast.LENGTH_SHORT;
+        }
+        Toast.makeText(context, msg, time)
+                .show();
+    }
+}

+ 3 - 0
downloaderHelper/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">downloaderHelper</string>
+</resources>

+ 17 - 0
downloaderHelper/src/test/java/com/yaoxiaowen/download/ExampleUnitTest.java

@@ -0,0 +1,17 @@
+package com.yaoxiaowen.download;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() throws Exception {
+        assertEquals(4, 2 + 2);
+    }
+}

+ 1 - 1
settings.gradle

@@ -1,2 +1,2 @@
-include ':app', ':lib_base'
+include ':app', ':lib_base',':downloaderHelper'
 rootProject.name = "HHOmc"