代码格式修改

pull/2/head
lyy 9 years ago
commit 9e3f70f59d
  1. 17
      .idea/misc.xml
  2. 8
      app/build.gradle
  3. 296
      app/src/main/java/com/example/arial/downloaddemo/MainActivity.java
  4. 32
      downloadutil/build.gradle
  5. 208
      downloadutil/jcenter.gradle
  6. 6
      downloadutil/src/androidTest/java/com/arialyy/downloadutil/ApplicationTest.java
  7. 10
      downloadutil/src/main/AndroidManifest.xml
  8. 9
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadCommand.java
  9. 153
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadManager.java
  10. 155
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadTarget.java
  11. 349
      downloadutil/src/main/java/com/arialyy/downloadutil/core/IDownloadTarget.java
  12. 346
      downloadutil/src/main/java/com/arialyy/downloadutil/core/Task.java
  13. 2
      downloadutil/src/main/java/com/arialyy/downloadutil/core/TaskEnum.java
  14. 51
      downloadutil/src/main/java/com/arialyy/downloadutil/core/TaskFactory.java
  15. 13
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/AddCommand.java
  16. 72
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/IDownloadCommand.java
  17. 15
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/StartCommand.java
  18. 49
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IDownloader.java
  19. 76
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IPool.java
  20. 74
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/ITask.java
  21. 162
      downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/CachePool.java
  22. 235
      downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/ExecutePool.java
  23. 358
      downloadutil/src/main/java/com/arialyy/downloadutil/entity/DownloadEntity.java
  24. 9
      downloadutil/src/main/java/com/arialyy/downloadutil/help/CheckHelp.java
  25. 321
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/DbEntity.java
  26. 560
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/DbUtil.java
  27. 6
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/Id.java
  28. 6
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/Ignore.java
  29. 36
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/SqlHelper.java
  30. 796
      downloadutil/src/main/java/com/arialyy/downloadutil/util/DownLoadUtil.java
  31. 99
      downloadutil/src/main/java/com/arialyy/downloadutil/util/IDownloadListener.java
  32. 401
      downloadutil/src/main/java/com/arialyy/downloadutil/util/Util.java
  33. 10
      downloadutil/src/main/res/values/strings.xml
  34. 9
      downloadutil/src/test/java/com/arialyy/downloadutil/ExampleUnitTest.java

@ -53,25 +53,10 @@
<ConfirmationsSetting value="0" id="Add" /> <ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" /> <ConfirmationsSetting value="0" id="Remove" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">
<option name="id" value="Android" /> <option name="id" value="Android" />
</component> </component>
<component name="masterDetails">
<states>
<state key="ScopeChooserConfigurable.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project> </project>

@ -17,6 +17,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
dataBinding {
enabled = true
}
} }
dependencies { dependencies {
@ -24,5 +28,9 @@ dependencies {
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.+' compile 'com.android.support:appcompat-v7:23.+'
compile 'com.android.support:design:23.+' compile 'com.android.support:design:23.+'
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.google.code.gson:gson:2.7'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.arialyy.frame:MVVM2:2.2.0'
compile project(':downloadutil') compile project(':downloadutil')
} }

@ -18,159 +18,149 @@ import com.arialyy.downloadutil.util.Util;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
private static final int DOWNLOAD_PRE = 0x01; private static final int DOWNLOAD_PRE = 0x01;
private static final int DOWNLOAD_STOP = 0x02; private static final int DOWNLOAD_STOP = 0x02;
private static final int DOWNLOAD_FAILE = 0x03; private static final int DOWNLOAD_FAILE = 0x03;
private static final int DOWNLOAD_CANCEL = 0x04; private static final int DOWNLOAD_CANCEL = 0x04;
private static final int DOWNLOAD_RESUME = 0x05; private static final int DOWNLOAD_RESUME = 0x05;
private static final int DOWNLOAD_COMPLETE = 0x06; private static final int DOWNLOAD_COMPLETE = 0x06;
private ProgressBar mPb; private ProgressBar mPb;
private String mDownloadUrl = "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk"; private String mDownloadUrl =
private DownLoadUtil mUtil; "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk";
private Button mStart, mStop, mCancel; private DownLoadUtil mUtil;
private TextView mSize; private Button mStart, mStop, mCancel;
private TextView mSize;
private Handler mUpdateHandler = new Handler() {
@Override private Handler mUpdateHandler = new Handler() {
public void handleMessage(Message msg) { @Override public void handleMessage(Message msg) {
super.handleMessage(msg); super.handleMessage(msg);
switch (msg.what) { switch (msg.what) {
case DOWNLOAD_PRE: case DOWNLOAD_PRE:
mSize.setText(Util.formatFileSize((Long) msg.obj)); mSize.setText(Util.formatFileSize((Long) msg.obj));
mStart.setEnabled(false); mStart.setEnabled(false);
break; break;
case DOWNLOAD_FAILE: case DOWNLOAD_FAILE:
Toast.makeText(MainActivity.this, "下载失败", Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
break; break;
case DOWNLOAD_STOP: case DOWNLOAD_STOP:
Toast.makeText(MainActivity.this, "暂停下载", Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, "暂停下载", Toast.LENGTH_SHORT).show();
mStart.setText("恢复"); mStart.setText("恢复");
mStart.setEnabled(true); mStart.setEnabled(true);
break; break;
case DOWNLOAD_CANCEL: case DOWNLOAD_CANCEL:
mPb.setProgress(0); mPb.setProgress(0);
Toast.makeText(MainActivity.this, "取消下载", Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, "取消下载", Toast.LENGTH_SHORT).show();
mStart.setEnabled(true); mStart.setEnabled(true);
mStart.setText("开始"); mStart.setText("开始");
break; break;
case DOWNLOAD_RESUME: case DOWNLOAD_RESUME:
Toast.makeText(MainActivity.this, "恢复下载,恢复位置 ==> " + Util.formatFileSize((Long) msg.obj), Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, "恢复下载,恢复位置 ==> " + Util.formatFileSize((Long) msg.obj),
mStart.setEnabled(false); Toast.LENGTH_SHORT).show();
break; mStart.setEnabled(false);
case DOWNLOAD_COMPLETE: break;
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show(); case DOWNLOAD_COMPLETE:
mStart.setEnabled(true); Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
mCancel.setEnabled(false); mStart.setEnabled(true);
mStop.setEnabled(false); mCancel.setEnabled(false);
break; mStop.setEnabled(false);
} break;
} }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
init();
} }
};
private void init() {
mPb = (ProgressBar) findViewById(R.id.progressBar); @Override protected void onCreate(Bundle savedInstanceState) {
mStart = (Button) findViewById(R.id.start); super.onCreate(savedInstanceState);
mStop = (Button) findViewById(R.id.stop); setContentView(R.layout.activity_main);
mCancel = (Button) findViewById(R.id.cancel); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
mSize = (TextView) findViewById(R.id.size); setSupportActionBar(toolbar);
mUtil = new DownLoadUtil(); init();
} }
public void onClick(View view) { private void init() {
switch (view.getId()) { mPb = (ProgressBar) findViewById(R.id.progressBar);
case R.id.start: mStart = (Button) findViewById(R.id.start);
start(); mStop = (Button) findViewById(R.id.stop);
break; mCancel = (Button) findViewById(R.id.cancel);
case R.id.stop: mSize = (TextView) findViewById(R.id.size);
stop(); mUtil = new DownLoadUtil();
break; }
case R.id.cancel:
cancel(); public void onClick(View view) {
break; switch (view.getId()) {
} case R.id.start:
} start();
break;
private void start() { case R.id.stop:
mUtil.download(this, mDownloadUrl, Environment.getExternalStorageDirectory().getPath() + "/test.apk" stop();
, new DownLoadUtil.DownloadListener() { break;
long fileSize = 1; case R.id.cancel:
cancel();
@Override break;
public void onPreDownload(HttpURLConnection connection) {
super.onPreDownload(connection);
mPb.setMax(100);
fileSize = connection.getContentLength();
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, fileSize).sendToTarget();
}
@Override
public void onStart(long startLocation) {
super.onStart(startLocation);
}
@Override
public void onChildResume(long resumeLocation) {
super.onChildResume(resumeLocation);
}
@Override
public void onChildComplete(long finishLocation) {
super.onChildComplete(finishLocation);
}
@Override
public void onProgress(long currentLocation) {
super.onProgress(currentLocation);
mPb.setProgress((int) (currentLocation * 100 / fileSize));
}
@Override
public void onStop(long stopLocation) {
super.onStop(stopLocation);
mUpdateHandler.obtainMessage(DOWNLOAD_STOP).sendToTarget();
}
@Override
public void onCancel() {
super.onCancel();
mUpdateHandler.obtainMessage(DOWNLOAD_CANCEL).sendToTarget();
}
@Override
public void onResume(long resumeLocation) {
super.onResume(resumeLocation);
mUpdateHandler.obtainMessage(DOWNLOAD_RESUME, resumeLocation).sendToTarget();
}
@Override
public void onFail() {
super.onFail();
mUpdateHandler.obtainMessage(DOWNLOAD_FAILE).sendToTarget();
}
@Override
public void onComplete() {
super.onComplete();
mUpdateHandler.obtainMessage(DOWNLOAD_COMPLETE).sendToTarget();
}
});
} }
}
private void stop() {
mUtil.stopDownload(); private void start() {
} mUtil.download(this, mDownloadUrl,
Environment.getExternalStorageDirectory().getPath() + "/test.apk",
private void cancel() { new DownLoadUtil.DownloadListener() {
mUtil.cancelDownload(); long fileSize = 1;
}
@Override public void onPreDownload(HttpURLConnection connection) {
super.onPreDownload(connection);
mPb.setMax(100);
fileSize = connection.getContentLength();
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, fileSize).sendToTarget();
}
@Override public void onStart(long startLocation) {
super.onStart(startLocation);
}
@Override public void onChildResume(long resumeLocation) {
super.onChildResume(resumeLocation);
}
@Override public void onChildComplete(long finishLocation) {
super.onChildComplete(finishLocation);
}
@Override public void onProgress(long currentLocation) {
super.onProgress(currentLocation);
mPb.setProgress((int) (currentLocation * 100 / fileSize));
}
@Override public void onStop(long stopLocation) {
super.onStop(stopLocation);
mUpdateHandler.obtainMessage(DOWNLOAD_STOP).sendToTarget();
}
@Override public void onCancel() {
super.onCancel();
mUpdateHandler.obtainMessage(DOWNLOAD_CANCEL).sendToTarget();
}
@Override public void onResume(long resumeLocation) {
super.onResume(resumeLocation);
mUpdateHandler.obtainMessage(DOWNLOAD_RESUME, resumeLocation).sendToTarget();
}
@Override public void onFail() {
super.onFail();
mUpdateHandler.obtainMessage(DOWNLOAD_FAILE).sendToTarget();
}
@Override public void onComplete() {
super.onComplete();
mUpdateHandler.obtainMessage(DOWNLOAD_COMPLETE).sendToTarget();
}
});
}
private void stop() {
mUtil.stopDownload();
}
private void cancel() {
mUtil.cancelDownload();
}
} }

@ -1,26 +1,26 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
android { android {
compileSdkVersion 23 compileSdkVersion 23
buildToolsVersion "23.0.2" buildToolsVersion "23.0.2"
defaultConfig { defaultConfig {
minSdkVersion 9 minSdkVersion 9
targetSdkVersion 23 targetSdkVersion 23
versionCode 13 versionCode 13
versionName "1.0.1" versionName "1.0.1"
} }
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
} }
}
} }
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:appcompat-v7:23.1.1'
} }
//apply from: 'jcenter.gradle' //apply from: 'jcenter.gradle'

@ -6,31 +6,31 @@ apply plugin: "com.jfrog.artifactory"
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
task sourcesJar(type: Jar) { task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs from android.sourceSets.main.java.srcDirs
classifier = 'sources' classifier = 'sources'
} }
task javadoc(type: Javadoc) { task javadoc(type: Javadoc) {
options.encoding = "utf-8" options.encoding = "utf-8"
source = android.sourceSets.main.java.srcDirs source = android.sourceSets.main.java.srcDirs
classpath += configurations.compile classpath += configurations.compile
classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
} }
task javadocJar(type: Jar, dependsOn: javadoc) { task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc' classifier = 'javadoc'
from javadoc.destinationDir from javadoc.destinationDir
} }
javadoc { javadoc {
options { options {
encoding "UTF-8" encoding "UTF-8"
charSet 'UTF-8' charSet 'UTF-8'
author true author true
version true version true
links "http://docs.oracle.com/javase/7/docs/api" links "http://docs.oracle.com/javase/7/docs/api"
title PROJ_ARTIFACTID title PROJ_ARTIFACTID
} }
} }
//JAVADOC打包时引用其它类库而出现问题 //JAVADOC打包时引用其它类库而出现问题
@ -40,119 +40,121 @@ javadoc {
// : JsonElement // : JsonElement
// : xxxx // : xxxx
android.libraryVariants.all { variant -> android.libraryVariants.all { variant ->
println variant.javaCompile.classpath.files println variant.javaCompile.classpath.files
if (variant.name == 'release') { // release javadoc if (variant.name == 'release') {
task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) { // release javadoc
// title = '' task("generate${variant.name.capitalize()}Javadoc", type: Javadoc) {
// description = '' // title = ''
source = variant.javaCompile.source // description = ''
classpath = files(variant.javaCompile.classpath.files, project.android.getBootClasspath()) source = variant.javaCompile.source
options { classpath = files(variant.javaCompile.classpath.files, project.android.getBootClasspath())
encoding "utf-8" options {
links "http://docs.oracle.com/javase/7/docs/api/" encoding "utf-8"
linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference" links "http://docs.oracle.com/javase/7/docs/api/"
} linksOffline "http://d.android.com/reference", "${android.sdkDirectory}/docs/reference"
exclude '**/BuildConfig.java' }
exclude '**/R.java' exclude '**/BuildConfig.java'
} exclude '**/R.java'
task("javadoc${variant.name.capitalize()}Jar", type: Jar, dependsOn: "generate${variant.name.capitalize()}Javadoc") { }
classifier = 'javadoc' task("javadoc${variant.name.capitalize()}Jar", type: Jar,
from tasks.getByName("generate${variant.name.capitalize()}Javadoc").destinationDir dependsOn: "generate${variant.name.capitalize()}Javadoc") {
} classifier = 'javadoc'
artifacts { from tasks.getByName("generate${variant.name.capitalize()}Javadoc").destinationDir
archives tasks.getByName("javadoc${variant.name.capitalize()}Jar") }
} artifacts {
archives tasks.getByName("javadoc${variant.name.capitalize()}Jar")
} }
}
} }
artifacts { artifacts {
archives javadocJar archives javadocJar
archives sourcesJar archives sourcesJar
} }
def pomConfig = { def pomConfig = {
scm { scm {
connection PROJ_VCSURL connection PROJ_VCSURL
developerConnection PROJ_VCSURL developerConnection PROJ_VCSURL
url PROJ_WEBSITEURL url PROJ_WEBSITEURL
}
licenses {
license {
name "The Apache Software License, Version 2.0"
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
distribution "repo"
} }
licenses { }
license { developers {
name "The Apache Software License, Version 2.0" developer {
url "http://www.apache.org/licenses/LICENSE-2.0.txt" id DEVELOPER_ID
distribution "repo" name DEVELOPER_NAME
} email DEVELOPER_EMAIL
}
developers {
developer {
id DEVELOPER_ID
name DEVELOPER_NAME
email DEVELOPER_EMAIL
}
} }
}
} }
publishing { publishing {
publications { publications {
mavenJava(MavenPublication) { mavenJava(MavenPublication) {
artifactId PROJ_ARTIFACTID artifactId PROJ_ARTIFACTID
artifact javadocJar artifact javadocJar
artifact sourcesJar artifact sourcesJar
pom { pom {
packaging 'aar' packaging 'aar'
} }
pom.withXml { pom.withXml {
def root = asNode() def root = asNode()
root.appendNode('description', PROJ_DESCRIPTION) root.appendNode('description', PROJ_DESCRIPTION)
root.children().last() + pomConfig root.children().last() + pomConfig
} }
}
} }
}
} }
afterEvaluate { afterEvaluate {
publishing.publications.mavenJava.artifact(bundleRelease) publishing.publications.mavenJava.artifact(bundleRelease)
} }
bintray { bintray {
user = hasProperty("bintrayUser") ? getProperty("bintrayUser") : getProperty("BINTRAY_USER") user = hasProperty("bintrayUser") ? getProperty("bintrayUser") : getProperty("BINTRAY_USER")
key = hasProperty("bintrayKey") ? getProperty("bintrayKey") : getProperty("BINTRAY_KEY") key = hasProperty("bintrayKey") ? getProperty("bintrayKey") : getProperty("BINTRAY_KEY")
configurations = ['archives'] configurations = ['archives']
publications = ['mavenJava'] publications = ['mavenJava']
publish = true publish = true
pkg { pkg {
repo = 'maven' repo = 'maven'
name = PROJ_NAME name = PROJ_NAME
desc = PROJ_DESCRIPTION desc = PROJ_DESCRIPTION
websiteUrl = PROJ_WEBSITEURL websiteUrl = PROJ_WEBSITEURL
issueTrackerUrl = PROJ_ISSUETRACKERURL issueTrackerUrl = PROJ_ISSUETRACKERURL
vcsUrl = PROJ_VCSURL vcsUrl = PROJ_VCSURL
licenses = ['Apache-2.0'] licenses = ['Apache-2.0']
publicDownloadNumbers = true publicDownloadNumbers = true
} }
} }
artifactory { artifactory {
contextUrl = 'http://oss.jfrog.org/artifactory' contextUrl = 'http://oss.jfrog.org/artifactory'
resolve { resolve {
repository { repository {
repoKey = 'libs-release' repoKey = 'libs-release'
} }
}
publish {
repository {
repoKey = 'oss-snapshot-local' //The Artifactory repository key to publish to
username = bintray.user
password = bintray.key
maven = true
} }
publish { defaults {
repository { publications('mavenJava')
repoKey = 'oss-snapshot-local' //The Artifactory repository key to publish to publishArtifacts = true
username = bintray.user
password = bintray.key
maven = true
}
defaults {
publications('mavenJava')
publishArtifacts = true
}
} }
}
} }

@ -7,7 +7,7 @@ import android.test.ApplicationTestCase;
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a> * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
*/ */
public class ApplicationTest extends ApplicationTestCase<Application> { public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() { public ApplicationTest() {
super(Application.class); super(Application.class);
} }
} }

@ -1,11 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.arialyy.downloadutil"> package="com.arialyy.downloadutil">
<application <application
android:allowBackup="true" android:allowBackup="true"
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true"> android:supportsRtl="true">
</application> </application>
</manifest> </manifest>

@ -1,9 +0,0 @@
package com.arialyy.downloadutil.core;
/**
* Created by lyy on 2016/8/14.
* 命令抽象类
*/
public abstract class DownloadCommand {
}

@ -1,70 +1,111 @@
package com.arialyy.downloadutil.core; package com.arialyy.downloadutil.core;
import android.content.Context; import android.content.Context;
import com.arialyy.downloadutil.core.command.IDownloadCommand;
import java.util.ArrayList;
import java.util.List;
/** /**
* Created by lyy on 2016/8/11. * Created by lyy on 2016/8/11.
* 下载管理器通过命令的方式控制下载 * 下载管理器通过命令的方式控制下载
*/ */
public class DownloadManager { public class DownloadManager {
/** private static final Object LOCK = new Object();
* 下载开始前事件 private static volatile DownloadManager INSTANCE = null;
*/ /**
public static final String ACTION_PRE = "ACTION_PRE"; * 下载开始前事件
*/
/** public static final String ACTION_PRE = "ACTION_PRE";
* 开始下载事件
*/ /**
public static final String ACTION_START = "ACTION_START"; * 开始下载事件
*/
/** public static final String ACTION_START = "ACTION_START";
* 恢复下载事件
*/ /**
public static final String ACTION_RESUME = "ACTION_RESUME"; * 恢复下载事件
*/
/** public static final String ACTION_RESUME = "ACTION_RESUME";
* 正在下载事件
*/ /**
public static final String ACTION_RUNNING = "ACTION_RUNNING"; * 正在下载事件
*/
/** public static final String ACTION_RUNNING = "ACTION_RUNNING";
* 停止下载事件
*/ /**
public static final String ACTION_STOP = "ACTION_STOP"; * 停止下载事件
*/
/** public static final String ACTION_STOP = "ACTION_STOP";
* 取消下载事件
*/ /**
public static final String ACTION_CANCEL = "ACTION_CANCEL"; * 取消下载事件
*/
/** public static final String ACTION_CANCEL = "ACTION_CANCEL";
* 下载完成事件
*/ /**
public static final String ACTION_COMPLETE = "ACTION_COMPLETE"; * 下载完成事件
*/
/** public static final String ACTION_COMPLETE = "ACTION_COMPLETE";
* 下载失败事件
*/ /**
public static final String ACTION_FAIL = "ACTION_FAIL"; * 下载失败事件
*/
/** public static final String ACTION_FAIL = "ACTION_FAIL";
* 下载实体
*/ /**
public static final String DATA = "DOWNLOAD_ENTITY"; * 下载实体
*/
/** public static final String DATA = "DOWNLOAD_ENTITY";
* 位置
*/ /**
public static final String CURRENT_LOCATION = "CURRENT_LOCATION"; * 位置
*/
private Context mContext; public static final String CURRENT_LOCATION = "CURRENT_LOCATION";
private DownloadManager(Context context) { private List<IDownloadCommand> mCommands = new ArrayList<>();
mContext = context;
private DownloadManager() {
}
private Context mContext;
private DownloadManager(Context context) {
mContext = context;
}
public static DownloadManager getInstance(Context context) {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new DownloadManager(context.getApplicationContext());
}
} }
return INSTANCE;
}
public static DownloadManager getInstance(Context context) { /**
return new DownloadManager(context); * 设置命令
*/
public void setCommant(IDownloadCommand command) {
mCommands.add(command);
}
/**
* 设置一组命令
*/
public void setCommands(List<IDownloadCommand> commands) {
if (commands != null && commands.size() > 0) {
mCommands.addAll(commands);
} }
}
/**
* 执行所有设置的命令
*/
public synchronized void exe() {
for (IDownloadCommand command : mCommands) {
command.executeComment();
}
mCommands.clear();
}
} }

@ -1,9 +1,7 @@
package com.arialyy.downloadutil.core; package com.arialyy.downloadutil.core;
import android.content.Context; import android.content.Context;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
/** /**
@ -11,105 +9,96 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
* 下载任务调度类 * 下载任务调度类
*/ */
public class DownloadTarget extends IDownloadTarget { public class DownloadTarget extends IDownloadTarget {
private static final String TAG = "DownloadTarget"; private static final String TAG = "DownloadTarget";
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private static volatile DownloadTarget INSTANCE = null; private static volatile DownloadTarget INSTANCE = null;
private Context mContext; private Context mContext;
public static DownloadTarget getInstance(Context context) { public static DownloadTarget getInstance(Context context) {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (LOCK) { synchronized (LOCK) {
INSTANCE = new DownloadTarget(context.getApplicationContext()); INSTANCE = new DownloadTarget(context.getApplicationContext());
} }
}
return INSTANCE;
} }
return INSTANCE;
}
private DownloadTarget() { private DownloadTarget() {
super(); super();
} }
private DownloadTarget(Context context) { private DownloadTarget(Context context) {
super(); super();
mContext = context; mContext = context;
} }
@Override @Override public void startTask(Task task) {
public void startTask(Task task) { if (mExecutePool.putTask(task)) {
if (mExecutePool.putTask(task)) { task.start();
task.start();
}
} }
}
@Override @Override public void stopTask(Task task) {
public void stopTask(Task task) { if (mExecutePool.removeTask(task)) {
if (mExecutePool.removeTask(task)) { task.stop();
task.stop();
}
} }
}
@Override @Override public void cancelTask(Task task) {
public void cancelTask(Task task) { if (mExecutePool.removeTask(task)) {
if (mExecutePool.removeTask(task)) { task.cancel();
task.cancel();
}
} }
}
@Override @Override public void reTryStart(Task task) {
public void reTryStart(Task task) { if (!task.getDownloadUtil().isDownloading()) {
if (!task.getDownloadUtil().isDownloading()) { task.start();
task.start(); } else {
} else { Log.w(TAG, "任务没有完全停止,重试下载失败");
Log.w(TAG, "任务没有完全停止,重试下载失败");
}
} }
}
@Override @Override public Task createTask(DownloadEntity entity) {
public Task createTask(DownloadEntity entity) { Task task = TaskFactory.getInstance().createTask(mContext, entity, mTaskHandler);
Task task = TaskFactory.getInstance().createTask(mContext, entity, mTaskHandler); mCachePool.putTask(task);
mCachePool.putTask(task); return task;
return task; }
}
@Override @Override public Task getTask(DownloadEntity entity) {
public Task getTask(DownloadEntity entity) { Task task = mExecutePool.getTask(entity.getDownloadUrl());
Task task = mExecutePool.getTask(entity.getDownloadUrl()); if (task == null) {
if (task == null) { task = mCachePool.getTask(entity.getDownloadUrl());
task = mCachePool.getTask(entity.getDownloadUrl());
}
if (task == null){
task = createTask(entity);
}
return task;
} }
if (task == null) {
@Override task = createTask(entity);
public int getTaskState(DownloadEntity entity) {
Task task = getTask(entity);
if (task == null) {
Log.e(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的下载任务");
return -1;
}
return task.getDownloadEntity().getState();
} }
return task;
}
@Override @Override public int getTaskState(DownloadEntity entity) {
public void removeTask(DownloadEntity entity) { Task task = getTask(entity);
Task task = mCachePool.getTask(entity.getDownloadUrl()); if (task == null) {
if (task != null) { Log.e(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的下载任务");
Log.d(TAG, "任务删除" + (mCachePool.removeTask(task) ? "成功" : "失败")); return -1;
} else {
task = mExecutePool.getTask(entity.getDownloadUrl());
}
if (task != null) {
Log.d(TAG, "任务删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
} else {
Log.w(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的任务");
}
} }
return task.getDownloadEntity().getState();
}
@Override @Override public void removeTask(DownloadEntity entity) {
public Task getNextTask() { Task task = mCachePool.getTask(entity.getDownloadUrl());
return mCachePool.pollTask(); if (task != null) {
Log.d(TAG, "任务删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
} else {
task = mExecutePool.getTask(entity.getDownloadUrl());
}
if (task != null) {
Log.d(TAG, "任务删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
} else {
Log.w(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的任务");
} }
}
@Override public Task getNextTask() {
return mCachePool.pollTask();
}
} }

@ -3,7 +3,6 @@ package com.arialyy.downloadutil.core;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.inf.IDownloader; import com.arialyy.downloadutil.core.inf.IDownloader;
import com.arialyy.downloadutil.core.inf.ITask; import com.arialyy.downloadutil.core.inf.ITask;
import com.arialyy.downloadutil.core.pool.CachePool; import com.arialyy.downloadutil.core.pool.CachePool;
@ -15,217 +14,205 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
* 任务下载器提供抽象的方法供具体的实现类操作 * 任务下载器提供抽象的方法供具体的实现类操作
*/ */
public abstract class IDownloadTarget implements IDownloader, ITask { public abstract class IDownloadTarget implements IDownloader, ITask {
/**
* 任务开始
*/
public static final int START = 1;
/**
* 任务停止
*/
public static final int STOP = 2;
/**
* 任务失败
*/
public static final int FAIL = 3;
/**
* 任务取消
*/
public static final int CANCEL = 4;
/**
* 任务完成
*/
public static final int COMPLETE = 5;
protected CachePool mCachePool = CachePool.getInstance();
protected ExecutePool mExecutePool = ExecutePool.getInstance();
protected AutoTaskHandler mTaskHandler;
/**
* 下载失败次数
*/
protected int mFailNum = 10;
/**
* 超时时间
*/
protected long mTimeOut = 10000;
/**
* 下载器任务监听
*/
protected OnTargetListener mTargetListener;
/**
* Target处理任务监听
*/
public interface OnTargetListener {
/** /**
* 任务开始 * 任务开始
*/ */
public static final int START = 1; public void onTaskStart(Task task);
/**
* 任务停止
*/
public static final int STOP = 2;
/**
* 任务失败
*/
public static final int FAIL = 3;
/**
* 任务取消
*/
public static final int CANCEL = 4;
/**
* 任务完成
*/
public static final int COMPLETE = 5;
protected CachePool mCachePool = CachePool.getInstance();
protected ExecutePool mExecutePool = ExecutePool.getInstance();
protected AutoTaskHandler mTaskHandler;
/** /**
* 下载失败次数 * 任务停止
*/ */
protected int mFailNum = 10; public void onTaskStop(Task task);
/** /**
* 超时时间 * 任务取消
*/ */
protected long mTimeOut = 10000; public void onTaskCancel(Task task);
/** /**
* 下载器任务监听 * 任务下载失败
*/ */
protected OnTargetListener mTargetListener; public void onTaskFail(Task task);
/** /**
* Target处理任务监听 * 任务完成
*/ */
public interface OnTargetListener { public void onTaskComplete(Task task);
/** }
* 任务开始
* protected IDownloadTarget() {
* @param task mTaskHandler = new AutoTaskHandler(this);
*/ }
public void onTaskStart(Task task);
/**
/** * 设置下载器监听
* 任务停止 *
* * @param targetListener {@link OnTargetListener}
* @param task */
*/ public void setOnTargetListener(OnTargetListener targetListener) {
public void onTaskStop(Task task); this.mTargetListener = targetListener;
}
/**
* 任务取消 /**
* * 获取当前运行的任务数
* @param task *
*/ * @return 当前正在执行的任务数
public void onTaskCancel(Task task); */
public int getCurrentTaskNum() {
/** return mExecutePool.size();
* 任务下载失败 }
*
* @param task /**
*/ * 获取缓存任务数
public void onTaskFail(Task task); *
* @return 获取缓存的任务数
/** */
* 任务完成 public int getCacheTaskNum() {
* return mCachePool.size();
* @param task }
*/
public void onTaskComplete(Task task); public void setFailNum(int mFailNum) {
this.mFailNum = mFailNum;
}
public void setTimeOut(long timeOut) {
this.mTimeOut = timeOut;
}
/**
* 自动处理任务停止下载失败取消下载自动下载下一个任务的操作
*/
private static class AutoTaskHandler extends Handler {
private static final String TAG = "AutoTaskHandler";
IDownloadTarget target;
public AutoTaskHandler(IDownloadTarget target) {
this.target = target;
} }
protected IDownloadTarget() { @Override public void handleMessage(Message msg) {
mTaskHandler = new AutoTaskHandler(this); super.handleMessage(msg);
DownloadEntity entity = (DownloadEntity) msg.obj;
if (entity == null) {
Log.e(TAG, "请传入下载实体DownloadEntity");
return;
}
switch (msg.what) {
case STOP:
startNextTask(entity);
break;
case CANCEL:
startNextTask(entity);
break;
case COMPLETE:
startNextTask(entity);
break;
case FAIL:
handleFailTask(entity);
break;
}
callback(msg.what, entity);
} }
/** /**
* 设置下载器监听 * 回调
* *
* @param targetListener {@link OnTargetListener} * @param state 状态
* @param entity 下载实体
*/ */
public void setOnTargetListener(OnTargetListener targetListener) { private void callback(int state, DownloadEntity entity) {
this.mTargetListener = targetListener; if (target.mTargetListener != null) {
Task task = target.getTask(entity);
switch (state) {
case START:
target.mTargetListener.onTaskStart(task);
break;
case STOP:
target.mTargetListener.onTaskStop(task);
break;
case CANCEL:
target.mTargetListener.onTaskCancel(task);
break;
case COMPLETE:
target.mTargetListener.onTaskCancel(task);
break;
case FAIL:
target.mTargetListener.onTaskFail(task);
break;
}
}
} }
/** /**
* 获取当前运行的任务数 * 处理下载任务下载失败的情形
* *
* @return 当前正在执行的任务数 * @param entity 失败实体
*/ */
public int getCurrentTaskNum() { private void handleFailTask(DownloadEntity entity) {
return mExecutePool.size(); if (entity.getFailNum() <= target.mFailNum) {
Task task = target.getTask(entity);
target.reTryStart(task);
} else {
startNextTask(entity);
}
} }
/** /**
* 获取缓存任务数 * 启动下一个任务条件任务停止取消下载任务完成
* *
* @return 获取缓存的任务数 * @param entity 通过Handler传递的下载实体
*/ */
public int getCacheTaskNum() { private void startNextTask(DownloadEntity entity) {
return mCachePool.size(); target.removeTask(entity);
} Task newTask = target.getNextTask();
if (newTask == null) {
public void setFailNum(int mFailNum) { Log.e(TAG, "没有下一任务");
this.mFailNum = mFailNum; return;
}
target.startTask(newTask);
} }
}
public void setTimeOut(long timeOut) {
this.mTimeOut = timeOut;
}
/**
* 自动处理任务停止下载失败取消下载自动下载下一个任务的操作
*/
private static class AutoTaskHandler extends Handler {
private static final String TAG = "AutoTaskHandler";
IDownloadTarget target;
public AutoTaskHandler(IDownloadTarget target) {
this.target = target;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
DownloadEntity entity = (DownloadEntity) msg.obj;
if (entity == null) {
Log.e(TAG, "请传入下载实体DownloadEntity");
return;
}
switch (msg.what) {
case STOP:
startNextTask(entity);
break;
case CANCEL:
startNextTask(entity);
break;
case COMPLETE:
startNextTask(entity);
break;
case FAIL:
handleFailTask(entity);
break;
}
callback(msg.what, entity);
}
/**
* 回调
*
* @param state 状态
* @param entity 下载实体
*/
private void callback(int state, DownloadEntity entity) {
if (target.mTargetListener != null) {
Task task = target.getTask(entity);
switch (state) {
case START:
target.mTargetListener.onTaskStart(task);
break;
case STOP:
target.mTargetListener.onTaskStop(task);
break;
case CANCEL:
target.mTargetListener.onTaskCancel(task);
break;
case COMPLETE:
target.mTargetListener.onTaskCancel(task);
break;
case FAIL:
target.mTargetListener.onTaskFail(task);
break;
}
}
}
/**
* 处理下载任务下载失败的情形
*
* @param entity 失败实体
*/
private void handleFailTask(DownloadEntity entity) {
if (entity.getFailNum() <= target.mFailNum) {
Task task = target.getTask(entity);
target.reTryStart(task);
} else {
startNextTask(entity);
}
}
/**
* 启动下一个任务条件任务停止取消下载任务完成
*
* @param entity 通过Handler传递的下载实体
*/
private void startNextTask(DownloadEntity entity) {
target.removeTask(entity);
Task newTask = target.getNextTask();
if (newTask == null) {
Log.e(TAG, "没有下一任务");
return;
}
target.startTask(newTask);
}
}
} }

@ -4,11 +4,9 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.IDownloadListener;
import com.arialyy.downloadutil.util.DownLoadUtil; import com.arialyy.downloadutil.util.DownLoadUtil;
import com.arialyy.downloadutil.util.IDownloadListener;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
/** /**
@ -16,197 +14,189 @@ import java.net.HttpURLConnection;
* 下载任务类 * 下载任务类
*/ */
public class Task { public class Task {
public static final String TAG = "Task"; public static final String TAG = "Task";
private DownloadEntity downloadEntity;
private IDownloadListener listener;
private Handler outHandler;
private Context context;
private DownLoadUtil util;
private Task() {
util = new DownLoadUtil();
}
/**
* 开始下载
*/
public void start() {
if (util.isDownloading()) {
Log.d(TAG, "任务正在下载");
} else {
if (listener == null) {
listener = new DownloadListener(context, downloadEntity, outHandler);
}
util.download(context, downloadEntity.getDownloadUrl(), downloadEntity.getDownloadPath(),
listener);
}
}
public DownloadEntity getDownloadEntity() {
return downloadEntity;
}
/**
* 停止下载
*/
public void stop() {
if (util.isDownloading()) {
util.stopDownload();
}
}
/**
* 获取下载工具
*/
public DownLoadUtil getDownloadUtil() {
return util;
}
/**
* 取消下载
*/
public void cancel() {
util.cancelDownload();
}
/**
* 下载监听类
*/
private static class DownloadListener extends DownLoadUtil.DownloadListener {
Handler outHandler;
Context context;
Intent sendIntent;
long INTERVAL = 1024 * 10; //10k大小的间隔
long lastLen = 0; //上一次发送长度
DownloadEntity downloadEntity;
public DownloadListener(Context context, DownloadEntity downloadEntity, Handler outHandler) {
this.context = context;
this.outHandler = outHandler;
this.downloadEntity = downloadEntity;
sendIntent = new Intent();
sendIntent.addCategory(context.getPackageName());
}
private DownloadEntity downloadEntity; @Override public void onPreDownload(HttpURLConnection connection) {
private IDownloadListener listener; super.onPreDownload(connection);
private Handler outHandler; long len = connection.getContentLength();
private Context context; downloadEntity.setFileSize(len);
private DownLoadUtil util; downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendIntent(DownloadManager.ACTION_PRE, -1);
}
private Task() { @Override public void onResume(long resumeLocation) {
util = new DownLoadUtil(); super.onResume(resumeLocation);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendIntent(DownloadManager.ACTION_RESUME, resumeLocation);
} }
/** @Override public void onStart(long startLocation) {
* 开始下载 super.onStart(startLocation);
*/ downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
public void start() { sendInState2Target(IDownloadTarget.START);
if (util.isDownloading()) { sendIntent(DownloadManager.ACTION_START, startLocation);
Log.d(TAG, "任务正在下载");
} else {
if (listener == null) {
listener = new DownloadListener(context, downloadEntity, outHandler);
}
util.download(context, downloadEntity.getDownloadUrl(), downloadEntity.getDownloadPath(), listener);
}
} }
public DownloadEntity getDownloadEntity() { @Override public void onProgress(long currentLocation) {
return downloadEntity; super.onProgress(currentLocation);
if (currentLocation - lastLen > INTERVAL) { //不要太过于频繁发送广播
sendIntent.putExtra(DownloadManager.ACTION_RUNNING, currentLocation);
lastLen = currentLocation;
}
} }
/** @Override public void onStop(long stopLocation) {
* 停止下载 super.onStop(stopLocation);
*/ downloadEntity.setState(DownloadEntity.STATE_STOP);
public void stop() { sendInState2Target(IDownloadTarget.STOP);
if (util.isDownloading()) { sendIntent(DownloadManager.ACTION_STOP, stopLocation);
util.stopDownload();
}
} }
/** @Override public void onCancel() {
* 获取下载工具 super.onCancel();
*/ downloadEntity.setState(DownloadEntity.STATE_CANCEL);
public DownLoadUtil getDownloadUtil() { sendInState2Target(IDownloadTarget.CANCEL);
return util; sendIntent(DownloadManager.ACTION_CANCEL, -1);
downloadEntity.deleteData();
} }
/** @Override public void onComplete() {
* 取消下载 super.onComplete();
*/ downloadEntity.setState(DownloadEntity.STATE_COMPLETE);
public void cancel() { downloadEntity.setDownloadComplete(true);
util.cancelDownload(); sendInState2Target(IDownloadTarget.COMPLETE);
sendIntent(DownloadManager.ACTION_COMPLETE, -1);
}
@Override public void onFail() {
super.onFail();
downloadEntity.setState(DownloadEntity.STATE_FAIL);
sendInState2Target(IDownloadTarget.FAIL);
sendIntent(DownloadManager.ACTION_FAIL, -1);
} }
/** /**
* 下载监听类 * 将任务状态发送给下载器
*
* @param state {@link IDownloadTarget#START}
*/ */
private static class DownloadListener extends DownLoadUtil.DownloadListener { private void sendInState2Target(int state) {
Handler outHandler; if (outHandler != null) {
Context context; outHandler.obtainMessage(state, downloadEntity).sendToTarget();
Intent sendIntent; }
long INTERVAL = 1024 * 10; //10k大小的间隔 }
long lastLen = 0; //上一次发送长度
DownloadEntity downloadEntity; private void sendIntent(String action, long location) {
downloadEntity.save();
public DownloadListener(Context context, DownloadEntity downloadEntity, Handler outHandler) { Intent intent = new Intent();
this.context = context; intent.addCategory(context.getPackageName());
this.outHandler = outHandler; intent.putExtra(action, downloadEntity);
this.downloadEntity = downloadEntity; if (location != -1) {
sendIntent = new Intent(); intent.putExtra(DownloadManager.CURRENT_LOCATION, location);
sendIntent.addCategory(context.getPackageName()); }
} context.sendBroadcast(intent);
}
@Override }
public void onPreDownload(HttpURLConnection connection) {
super.onPreDownload(connection); public static class Builder {
long len = connection.getContentLength(); DownloadEntity downloadEntity;
downloadEntity.setFileSize(len); IDownloadListener listener;
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING); Handler outHandler;
sendIntent(DownloadManager.ACTION_PRE, -1); Context context;
}
public Builder(Context context, DownloadEntity downloadEntity) {
@Override this.context = context;
public void onResume(long resumeLocation) { this.downloadEntity = downloadEntity;
super.onResume(resumeLocation); }
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendIntent(DownloadManager.ACTION_RESUME, resumeLocation); public Builder setDownloadListener(IDownloadListener listener) {
} this.listener = listener;
return this;
@Override
public void onStart(long startLocation) {
super.onStart(startLocation);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendInState2Target(IDownloadTarget.START);
sendIntent(DownloadManager.ACTION_START, startLocation);
}
@Override
public void onProgress(long currentLocation) {
super.onProgress(currentLocation);
if (currentLocation - lastLen > INTERVAL) { //不要太过于频繁发送广播
sendIntent.putExtra(DownloadManager.ACTION_RUNNING, currentLocation);
lastLen = currentLocation;
}
}
@Override
public void onStop(long stopLocation) {
super.onStop(stopLocation);
downloadEntity.setState(DownloadEntity.STATE_STOP);
sendInState2Target(IDownloadTarget.STOP);
sendIntent(DownloadManager.ACTION_STOP, stopLocation);
}
@Override
public void onCancel() {
super.onCancel();
downloadEntity.setState(DownloadEntity.STATE_CANCEL);
sendInState2Target(IDownloadTarget.CANCEL);
sendIntent(DownloadManager.ACTION_CANCEL, -1);
downloadEntity.deleteData();
}
@Override
public void onComplete() {
super.onComplete();
downloadEntity.setState(DownloadEntity.STATE_COMPLETE);
downloadEntity.setDownloadComplete(true);
sendInState2Target(IDownloadTarget.COMPLETE);
sendIntent(DownloadManager.ACTION_COMPLETE, -1);
}
@Override
public void onFail() {
super.onFail();
downloadEntity.setState(DownloadEntity.STATE_FAIL);
sendInState2Target(IDownloadTarget.FAIL);
sendIntent(DownloadManager.ACTION_FAIL, -1);
}
/**
* 将任务状态发送给下载器
*
* @param state {@link IDownloadTarget#START}
*/
private void sendInState2Target(int state) {
if (outHandler != null) {
outHandler.obtainMessage(state, downloadEntity).sendToTarget();
}
}
private void sendIntent(String action, long location) {
downloadEntity.save();
Intent intent = new Intent();
intent.addCategory(context.getPackageName());
intent.putExtra(action, downloadEntity);
if (location != -1) {
intent.putExtra(DownloadManager.CURRENT_LOCATION, location);
}
context.sendBroadcast(intent);
}
}
public static class Builder {
DownloadEntity downloadEntity;
IDownloadListener listener;
Handler outHandler;
Context context;
public Builder(Context context, DownloadEntity downloadEntity) {
this.context = context;
this.downloadEntity = downloadEntity;
}
public Builder setDownloadListener(IDownloadListener listener) {
this.listener = listener;
return this;
}
public Builder setOutHandler(Handler outHandler) {
this.outHandler = outHandler;
return this;
}
public Task builder() {
Task task = new Task();
task.context = context;
task.downloadEntity = downloadEntity;
task.listener = listener;
task.outHandler = outHandler;
return task;
}
} }
public Builder setOutHandler(Handler outHandler) {
this.outHandler = outHandler;
return this;
}
public Task builder() {
Task task = new Task();
task.context = context;
task.downloadEntity = downloadEntity;
task.listener = listener;
task.outHandler = outHandler;
return task;
}
}
} }

@ -5,5 +5,5 @@ package com.arialyy.downloadutil.core;
* 创建任务类型 * 创建任务类型
*/ */
public enum TaskEnum { public enum TaskEnum {
ORDINARY, NO_USR_CALLBACK ORDINARY, NO_USR_CALLBACK
} }

@ -2,7 +2,6 @@ package com.arialyy.downloadutil.core;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
/** /**
@ -10,35 +9,33 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
* 任务工厂 * 任务工厂
*/ */
public class TaskFactory { public class TaskFactory {
private static final String TAG = "TaskFactory"; private static final String TAG = "TaskFactory";
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private static volatile TaskFactory INSTANCE = null; private static volatile TaskFactory INSTANCE = null;
private TaskFactory() { private TaskFactory() {
} }
public static TaskFactory getInstance() { public static TaskFactory getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (LOCK) { synchronized (LOCK) {
INSTANCE = new TaskFactory(); INSTANCE = new TaskFactory();
} }
}
return INSTANCE;
} }
return INSTANCE;
/** }
* 创建普通下载任务
* @param context /**
* @param entity 下载实体 * 创建普通下载任务
* @param handler {@link com.arialyy.downloadutil.core.IDownloadTarget.AutoTaskHandler} *
* @return * @param entity 下载实体
*/ * @param handler {@link com.arialyy.downloadutil.core.IDownloadTarget.AutoTaskHandler}
public Task createTask(Context context, DownloadEntity entity, Handler handler) { */
Task.Builder builder = new Task.Builder(context, entity); public Task createTask(Context context, DownloadEntity entity, Handler handler) {
builder.setOutHandler(handler); Task.Builder builder = new Task.Builder(context, entity);
return builder.builder(); builder.setOutHandler(handler);
} return builder.builder();
}
} }

@ -9,12 +9,11 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
*/ */
class AddCommand extends IDownloadCommand { class AddCommand extends IDownloadCommand {
AddCommand(Context context, DownloadEntity entity) { AddCommand(Context context, DownloadEntity entity) {
super(context, entity); super(context, entity);
} }
@Override @Override public void executeComment() {
public void executeComment() { target.createTask(mEntity);
target.createTask(mEntity); }
}
} }

@ -1,54 +1,48 @@
package com.arialyy.downloadutil.core.command; package com.arialyy.downloadutil.core.command;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull;
import com.arialyy.downloadutil.core.DownloadTarget; import com.arialyy.downloadutil.core.DownloadTarget;
import com.arialyy.downloadutil.core.IDownloadTarget; import com.arialyy.downloadutil.core.IDownloadTarget;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.help.CheckHelp; import com.arialyy.downloadutil.help.CheckHelp;
import java.util.List;
/** /**
* Created by lyy on 2016/8/22. * Created by lyy on 2016/8/22.
* 下载命令 * 下载命令
*/ */
public abstract class IDownloadCommand { public abstract class IDownloadCommand {
protected IDownloadTarget target; protected IDownloadTarget target;
protected Context mContext; protected Context mContext;
protected DownloadEntity mEntity; protected DownloadEntity mEntity;
/** /**
* @param context context * @param context context
* @param entity 下载实体 * @param entity 下载实体
*/ */
protected IDownloadCommand(Context context, DownloadEntity entity){ protected IDownloadCommand(Context context, DownloadEntity entity) {
if (!CheckHelp.checkDownloadEntity(entity)){ if (!CheckHelp.checkDownloadEntity(entity)) {
return; return;
}
target = DownloadTarget.getInstance(context);
mContext = context;
mEntity = entity;
}
public Context getContext(){
return mContext;
} }
target = DownloadTarget.getInstance(context);
/** mContext = context;
* 执行命令 mEntity = entity;
*/ }
public abstract void executeComment();
public Context getContext() {
/** return mContext;
* 设置下载器 }
*
* @param downloadTarget {@link IDownloadTarget} /**
*/ * 执行命令
public void setDownloadTarget(IDownloadTarget downloadTarget) { */
target = downloadTarget; public abstract void executeComment();
}
/**
* 设置下载器
*
* @param downloadTarget {@link IDownloadTarget}
*/
public void setDownloadTarget(IDownloadTarget downloadTarget) {
target = downloadTarget;
}
} }

@ -7,14 +7,13 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
* Created by lyy on 2016/8/22. * Created by lyy on 2016/8/22.
* 开始命令 * 开始命令
*/ */
class StartCommand extends IDownloadCommand{ class StartCommand extends IDownloadCommand {
StartCommand(Context context, DownloadEntity entity) { StartCommand(Context context, DownloadEntity entity) {
super(context, entity); super(context, entity);
} }
@Override @Override public void executeComment() {
public void executeComment() { target.startTask(target.getTask(mEntity));
target.startTask(target.getTask(mEntity)); }
}
} }

@ -7,32 +7,31 @@ import com.arialyy.downloadutil.core.Task;
* 下载功能接口 * 下载功能接口
*/ */
public interface IDownloader { public interface IDownloader {
/** /**
* 开始任务 * 开始任务
* *
* @param task {@link Task} * @param task {@link Task}
*/ */
public void startTask(Task task); public void startTask(Task task);
/** /**
* 停止任务 * 停止任务
* *
* @param task {@link Task} * @param task {@link Task}
*/ */
public void stopTask(Task task); public void stopTask(Task task);
/** /**
* 取消任务 * 取消任务
* *
* @param task {@link Task} * @param task {@link Task}
*/ */
public void cancelTask(Task task); public void cancelTask(Task task);
/**
* 重试下载
*
* @param task {@link Task}
*/
public void reTryStart(Task task);
/**
* 重试下载
*
* @param task {@link Task}
*/
public void reTryStart(Task task);
} }

@ -7,48 +7,46 @@ import com.arialyy.downloadutil.core.Task;
* 任务池 * 任务池
*/ */
public interface IPool { public interface IPool {
/** /**
* 将下载任务添加到任务池中 * 将下载任务添加到任务池中
* */
* @param task public boolean putTask(Task task);
*/
public boolean putTask(Task task);
/** /**
* 按照队列原则取出下载任务 * 按照队列原则取出下载任务
* *
* @return 返回null或者下载任务 * @return 返回null或者下载任务
*/ */
public Task pollTask(); public Task pollTask();
/** /**
* 通过下载链接获取下载任务当任务不为空时队列将删除该下载任务 * 通过下载链接获取下载任务当任务不为空时队列将删除该下载任务
* *
* @param downloadUrl 下载链接 * @param downloadUrl 下载链接
* @return 返回null或者下载任务 * @return 返回null或者下载任务
*/ */
public Task getTask(String downloadUrl); public Task getTask(String downloadUrl);
/** /**
* 删除任务池中的下载任务 * 删除任务池中的下载任务
* *
* @param task 下载任务 * @param task 下载任务
* @return true:移除成功 * @return true:移除成功
*/ */
public boolean removeTask(Task task); public boolean removeTask(Task task);
/** /**
* 通过下载链接移除下载任务 * 通过下载链接移除下载任务
* *
* @param downloadUrl 下载链接 * @param downloadUrl 下载链接
* @return true:移除成功 * @return true:移除成功
*/ */
public boolean removeTask(String downloadUrl); public boolean removeTask(String downloadUrl);
/** /**
* 池子大小 * 池子大小
* *
* @return 返回缓存池或者当前任务池大小 * @return 返回缓存池或者当前任务池大小
*/ */
public int size(); public int size();
} }

@ -9,41 +9,41 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
*/ */
public interface ITask { public interface ITask {
/** /**
* 创建一个新的下载任务创建时只是将新任务存储到缓存池 * 创建一个新的下载任务创建时只是将新任务存储到缓存池
* *
* @param entity 下载实体{@link DownloadEntity} * @param entity 下载实体{@link DownloadEntity}
* @return {@link Task} * @return {@link Task}
*/ */
public Task createTask(DownloadEntity entity); public Task createTask(DownloadEntity entity);
/** /**
* 通过下载链接从缓存池或任务池搜索下载任务如果缓存池或任务池都没有任务则创建新任务 * 通过下载链接从缓存池或任务池搜索下载任务如果缓存池或任务池都没有任务则创建新任务
* *
* @param entity 下载实体{@link DownloadEntity} * @param entity 下载实体{@link DownloadEntity}
* @return {@link Task} * @return {@link Task}
*/ */
public Task getTask(DownloadEntity entity); public Task getTask(DownloadEntity entity);
/** /**
* 通过下载链接搜索下载任务 * 通过下载链接搜索下载任务
* *
* @param entity 下载实体{@link DownloadEntity} * @param entity 下载实体{@link DownloadEntity}
* @return {@code -1 ==> 错误}{@link com.arialyy.downloadutil.entity.DownloadEntity#STATE_FAIL} * @return {@code -1 ==> 错误}{@link com.arialyy.downloadutil.entity.DownloadEntity#STATE_FAIL}
*/ */
public int getTaskState(DownloadEntity entity); public int getTaskState(DownloadEntity entity);
/** /**
* 通过下载链接删除任务 * 通过下载链接删除任务
* @param entity 下载实体{@link DownloadEntity} *
*/ * @param entity 下载实体{@link DownloadEntity}
public void removeTask(DownloadEntity entity); */
public void removeTask(DownloadEntity entity);
/**
* 获取缓存池的下一个任务 /**
* * 获取缓存池的下一个任务
* @return 下载任务 or null *
*/ * @return 下载任务 or null
public Task getNextTask(); */
public Task getNextTask();
} }

@ -2,11 +2,9 @@ package com.arialyy.downloadutil.core.pool;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.Task; import com.arialyy.downloadutil.core.Task;
import com.arialyy.downloadutil.core.inf.IPool; import com.arialyy.downloadutil.core.inf.IPool;
import com.arialyy.downloadutil.util.Util; import com.arialyy.downloadutil.util.Util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.PriorityQueue; import java.util.PriorityQueue;
@ -17,102 +15,96 @@ import java.util.Queue;
* 任务缓存池所有下载任务最先缓存在这个池中 * 任务缓存池所有下载任务最先缓存在这个池中
*/ */
public class CachePool implements IPool { public class CachePool implements IPool {
private static final String TAG = "CachePool"; private static final String TAG = "CachePool";
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private static volatile CachePool INSTANCE = null; private static volatile CachePool INSTANCE = null;
private Map<String, Task> mCacheArray; private Map<String, Task> mCacheArray;
private Queue<Task> mCacheQueue; private Queue<Task> mCacheQueue;
public static CachePool getInstance() { public static CachePool getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (LOCK) { synchronized (LOCK) {
INSTANCE = new CachePool(); INSTANCE = new CachePool();
} }
}
return INSTANCE;
} }
return INSTANCE;
}
private CachePool() { private CachePool() {
mCacheQueue = new PriorityQueue<>(); mCacheQueue = new PriorityQueue<>();
mCacheArray = new HashMap<>(); mCacheArray = new HashMap<>();
} }
@Override @Override public boolean putTask(Task task) {
public boolean putTask(Task task) { synchronized (LOCK) {
synchronized (LOCK) { if (task == null) {
if (task == null) { Log.e(TAG, "下载任务不能为空!!");
Log.e(TAG, "下载任务不能为空!!"); return false;
return false; }
} String url = task.getDownloadEntity().getDownloadUrl();
String url = task.getDownloadEntity().getDownloadUrl(); if (mCacheQueue.contains(task)) {
if (mCacheQueue.contains(task)) { Log.e(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】");
Log.e(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】"); return false;
return false; } else {
} else { boolean s = mCacheQueue.offer(task);
boolean s = mCacheQueue.offer(task); Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】"));
Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】")); if (s) {
if (s) { mCacheArray.put(Util.keyToHashKey(url), task);
mCacheArray.put(Util.keyToHashKey(url), task);
}
return s;
}
} }
return s;
}
} }
}
@Override @Override public Task pollTask() {
public Task pollTask() { synchronized (LOCK) {
synchronized (LOCK) { Task task = mCacheQueue.poll();
Task task = mCacheQueue.poll(); if (task != null) {
if (task != null) { String url = task.getDownloadEntity().getDownloadUrl();
String url = task.getDownloadEntity().getDownloadUrl(); mCacheArray.remove(Util.keyToHashKey(url));
mCacheArray.remove(Util.keyToHashKey(url)); }
} return task;
return task;
}
} }
}
@Override @Override public Task getTask(String downloadUrl) {
public Task getTask(String downloadUrl) { synchronized (LOCK) {
synchronized (LOCK) { if (TextUtils.isEmpty(downloadUrl)) {
if (TextUtils.isEmpty(downloadUrl)) { Log.e(TAG, "请传入有效的下载链接");
Log.e(TAG, "请传入有效的下载链接"); return null;
return null; }
} String key = Util.keyToHashKey(downloadUrl);
String key = Util.keyToHashKey(downloadUrl); return mCacheArray.get(key);
return mCacheArray.get(key);
}
} }
}
@Override @Override public boolean removeTask(Task task) {
public boolean removeTask(Task task) { synchronized (LOCK) {
synchronized (LOCK) { if (task == null) {
if (task == null) { Log.e(TAG, "任务不能为空");
Log.e(TAG, "任务不能为空"); return false;
return false; } else {
} else { String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl());
String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl()); mCacheArray.remove(key);
mCacheArray.remove(key); return mCacheQueue.remove(task);
return mCacheQueue.remove(task); }
}
}
} }
}
@Override @Override public boolean removeTask(String downloadUrl) {
public boolean removeTask(String downloadUrl) { synchronized (LOCK) {
synchronized (LOCK) { if (TextUtils.isEmpty(downloadUrl)) {
if (TextUtils.isEmpty(downloadUrl)) { Log.e(TAG, "请传入有效的下载链接");
Log.e(TAG, "请传入有效的下载链接"); return false;
return false; }
} String key = Util.keyToHashKey(downloadUrl);
String key = Util.keyToHashKey(downloadUrl); Task task = mCacheArray.get(key);
Task task = mCacheArray.get(key); mCacheArray.remove(key);
mCacheArray.remove(key); return mCacheQueue.remove(task);
return mCacheQueue.remove(task);
}
} }
}
@Override @Override public int size() {
public int size() { return mCacheQueue.size();
return mCacheQueue.size(); }
}
} }

@ -2,11 +2,9 @@ package com.arialyy.downloadutil.core.pool;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.Task; import com.arialyy.downloadutil.core.Task;
import com.arialyy.downloadutil.core.inf.IPool; import com.arialyy.downloadutil.core.inf.IPool;
import com.arialyy.downloadutil.util.Util; import com.arialyy.downloadutil.util.Util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
@ -17,144 +15,137 @@ import java.util.concurrent.TimeUnit;
* 任务执行池所有当前下载任务都该任务池中默认下载大小为2 * 任务执行池所有当前下载任务都该任务池中默认下载大小为2
*/ */
public class ExecutePool implements IPool { public class ExecutePool implements IPool {
private static final String TAG = "ExecutePool"; private static final String TAG = "ExecutePool";
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private static final long TIME_OUT = 1000; private static final long TIME_OUT = 1000;
private static volatile ExecutePool INSTANCE = null; private static volatile ExecutePool INSTANCE = null;
private static int SIZE = 2; private static int SIZE = 2;
private ArrayBlockingQueue<Task> mExecuteQueue; private ArrayBlockingQueue<Task> mExecuteQueue;
private Map<String, Task> mExecuteArray; private Map<String, Task> mExecuteArray;
public static ExecutePool getInstance() { public static ExecutePool getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (LOCK) { synchronized (LOCK) {
INSTANCE = new ExecutePool(); INSTANCE = new ExecutePool();
} }
}
return INSTANCE;
} }
return INSTANCE;
}
private ExecutePool() { private ExecutePool() {
mExecuteQueue = new ArrayBlockingQueue<>(SIZE); mExecuteQueue = new ArrayBlockingQueue<>(SIZE);
mExecuteArray = new HashMap<>(); mExecuteArray = new HashMap<>();
} }
@Override @Override public boolean putTask(Task task) {
public boolean putTask(Task task) { synchronized (LOCK) {
synchronized (LOCK) { if (task == null) {
if (task == null) { Log.e(TAG, "下载任务不能为空!!");
Log.e(TAG, "下载任务不能为空!!");
return false;
}
String url = task.getDownloadEntity().getDownloadUrl();
if (mExecuteQueue.contains(task)) {
Log.e(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】");
return false;
} else {
if (mExecuteQueue.size() >= SIZE) {
if (pollFirstTask()) {
return putNewTask(task);
}
} else {
return putNewTask(task);
}
}
}
return false; return false;
} }
String url = task.getDownloadEntity().getDownloadUrl();
/** if (mExecuteQueue.contains(task)) {
* 添加新任务 Log.e(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】");
* return false;
* @param newTask 新下载任务 } else {
*/ if (mExecuteQueue.size() >= SIZE) {
private boolean putNewTask(Task newTask) { if (pollFirstTask()) {
String url = newTask.getDownloadEntity().getDownloadUrl(); return putNewTask(task);
boolean s = mExecuteQueue.offer(newTask); }
Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】")); } else {
if (s) { return putNewTask(task);
newTask.start();
mExecuteArray.put(Util.keyToHashKey(url), newTask);
} }
return s; }
} }
return false;
}
/** /**
* 队列满时将移除下载队列中的第一个任务 * 添加新任务
*/ *
private boolean pollFirstTask() { * @param newTask 新下载任务
try { */
Task oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS); private boolean putNewTask(Task newTask) {
if (oldTask == null) { String url = newTask.getDownloadEntity().getDownloadUrl();
Log.e(TAG, "移除任务失败"); boolean s = mExecuteQueue.offer(newTask);
return false; Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】"));
} if (s) {
oldTask.stop(); newTask.start();
wait(200); mExecuteArray.put(Util.keyToHashKey(url), newTask);
String key = Util.keyToHashKey(oldTask.getDownloadEntity().getDownloadUrl());
mExecuteArray.remove(key);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
return true;
} }
return s;
}
@Override /**
public Task pollTask() { * 队列满时将移除下载队列中的第一个任务
synchronized (LOCK) { */
Task task = mExecuteQueue.poll(); private boolean pollFirstTask() {
if (task != null) { try {
String url = task.getDownloadEntity().getDownloadUrl(); Task oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
mExecuteArray.remove(Util.keyToHashKey(url)); if (oldTask == null) {
} Log.e(TAG, "移除任务失败");
return task; return false;
} }
oldTask.stop();
wait(200);
String key = Util.keyToHashKey(oldTask.getDownloadEntity().getDownloadUrl());
mExecuteArray.remove(key);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
} }
return true;
}
@Override @Override public Task pollTask() {
public Task getTask(String downloadUrl) { synchronized (LOCK) {
synchronized (LOCK) { Task task = mExecuteQueue.poll();
if (TextUtils.isEmpty(downloadUrl)) { if (task != null) {
Log.e(TAG, "请传入有效的下载链接"); String url = task.getDownloadEntity().getDownloadUrl();
return null; mExecuteArray.remove(Util.keyToHashKey(url));
} }
String key = Util.keyToHashKey(downloadUrl); return task;
return mExecuteArray.get(key);
}
} }
}
@Override @Override public Task getTask(String downloadUrl) {
public boolean removeTask(Task task) { synchronized (LOCK) {
synchronized (LOCK) { if (TextUtils.isEmpty(downloadUrl)) {
if (task == null) { Log.e(TAG, "请传入有效的下载链接");
Log.e(TAG, "任务不能为空"); return null;
return false; }
} else { String key = Util.keyToHashKey(downloadUrl);
String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl()); return mExecuteArray.get(key);
mExecuteArray.remove(key);
return mExecuteQueue.remove(task);
}
}
} }
}
@Override @Override public boolean removeTask(Task task) {
public boolean removeTask(String downloadUrl) { synchronized (LOCK) {
synchronized (LOCK) { if (task == null) {
if (TextUtils.isEmpty(downloadUrl)) { Log.e(TAG, "任务不能为空");
Log.e(TAG, "请传入有效的下载链接"); return false;
return false; } else {
} String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl());
String key = Util.keyToHashKey(downloadUrl); mExecuteArray.remove(key);
Task task = mExecuteArray.get(key); return mExecuteQueue.remove(task);
mExecuteArray.remove(key); }
return mExecuteQueue.remove(task);
}
} }
}
@Override @Override public boolean removeTask(String downloadUrl) {
public int size() { synchronized (LOCK) {
return mExecuteQueue.size(); if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接");
return false;
}
String key = Util.keyToHashKey(downloadUrl);
Task task = mExecuteArray.get(key);
mExecuteArray.remove(key);
return mExecuteQueue.remove(task);
} }
}
@Override public int size() {
return mExecuteQueue.size();
}
} }

@ -2,7 +2,6 @@ package com.arialyy.downloadutil.entity;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import com.arialyy.downloadutil.orm.DbEntity; import com.arialyy.downloadutil.orm.DbEntity;
/** /**
@ -10,186 +9,179 @@ import com.arialyy.downloadutil.orm.DbEntity;
* 下载实体 * 下载实体
*/ */
public class DownloadEntity extends DbEntity implements Parcelable, Cloneable { public class DownloadEntity extends DbEntity implements Parcelable, Cloneable {
/** /**
* 其它状态 * 其它状态
*/ */
public static final int STATE_OTHER = -1; public static final int STATE_OTHER = -1;
/** /**
* 失败状态 * 失败状态
*/ */
public static final int STATE_FAIL = 0; public static final int STATE_FAIL = 0;
/** /**
* 完成状态 * 完成状态
*/ */
public static final int STATE_COMPLETE = 1; public static final int STATE_COMPLETE = 1;
/** /**
* 停止状态 * 停止状态
*/ */
public static final int STATE_STOP = 2; public static final int STATE_STOP = 2;
/** /**
* 未开始状态 * 未开始状态
*/ */
public static final int STATE_WAIT = 3; public static final int STATE_WAIT = 3;
/** /**
* 下载中 * 下载中
*/ */
public static final int STATE_DOWNLOAD_ING = 4; public static final int STATE_DOWNLOAD_ING = 4;
/** /**
* 取消下载 * 取消下载
*/ */
public static final int STATE_CANCEL = 5; public static final int STATE_CANCEL = 5;
private String downloadUrl; //下载路径 private String downloadUrl; //下载路径
private String downloadPath; //保存路径 private String downloadPath; //保存路径
private String fileName; //文件名 private String fileName; //文件名
private String str; //其它字段 private String str; //其它字段
private long completeTime; //完成时间 private long completeTime; //完成时间
private long fileSize = 1; private long fileSize = 1;
private int state = STATE_WAIT; private int state = STATE_WAIT;
private boolean isDownloadComplete = false; //是否下载完成 private boolean isDownloadComplete = false; //是否下载完成
private long currentProgress = 0; //当前下载进度 private long currentProgress = 0; //当前下载进度
private int failNum = 0; private int failNum = 0;
public String getStr() { public String getStr() {
return str; return str;
} }
public void setStr(String str) { public void setStr(String str) {
this.str = str; this.str = str;
} }
public String getFileName() { public String getFileName() {
return fileName; return fileName;
} }
public void setFileName(String fileName) { public void setFileName(String fileName) {
this.fileName = fileName; this.fileName = fileName;
} }
public int getFailNum() { public int getFailNum() {
return failNum; return failNum;
} }
public void setFailNum(int failNum) { public void setFailNum(int failNum) {
this.failNum = failNum; this.failNum = failNum;
} }
public String getDownloadUrl() { public String getDownloadUrl() {
return downloadUrl; return downloadUrl;
} }
public long getCompleteTime() { public long getCompleteTime() {
return completeTime; return completeTime;
} }
public void setCompleteTime(long completeTime) { public void setCompleteTime(long completeTime) {
this.completeTime = completeTime; this.completeTime = completeTime;
} }
public void setDownloadUrl(String downloadUrl) { public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl; this.downloadUrl = downloadUrl;
} }
public String getDownloadPath() { public String getDownloadPath() {
return downloadPath; return downloadPath;
} }
public void setDownloadPath(String downloadPath) { public void setDownloadPath(String downloadPath) {
this.downloadPath = downloadPath; this.downloadPath = downloadPath;
} }
public long getFileSize() { public long getFileSize() {
return fileSize; return fileSize;
} }
public void setFileSize(long fileSize) { public void setFileSize(long fileSize) {
this.fileSize = fileSize; this.fileSize = fileSize;
} }
public int getState() { public int getState() {
return state; return state;
} }
public void setState(int state) { public void setState(int state) {
this.state = state; this.state = state;
} }
public boolean isDownloadComplete() { public boolean isDownloadComplete() {
return isDownloadComplete; return isDownloadComplete;
} }
public void setDownloadComplete(boolean downloadComplete) { public void setDownloadComplete(boolean downloadComplete) {
isDownloadComplete = downloadComplete; isDownloadComplete = downloadComplete;
} }
public long getCurrentProgress() { public long getCurrentProgress() {
return currentProgress; return currentProgress;
} }
public void setCurrentProgress(long currentProgress) { public void setCurrentProgress(long currentProgress) {
this.currentProgress = currentProgress; this.currentProgress = currentProgress;
} }
@Override @Override public DownloadEntity clone() throws CloneNotSupportedException {
public DownloadEntity clone() throws CloneNotSupportedException { return (DownloadEntity) super.clone();
return (DownloadEntity) super.clone(); }
}
public DownloadEntity() {
}
public DownloadEntity() {
} @Override public int describeContents() {
return 0;
@Override }
public int describeContents() {
return 0; @Override public void writeToParcel(Parcel dest, int flags) {
} dest.writeString(this.downloadUrl);
dest.writeString(this.downloadPath);
@Override dest.writeLong(this.completeTime);
public void writeToParcel(Parcel dest, int flags) { dest.writeLong(this.fileSize);
dest.writeString(this.downloadUrl); dest.writeInt(this.state);
dest.writeString(this.downloadPath); dest.writeByte(this.isDownloadComplete ? (byte) 1 : (byte) 0);
dest.writeLong(this.completeTime); dest.writeLong(this.currentProgress);
dest.writeLong(this.fileSize); dest.writeInt(this.failNum);
dest.writeInt(this.state); }
dest.writeByte(this.isDownloadComplete ? (byte) 1 : (byte) 0);
dest.writeLong(this.currentProgress); protected DownloadEntity(Parcel in) {
dest.writeInt(this.failNum); this.downloadUrl = in.readString();
} this.downloadPath = in.readString();
this.completeTime = in.readLong();
protected DownloadEntity(Parcel in) { this.fileSize = in.readLong();
this.downloadUrl = in.readString(); this.state = in.readInt();
this.downloadPath = in.readString(); this.isDownloadComplete = in.readByte() != 0;
this.completeTime = in.readLong(); this.currentProgress = in.readLong();
this.fileSize = in.readLong(); this.failNum = in.readInt();
this.state = in.readInt(); }
this.isDownloadComplete = in.readByte() != 0;
this.currentProgress = in.readLong(); public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
this.failNum = in.readInt(); @Override public DownloadEntity createFromParcel(Parcel source) {
} return new DownloadEntity(source);
}
public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
@Override @Override public DownloadEntity[] newArray(int size) {
public DownloadEntity createFromParcel(Parcel source) { return new DownloadEntity[size];
return new DownloadEntity(source); }
} };
@Override @Override public String toString() {
public DownloadEntity[] newArray(int size) { return "DownloadEntity{" +
return new DownloadEntity[size]; "downloadUrl='" + downloadUrl + '\'' +
} ", downloadPath='" + downloadPath + '\'' +
}; ", completeTime=" + completeTime +
", fileSize=" + fileSize +
@Override ", state=" + state +
public String toString() { ", isDownloadComplete=" + isDownloadComplete +
return "DownloadEntity{" + ", currentProgress=" + currentProgress +
"downloadUrl='" + downloadUrl + '\'' + ", failNum=" + failNum +
", downloadPath='" + downloadPath + '\'' + '}';
", completeTime=" + completeTime + }
", fileSize=" + fileSize +
", state=" + state +
", isDownloadComplete=" + isDownloadComplete +
", currentProgress=" + currentProgress +
", failNum=" + failNum +
'}';
}
} }

@ -1,6 +1,5 @@
package com.arialyy.downloadutil.help; package com.arialyy.downloadutil.help;
import android.app.Application;
import android.content.res.Resources; import android.content.res.Resources;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@ -28,20 +27,20 @@ public class CheckHelp {
} else if (TextUtils.isEmpty(entity.getDownloadUrl())) { } else if (TextUtils.isEmpty(entity.getDownloadUrl())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_url_null)); Log.w(TAG, Resources.getSystem().getString(R.string.error_download_url_null));
return false; return false;
} else if (TextUtils.isEmpty(entity.getFileName())){ } else if (TextUtils.isEmpty(entity.getFileName())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_file_name_null)); Log.w(TAG, Resources.getSystem().getString(R.string.error_file_name_null));
return false; return false;
} else if (TextUtils.isEmpty(entity.getDownloadPath())){ } else if (TextUtils.isEmpty(entity.getDownloadPath())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_file_name_null)); Log.w(TAG, Resources.getSystem().getString(R.string.error_file_name_null));
return false; return false;
} }
String fileName = entity.getFileName(); String fileName = entity.getFileName();
if (fileName.contains(" ")){ if (fileName.contains(" ")) {
fileName = fileName.replace(" ", "_"); fileName = fileName.replace(" ", "_");
} }
String dPath = entity.getDownloadPath(); String dPath = entity.getDownloadPath();
File file = new File(dPath); File file = new File(dPath);
if (file.isDirectory()){ if (file.isDirectory()) {
dPath += fileName; dPath += fileName;
entity.setDownloadPath(dPath); entity.setDownloadPath(dPath);
} }

@ -4,10 +4,7 @@ import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import com.arialyy.downloadutil.util.Util; import com.arialyy.downloadutil.util.Util;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -20,176 +17,176 @@ import java.util.List;
* 所有数据库实体父类 * 所有数据库实体父类
*/ */
public class DbEntity { public class DbEntity {
private static final String TAG = "DbEntity"; private static final String TAG = "DbEntity";
private volatile static SQLiteDatabase mDb = null; private volatile static SQLiteDatabase mDb = null;
private volatile static DbUtil mUtil; private volatile static DbUtil mUtil;
private Context mContext; private Context mContext;
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
protected int rowID = -1; protected int rowID = -1;
protected DbEntity() { protected DbEntity() {
} }
public DbEntity(Context context) { public DbEntity(Context context) {
this(context, true); this(context, true);
} }
public DbEntity(Context context, boolean newTable) { public DbEntity(Context context, boolean newTable) {
mContext = context; mContext = context;
init(newTable); init(newTable);
} }
private void init(boolean newTable) { private void init(boolean newTable) {
if (mDb == null) {
synchronized (LOCK) {
if (mDb == null) { if (mDb == null) {
synchronized (LOCK) { SqlHelper mHelper = new SqlHelper(mContext);
if (mDb == null) { mDb = mHelper.getWritableDatabase();
SqlHelper mHelper = new SqlHelper(mContext); mUtil = DbUtil.getInstance(mDb);
mDb = mHelper.getWritableDatabase();
mUtil = DbUtil.getInstance(mDb);
}
}
}
if (newTable && !mUtil.tableExists(this)) {
mUtil.createTable(this);
} }
}
} }
if (newTable && !mUtil.tableExists(this)) {
/** mUtil.createTable(this);
* 获取所有行的rowid
*/
public int[] getRowId() {
Cursor cursor = mUtil.getRowId(this);
int[] ids = new int[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()) {
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid"));
i++;
}
return ids;
}
/**
* 获取rowid
*/
public int getRowId(@NonNull Object[] wheres, @NonNull Object[] values) {
return mUtil.getRowId(this, wheres, values);
}
/**
* 删除当前数据
*/
public void deleteData() {
mUtil.delData(this, new Object[]{"rowid"}, new Object[]{rowID});
} }
}
/**
* 根据条件删除数据 /**
*/ * 获取所有行的rowid
public void deleteData(@NonNull Object[] wheres, @NonNull Object[] values) { */
mUtil.delData(this, wheres, values); public int[] getRowId() {
Cursor cursor = mUtil.getRowId(this);
int[] ids = new int[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()) {
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid"));
i++;
} }
return ids;
/** }
* 修改数据
*/ /**
public void update() { * 获取rowid
mUtil.modifyData(this); */
} public int getRowId(@NonNull Object[] wheres, @NonNull Object[] values) {
return mUtil.getRowId(this, wheres, values);
/** }
* 插入数据
*/ /**
public void save() { * 删除当前数据
mUtil.insertData(this); */
} public void deleteData() {
mUtil.delData(this, new Object[] { "rowid" }, new Object[] { rowID });
/** }
* 查询所有数据
* /**
* @return 没有数据返回null * 根据条件删除数据
*/ */
public <T extends DbEntity> List<T> findAllData(Class<T> clazz) { public void deleteData(@NonNull Object[] wheres, @NonNull Object[] values) {
Cursor cursor = mUtil.findAllData(this); mUtil.delData(this, wheres, values);
return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; }
}
/**
/** * 修改数据
* 查询一组数据 */
* public void update() {
* @return 没有数据返回null mUtil.modifyData(this);
*/ }
public <T extends DbEntity> List<T> findDatas(Class<T> clazz, @NonNull Object[] wheres, @NonNull Object[] values) {
Cursor cursor = mUtil.findData(this, wheres, values); /**
return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null; * 插入数据
} */
public void save() {
/** mUtil.insertData(this);
* 查询一行数据 }
*
* @return 没有数据返回null /**
*/ * 查询所有数据
public <T extends DbEntity> T findData(Class<T> clazz, @NonNull Object[] wheres, @NonNull Object[] values) { *
Cursor cursor = mUtil.findData(this, wheres, values); * @return 没有数据返回null
return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor).get(0) : null; */
} public <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
Cursor cursor = mUtil.findAllData(this);
/** return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
* 根据数据游标创建一个具体的对象 }
*/
private <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz, Cursor cursor) { /**
Field[] fields = Util.getFields(clazz); * 查询一组数据
List<T> entitys = new ArrayList<>(); *
if (fields != null && fields.length > 0) { * @return 没有数据返回null
try { */
while (cursor.moveToNext()) { public <T extends DbEntity> List<T> findDatas(Class<T> clazz, @NonNull Object[] wheres,
Class[] paramTypes = {Context.class, boolean.class}; @NonNull Object[] values) {
Object[] params = {mContext, false}; Cursor cursor = mUtil.findData(this, wheres, values);
Constructor<T> con = clazz.getConstructor(paramTypes); return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
T entity = con.newInstance(params); }
for (Field field : fields) {
field.setAccessible(true); /**
Ignore ignore = field.getAnnotation(Ignore.class); * 查询一行数据
if (ignore != null && ignore.value()) { *
continue; * @return 没有数据返回null
} */
Class<?> type = field.getType(); public <T extends DbEntity> T findData(Class<T> clazz, @NonNull Object[] wheres,
int column = cursor.getColumnIndex(field.getName()); @NonNull Object[] values) {
if (type == String.class) { Cursor cursor = mUtil.findData(this, wheres, values);
field.set(entity, cursor.getString(column)); return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor).get(0) : null;
} else if (type == int.class || type == Integer.class) { }
field.setInt(entity, cursor.getInt(column));
} else if (type == float.class || type == Float.class) { /**
field.setFloat(entity, cursor.getFloat(column)); * 根据数据游标创建一个具体的对象
} else if (type == double.class || type == Double.class) { */
field.setDouble(entity, cursor.getDouble(column)); private <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz, Cursor cursor) {
} else if (type == long.class || type == Long.class) { Field[] fields = Util.getFields(clazz);
field.setLong(entity, cursor.getLong(column)); List<T> entitys = new ArrayList<>();
} else if (type == boolean.class || type == Boolean.class) { if (fields != null && fields.length > 0) {
field.setBoolean(entity, !cursor.getString(column).equalsIgnoreCase("false")); try {
} else if (type == java.util.Date.class || type == java.sql.Date.class) { while (cursor.moveToNext()) {
field.set(entity, new Date(cursor.getString(column))); Class[] paramTypes = { Context.class, boolean.class };
} else if (type == byte[].class) { Object[] params = { mContext, false };
field.set(entity, cursor.getBlob(column)); Constructor<T> con = clazz.getConstructor(paramTypes);
} T entity = con.newInstance(params);
// field.set(entity, cursor.getColumnIndex("entity_id")); for (Field field : fields) {
} field.setAccessible(true);
entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid")); Ignore ignore = field.getAnnotation(Ignore.class);
entitys.add(entity); if (ignore != null && ignore.value()) {
} continue;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} }
Class<?> type = field.getType();
int column = cursor.getColumnIndex(field.getName());
if (type == String.class) {
field.set(entity, cursor.getString(column));
} else if (type == int.class || type == Integer.class) {
field.setInt(entity, cursor.getInt(column));
} else if (type == float.class || type == Float.class) {
field.setFloat(entity, cursor.getFloat(column));
} else if (type == double.class || type == Double.class) {
field.setDouble(entity, cursor.getDouble(column));
} else if (type == long.class || type == Long.class) {
field.setLong(entity, cursor.getLong(column));
} else if (type == boolean.class || type == Boolean.class) {
field.setBoolean(entity, !cursor.getString(column).equalsIgnoreCase("false"));
} else if (type == java.util.Date.class || type == java.sql.Date.class) {
field.set(entity, new Date(cursor.getString(column)));
} else if (type == byte[].class) {
field.set(entity, cursor.getBlob(column));
}
// field.set(entity, cursor.getColumnIndex("entity_id"));
}
entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid"));
entitys.add(entity);
} }
cursor.close(); } catch (InstantiationException e) {
return entitys; e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} }
cursor.close();
return entitys;
}
} }

@ -1,11 +1,10 @@
package com.arialyy.downloadutil.orm; package com.arialyy.downloadutil.orm;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.util.Util; import com.arialyy.downloadutil.util.Util;
import java.lang.reflect.Field; import java.lang.reflect.Field;
/** /**
@ -13,318 +12,311 @@ import java.lang.reflect.Field;
* 数据库操作工具 * 数据库操作工具
*/ */
public class DbUtil { public class DbUtil {
private static final String TAG = "DbUtil"; private static final String TAG = "DbUtil";
private volatile static DbUtil mDbUtil = null; private volatile static DbUtil mDbUtil = null;
private int CREATE_TABLE = 0; private int CREATE_TABLE = 0;
private int TABLE_EXISTS = 1; private int TABLE_EXISTS = 1;
private int INSERT_DATA = 2; private int INSERT_DATA = 2;
private int MODIFY_DATA = 3; private int MODIFY_DATA = 3;
private int FIND_DATA = 4; private int FIND_DATA = 4;
private int FIND_ALL_DATA = 5; private int FIND_ALL_DATA = 5;
private int DEL_DATA = 6; private int DEL_DATA = 6;
private int ROW_ID = 7; private int ROW_ID = 7;
private static final Object LOCK = new Object(); private static final Object LOCK = new Object();
private SQLiteDatabase mDb; private SQLiteDatabase mDb;
private DbUtil() { private DbUtil() {
} }
private DbUtil(SQLiteDatabase db) { private DbUtil(SQLiteDatabase db) {
mDb = db; mDb = db;
} }
protected static DbUtil getInstance(SQLiteDatabase db) { protected static DbUtil getInstance(SQLiteDatabase db) {
if (mDbUtil == null) {
synchronized (LOCK) {
if (mDbUtil == null) { if (mDbUtil == null) {
synchronized (LOCK) { mDbUtil = new DbUtil(db);
if (mDbUtil == null) {
mDbUtil = new DbUtil(db);
}
}
} }
return mDbUtil; }
} }
return mDbUtil;
}
/** /**
* 删除某条数据 * 删除某条数据
*/ */
protected void delData(DbEntity dbEntity, @NonNull Object[] wheres, @NonNull Object[] values) { protected void delData(DbEntity dbEntity, @NonNull Object[] wheres, @NonNull Object[] values) {
if (wheres.length <= 0 || values.length <= 0) { if (wheres.length <= 0 || values.length <= 0) {
Log.e(TAG, "输入删除条件"); Log.e(TAG, "输入删除条件");
return; return;
} else if (wheres.length != values.length) { } else if (wheres.length != values.length) {
Log.e(TAG, "key 和 vaule 长度不相等"); Log.e(TAG, "key 和 vaule 长度不相等");
return; return;
}
StringBuilder sb = new StringBuilder();
sb.append("DELETE FROM ").append(Util.getClassName(dbEntity)).append(" WHERE ");
int i = 0;
for (Object where : wheres) {
sb.append(where).append("=").append("'").append(values[i]).append("'");
sb.append(i >= wheres.length - 1 ? "" : ",");
i++;
}
print(DEL_DATA, sb.toString());
mDb.execSQL(sb.toString());
}
/**
* 修改某行数据
*/
protected void modifyData(DbEntity dbEntity) {
Class<?> clazz = dbEntity.getClass();
Field[] fields = Util.getFields(clazz);
if (fields != null && fields.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("UPDATE ").append(Util.getClassName(dbEntity)).append(" SET ");
int i = 0;
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
sb.append(i > 0 ? ", " : "");
try {
sb.append(field.getName()).append(" = '").append(field.get(dbEntity).toString()).append("'");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
i++;
}
print(MODIFY_DATA, sb.toString());
mDb.execSQL(sb.toString());
}
} }
StringBuilder sb = new StringBuilder();
/** sb.append("DELETE FROM ").append(Util.getClassName(dbEntity)).append(" WHERE ");
* 遍历所有数据 int i = 0;
*/ for (Object where : wheres) {
protected Cursor findAllData(DbEntity dbEntity) { sb.append(where).append("=").append("'").append(values[i]).append("'");
StringBuilder sb = new StringBuilder(); sb.append(i >= wheres.length - 1 ? "" : ",");
sb.append("SELECT rowid, * FROM ").append(Util.getClassName(dbEntity)); i++;
print(FIND_ALL_DATA, sb.toString());
return mDb.rawQuery(sb.toString(), null);
} }
print(DEL_DATA, sb.toString());
mDb.execSQL(sb.toString());
}
/**
/** * 修改某行数据
* 条件查寻数据 */
*/ protected void modifyData(DbEntity dbEntity) {
protected Cursor findData(DbEntity dbEntity, @NonNull Object[] wheres, @NonNull Object[] values) { Class<?> clazz = dbEntity.getClass();
if (wheres.length <= 0 || values.length <= 0) { Field[] fields = Util.getFields(clazz);
Log.e(TAG, "请输入查询条件"); if (fields != null && fields.length > 0) {
return null; StringBuilder sb = new StringBuilder();
} else if (wheres.length != values.length) { sb.append("UPDATE ").append(Util.getClassName(dbEntity)).append(" SET ");
Log.e(TAG, "key 和 vaule 长度不相等"); int i = 0;
return null; for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
} }
StringBuilder sb = new StringBuilder(); sb.append(i > 0 ? ", " : "");
sb.append("SELECT rowid, * FROM ").append(Util.getClassName(dbEntity)).append(" where "); try {
int i = 0; sb.append(field.getName())
for (Object where : wheres) { .append(" = '")
sb.append(where).append("=").append("'").append(values[i]).append("'"); .append(field.get(dbEntity).toString())
sb.append(i >= wheres.length - 1 ? "" : ", "); .append("'");
i++; } catch (IllegalAccessException e) {
e.printStackTrace();
} }
print(FIND_DATA, sb.toString()); i++;
return mDb.rawQuery(sb.toString(), null); }
print(MODIFY_DATA, sb.toString());
mDb.execSQL(sb.toString());
} }
}
/** /**
* 插入数据 * 遍历所有数据
*/ */
protected void insertData(DbEntity dbEntity) { protected Cursor findAllData(DbEntity dbEntity) {
Class<?> clazz = dbEntity.getClass(); StringBuilder sb = new StringBuilder();
Field[] fields = Util.getFields(clazz); sb.append("SELECT rowid, * FROM ").append(Util.getClassName(dbEntity));
if (fields != null && fields.length > 0) { print(FIND_ALL_DATA, sb.toString());
StringBuilder sb = new StringBuilder(); return mDb.rawQuery(sb.toString(), null);
sb.append("INSERT INTO ").append(Util.getClassName(dbEntity)).append("("); }
int i = 0;
for (Field field : fields) { /**
field.setAccessible(true); * 条件查寻数据
Ignore ignore = field.getAnnotation(Ignore.class); */
if (ignore != null && ignore.value()) { protected Cursor findData(DbEntity dbEntity, @NonNull Object[] wheres, @NonNull Object[] values) {
continue; if (wheres.length <= 0 || values.length <= 0) {
} Log.e(TAG, "请输入查询条件");
sb.append(i > 0 ? ", " : ""); return null;
sb.append(field.getName()); } else if (wheres.length != values.length) {
i++; Log.e(TAG, "key 和 vaule 长度不相等");
} return null;
sb.append(") VALUES (");
i = 0;
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
sb.append(i > 0 ? ", " : "");
sb.append("'");
try {
sb.append(field.get(dbEntity)).append("'");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
i++;
}
sb.append(")");
print(INSERT_DATA, sb.toString());
mDb.execSQL(sb.toString());
}
} }
StringBuilder sb = new StringBuilder();
sb.append("SELECT rowid, * FROM ").append(Util.getClassName(dbEntity)).append(" where ");
int i = 0;
for (Object where : wheres) {
sb.append(where).append("=").append("'").append(values[i]).append("'");
sb.append(i >= wheres.length - 1 ? "" : ", ");
i++;
}
print(FIND_DATA, sb.toString());
return mDb.rawQuery(sb.toString(), null);
}
/** /**
* 查找某张表是否存在 * 插入数据
*/ */
protected boolean tableExists(DbEntity dbEntity) { protected void insertData(DbEntity dbEntity) {
Cursor cursor = null; Class<?> clazz = dbEntity.getClass();
Field[] fields = Util.getFields(clazz);
if (fields != null && fields.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("INSERT INTO ").append(Util.getClassName(dbEntity)).append("(");
int i = 0;
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
sb.append(i > 0 ? ", " : "");
sb.append(field.getName());
i++;
}
sb.append(") VALUES (");
i = 0;
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
sb.append(i > 0 ? ", " : "");
sb.append("'");
try { try {
StringBuilder sb = new StringBuilder(); sb.append(field.get(dbEntity)).append("'");
sb.append("SELECT COUNT(*) AS c FROM sqlite_master WHERE type ='table' AND name ='"); } catch (IllegalAccessException e) {
sb.append(Util.getClassName(dbEntity)); e.printStackTrace();
sb.append("'");
print(TABLE_EXISTS, sb.toString());
cursor = mDb.rawQuery(sb.toString(), null);
if (cursor != null && cursor.moveToNext()) {
int count = cursor.getInt(0);
if (count > 0) {
return true;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
} }
return false; i++;
}
sb.append(")");
print(INSERT_DATA, sb.toString());
mDb.execSQL(sb.toString());
} }
}
/** /**
* 创建表 * 查找某张表是否存在
* */
* @param dbEntity protected boolean tableExists(DbEntity dbEntity) {
*/ Cursor cursor = null;
protected void createTable(DbEntity dbEntity) { try {
Field[] fields = Util.getFields(dbEntity.getClass()); StringBuilder sb = new StringBuilder();
if (fields != null && fields.length > 0) { sb.append("SELECT COUNT(*) AS c FROM sqlite_master WHERE type ='table' AND name ='");
StringBuilder sb = new StringBuilder(); sb.append(Util.getClassName(dbEntity));
sb.append("create table ") sb.append("'");
.append(Util.getClassName(dbEntity)) print(TABLE_EXISTS, sb.toString());
.append("("); cursor = mDb.rawQuery(sb.toString(), null);
int i = 0; if (cursor != null && cursor.moveToNext()) {
int ignoreNum = 0; int count = cursor.getInt(0);
for (Field field : fields) { if (count > 0) {
i++; return true;
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
ignoreNum++;
continue;
}
sb.append(field.getName());
Class<?> type = field.getType();
if (type == String.class) {
sb.append(" varchar");
} else if (type == int.class || type == Integer.class) {
sb.append(" interger");
} else if (type == float.class || type == Float.class) {
sb.append(" float");
} else if (type == double.class || type == Double.class) {
sb.append(" double");
} else if (type == long.class || type == Long.class) {
sb.append(" bigint");
} else if (type == boolean.class || type == Boolean.class) {
sb.append(" boolean");
} else if (type == java.util.Date.class || type == java.sql.Date.class) {
sb.append(" data");
} else {
sb.append(" blob");
}
sb.append(i >= fields.length - ignoreNum - 1 ? "" : ", ");
}
sb.append(");");
print(CREATE_TABLE, sb.toString());
mDb.execSQL(sb.toString());
} }
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) cursor.close();
} }
return false;
}
/** /**
* 打印数据库日志 * 创建表
* */
* @param type {@link DbUtil} protected void createTable(DbEntity dbEntity) {
* @param sql Field[] fields = Util.getFields(dbEntity.getClass());
*/ if (fields != null && fields.length > 0) {
private void print(int type, String sql) { StringBuilder sb = new StringBuilder();
String str = ""; sb.append("create table ").append(Util.getClassName(dbEntity)).append("(");
switch (type) { int i = 0;
case 0: int ignoreNum = 0;
str = "创建表 >>>> "; for (Field field : fields) {
break; i++;
case 1: field.setAccessible(true);
str = "表是否存在 >>>> "; Ignore ignore = field.getAnnotation(Ignore.class);
break; if (ignore != null && ignore.value()) {
case 2: ignoreNum++;
str = "插入数据 >>>> "; continue;
break;
case 3:
str = "修改数据 >>>> ";
break;
case 4:
str = "查询一行数据 >>>> ";
break;
case 5:
str = "遍历整个数据库 >>>> ";
break;
} }
Log.v(TAG, str + sql); sb.append(field.getName());
Class<?> type = field.getType();
if (type == String.class) {
sb.append(" varchar");
} else if (type == int.class || type == Integer.class) {
sb.append(" interger");
} else if (type == float.class || type == Float.class) {
sb.append(" float");
} else if (type == double.class || type == Double.class) {
sb.append(" double");
} else if (type == long.class || type == Long.class) {
sb.append(" bigint");
} else if (type == boolean.class || type == Boolean.class) {
sb.append(" boolean");
} else if (type == java.util.Date.class || type == java.sql.Date.class) {
sb.append(" data");
} else {
sb.append(" blob");
}
sb.append(i >= fields.length - ignoreNum - 1 ? "" : ", ");
}
sb.append(");");
print(CREATE_TABLE, sb.toString());
mDb.execSQL(sb.toString());
} }
}
/** /**
* 关闭数据库 * 打印数据库日志
*/ *
protected void close() { * @param type {@link DbUtil}
if (mDb != null) { */
mDb.close(); private void print(int type, String sql) {
} String str = "";
switch (type) {
case 0:
str = "创建表 >>>> ";
break;
case 1:
str = "表是否存在 >>>> ";
break;
case 2:
str = "插入数据 >>>> ";
break;
case 3:
str = "修改数据 >>>> ";
break;
case 4:
str = "查询一行数据 >>>> ";
break;
case 5:
str = "遍历整个数据库 >>>> ";
break;
} }
Log.v(TAG, str + sql);
}
/** /**
* 获取所有行Id * 关闭数据库
*/ */
protected Cursor getRowId(DbEntity dbEntity) { protected void close() {
StringBuilder sb = new StringBuilder(); if (mDb != null) {
sb.append("SELECT rowid, * FROM ").append(Util.getClassName(dbEntity)); mDb.close();
return mDb.rawQuery(sb.toString(), null);
} }
}
/** /**
* 获取行Id * 获取所有行Id
* */
* @return protected Cursor getRowId(DbEntity dbEntity) {
*/ StringBuilder sb = new StringBuilder();
protected int getRowId(DbEntity dbEntity, Object[] wheres, Object[] values) { sb.append("SELECT rowid, * FROM ").append(Util.getClassName(dbEntity));
if (wheres.length <= 0 || values.length <= 0) { return mDb.rawQuery(sb.toString(), null);
Log.e(TAG, "请输入删除条件"); }
return -1;
} else if (wheres.length != values.length) { /**
Log.e(TAG, "key 和 vaule 长度不相等"); * 获取行Id
return -1; */
} protected int getRowId(DbEntity dbEntity, Object[] wheres, Object[] values) {
StringBuilder sb = new StringBuilder(); if (wheres.length <= 0 || values.length <= 0) {
sb.append("SELECT rowid FROM ").append(Util.getClassName(dbEntity)).append(" WHERE "); Log.e(TAG, "请输入删除条件");
int i = 0; return -1;
for (Object where : wheres) { } else if (wheres.length != values.length) {
sb.append(where).append("=").append("'").append(values[i]).append("'"); Log.e(TAG, "key 和 vaule 长度不相等");
sb.append(i >= wheres.length - 1 ? "" : ","); return -1;
i++; }
} StringBuilder sb = new StringBuilder();
print(ROW_ID, sb.toString()); sb.append("SELECT rowid FROM ").append(Util.getClassName(dbEntity)).append(" WHERE ");
Cursor c = mDb.rawQuery(sb.toString(), null); int i = 0;
int id = c.getColumnIndex("rowid"); for (Object where : wheres) {
c.close(); sb.append(where).append("=").append("'").append(values[i]).append("'");
return id; sb.append(i >= wheres.length - 1 ? "" : ",");
i++;
} }
print(ROW_ID, sb.toString());
Cursor c = mDb.rawQuery(sb.toString(), null);
int id = c.getColumnIndex("rowid");
c.close();
return id;
}
} }

@ -9,8 +9,6 @@ import java.lang.annotation.Target;
* Created by lyy on 2015/11/2. * Created by lyy on 2015/11/2.
* 表ID字段指定 * 表ID字段指定
*/ */
@Target(ElementType.FIELD) @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Id {
@Retention(RetentionPolicy.RUNTIME) int value() default -1;
public @interface Id {
int value() default -1;
} }

@ -9,8 +9,6 @@ import java.lang.annotation.Target;
* Created by lyy on 2015/11/2. * Created by lyy on 2015/11/2.
* 忽略某个字段 * 忽略某个字段
*/ */
@Target(ElementType.FIELD) @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Ignore {
@Retention(RetentionPolicy.RUNTIME) boolean value() default false;
public @interface Ignore {
boolean value() default false;
} }

@ -10,29 +10,27 @@ import android.text.TextUtils;
* sql帮助类 * sql帮助类
*/ */
public class SqlHelper extends SQLiteOpenHelper { public class SqlHelper extends SQLiteOpenHelper {
protected static String DB_NAME; protected static String DB_NAME;
protected static int VERSION = -1; protected static int VERSION = -1;
static {
if (TextUtils.isEmpty(DB_NAME)) {
DB_NAME = "AriaLyyDb";
}
if (VERSION == -1) {
VERSION = 1;
}
}
public SqlHelper(Context context) { static {
super(context, DB_NAME, null, VERSION); if (TextUtils.isEmpty(DB_NAME)) {
DB_NAME = "AriaLyyDb";
}
if (VERSION == -1) {
VERSION = 1;
} }
}
@Override public SqlHelper(Context context) {
public void onCreate(SQLiteDatabase db) { super(context, DB_NAME, null, VERSION);
}
} @Override public void onCreate(SQLiteDatabase db) {
@Override }
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
} @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
} }

@ -4,7 +4,6 @@ import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -13,431 +12,456 @@ import java.net.HttpURLConnection;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Properties; import java.util.Properties;
/** /**
* Created by lyy on 2015/8/25. * Created by lyy on 2015/8/25.
* 下载工具类 * 下载工具类
*/ */
public class DownLoadUtil { public class DownLoadUtil {
private static final String TAG = "DownLoadUtil"; private static final String TAG = "DownLoadUtil";
//下载监听 //下载监听
private IDownloadListener mListener; private IDownloadListener mListener;
/** /**
* 线程数 * 线程数
*/ */
private static final int THREAD_NUM = 3; private static final int THREAD_NUM = 3;
/** /**
* 已经完成下载任务的线程数量 * 已经完成下载任务的线程数量
*/ */
private int mCompleteThreadNum = 0; private int mCompleteThreadNum = 0;
private long mCurrentLocation; private long mCurrentLocation;
private boolean isDownloading = false; private boolean isDownloading = false;
private boolean isStop = false; private boolean isStop = false;
private boolean isCancel = false; private boolean isCancel = false;
private static final int TIME_OUT = 5000; //超时时间 private static final int TIME_OUT = 5000; //超时时间
boolean isNewTask = true; boolean isNewTask = true;
private int mCancelNum = 0; private int mCancelNum = 0;
private int mStopNum = 0; private int mStopNum = 0;
public DownLoadUtil() {
} public DownLoadUtil() {
public IDownloadListener getListener(){ }
return mListener;
} public IDownloadListener getListener() {
/** return mListener;
* 获取当前下载位置 }
*
* @return /**
*/ * 获取当前下载位置
public long getCurrentLocation() { */
return mCurrentLocation; public long getCurrentLocation() {
} return mCurrentLocation;
public boolean isDownloading() { }
return isDownloading;
} public boolean isDownloading() {
/** return isDownloading;
* 取消下载 }
*/
public void cancelDownload() { /**
isCancel = true; * 取消下载
} */
/** public void cancelDownload() {
* 停止下载 isCancel = true;
*/ }
public void stopDownload() {
isStop = true; /**
* 停止下载
*/
public void stopDownload() {
isStop = true;
}
/**
* 多线程断点续传下载文件暂停和继续
*
* @param context 必须添加该参数不能使用全局变量的context
* @param downloadUrl 下载路径
* @param filePath 保存路径
* @param downloadListener 下载进度监听 {@link DownloadListener}
*/
public void download(final Context context, @NonNull final String downloadUrl,
@NonNull final String filePath, @NonNull final IDownloadListener downloadListener) {
isDownloading = true;
mCurrentLocation = 0;
isStop = false;
isCancel = false;
mCancelNum = 0;
mStopNum = 0;
final File dFile = new File(filePath);
//读取已完成的线程数
final File configFile =
new File(context.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties");
try {
if (!configFile.exists()) { //记录文件被删除,则重新下载
isNewTask = true;
Util.createFile(configFile.getPath());
} else {
isNewTask = !dFile.exists();
}
} catch (Exception e) {
e.printStackTrace();
failDownload("下载失败,记录文件被删除");
return;
} }
/** new Thread(new Runnable() {
* 多线程断点续传下载文件暂停和继续 @Override public void run() {
*
* @param context 必须添加该参数不能使用全局变量的context
* @param downloadUrl 下载路径
* @param filePath 保存路径
* @param downloadListener 下载进度监听 {@link DownloadListener}
*/
public void download(final Context context, @NonNull final String downloadUrl, @NonNull final String filePath,
@NonNull final IDownloadListener downloadListener) {
isDownloading = true;
mCurrentLocation = 0;
isStop = false;
isCancel = false;
mCancelNum = 0;
mStopNum = 0;
final File dFile = new File(filePath);
//读取已完成的线程数
final File configFile = new File(context.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties");
try { try {
if (!configFile.exists()) { //记录文件被删除,则重新下载 mListener = downloadListener;
isNewTask = true; URL url = new URL(downloadUrl);
Util.createFile(configFile.getPath()); HttpURLConnection conn = (HttpURLConnection) url.openConnection();
} else { conn.setRequestMethod("GET");
isNewTask = !dFile.exists(); conn.setRequestProperty("Charset", "UTF-8");
} conn.setConnectTimeout(TIME_OUT * 4);
} catch (Exception e) { conn.setRequestProperty("User-Agent",
e.printStackTrace(); "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
failDownload("下载失败,记录文件被删除"); conn.setRequestProperty("Accept",
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
conn.connect();
int len = conn.getContentLength();
if (len < 0) { //网络被劫持时会出现这个问题
failDownload("下载失败,网络被劫持");
return; return;
} }
new Thread(new Runnable() { int code = conn.getResponseCode();
@Override if (code == 200) {
public void run() { int fileLength = conn.getContentLength();
try { //必须建一个文件
mListener = downloadListener; Util.createFile(filePath);
URL url = new URL(downloadUrl); RandomAccessFile file = new RandomAccessFile(filePath, "rwd");
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置文件长度
conn.setRequestMethod("GET"); file.setLength(fileLength);
conn.setRequestProperty("Charset", "UTF-8"); mListener.onPreDownload(conn);
conn.setConnectTimeout(TIME_OUT * 4); //分配每条线程的下载区间
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"); Properties pro = null;
conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*"); pro = Util.loadConfig(configFile);
conn.connect(); if (pro.isEmpty()) {
int len = conn.getContentLength(); isNewTask = true;
if (len < 0) { //网络被劫持时会出现这个问题 } else {
failDownload("下载失败,网络被劫持"); for (int i = 0; i < THREAD_NUM; i++) {
return; if (pro.getProperty(dFile.getName() + "_record_" + i) == null) {
} Object state = pro.getProperty(dFile.getName() + "_state_" + i);
int code = conn.getResponseCode(); if (state != null && Integer.parseInt(state + "") == 1) {
if (code == 200) { continue;
int fileLength = conn.getContentLength(); }
//必须建一个文件 isNewTask = true;
Util.createFile(filePath); break;
RandomAccessFile file = new RandomAccessFile(filePath, "rwd");
//设置文件长度
file.setLength(fileLength);
mListener.onPreDownload(conn);
//分配每条线程的下载区间
Properties pro = null;
pro = Util.loadConfig(configFile);
if (pro.isEmpty()) {
isNewTask = true;
} else {
for (int i = 0; i < THREAD_NUM; i++) {
if (pro.getProperty(dFile.getName() + "_record_" + i) == null) {
Object state = pro.getProperty(dFile.getName() + "_state_" + i);
if (state != null && Integer.parseInt(state + "") == 1) {
continue;
}
isNewTask = true;
break;
}
}
}
int blockSize = fileLength / THREAD_NUM;
SparseArray<Thread> tasks = new SparseArray<>();
int[] recordL = new int[THREAD_NUM];
int rl = 0;
for (int i = 0; i < THREAD_NUM; i++) {
recordL[i] = -1;
}
for (int i = 0; i < THREAD_NUM; i++) {
long startL = i * blockSize, endL = (i + 1) * blockSize;
Object state = pro.getProperty(dFile.getName() + "_state_" + i);
if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
mCurrentLocation += endL - startL;
Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
mCompleteThreadNum++;
mStopNum++;
mCancelNum++;
if (mCompleteThreadNum == THREAD_NUM) {
if (configFile.exists()) {
configFile.delete();
}
mListener.onComplete();
isDownloading = false;
return;
}
continue;
}
//分配下载位置
Object record = pro.getProperty(dFile.getName() + "_record_" + i);
if (!isNewTask && record != null && Long.parseLong(record + "") > 0) { //如果有记录,则恢复下载
Long r = Long.parseLong(record + "");
mCurrentLocation += r - startL;
Log.d(TAG, "++++++++++ 线程_" + i + "_恢复下载 ++++++++++");
mListener.onChildResume(r);
startL = r;
recordL[rl] = i;
rl++;
}else {
isNewTask = true;
}
if (isNewTask) {
recordL[rl] = i;
rl++;
}
if (i == (THREAD_NUM - 1)) {
endL = fileLength;//如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度
}
DownloadEntity entity = new DownloadEntity(context, fileLength, downloadUrl, dFile, i, startL, endL);
DownLoadTask task = new DownLoadTask(entity);
tasks.put(i, new Thread(task));
}
if (mCurrentLocation > 0) {
mListener.onResume(mCurrentLocation);
} else {
mListener.onStart(mCurrentLocation);
}
for (int l : recordL) {
if (l == -1) continue;
Thread task = tasks.get(l);
if (task != null) {
task.start();
}
}
} else {
failDownload("下载失败,返回码:" + code);
}
} catch (IOException e) {
failDownload("下载失败【downloadUrl:" + downloadUrl + "】\n【filePath:" + filePath + "】" + Util.getPrintException(e));
} }
}
} }
}).start(); int blockSize = fileLength / THREAD_NUM;
} SparseArray<Thread> tasks = new SparseArray<>();
private void failDownload(String msg){ int[] recordL = new int[THREAD_NUM];
Log.e(TAG, msg); int rl = 0;
isDownloading = false; for (int i = 0; i < THREAD_NUM; i++) {
stopDownload(); recordL[i] = -1;
mListener.onFail(); }
System.gc(); for (int i = 0; i < THREAD_NUM; i++) {
} long startL = i * blockSize, endL = (i + 1) * blockSize;
/** Object state = pro.getProperty(dFile.getName() + "_state_" + i);
* 多线程下载任务类,不能使用AsyncTask来进行多线程下载因为AsyncTask是串行执行的这种方式下载速度太慢了 if (state != null && Integer.parseInt(state + "") == 1) { //该线程已经完成
*/ mCurrentLocation += endL - startL;
private class DownLoadTask implements Runnable { Log.d(TAG, "++++++++++ 线程_" + i + "_已经下载完成 ++++++++++");
private static final String TAG = "DownLoadTask";
private DownloadEntity dEntity;
private String configFPath;
public DownLoadTask(DownloadEntity downloadInfo) {
this.dEntity = downloadInfo;
configFPath = dEntity.context.getFilesDir().getPath() + "/temp/" + dEntity.tempFile.getName() + ".properties";
}
@Override
public void run() {
long currentLocation = 0;
try {
Log.d(TAG, "线程_" + dEntity.threadId + "_正在下载【" + "开始位置 : " + dEntity.startLocation + ",结束位置:" + dEntity.endLocation + "】");
URL url = new URL(dEntity.downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//在头里面请求下载开始位置和结束位置
conn.setRequestProperty("Range", "bytes=" + dEntity.startLocation + "-" + dEntity.endLocation);
conn.setRequestMethod("GET");
conn.setRequestProperty("Charset", "UTF-8");
conn.setConnectTimeout(TIME_OUT * 4);
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
conn.setReadTimeout(TIME_OUT * 24); //设置读取流的等待时间,必须设置该参数
InputStream is = conn.getInputStream();
//创建可设置位置的文件
RandomAccessFile file = new RandomAccessFile(dEntity.tempFile, "rwd");
//设置每条线程写入文件的位置
file.seek(dEntity.startLocation);
byte[] buffer = new byte[1024];
int len;
//当前子线程的下载位置
currentLocation = dEntity.startLocation;
while ((len = is.read(buffer)) != -1) {
if (isCancel) {
Log.d(TAG, "++++++++++ thread_" + dEntity.threadId + "_cancel ++++++++++");
break;
}
if (isStop) {
break;
}
//把下载数据数据写入文件
file.write(buffer, 0, len);
synchronized (DownLoadUtil.this) {
mCurrentLocation += len;
mListener.onProgress(mCurrentLocation);
}
currentLocation += len;
}
file.close();
is.close();
if (isCancel) {
synchronized (DownLoadUtil.this) {
mCancelNum++;
if (mCancelNum == THREAD_NUM) {
File configFile = new File(configFPath);
if (configFile.exists()) {
configFile.delete();
}
if (dEntity.tempFile.exists()) {
dEntity.tempFile.delete();
}
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
isDownloading = false;
mListener.onCancel();
System.gc();
}
}
return;
}
//停止状态不需要删除记录文件
if (isStop) {
synchronized (DownLoadUtil.this) {
mStopNum++;
String location = String.valueOf(currentLocation);
Log.i(TAG, "thread_" + dEntity.threadId + "_stop, stop location ==> " + currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
if (mStopNum == THREAD_NUM) {
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
isDownloading = false;
mListener.onStop(mCurrentLocation);
System.gc();
}
}
return;
}
Log.i(TAG, "线程【" + dEntity.threadId + "】下载完毕");
writeConfig(dEntity.tempFile.getName() + "_state_" + dEntity.threadId, 1 + "");
mListener.onChildComplete(dEntity.endLocation);
mCompleteThreadNum++; mCompleteThreadNum++;
mStopNum++;
mCancelNum++;
if (mCompleteThreadNum == THREAD_NUM) { if (mCompleteThreadNum == THREAD_NUM) {
File configFile = new File(configFPath); if (configFile.exists()) {
if (configFile.exists()) { configFile.delete();
configFile.delete(); }
} mListener.onComplete();
isDownloading = false; isDownloading = false;
mListener.onComplete(); return;
System.gc();
}
} catch (MalformedURLException e) {
e.printStackTrace();
isDownloading = false;
synchronized (DownLoadUtil.this) {
try {
String location = String.valueOf(currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
failDownload("下载链接异常");
} catch (IOException e1) {
e1.printStackTrace();
}
}
} catch (IOException e) {
synchronized (DownLoadUtil.this) {
try {
String location = String.valueOf(currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
failDownload("下载失败【" + dEntity.downloadUrl + "】" + Util.getPrintException(e));
} catch (IOException e1) {
e1.printStackTrace();
}
}
} catch (Exception e) {
synchronized (DownLoadUtil.this) {
try {
String location = String.valueOf(currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
failDownload("获取流失败" + Util.getPrintException(e));
} catch (IOException e1) {
e1.printStackTrace();
}
} }
continue;
}
//分配下载位置
Object record = pro.getProperty(dFile.getName() + "_record_" + i);
if (!isNewTask
&& record != null
&& Long.parseLong(record + "") > 0) { //如果有记录,则恢复下载
Long r = Long.parseLong(record + "");
mCurrentLocation += r - startL;
Log.d(TAG, "++++++++++ 线程_" + i + "_恢复下载 ++++++++++");
mListener.onChildResume(r);
startL = r;
recordL[rl] = i;
rl++;
} else {
isNewTask = true;
}
if (isNewTask) {
recordL[rl] = i;
rl++;
}
if (i == (THREAD_NUM - 1)) {
endL = fileLength;//如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度
}
DownloadEntity entity =
new DownloadEntity(context, fileLength, downloadUrl, dFile, i, startL, endL);
DownLoadTask task = new DownLoadTask(entity);
tasks.put(i, new Thread(task));
}
if (mCurrentLocation > 0) {
mListener.onResume(mCurrentLocation);
} else {
mListener.onStart(mCurrentLocation);
}
for (int l : recordL) {
if (l == -1) continue;
Thread task = tasks.get(l);
if (task != null) {
task.start();
}
}
} else {
failDownload("下载失败,返回码:" + code);
}
} catch (IOException e) {
failDownload("下载失败【downloadUrl:"
+ downloadUrl
+ "】\n【filePath:"
+ filePath
+ "】"
+ Util.getPrintException(e));
}
}
}).start();
}
private void failDownload(String msg) {
Log.e(TAG, msg);
isDownloading = false;
stopDownload();
mListener.onFail();
System.gc();
}
/**
* 多线程下载任务类,不能使用AsyncTask来进行多线程下载因为AsyncTask是串行执行的这种方式下载速度太慢了
*/
private class DownLoadTask implements Runnable {
private static final String TAG = "DownLoadTask";
private DownloadEntity dEntity;
private String configFPath;
public DownLoadTask(DownloadEntity downloadInfo) {
this.dEntity = downloadInfo;
configFPath = dEntity.context.getFilesDir().getPath()
+ "/temp/"
+ dEntity.tempFile.getName()
+ ".properties";
}
@Override public void run() {
long currentLocation = 0;
try {
Log.d(TAG, "线程_"
+ dEntity.threadId
+ "_正在下载【"
+ "开始位置 : "
+ dEntity.startLocation
+ ",结束位置:"
+ dEntity.endLocation
+ "】");
URL url = new URL(dEntity.downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//在头里面请求下载开始位置和结束位置
conn.setRequestProperty("Range",
"bytes=" + dEntity.startLocation + "-" + dEntity.endLocation);
conn.setRequestMethod("GET");
conn.setRequestProperty("Charset", "UTF-8");
conn.setConnectTimeout(TIME_OUT * 4);
conn.setRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
conn.setRequestProperty("Accept",
"image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
conn.setReadTimeout(TIME_OUT * 24); //设置读取流的等待时间,必须设置该参数
InputStream is = conn.getInputStream();
//创建可设置位置的文件
RandomAccessFile file = new RandomAccessFile(dEntity.tempFile, "rwd");
//设置每条线程写入文件的位置
file.seek(dEntity.startLocation);
byte[] buffer = new byte[1024];
int len;
//当前子线程的下载位置
currentLocation = dEntity.startLocation;
while ((len = is.read(buffer)) != -1) {
if (isCancel) {
Log.d(TAG, "++++++++++ thread_" + dEntity.threadId + "_cancel ++++++++++");
break;
}
if (isStop) {
break;
}
//把下载数据数据写入文件
file.write(buffer, 0, len);
synchronized (DownLoadUtil.this) {
mCurrentLocation += len;
mListener.onProgress(mCurrentLocation);
}
currentLocation += len;
}
file.close();
is.close();
if (isCancel) {
synchronized (DownLoadUtil.this) {
mCancelNum++;
if (mCancelNum == THREAD_NUM) {
File configFile = new File(configFPath);
if (configFile.exists()) {
configFile.delete();
}
if (dEntity.tempFile.exists()) {
dEntity.tempFile.delete();
}
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
isDownloading = false;
mListener.onCancel();
System.gc();
}
}
return;
}
//停止状态不需要删除记录文件
if (isStop) {
synchronized (DownLoadUtil.this) {
mStopNum++;
String location = String.valueOf(currentLocation);
Log.i(TAG,
"thread_" + dEntity.threadId + "_stop, stop location ==> " + currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
if (mStopNum == THREAD_NUM) {
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
isDownloading = false;
mListener.onStop(mCurrentLocation);
System.gc();
} }
}
return;
}
Log.i(TAG, "线程【" + dEntity.threadId + "】下载完毕");
writeConfig(dEntity.tempFile.getName() + "_state_" + dEntity.threadId, 1 + "");
mListener.onChildComplete(dEntity.endLocation);
mCompleteThreadNum++;
if (mCompleteThreadNum == THREAD_NUM) {
File configFile = new File(configFPath);
if (configFile.exists()) {
configFile.delete();
}
isDownloading = false;
mListener.onComplete();
System.gc();
} }
/** } catch (MalformedURLException e) {
* 将记录写入到配置文件 e.printStackTrace();
* isDownloading = false;
* @param record synchronized (DownLoadUtil.this) {
*/ try {
private void writeConfig(String key, String record) throws IOException { String location = String.valueOf(currentLocation);
File configFile = new File(configFPath); writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
Properties pro = Util.loadConfig(configFile); failDownload("下载链接异常");
pro.setProperty(key, record); } catch (IOException e1) {
Util.saveConfig(configFile, pro); e1.printStackTrace();
}
} }
} catch (IOException e) {
synchronized (DownLoadUtil.this) {
try {
String location = String.valueOf(currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
failDownload("下载失败【" + dEntity.downloadUrl + "】" + Util.getPrintException(e));
} catch (IOException e1) {
e1.printStackTrace();
}
}
} catch (Exception e) {
synchronized (DownLoadUtil.this) {
try {
String location = String.valueOf(currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
failDownload("获取流失败" + Util.getPrintException(e));
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
} }
/** /**
* 子线程下载信息类 * 将记录写入到配置文件
*/ */
private class DownloadEntity { private void writeConfig(String key, String record) throws IOException {
//文件大小 File configFile = new File(configFPath);
long fileSize; Properties pro = Util.loadConfig(configFile);
String downloadUrl; pro.setProperty(key, record);
int threadId; Util.saveConfig(configFile, pro);
long startLocation;
long endLocation;
File tempFile;
Context context;
public DownloadEntity(Context context, long fileSize, String downloadUrl, File file, int threadId, long startLocation, long endLocation) {
this.fileSize = fileSize;
this.downloadUrl = downloadUrl;
this.tempFile = file;
this.threadId = threadId;
this.startLocation = startLocation;
this.endLocation = endLocation;
this.context = context;
}
} }
}
public static class DownloadListener implements IDownloadListener { /**
* 子线程下载信息类
*/
private class DownloadEntity {
//文件大小
long fileSize;
String downloadUrl;
int threadId;
long startLocation;
long endLocation;
File tempFile;
Context context;
@Override public DownloadEntity(Context context, long fileSize, String downloadUrl, File file,
public void onResume(long resumeLocation) { int threadId, long startLocation, long endLocation) {
this.fileSize = fileSize;
this.downloadUrl = downloadUrl;
this.tempFile = file;
this.threadId = threadId;
this.startLocation = startLocation;
this.endLocation = endLocation;
this.context = context;
}
}
} public static class DownloadListener implements IDownloadListener {
@Override @Override public void onResume(long resumeLocation) {
public void onCancel() {
} }
@Override @Override public void onCancel() {
public void onFail() {
} }
@Override @Override public void onFail() {
public void onPreDownload(HttpURLConnection connection) {
} }
@Override @Override public void onPreDownload(HttpURLConnection connection) {
public void onProgress(long currentLocation) {
} }
@Override @Override public void onProgress(long currentLocation) {
public void onChildComplete(long finishLocation) {
} }
@Override @Override public void onChildComplete(long finishLocation) {
public void onStart(long startLocation) {
} }
@Override @Override public void onStart(long startLocation) {
public void onChildResume(long resumeLocation) {
} }
@Override @Override public void onChildResume(long resumeLocation) {
public void onStop(long stopLocation) {
} }
@Override @Override public void onStop(long stopLocation) {
public void onComplete() {
}
@Override public void onComplete() {
}
} }
}
} }

@ -6,54 +6,53 @@ import java.net.HttpURLConnection;
* 下载监听 * 下载监听
*/ */
public interface IDownloadListener { public interface IDownloadListener {
/** /**
* 取消下载 * 取消下载
*/ */
public void onCancel(); public void onCancel();
/** /**
* 下载失败 * 下载失败
*/ */
public void onFail(); public void onFail();
/** /**
* 下载预处理,可通过HttpURLConnection获取文件长度 * 下载预处理,可通过HttpURLConnection获取文件长度
*/ */
public void onPreDownload(HttpURLConnection connection); public void onPreDownload(HttpURLConnection connection);
/** /**
* 下载监听 * 下载监听
*/ */
public void onProgress(long currentLocation); public void onProgress(long currentLocation);
/** /**
* 单一线程的结束位置 * 单一线程的结束位置
*/ */
public void onChildComplete(long finishLocation); public void onChildComplete(long finishLocation);
/** /**
* 开始 * 开始
*/ */
public void onStart(long startLocation); public void onStart(long startLocation);
/** /**
* 子程恢复下载的位置 * 子程恢复下载的位置
*/ */
public void onChildResume(long resumeLocation); public void onChildResume(long resumeLocation);
/** /**
* 恢复位置 * 恢复位置
*/ */
public void onResume(long resumeLocation); public void onResume(long resumeLocation);
/** /**
* 停止 * 停止
*/ */
public void onStop(long stopLocation); public void onStop(long stopLocation);
/** /**
* 下载完成 * 下载完成
*/ */
public void onComplete(); public void onComplete();
} }

@ -1,13 +1,10 @@
package com.arialyy.downloadutil.util; package com.arialyy.downloadutil.util;
import android.util.Log; import android.util.Log;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.security.MessageDigest; import java.security.MessageDigest;
@ -18,228 +15,212 @@ import java.util.Properties;
* Created by lyy on 2016/1/22. * Created by lyy on 2016/1/22.
*/ */
public class Util { public class Util {
private static final String TAG = "util"; private static final String TAG = "util";
/** /**
* 将缓存的key转换为hash码 * 将缓存的key转换为hash码
* *
* @param key 缓存的key * @param key 缓存的key
* @return 转换后的key的值, 系统便是通过该key来读写缓存 * @return 转换后的key的值, 系统便是通过该key来读写缓存
*/ */
public static String keyToHashKey(String key) { public static String keyToHashKey(String key) {
String cacheKey; String cacheKey;
try { try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5"); final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes()); mDigest.update(key.getBytes());
cacheKey = bytesToHexString(mDigest.digest()); cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode()); cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
} }
return cacheKey;
/** }
* 将普通字符串转换为16位进制字符串
* /**
* @param src * 将普通字符串转换为16位进制字符串
* @return */
*/ public static String bytesToHexString(byte[] src) {
public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder("0x");
StringBuilder stringBuilder = new StringBuilder("0x"); if (src == null || src.length <= 0) {
if (src == null || src.length <= 0) { return null;
return null;
}
char[] buffer = new char[2];
for (byte aSrc : src) {
buffer[0] = Character.forDigit((aSrc >>> 4) & 0x0F, 16);
buffer[1] = Character.forDigit(aSrc & 0x0F, 16);
stringBuilder.append(buffer);
}
return stringBuilder.toString();
} }
char[] buffer = new char[2];
/** for (byte aSrc : src) {
* 获取类里面的所在字段 buffer[0] = Character.forDigit((aSrc >>> 4) & 0x0F, 16);
*/ buffer[1] = Character.forDigit(aSrc & 0x0F, 16);
public static Field[] getFields(Class clazz) { stringBuilder.append(buffer);
Field[] fields = null;
fields = clazz.getDeclaredFields();
if (fields == null || fields.length == 0) {
Class superClazz = clazz.getSuperclass();
if (superClazz != null) {
fields = getFields(superClazz);
}
}
return fields;
} }
return stringBuilder.toString();
/** }
* 获取对象名
* /**
* @param obj 对象 * 获取类里面的所在字段
* @return 对象名 */
*/ public static Field[] getFields(Class clazz) {
public static String getClassName(Object obj) { Field[] fields = null;
String arrays[] = obj.getClass().getName().split("\\."); fields = clazz.getDeclaredFields();
return arrays[arrays.length - 1]; if (fields == null || fields.length == 0) {
Class superClazz = clazz.getSuperclass();
if (superClazz != null) {
fields = getFields(superClazz);
}
}
return fields;
}
/**
* 获取对象名
*
* @param obj 对象
* @return 对象名
*/
public static String getClassName(Object obj) {
String arrays[] = obj.getClass().getName().split("\\.");
return arrays[arrays.length - 1];
}
/**
* 格式化文件大小
*
* @param size file.length() 获取文件大小
*/
public static String formatFileSize(double size) {
double kiloByte = size / 1024;
if (kiloByte < 1) {
return size + "Byte(s)";
} }
/** double megaByte = kiloByte / 1024;
* 格式化文件大小 if (megaByte < 1) {
* BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
* @param size file.length() 获取文件大小 return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
* @return }
*/
public static String formatFileSize(double size) {
double kiloByte = size / 1024;
if (kiloByte < 1) {
return size + "Byte(s)";
}
double megaByte = kiloByte / 1024;
if (megaByte < 1) {
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
}
double gigaByte = megaByte / 1024;
if (gigaByte < 1) {
BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
}
double teraBytes = gigaByte / 1024; double gigaByte = megaByte / 1024;
if (teraBytes < 1) { if (gigaByte < 1) {
BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB"; return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
}
BigDecimal result4 = new BigDecimal(teraBytes);
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
} }
/** double teraBytes = gigaByte / 1024;
* 创建目录 当目录不存在的时候创建文件否则返回false if (teraBytes < 1) {
* BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
* @param path return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB";
* @return }
*/ BigDecimal result4 = new BigDecimal(teraBytes);
public static boolean createDir(String path) { return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
File file = new File(path); }
if (!file.exists()) {
if (!file.mkdirs()) { /**
Log.d(TAG, "创建失败,请检查路径和是否配置文件权限!"); * 创建目录 当目录不存在的时候创建文件否则返回false
return false; */
} public static boolean createDir(String path) {
return true; File file = new File(path);
} if (!file.exists()) {
if (!file.mkdirs()) {
Log.d(TAG, "创建失败,请检查路径和是否配置文件权限!");
return false; return false;
}
return true;
} }
return false;
/** }
* 创建文件 当文件不存在的时候就创建一个文件否则直接返回文件
* /**
* @param path * 创建文件 当文件不存在的时候就创建一个文件否则直接返回文件
* @return */
*/ public static File createFile(String path) {
public static File createFile(String path) { File file = new File(path);
File file = new File(path); if (!file.getParentFile().exists()) {
if (!file.getParentFile().exists()) { Log.d(TAG, "目标文件所在路径不存在,准备创建……");
Log.d(TAG, "目标文件所在路径不存在,准备创建……"); if (!createDir(file.getParent())) {
if (!createDir(file.getParent())) { Log.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】");
Log.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】"); }
}
}
// 创建目标文件
try {
if (!file.exists()) {
if (file.createNewFile()) {
Log.d(TAG, "创建文件成功:" + file.getAbsolutePath());
}
return file;
} else {
return file;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
} }
// 创建目标文件
/** try {
* 设置打印的异常格式 if (!file.exists()) {
*/ if (file.createNewFile()) {
public static String getPrintException(Throwable ex) { Log.d(TAG, "创建文件成功:" + file.getAbsolutePath());
StringBuilder err = new StringBuilder();
err.append("ExceptionDetailed:\n");
err.append("====================Exception Info====================\n");
err.append(ex.toString());
err.append("\n");
StackTraceElement[] stack = ex.getStackTrace();
for (StackTraceElement stackTraceElement : stack) {
err.append(stackTraceElement.toString()).append("\n");
} }
Throwable cause = ex.getCause(); return file;
if (cause != null) { } else {
err.append("【Caused by】: "); return file;
err.append(cause.toString()); }
err.append("\n"); } catch (IOException e) {
StackTraceElement[] stackTrace = cause.getStackTrace(); e.printStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
err.append(stackTraceElement.toString()).append("\n");
}
}
err.append("===================================================");
return err.toString();
} }
return null;
/** }
* 读取下载配置文件
* /**
* @param file * 设置打印的异常格式
* @return */
*/ public static String getPrintException(Throwable ex) {
public static Properties loadConfig(File file) { StringBuilder err = new StringBuilder();
Properties properties = new Properties(); err.append("ExceptionDetailed:\n");
FileInputStream fis = null; err.append("====================Exception Info====================\n");
try { err.append(ex.toString());
fis = new FileInputStream(file); err.append("\n");
properties.load(fis); StackTraceElement[] stack = ex.getStackTrace();
} catch (Exception e) { for (StackTraceElement stackTraceElement : stack) {
e.printStackTrace(); err.append(stackTraceElement.toString()).append("\n");
} finally { }
try { Throwable cause = ex.getCause();
if (fis != null) { if (cause != null) {
fis.close(); err.append("【Caused by】: ");
} err.append(cause.toString());
} catch (IOException e) { err.append("\n");
e.printStackTrace(); StackTraceElement[] stackTrace = cause.getStackTrace();
} for (StackTraceElement stackTraceElement : stackTrace) {
err.append(stackTraceElement.toString()).append("\n");
}
}
err.append("===================================================");
return err.toString();
}
/**
* 读取下载配置文件
*/
public static Properties loadConfig(File file) {
Properties properties = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
properties.load(fis);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
} }
return properties; } catch (IOException e) {
e.printStackTrace();
}
} }
return properties;
/** }
* 保存配置文件
* /**
* @param file * 保存配置文件
* @param properties */
*/ public static void saveConfig(File file, Properties properties) {
public static void saveConfig(File file, Properties properties) { FileOutputStream fos = null;
FileOutputStream fos = null; try {
try { fos = new FileOutputStream(file, false);
fos = new FileOutputStream(file, false); properties.store(fos, null);
properties.store(fos, null); } catch (Exception e) {
} catch (Exception e) { e.printStackTrace();
e.printStackTrace(); } finally {
} finally { try {
try { if (fos != null) {
if (fos != null) { fos.flush();
fos.flush(); fos.close();
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
} }
} catch (IOException e) {
e.printStackTrace();
}
} }
}
} }

@ -1,8 +1,8 @@
<resources> <resources>
<string name="app_name">DownloadUtil</string> <string name="app_name">DownloadUtil</string>
<string name="error_entity_null">下载实体不能为空</string> <string name="error_entity_null">下载实体不能为空</string>
<string name="error_download_url_null">下载链接不能为空</string> <string name="error_download_url_null">下载链接不能为空</string>
<string name="error_download_path_null">存储地址不能为空</string> <string name="error_download_path_null">存储地址不能为空</string>
<string name="error_file_name_null">文件名不能为空</string> <string name="error_file_name_null">文件名不能为空</string>
</resources> </resources>

@ -2,14 +2,13 @@ package com.arialyy.downloadutil;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
/** /**
* To work on unit tests, switch the Test Artifact in the Build Variants view. * To work on unit tests, switch the Test Artifact in the Build Variants view.
*/ */
public class ExampleUnitTest { public class ExampleUnitTest {
@Test @Test public void addition_isCorrect() throws Exception {
public void addition_isCorrect() throws Exception { assertEquals(4, 2 + 2);
assertEquals(4, 2 + 2); }
}
} }
Loading…
Cancel
Save