下载工具死锁修复

pull/2/head
lyy 9 years ago
commit 4a589e947c
  1. BIN
      .gradle/2.10/taskArtifacts/cache.properties.lock
  2. BIN
      .gradle/2.10/taskArtifacts/fileHashes.bin
  3. BIN
      .gradle/2.10/taskArtifacts/fileSnapshots.bin
  4. BIN
      .gradle/2.10/taskArtifacts/outputFileStates.bin
  5. BIN
      .gradle/2.10/taskArtifacts/taskArtifacts.bin
  6. 229
      .idea/codeStyleSettings.xml
  7. 3
      .idea/dictionaries/AriaL.xml
  8. 2
      .idea/misc.xml
  9. 2
      app/build.gradle
  10. 6
      app/src/androidTest/java/com/example/arial/downloaddemo/ApplicationTest.java
  11. 45
      app/src/main/AndroidManifest.xml
  12. 102
      app/src/main/java/com/arialyy/simple/activity/MainActivity.java
  13. 91
      app/src/main/java/com/arialyy/simple/activity/MultiTaskActivity.java
  14. 248
      app/src/main/java/com/arialyy/simple/activity/SimpleTestActivity.java
  15. 241
      app/src/main/java/com/arialyy/simple/activity/SingleTaskActivity.java
  16. 265
      app/src/main/java/com/arialyy/simple/adapter/DownloadAdapter.java
  17. 11
      app/src/main/java/com/arialyy/simple/base/BaseActivity.java
  18. 11
      app/src/main/java/com/arialyy/simple/base/BaseApplication.java
  19. 7
      app/src/main/java/com/arialyy/simple/base/BaseModule.java
  20. 136
      app/src/main/java/com/arialyy/simple/module/DownloadModule.java
  21. 319
      app/src/main/java/com/arialyy/simple/widget/HorizontalProgressBarWithNumber.java
  22. 38
      app/src/main/res/layout/activity_main.xml
  23. 20
      app/src/main/res/layout/activity_multi.xml
  24. 42
      app/src/main/res/layout/activity_simple.xml
  25. 34
      app/src/main/res/layout/activity_single.xml
  26. 72
      app/src/main/res/layout/content_simple.xml
  27. 72
      app/src/main/res/layout/content_single.xml
  28. 40
      app/src/main/res/layout/item_download.xml
  29. 10
      app/src/main/res/layout/layout_bar.xml
  30. 16
      app/src/main/res/menu/menu_main.xml
  31. 34
      app/src/main/res/values-v21/styles.xml
  32. 8
      app/src/main/res/values-w820dp/dimens.xml
  33. 26
      app/src/main/res/values/attr.xml
  34. 6
      app/src/main/res/values/colors.xml
  35. 8
      app/src/main/res/values/dimens.xml
  36. 30
      app/src/main/res/values/strings.xml
  37. 34
      app/src/main/res/values/styles.xml
  38. 14
      app/src/test/java/com/example/arial/downloaddemo/ExampleUnitTest.java
  39. 0
      cache/build/mPro.properties
  40. 6
      downloadutil/src/androidTest/java/com/arialyy/downloadutil/ApplicationTest.java
  41. 12
      downloadutil/src/main/AndroidManifest.xml
  42. 227
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadManager.java
  43. 171
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadTarget.java
  44. 349
      downloadutil/src/main/java/com/arialyy/downloadutil/core/IDownloadTarget.java
  45. 2
      downloadutil/src/main/java/com/arialyy/downloadutil/core/TaskEnum.java
  46. 49
      downloadutil/src/main/java/com/arialyy/downloadutil/core/TaskFactory.java
  47. 23
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/AddCommand.java
  48. 25
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/CancelCommand.java
  49. 195
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/CommandFactory.java
  50. 63
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/IDownloadCommand.java
  51. 25
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/StartCommand.java
  52. 21
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/StateCommand.java
  53. 39
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/StopCommand.java
  54. 48
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IDownloader.java
  55. 74
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/IPool.java
  56. 68
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/ITask.java
  57. 158
      downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/CachePool.java
  58. 232
      downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/ExecutePool.java
  59. 351
      downloadutil/src/main/java/com/arialyy/downloadutil/entity/DownloadEntity.java
  60. 66
      downloadutil/src/main/java/com/arialyy/downloadutil/help/CheckHelp.java
  61. 83
      downloadutil/src/main/java/com/arialyy/downloadutil/help/PathHelp.java
  62. 245
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/DbEntity.java
  63. 724
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/DbUtil.java
  64. 2
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/Id.java
  65. 2
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/Ignore.java
  66. 34
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/SqlHelper.java
  67. 857
      downloadutil/src/main/java/com/arialyy/downloadutil/util/DownLoadUtil.java
  68. 98
      downloadutil/src/main/java/com/arialyy/downloadutil/util/IDownloadListener.java
  69. 430
      downloadutil/src/main/java/com/arialyy/downloadutil/util/Task.java
  70. 454
      downloadutil/src/main/java/com/arialyy/downloadutil/util/Util.java
  71. 10
      downloadutil/src/main/res/values/strings.xml
  72. 14
      downloadutil/src/test/java/com/arialyy/downloadutil/ExampleUnitTest.java

@ -0,0 +1,229 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value />
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="android" withSubpackages="true" static="false" />
<emptyLine />
<package name="com" withSubpackages="true" static="false" />
<emptyLine />
<package name="junit" withSubpackages="true" static="false" />
<emptyLine />
<package name="net" withSubpackages="true" static="false" />
<emptyLine />
<package name="org" withSubpackages="true" static="false" />
<emptyLine />
<package name="java" withSubpackages="true" static="false" />
<emptyLine />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="true" />
<emptyLine />
</value>
</option>
<option name="RIGHT_MARGIN" value="100" />
<AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true" />
</AndroidXmlCodeStyleSettings>
<Objective-C-extensions>
<option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
<option name="RELEASE_STYLE" value="IVAR" />
<option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" />
<pair source="c" header="h" />
</extensions>
</Objective-C-extensions>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</value>
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Aria" />
</component>
</project>

@ -0,0 +1,3 @@
<component name="ProjectDictionaryState">
<dictionary name="AriaL" />
</component>

@ -37,7 +37,7 @@
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<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">
<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">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

@ -1,7 +1,7 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 'Google Inc.:Google APIs:23'
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {

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

@ -1,29 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.arialyy.simple">
package="com.arialyy.simple">
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:name=".base.BaseApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
<application
android:name=".base.BaseApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--android:name=".activity.SingleTaskActivity"-->
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!--android:name=".activity.SimpleTestActivity"-->
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".activity.SingleTaskActivity"/>
<activity android:name=".activity.MultiTaskActivity"/>
</application>
</manifest>

@ -1,90 +1,38 @@
package com.arialyy.simple.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.frame.util.show.L;
import android.support.v7.widget.Toolbar;
import android.view.View;
import butterknife.Bind;
import com.arialyy.simple.R;
import com.arialyy.simple.adapter.DownloadAdapter;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityMainBinding;
import com.arialyy.simple.module.DownloadModule;
import butterknife.Bind;
/**
* Created by Lyy on 2016/9/27.
* Created by Lyy on 2016/10/13.
*/
public class MainActivity extends BaseActivity<ActivityMainBinding> {
@Bind(R.id.list) RecyclerView mList;
DownloadAdapter mAdapter;
@Override protected int setLayoutId() {
return R.layout.activity_main;
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
mAdapter = new DownloadAdapter(this, getModule(DownloadModule.class).getDownloadData());
mList.setLayoutManager(new LinearLayoutManager(this));
mList.setAdapter(mAdapter);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
long len = 0;
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
DownloadEntity entity = intent.getParcelableExtra(DownloadManager.ENTITY);
switch (action) {
case DownloadManager.ACTION_PRE:
len = entity.getFileSize();
L.d(TAG, "download pre");
break;
case DownloadManager.ACTION_START:
L.d(TAG, "download start");
break;
case DownloadManager.ACTION_RESUME:
L.d(TAG, "download resume");
long location = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 1);
mAdapter.updateState(entity);
break;
case DownloadManager.ACTION_RUNNING:
long current = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 0);
mAdapter.setProgress(entity.getDownloadUrl(), current);
break;
case DownloadManager.ACTION_STOP:
L.d(TAG, "download stop");
mAdapter.updateState(entity);
break;
case DownloadManager.ACTION_COMPLETE:
L.d(TAG, "download complete");
mAdapter.updateState(entity);
break;
case DownloadManager.ACTION_CANCEL:
L.d(TAG, "download cancel");
break;
case DownloadManager.ACTION_FAIL:
L.d(TAG, "download fail");
break;
}
}
};
@Override protected void onResume() {
super.onResume();
registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter());
}
@Override protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
@Bind(R.id.toolbar) Toolbar mBar;
@Override protected int setLayoutId() {
return R.layout.activity_main;
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
setSupportActionBar(mBar);
mBar.setTitle("多线程多任务下载");
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.single_task:
startActivity(new Intent(this, SingleTaskActivity.class));
break;
case R.id.multi_task:
startActivity(new Intent(this, MultiTaskActivity.class));
break;
}
}
}

@ -0,0 +1,91 @@
package com.arialyy.simple.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import butterknife.Bind;
import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R;
import com.arialyy.simple.adapter.DownloadAdapter;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityMultiBinding;
import com.arialyy.simple.module.DownloadModule;
/**
* Created by Lyy on 2016/9/27.
*/
public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> {
@Bind(R.id.list) RecyclerView mList;
@Bind(R.id.toolbar) Toolbar mBar;
DownloadAdapter mAdapter;
@Override protected int setLayoutId() {
return R.layout.activity_multi;
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
setSupportActionBar(mBar);
mBar.setTitle("多任务下载");
mAdapter = new DownloadAdapter(this, getModule(DownloadModule.class).getDownloadData());
mList.setLayoutManager(new LinearLayoutManager(this));
mList.setAdapter(mAdapter);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
long len = 0;
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
DownloadEntity entity = intent.getParcelableExtra(DownloadManager.ENTITY);
switch (action) {
case DownloadManager.ACTION_PRE:
len = entity.getFileSize();
L.d(TAG, "download pre");
break;
case DownloadManager.ACTION_START:
L.d(TAG, "download start");
break;
case DownloadManager.ACTION_RESUME:
L.d(TAG, "download resume");
long location = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 1);
mAdapter.updateState(entity);
break;
case DownloadManager.ACTION_RUNNING:
long current = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 0);
mAdapter.setProgress(entity.getDownloadUrl(), current);
break;
case DownloadManager.ACTION_STOP:
L.d(TAG, "download stop");
mAdapter.updateState(entity);
break;
case DownloadManager.ACTION_COMPLETE:
L.d(TAG, "download complete");
mAdapter.updateState(entity);
break;
case DownloadManager.ACTION_CANCEL:
L.d(TAG, "download cancel");
break;
case DownloadManager.ACTION_FAIL:
L.d(TAG, "download fail");
break;
}
}
};
@Override protected void onResume() {
super.onResume();
registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter());
}
@Override protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}

@ -1,248 +0,0 @@
package com.arialyy.simple.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.downloadutil.core.command.CommandFactory;
import com.arialyy.downloadutil.core.command.IDownloadCommand;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.orm.DbEntity;
import com.arialyy.downloadutil.util.Util;
import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivitySimpleBinding;
import com.arialyy.simple.module.DownloadModule;
import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
public class SimpleTestActivity extends BaseActivity<ActivitySimpleBinding> {
private static final int DOWNLOAD_PRE = 0x01;
private static final int DOWNLOAD_STOP = 0x02;
private static final int DOWNLOAD_FAILE = 0x03;
private static final int DOWNLOAD_CANCEL = 0x04;
private static final int DOWNLOAD_RESUME = 0x05;
private static final int DOWNLOAD_COMPLETE = 0x06;
private ProgressBar mPb;
private String mDownloadUrl = "http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk";
private Button mStart, mStop, mCancel;
private TextView mSize;
@Bind(R.id.toolbar) Toolbar toolbar;
private CommandFactory mFactory;
private DownloadManager mManager;
private DownloadEntity mEntity;
private Handler mUpdateHandler = new Handler() {
@Override public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case DOWNLOAD_PRE:
mSize.setText(Util.formatFileSize((Long) msg.obj));
setBtState(false);
break;
case DOWNLOAD_FAILE:
Toast.makeText(SimpleTestActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
setBtState(true);
break;
case DOWNLOAD_STOP:
Toast.makeText(SimpleTestActivity.this, "暂停下载", Toast.LENGTH_SHORT).show();
mStart.setText("恢复");
setBtState(true);
break;
case DOWNLOAD_CANCEL:
mPb.setProgress(0);
Toast.makeText(SimpleTestActivity.this, "取消下载", Toast.LENGTH_SHORT).show();
mStart.setText("开始");
setBtState(true);
break;
case DOWNLOAD_RESUME:
Toast.makeText(SimpleTestActivity.this,
"恢复下载,恢复位置 ==> " + Util.formatFileSize((Long) msg.obj),
Toast.LENGTH_SHORT).show();
setBtState(false);
break;
case DOWNLOAD_COMPLETE:
Toast.makeText(SimpleTestActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
mStart.setText("重新开始?");
mCancel.setEnabled(false);
setBtState(true);
break;
}
}
};
/**
* 设置start stop 按钮状态
*
* @param state
*/
private void setBtState(boolean state) {
mStart.setEnabled(state);
mStop.setEnabled(!state);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
long len = 0;
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case DownloadManager.ACTION_PRE:
DownloadEntity entity = intent.getParcelableExtra(DownloadManager.ENTITY);
len = entity.getFileSize();
L.d(TAG, "download pre");
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, len).sendToTarget();
break;
case DownloadManager.ACTION_START:
L.d(TAG, "download start");
break;
case DownloadManager.ACTION_RESUME:
L.d(TAG, "download resume");
long location = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 1);
mUpdateHandler.obtainMessage(DOWNLOAD_RESUME, location).sendToTarget();
break;
case DownloadManager.ACTION_RUNNING:
long current = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 0);
if (len == 0) {
mPb.setProgress(0);
} else {
mPb.setProgress((int) ((current * 100) / len));
}
break;
case DownloadManager.ACTION_STOP:
L.d(TAG, "download stop");
mUpdateHandler.sendEmptyMessage(DOWNLOAD_STOP);
break;
case DownloadManager.ACTION_COMPLETE:
mUpdateHandler.sendEmptyMessage(DOWNLOAD_COMPLETE);
break;
case DownloadManager.ACTION_CANCEL:
mUpdateHandler.sendEmptyMessage(DOWNLOAD_CANCEL);
break;
case DownloadManager.ACTION_FAIL:
mUpdateHandler.sendEmptyMessage(DOWNLOAD_FAILE);
break;
}
}
};
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
@Override protected void onResume() {
super.onResume();
registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter());
}
@Override protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
@Override protected int setLayoutId() {
return R.layout.activity_simple;
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
setSupportActionBar(toolbar);
init();
}
private void init() {
mPb = (ProgressBar) findViewById(R.id.progressBar);
mStart = (Button) findViewById(R.id.start);
mStop = (Button) findViewById(R.id.stop);
mCancel = (Button) findViewById(R.id.cancel);
mSize = (TextView) findViewById(R.id.size);
mFactory = CommandFactory.getInstance();
mManager = DownloadManager.getInstance();
mEntity = DbEntity.findData(DownloadEntity.class, new String[]{"downloadUrl"},
new String[]{mDownloadUrl});
if (mEntity != null) {
mPb.setProgress((int) ((mEntity.getCurrentProgress() * 100) / mEntity.getFileSize()));
mSize.setText(Util.formatFileSize(mEntity.getFileSize()));
if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) {
setBtState(false);
} else if (mEntity.isDownloadComplete()) {
mStart.setText("重新开始?");
setBtState(true);
}
} else {
mEntity = new DownloadEntity();
}
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
start();
// if (PermissionManager.getInstance()
// .checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// start();
// } else {
// PermissionManager.getInstance()
// .requestPermission(this, new OnPermissionCallback() {
// @Override public void onSuccess(String... permissions) {
// start();
// }
//
// @Override public void onFail(String... permissions) {
//
// }
// }, Manifest.permission.WRITE_EXTERNAL_STORAGE);
// }
break;
case R.id.stop:
stop();
break;
case R.id.cancel:
cancel();
break;
}
}
private void start() {
mEntity.setFileName("test.apk");
mEntity.setDownloadUrl(mDownloadUrl);
mEntity.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk");
List<IDownloadCommand> commands = new ArrayList<>();
IDownloadCommand addCommand = mFactory.createCommand(this, mEntity,
CommandFactory.TASK_CREATE);
IDownloadCommand startCommand = mFactory.createCommand(this, mEntity,
CommandFactory.TASK_START);
commands.add(addCommand);
commands.add(startCommand);
mManager.setCommands(commands).exe();
}
private void stop() {
IDownloadCommand stopCommand = mFactory.createCommand(this, mEntity,
CommandFactory.TASK_STOP);
mManager.setCommand(stopCommand).exe();
}
private void cancel() {
IDownloadCommand cancelCommand = mFactory.createCommand(this, mEntity,
CommandFactory.TASK_CANCEL);
mManager.setCommand(cancelCommand).exe();
}
}

@ -0,0 +1,241 @@
package com.arialyy.simple.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.Bind;
import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.downloadutil.core.command.CommandFactory;
import com.arialyy.downloadutil.core.command.IDownloadCommand;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.orm.DbEntity;
import com.arialyy.downloadutil.util.Util;
import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivitySingleBinding;
import com.arialyy.simple.module.DownloadModule;
import java.util.ArrayList;
import java.util.List;
public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
private static final int DOWNLOAD_PRE = 0x01;
private static final int DOWNLOAD_STOP = 0x02;
private static final int DOWNLOAD_FAILE = 0x03;
private static final int DOWNLOAD_CANCEL = 0x04;
private static final int DOWNLOAD_RESUME = 0x05;
private static final int DOWNLOAD_COMPLETE = 0x06;
private ProgressBar mPb;
private String mDownloadUrl =
"http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk";
private Button mStart, mStop, mCancel;
private TextView mSize;
@Bind(R.id.toolbar) Toolbar toolbar;
private CommandFactory mFactory;
private DownloadManager mManager;
private DownloadEntity mEntity;
private Handler mUpdateHandler = new Handler() {
@Override public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case DOWNLOAD_PRE:
mSize.setText(Util.formatFileSize((Long) msg.obj));
setBtState(false);
break;
case DOWNLOAD_FAILE:
Toast.makeText(SingleTaskActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
setBtState(true);
break;
case DOWNLOAD_STOP:
Toast.makeText(SingleTaskActivity.this, "暂停下载", Toast.LENGTH_SHORT).show();
mStart.setText("恢复");
setBtState(true);
break;
case DOWNLOAD_CANCEL:
mPb.setProgress(0);
Toast.makeText(SingleTaskActivity.this, "取消下载", Toast.LENGTH_SHORT).show();
mStart.setText("开始");
setBtState(true);
break;
case DOWNLOAD_RESUME:
Toast.makeText(SingleTaskActivity.this,
"恢复下载,恢复位置 ==> " + Util.formatFileSize((Long) msg.obj), Toast.LENGTH_SHORT).show();
setBtState(false);
break;
case DOWNLOAD_COMPLETE:
Toast.makeText(SingleTaskActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
mStart.setText("重新开始?");
mCancel.setEnabled(false);
setBtState(true);
break;
}
}
};
/**
* 设置start stop 按钮状态
*/
private void setBtState(boolean state) {
mStart.setEnabled(state);
mStop.setEnabled(!state);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
long len = 0;
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case DownloadManager.ACTION_PRE:
DownloadEntity entity = intent.getParcelableExtra(DownloadManager.ENTITY);
len = entity.getFileSize();
L.d(TAG, "download pre");
mUpdateHandler.obtainMessage(DOWNLOAD_PRE, len).sendToTarget();
break;
case DownloadManager.ACTION_START:
L.d(TAG, "download start");
break;
case DownloadManager.ACTION_RESUME:
L.d(TAG, "download resume");
long location = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 1);
mUpdateHandler.obtainMessage(DOWNLOAD_RESUME, location).sendToTarget();
break;
case DownloadManager.ACTION_RUNNING:
long current = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 0);
if (len == 0) {
mPb.setProgress(0);
} else {
mPb.setProgress((int) ((current * 100) / len));
}
break;
case DownloadManager.ACTION_STOP:
L.d(TAG, "download stop");
mUpdateHandler.sendEmptyMessage(DOWNLOAD_STOP);
break;
case DownloadManager.ACTION_COMPLETE:
mUpdateHandler.sendEmptyMessage(DOWNLOAD_COMPLETE);
break;
case DownloadManager.ACTION_CANCEL:
mUpdateHandler.sendEmptyMessage(DOWNLOAD_CANCEL);
break;
case DownloadManager.ACTION_FAIL:
mUpdateHandler.sendEmptyMessage(DOWNLOAD_FAILE);
break;
}
}
};
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init();
}
@Override protected void onResume() {
super.onResume();
registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter());
}
@Override protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
@Override protected int setLayoutId() {
return R.layout.activity_single;
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
setSupportActionBar(toolbar);
toolbar.setTitle("单任务下载");
init();
}
private void init() {
mPb = (ProgressBar) findViewById(R.id.progressBar);
mStart = (Button) findViewById(R.id.start);
mStop = (Button) findViewById(R.id.stop);
mCancel = (Button) findViewById(R.id.cancel);
mSize = (TextView) findViewById(R.id.size);
mFactory = CommandFactory.getInstance();
mManager = DownloadManager.getInstance();
mEntity = DbEntity.findData(DownloadEntity.class, new String[] { "downloadUrl" },
new String[] { mDownloadUrl });
if (mEntity != null) {
mPb.setProgress((int) ((mEntity.getCurrentProgress() * 100) / mEntity.getFileSize()));
mSize.setText(Util.formatFileSize(mEntity.getFileSize()));
if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) {
setBtState(false);
} else if (mEntity.isDownloadComplete()) {
mStart.setText("重新开始?");
setBtState(true);
}
} else {
mEntity = new DownloadEntity();
}
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.start:
start();
// if (PermissionManager.getInstance()
// .checkPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// start();
// } else {
// PermissionManager.getInstance()
// .requestPermission(this, new OnPermissionCallback() {
// @Override public void onSuccess(String... permissions) {
// start();
// }
//
// @Override public void onFail(String... permissions) {
//
// }
// }, Manifest.permission.WRITE_EXTERNAL_STORAGE);
// }
break;
case R.id.stop:
stop();
break;
case R.id.cancel:
cancel();
break;
}
}
private void start() {
mEntity.setFileName("test.apk");
mEntity.setDownloadUrl(mDownloadUrl);
mEntity.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk");
List<IDownloadCommand> commands = new ArrayList<>();
IDownloadCommand addCommand = mFactory.createCommand(this, mEntity, CommandFactory.TASK_CREATE);
IDownloadCommand startCommand =
mFactory.createCommand(this, mEntity, CommandFactory.TASK_START);
commands.add(addCommand);
commands.add(startCommand);
mManager.setCommands(commands).exe();
}
private void stop() {
IDownloadCommand stopCommand = mFactory.createCommand(this, mEntity, CommandFactory.TASK_STOP);
mManager.setCommand(stopCommand).exe();
}
private void cancel() {
IDownloadCommand cancelCommand =
mFactory.createCommand(this, mEntity, CommandFactory.TASK_CANCEL);
mManager.setCommand(cancelCommand).exe();
}
}

@ -4,7 +4,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.view.View;
import android.widget.Button;
import butterknife.Bind;
import com.arialyy.absadapter.common.AbsHolder;
import com.arialyy.absadapter.recycler_view.AbsRVAdapter;
import com.arialyy.downloadutil.core.DownloadManager;
@ -14,165 +14,162 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R;
import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import butterknife.Bind;
/**
* Created by Lyy on 2016/9/27.
* 下载列表适配器
*/
public class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapter.MyHolder> {
private static final String TAG = "DownloadAdapter";
private DownloadManager mManager;
private CommandFactory mFactory;
private Map<String, Long> mProgress = new HashMap<>();
private Map<String, Integer> mPositions = new HashMap<>();
public DownloadAdapter(Context context, List<DownloadEntity> data) {
super(context, data);
int i = 0;
for (DownloadEntity entity : data) {
mProgress.put(entity.getDownloadUrl(), entity.getCurrentProgress());
mPositions.put(entity.getDownloadUrl(), i);
i++;
}
mFactory = CommandFactory.getInstance();
mManager = DownloadManager.getInstance();
private static final String TAG = "DownloadAdapter";
private DownloadManager mManager;
private CommandFactory mFactory;
private Map<String, Long> mProgress = new HashMap<>();
private Map<String, Integer> mPositions = new HashMap<>();
public DownloadAdapter(Context context, List<DownloadEntity> data) {
super(context, data);
int i = 0;
for (DownloadEntity entity : data) {
mProgress.put(entity.getDownloadUrl(), entity.getCurrentProgress());
mPositions.put(entity.getDownloadUrl(), i);
i++;
}
@Override protected MyHolder getViewHolder(View convertView, int viewType) {
return new MyHolder(convertView);
mFactory = CommandFactory.getInstance();
mManager = DownloadManager.getInstance();
}
@Override protected MyHolder getViewHolder(View convertView, int viewType) {
return new MyHolder(convertView);
}
@Override protected int setLayoutId(int type) {
return R.layout.item_download;
}
public synchronized void updateState(DownloadEntity entity) {
notifyItemChanged(indexItem(entity.getDownloadUrl()));
}
public synchronized void setProgress(String url, long currentPosition) {
mProgress.put(url, currentPosition);
// int index = indexItem(url);
// L.d(TAG, "index ==> " + index);
// notifyItemChanged(index);
notifyItemChanged(indexItem(url));
}
private synchronized int indexItem(String url) {
Set set = mPositions.entrySet();
for (Object aSet : set) {
Map.Entry entry = (Map.Entry) aSet;
if (entry.getKey().equals(url)) {
return (int) entry.getValue();
}
}
@Override protected int setLayoutId(int type) {
return R.layout.item_download;
return -1;
}
@Override protected void bindData(MyHolder holder, int position, DownloadEntity item) {
//holder.progress.setProgress(item.getCurrentProgress());
long size = item.getFileSize();
int current = 0;
if (size == 0) {
current = 0;
}
public synchronized void updateState(DownloadEntity entity) {
notifyItemChanged(indexItem(entity.getDownloadUrl()));
current = (int) (mProgress.get(item.getDownloadUrl()) * 100 / item.getFileSize());
holder.progress.setProgress(current);
BtClickListener listener = new BtClickListener(position, item);
holder.bt.setOnClickListener(listener);
String str = "";
int color = android.R.color.holo_green_light;
switch (item.getState()) {
case DownloadEntity.STATE_WAIT:
case DownloadEntity.STATE_OTHER:
case DownloadEntity.STATE_FAIL:
str = "开始";
break;
case DownloadEntity.STATE_STOP:
str = "恢复";
color = android.R.color.holo_blue_light;
break;
case DownloadEntity.STATE_DOWNLOAD_ING:
str = "暂停";
color = android.R.color.holo_red_light;
break;
case DownloadEntity.STATE_COMPLETE:
str = "重新开始?";
holder.progress.setProgress(100);
break;
}
holder.bt.setText(str);
holder.bt.setTextColor(getColor(color));
}
private int getColor(int color) {
return Resources.getSystem().getColor(color);
}
public synchronized void setProgress(String url, long currentPosition) {
mProgress.put(url, currentPosition);
// int index = indexItem(url);
// L.d(TAG, "index ==> " + index);
// notifyItemChanged(index);
notifyItemChanged(indexItem(url));
private class BtClickListener implements View.OnClickListener {
private DownloadEntity entity;
private int position;
BtClickListener(int position, DownloadEntity entity) {
this.entity = entity;
this.position = position;
}
private synchronized int indexItem(String url) {
Set set = mPositions.entrySet();
for (Object aSet : set) {
Map.Entry entry = (Map.Entry) aSet;
if (entry.getKey().equals(url)) {
return (int) entry.getValue();
}
}
return -1;
@Override public void onClick(View v) {
L.d(TAG, "position ==> " + position);
switch (entity.getState()) {
case DownloadEntity.STATE_WAIT:
case DownloadEntity.STATE_OTHER:
case DownloadEntity.STATE_FAIL:
case DownloadEntity.STATE_STOP:
case DownloadEntity.STATE_COMPLETE:
start(entity);
break;
case DownloadEntity.STATE_DOWNLOAD_ING:
stop(entity);
break;
}
}
@Override protected void bindData(MyHolder holder, int position, DownloadEntity item) {
//holder.progress.setProgress(item.getCurrentProgress());
long size = item.getFileSize();
int current = 0;
if (size == 0) {
current = 0;
}
current = (int) (mProgress.get(item.getDownloadUrl()) * 100 / item.getFileSize());
holder.progress.setProgress(current);
BtClickListener listener = new BtClickListener(position, item);
holder.bt.setOnClickListener(listener);
String str = "";
int color = android.R.color.holo_green_light;
switch (item.getState()) {
case DownloadEntity.STATE_WAIT:
case DownloadEntity.STATE_OTHER:
case DownloadEntity.STATE_FAIL:
str = "开始";
break;
case DownloadEntity.STATE_STOP:
str = "恢复";
color = android.R.color.holo_blue_light;
break;
case DownloadEntity.STATE_DOWNLOAD_ING:
str = "暂停";
color = android.R.color.holo_red_light;
break;
case DownloadEntity.STATE_COMPLETE:
str = "重新开始?";
holder.progress.setProgress(100);
break;
}
holder.bt.setText(str);
holder.bt.setTextColor(getColor(color));
private void start(DownloadEntity entity) {
List<IDownloadCommand> commands = new ArrayList<>();
IDownloadCommand addCommand =
mFactory.createCommand(getContext(), entity, CommandFactory.TASK_CREATE);
IDownloadCommand startCommand =
mFactory.createCommand(getContext(), entity, CommandFactory.TASK_START);
commands.add(addCommand);
commands.add(startCommand);
mManager.setCommands(commands).exe();
}
private int getColor(int color) {
return Resources.getSystem().getColor(color);
private void stop(DownloadEntity entity) {
IDownloadCommand stopCommand =
mFactory.createCommand(getContext(), entity, CommandFactory.TASK_STOP);
mManager.setCommand(stopCommand).exe();
}
private class BtClickListener implements View.OnClickListener {
private DownloadEntity entity;
private int position;
BtClickListener(int position, DownloadEntity entity) {
this.entity = entity;
this.position = position;
}
@Override public void onClick(View v) {
L.d(TAG, "position ==> " + position);
switch (entity.getState()) {
case DownloadEntity.STATE_WAIT:
case DownloadEntity.STATE_OTHER:
case DownloadEntity.STATE_FAIL:
case DownloadEntity.STATE_STOP:
case DownloadEntity.STATE_COMPLETE:
start(entity);
break;
case DownloadEntity.STATE_DOWNLOAD_ING:
stop(entity);
break;
}
}
private void start(DownloadEntity entity) {
List<IDownloadCommand> commands = new ArrayList<>();
IDownloadCommand addCommand = mFactory.createCommand(getContext(), entity,
CommandFactory.TASK_CREATE);
IDownloadCommand startCommand = mFactory.createCommand(getContext(), entity,
CommandFactory.TASK_START);
commands.add(addCommand);
commands.add(startCommand);
mManager.setCommands(commands).exe();
}
private void stop(DownloadEntity entity) {
IDownloadCommand stopCommand = mFactory.createCommand(getContext(), entity,
CommandFactory.TASK_STOP);
mManager.setCommand(stopCommand).exe();
}
private void cancel(DownloadEntity entity) {
IDownloadCommand cancelCommand = mFactory.createCommand(getContext(), entity,
CommandFactory.TASK_CANCEL);
mManager.setCommand(cancelCommand).exe();
}
private void cancel(DownloadEntity entity) {
IDownloadCommand cancelCommand =
mFactory.createCommand(getContext(), entity, CommandFactory.TASK_CANCEL);
mManager.setCommand(cancelCommand).exe();
}
}
class MyHolder extends AbsHolder {
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber progress;
@Bind(R.id.bt) Button bt;
class MyHolder extends AbsHolder {
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber progress;
@Bind(R.id.bt) Button bt;
MyHolder(View itemView) {
super(itemView);
}
MyHolder(View itemView) {
super(itemView);
}
}
}

@ -2,18 +2,17 @@ package com.arialyy.simple.base;
import android.databinding.ViewDataBinding;
import android.os.Bundle;
import com.arialyy.frame.core.AbsActivity;
/**
* Created by Lyy on 2016/9/27.
*/
public abstract class BaseActivity<VB extends ViewDataBinding> extends AbsActivity<VB> {
@Override protected void dataCallback(int result, Object data) {
@Override protected void dataCallback(int result, Object data) {
}
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
}
@Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState);
}
}

@ -1,7 +1,6 @@
package com.arialyy.simple.base;
import android.app.Application;
import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.frame.core.AbsFrame;
@ -9,9 +8,9 @@ import com.arialyy.frame.core.AbsFrame;
* Created by Lyy on 2016/9/27.
*/
public class BaseApplication extends Application {
@Override public void onCreate() {
super.onCreate();
AbsFrame.init(this);
DownloadManager.init(this);
}
@Override public void onCreate() {
super.onCreate();
AbsFrame.init(this);
DownloadManager.init(this);
}
}

@ -1,14 +1,13 @@
package com.arialyy.simple.base;
import android.content.Context;
import com.arialyy.frame.module.AbsModule;
/**
* Created by Lyy on 2016/9/27.
*/
public class BaseModule extends AbsModule {
public BaseModule(Context context) {
super(context);
}
public BaseModule(Context context) {
super(context);
}
}

@ -3,7 +3,6 @@ package com.arialyy.simple.module;
import android.content.Context;
import android.content.IntentFilter;
import android.os.Environment;
import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Util;
@ -11,7 +10,6 @@ import com.arialyy.frame.util.AndroidUtils;
import com.arialyy.frame.util.StringUtil;
import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseModule;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@ -20,65 +18,95 @@ import java.util.List;
* Created by Lyy on 2016/9/27.
*/
public class DownloadModule extends BaseModule {
public DownloadModule(Context context) {
super(context);
}
public DownloadModule(Context context) {
super(context);
}
/**
* 设置下载数据
*
* @return
*/
public List<DownloadEntity> getDownloadData() {
List<DownloadEntity> list = DownloadEntity.findAllData(DownloadEntity.class);
if (list == null) {
list = createNewDownload();
}
return list;
/**
* 设置下载数据
*/
public List<DownloadEntity> getDownloadData() {
List<DownloadEntity> list = DownloadEntity.findAllData(DownloadEntity.class);
List<DownloadEntity> newDownload = createNewDownload();
if (list == null) {
list = newDownload;
} else {
list = filter(list, newDownload);
}
return list;
}
private List<DownloadEntity> createNewDownload() {
List<DownloadEntity> list = new ArrayList<>();
String[] urls = getContext().getResources()
.getStringArray(R.array.test_apk_download_url);
for (String url : urls) {
String fileName = Util.keyToHashCode(url) + ".apk";
DownloadEntity entity = new DownloadEntity();
entity.setDownloadUrl(url);
entity.setDownloadPath(getDownloadPath(url));
entity.setFileName(fileName);
list.add(entity);
/**
* 过滤任务
*
* @param sqlEntity 数据库的下载实体
* @param createdEntity 通过下载链接生成的下载实体
*/
private List<DownloadEntity> filter(List<DownloadEntity> sqlEntity,
List<DownloadEntity> createdEntity) {
List<DownloadEntity> list = new ArrayList<>();
list.addAll(sqlEntity);
for (DownloadEntity cEntity : createdEntity) {
int count = 0;
for (DownloadEntity sEntity : sqlEntity) {
if (cEntity.getDownloadUrl().equals(sEntity.getDownloadUrl())) {
break;
}
return list;
count++;
if (count == sqlEntity.size()) {
list.add(cEntity);
}
}
}
return list;
}
/**
* 下载广播过滤器
*
* @return
*/
public IntentFilter getDownloadFilter() {
IntentFilter filter = new IntentFilter();
filter.addDataScheme(getContext().getPackageName());
filter.addAction(DownloadManager.ACTION_PRE);
filter.addAction(DownloadManager.ACTION_RESUME);
filter.addAction(DownloadManager.ACTION_START);
filter.addAction(DownloadManager.ACTION_RUNNING);
filter.addAction(DownloadManager.ACTION_STOP);
filter.addAction(DownloadManager.ACTION_CANCEL);
filter.addAction(DownloadManager.ACTION_COMPLETE);
filter.addAction(DownloadManager.ACTION_FAIL);
return filter;
/**
* 创建下载列表
*/
private List<DownloadEntity> createNewDownload() {
List<DownloadEntity> list = new ArrayList<>();
String[] urls =
getContext().getResources().getStringArray(R.array.test_apk_download_url);
for (String url : urls) {
String fileName = Util.keyToHashCode(url) + ".apk";
DownloadEntity entity = new DownloadEntity();
entity.setDownloadUrl(url);
entity.setDownloadPath(getDownloadPath(url));
entity.setFileName(fileName);
list.add(entity);
}
return list;
}
private String getDownloadPath(String url) {
String path = Environment.getExternalStorageDirectory()
.getPath() + "/" + AndroidUtils.getAppName(getContext()) + "downloads/" + StringUtil
.keyToHashKey(url) + ".apk";
File file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
return path;
/**
* 下载广播过滤器
*/
public IntentFilter getDownloadFilter() {
IntentFilter filter = new IntentFilter();
filter.addDataScheme(getContext().getPackageName());
filter.addAction(DownloadManager.ACTION_PRE);
filter.addAction(DownloadManager.ACTION_RESUME);
filter.addAction(DownloadManager.ACTION_START);
filter.addAction(DownloadManager.ACTION_RUNNING);
filter.addAction(DownloadManager.ACTION_STOP);
filter.addAction(DownloadManager.ACTION_CANCEL);
filter.addAction(DownloadManager.ACTION_COMPLETE);
filter.addAction(DownloadManager.ACTION_FAIL);
return filter;
}
/**
* 设置下载队列
*/
private String getDownloadPath(String url) {
String path =
Environment.getExternalStorageDirectory().getPath() + "/" + AndroidUtils.getAppName(
getContext()) + "downloads/" + StringUtil.keyToHashKey(url) + ".apk";
File file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
return path;
}
}

@ -7,178 +7,177 @@ import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ProgressBar;
import com.arialyy.simple.R;
public class HorizontalProgressBarWithNumber extends ProgressBar {
private static final int DEFAULT_TEXT_SIZE = 10;
private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1;
private static final int DEFAULT_COLOR_UNREACHED_COLOR = 0xFFd3d6da;
private static final int DEFAULT_HEIGHT_REACHED_PROGRESS_BAR = 2;
private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2;
private static final int DEFAULT_SIZE_TEXT_OFFSET = 10;
/**
* painter of all drawing things
*/
protected Paint mPaint = new Paint();
/**
* color of progress number
*/
protected int mTextColor = DEFAULT_TEXT_COLOR;
/**
* size of text (sp)
*/
protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
/**
* offset of draw progress
*/
protected int mTextOffset = dp2px(
DEFAULT_SIZE_TEXT_OFFSET);
/**
* height of reached progress bar
*/
protected int mReachedProgressBarHeight = dp2px(
DEFAULT_HEIGHT_REACHED_PROGRESS_BAR);
/**
* color of reached bar
*/
protected int mReachedBarColor = DEFAULT_TEXT_COLOR;
/**
* color of unreached bar
*/
protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR;
/**
* height of unreached progress bar
*/
protected int mUnReachedProgressBarHeight = dp2px(
DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR);
/**
* view width except padding
*/
protected int mRealWidth;
protected boolean mIfDrawText = true;
protected static final int VISIBLE = 0;
private static final int DEFAULT_TEXT_SIZE = 10;
private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1;
private static final int DEFAULT_COLOR_UNREACHED_COLOR = 0xFFd3d6da;
private static final int DEFAULT_HEIGHT_REACHED_PROGRESS_BAR = 2;
private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2;
private static final int DEFAULT_SIZE_TEXT_OFFSET = 10;
/**
* painter of all drawing things
*/
protected Paint mPaint = new Paint();
/**
* color of progress number
*/
protected int mTextColor = DEFAULT_TEXT_COLOR;
/**
* size of text (sp)
*/
protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
/**
* offset of draw progress
*/
protected int mTextOffset =
dp2px(DEFAULT_SIZE_TEXT_OFFSET);
/**
* height of reached progress bar
*/
protected int mReachedProgressBarHeight =
dp2px(DEFAULT_HEIGHT_REACHED_PROGRESS_BAR);
/**
* color of reached bar
*/
protected int mReachedBarColor = DEFAULT_TEXT_COLOR;
/**
* color of unreached bar
*/
protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR;
/**
* height of unreached progress bar
*/
protected int mUnReachedProgressBarHeight =
dp2px(DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR);
/**
* view width except padding
*/
protected int mRealWidth;
protected boolean mIfDrawText = true;
protected static final int VISIBLE = 0;
public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
obtainStyledAttributes(attrs);
mPaint.setTextSize(mTextSize);
mPaint.setColor(mTextColor);
}
public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
obtainStyledAttributes(attrs);
mPaint.setTextSize(mTextSize);
mPaint.setColor(mTextColor);
}
@Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft();
}
@Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft();
}
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
float textHeight = (mPaint.descent() - mPaint.ascent());
result = (int) (getPaddingTop() + getPaddingBottom() + Math.max(
Math.max(mReachedProgressBarHeight, mUnReachedProgressBarHeight),
Math.abs(textHeight))
);
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
float textHeight = (mPaint.descent() - mPaint.ascent());
result = (int) (getPaddingTop() + getPaddingBottom() + Math.max(
Math.max(mReachedProgressBarHeight, mUnReachedProgressBarHeight), Math.abs(textHeight)));
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
/**
* get the styled attributes
*/
private void obtainStyledAttributes(AttributeSet attrs) {
// init values from custom attributes
final TypedArray attributes = getContext().obtainStyledAttributes(attrs,
R.styleable.HorizontalProgressBarWithNumber);
mTextColor = attributes.getColor(
R.styleable.HorizontalProgressBarWithNumber_progress_text_color,
DEFAULT_TEXT_COLOR);
mTextSize = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_text_size, mTextSize);
mReachedBarColor = attributes.getColor(
R.styleable.HorizontalProgressBarWithNumber_progress_reached_color, mTextColor);
mUnReachedBarColor = attributes.getColor(
R.styleable.HorizontalProgressBarWithNumber_progress_unreached_color,
DEFAULT_COLOR_UNREACHED_COLOR);
mReachedProgressBarHeight = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height,
mReachedProgressBarHeight);
mUnReachedProgressBarHeight = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_unreached_bar_height,
mUnReachedProgressBarHeight);
mTextOffset = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_text_offset, mTextOffset);
int textVisible = attributes.getInt(
R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility, VISIBLE);
if (textVisible != VISIBLE) {
mIfDrawText = false;
}
attributes.recycle();
/**
* get the styled attributes
*/
private void obtainStyledAttributes(AttributeSet attrs) {
// init values from custom attributes
final TypedArray attributes =
getContext().obtainStyledAttributes(attrs, R.styleable.HorizontalProgressBarWithNumber);
mTextColor =
attributes.getColor(R.styleable.HorizontalProgressBarWithNumber_progress_text_color,
DEFAULT_TEXT_COLOR);
mTextSize = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_text_size, mTextSize);
mReachedBarColor =
attributes.getColor(R.styleable.HorizontalProgressBarWithNumber_progress_reached_color,
mTextColor);
mUnReachedBarColor =
attributes.getColor(R.styleable.HorizontalProgressBarWithNumber_progress_unreached_color,
DEFAULT_COLOR_UNREACHED_COLOR);
mReachedProgressBarHeight = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height,
mReachedProgressBarHeight);
mUnReachedProgressBarHeight = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_unreached_bar_height,
mUnReachedProgressBarHeight);
mTextOffset = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_text_offset, mTextOffset);
int textVisible =
attributes.getInt(R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility,
VISIBLE);
if (textVisible != VISIBLE) {
mIfDrawText = false;
}
attributes.recycle();
}
@Override protected synchronized void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(getPaddingLeft(), getHeight() / 2);
boolean noNeedBg = false;
float radio = getProgress() * 1.0f / getMax();
float progressPosX = (int) (mRealWidth * radio);
String text = getProgress() + "%";
// mPaint.getTextBounds(text, 0, text.length(), mTextBound);
float textWidth = mPaint.measureText(text);
float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;
if (progressPosX + textWidth > mRealWidth) {
progressPosX = mRealWidth - textWidth;
noNeedBg = true;
}
// draw reached bar
float endX = progressPosX - mTextOffset / 2;
if (endX > 0) {
mPaint.setColor(mReachedBarColor);
mPaint.setStrokeWidth(mReachedProgressBarHeight);
canvas.drawLine(0, 0, endX, 0, mPaint);
}
// draw progress bar
// measure text bound
if (mIfDrawText) {
mPaint.setColor(mTextColor);
canvas.drawText(text, progressPosX, -textHeight, mPaint);
}
// draw unreached bar
if (!noNeedBg) {
float start = progressPosX + mTextOffset / 2 + textWidth;
mPaint.setColor(mUnReachedBarColor);
mPaint.setStrokeWidth(mUnReachedProgressBarHeight);
canvas.drawLine(start, 0, mRealWidth, 0, mPaint);
}
canvas.restore();
@Override protected synchronized void onDraw(Canvas canvas) {
canvas.save();
canvas.translate(getPaddingLeft(), getHeight() / 2);
boolean noNeedBg = false;
float radio = getProgress() * 1.0f / getMax();
float progressPosX = (int) (mRealWidth * radio);
String text = getProgress() + "%";
// mPaint.getTextBounds(text, 0, text.length(), mTextBound);
float textWidth = mPaint.measureText(text);
float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;
if (progressPosX + textWidth > mRealWidth) {
progressPosX = mRealWidth - textWidth;
noNeedBg = true;
}
/**
* dp 2 px
*/
protected int dp2px(int dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
getResources().getDisplayMetrics());
// draw reached bar
float endX = progressPosX - mTextOffset / 2;
if (endX > 0) {
mPaint.setColor(mReachedBarColor);
mPaint.setStrokeWidth(mReachedProgressBarHeight);
canvas.drawLine(0, 0, endX, 0, mPaint);
}
/**
* sp 2 px
*/
protected int sp2px(int spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
getResources().getDisplayMetrics());
// draw progress bar
// measure text bound
if (mIfDrawText) {
mPaint.setColor(mTextColor);
canvas.drawText(text, progressPosX, -textHeight, mPaint);
}
// draw unreached bar
if (!noNeedBg) {
float start = progressPosX + mTextOffset / 2 + textWidth;
mPaint.setColor(mUnReachedBarColor);
mPaint.setStrokeWidth(mUnReachedProgressBarHeight);
canvas.drawLine(start, 0, mRealWidth, 0, mPaint);
}
canvas.restore();
}
/**
* dp 2 px
*/
protected int dp2px(int dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
getResources().getDisplayMetrics());
}
/**
* sp 2 px
*/
protected int sp2px(int spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
getResources().getDisplayMetrics());
}
}

@ -1,18 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<layout xmlns:android="http://schemas.android.com/apk/res/android"
>
<LinearLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include layout="@layout/layout_bar"/>
<Button
android:id="@+id/single_task"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="单任务下载"
style="?buttonBarButtonStyle"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<Button
android:id="@+id/multi_task"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="多任务下载"
style="?buttonBarButtonStyle"
/>
</LinearLayout>
</LinearLayout>
</layout>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include layout="@layout/layout_bar"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
</layout>

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.design.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.arialyy.simple.activity.SimpleTestActivity"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay"
>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
/>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_simple"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email"
/>
</android.support.design.widget.CoordinatorLayout>
</layout>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.design.widget.CoordinatorLayout
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.arialyy.simple.activity.SingleTaskActivity"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay"
>
<include layout="@layout/layout_bar"/>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_single"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email"
/>
</android.support.design.widget.CoordinatorLayout>
</layout>

@ -1,72 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.arialyy.simple.activity.SimpleTestActivity"
tools:showIn="@layout/activity_simple"
>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_margin="16dp"
android:layout_toLeftOf="@+id/size"
/>
<TextView
android:id="@+id/size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/progressBar"
android:layout_marginRight="16dp"
android:text="ssss"
android:textSize="16sp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/progressBar"
android:orientation="horizontal"
>
<Button
android:id="@+id/start"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="开始"
/>
<Button
android:id="@+id/stop"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="暂停"
/>
<Button
android:id="@+id/cancel"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="删除任务"
/>
</LinearLayout>
</RelativeLayout>

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.arialyy.simple.activity.SingleTaskActivity"
tools:showIn="@layout/activity_single"
>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_margin="16dp"
android:layout_toLeftOf="@+id/size"
/>
<TextView
android:id="@+id/size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/progressBar"
android:layout_marginRight="16dp"
android:text="ssss"
android:textSize="16sp"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/progressBar"
android:orientation="horizontal"
>
<Button
android:id="@+id/start"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="开始"
/>
<Button
android:id="@+id/stop"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="暂停"
/>
<Button
android:id="@+id/cancel"
style="?buttonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClick"
android:text="删除任务"
/>
</LinearLayout>
</RelativeLayout>

@ -1,27 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
>
<com.arialyy.simple.widget.HorizontalProgressBarWithNumber
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="16dp"
android:layout_toLeftOf="@+id/bt"
android:max="100"
/>
<com.arialyy.simple.widget.HorizontalProgressBarWithNumber
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="16dp"
android:layout_toLeftOf="@+id/bt"
android:max="100"
/>
<Button
android:id="@+id/bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="开始"
style="?buttonBarButtonStyle"
/>
<Button
android:id="@+id/bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="开始"
style="?buttonBarButtonStyle"
/>
</RelativeLayout>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
/>

@ -1,10 +1,10 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.arial.downloaddemo.com.arialyy.simple.MainActivity">
<item
android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
app:showAsAction="never"/>
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.arial.downloaddemo.com.arialyy.simple.MainActivity">
<item
android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
app:showAsAction="never"/>
</menu>

@ -1,12 +1,28 @@
<resources>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<!--设置导航栏内容可用-->
<!--<item name="android:windowTranslucentNavigation">true</item>-->
<!--设置状态栏内容可以-->
<!--<item name="android:windowTranslucentStatus">true</item>-->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowIsTranslucent">true</item>
</style>
</resources>

@ -1,6 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="HorizontalProgressBarWithNumber">
<attr name="progress_unreached_color" format="color"/>
<attr name="progress_reached_color" format="color"/>
<attr name="progress_reached_bar_height" format="dimension"/>
<attr name="progress_unreached_bar_height" format="dimension"/>
<attr name="progress_text_size" format="dimension"/>
<attr name="progress_text_color" format="color"/>
<attr name="progress_text_offset" format="dimension"/>
<attr name="progress_text_visibility" format="enum">
<enum name="visible" value="0"/>
<enum name="invisible" value="1"/>
</attr>
</declare-styleable>
<declare-styleable name="HorizontalProgressBarWithNumber">
<attr name="progress_unreached_color" format="color"/>
<attr name="progress_reached_color" format="color"/>
<attr name="progress_reached_bar_height" format="dimension"/>
<attr name="progress_unreached_bar_height" format="dimension"/>
<attr name="progress_text_size" format="dimension"/>
<attr name="progress_text_color" format="color"/>
<attr name="progress_text_offset" format="dimension"/>
<attr name="progress_text_visibility" format="enum">
<enum name="visible" value="0"/>
<enum name="invisible" value="1"/>
</attr>
</declare-styleable>
</resources>

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>

@ -1,6 +1,6 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
</resources>

@ -1,18 +1,18 @@
<resources>
<string name="app_name">DownloadDemo</string>
<string name="action_settings">Settings</string>
<string name="app_name">DownloadDemo</string>
<string name="action_settings">Settings</string>
<string-array name="test_apk_download_url">
<item>http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk</item> <!--300M的文件-->
<item>http://static.gaoshouyou.com/d/21/e8/61218d78d0e8b79df68dbc18dd484c97.apk</item>
<item>http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk</item>
<item>http://static.gaoshouyou.com/d/d4/4f/d6d48db3794fb9ecf47e83c346570881.apk</item>
<!--<item>http://static.gaoshouyou.com/d/18/cf/ba18113bc6cf56c1c5863e761e717003.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/60/17/2460921367173ea7145f11194a6f2587.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/32/e0/1a32123ecbe0ee010d35479df248f90f.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/e6/f5/4de6329f9cf5dc3a1d1e6bbcca0d003c.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/6e/e5/ff6ecaaf45e532e6d07747af82357472.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk</item>-->
</string-array>
<string-array name="test_apk_download_url">
<item>http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk</item> <!--300M的文件-->
<item>http://static.gaoshouyou.com/d/21/e8/61218d78d0e8b79df68dbc18dd484c97.apk</item>
<item>http://static.gaoshouyou.com/d/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk</item>
<item>http://static.gaoshouyou.com/d/d4/4f/d6d48db3794fb9ecf47e83c346570881.apk</item>
<!--<item>http://static.gaoshouyou.com/d/18/cf/ba18113bc6cf56c1c5863e761e717003.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/60/17/2460921367173ea7145f11194a6f2587.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/32/e0/1a32123ecbe0ee010d35479df248f90f.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/e6/f5/4de6329f9cf5dc3a1d1e6bbcca0d003c.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/6e/e5/ff6ecaaf45e532e6d07747af82357472.apk</item>-->
<!--<item>http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk</item>-->
</string-array>
</resources>

@ -1,23 +1,25 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
</resources>

@ -1,14 +0,0 @@
package com.example.arial.downloaddemo;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test public void addition_isCorrect() throws Exception {
assertEquals(4, 2 + 2);
}
}

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

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

@ -3,13 +3,10 @@ package com.arialyy.downloadutil.core;
import android.app.Application;
import android.content.Context;
import android.util.Log;
import com.arialyy.downloadutil.core.command.IDownloadCommand;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.orm.DbEntity;
import com.arialyy.downloadutil.orm.DbUtil;
import com.arialyy.downloadutil.util.Task;
import java.util.ArrayList;
import java.util.List;
@ -18,122 +15,122 @@ import java.util.List;
* 下载管理器通过命令的方式控制下载
*/
public class DownloadManager {
private static final String TAG = "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_START = "ACTION_START";
/**
* 恢复下载事件
*/
public static final String ACTION_RESUME = "ACTION_RESUME";
/**
* 正在下载事件
*/
public static final String ACTION_RUNNING = "ACTION_RUNNING";
/**
* 停止下载事件
*/
public static final String ACTION_STOP = "ACTION_STOP";
/**
* 取消下载事件
*/
public static final String ACTION_CANCEL = "ACTION_CANCEL";
/**
* 下载完成事件
*/
public static final String ACTION_COMPLETE = "ACTION_COMPLETE";
/**
* 下载失败事件
*/
public static final String ACTION_FAIL = "ACTION_FAIL";
/**
* 下载实体
*/
public static final String ENTITY = "DOWNLOAD_ENTITY";
/**
* 位置
*/
public static final String CURRENT_LOCATION = "CURRENT_LOCATION";
private List<IDownloadCommand> mCommands = new ArrayList<>();
private DownloadManager() {
}
private Context mContext;
private DownloadManager(Context context) {
mContext = context;
DownloadTarget.init(context);
DbUtil.init(context);
}
public static DownloadManager init(Context context) {
if (context instanceof Application) {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new DownloadManager(context.getApplicationContext());
}
}
} else {
Log.e(TAG, "Context 只能为application");
private static final String TAG = "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_START = "ACTION_START";
/**
* 恢复下载事件
*/
public static final String ACTION_RESUME = "ACTION_RESUME";
/**
* 正在下载事件
*/
public static final String ACTION_RUNNING = "ACTION_RUNNING";
/**
* 停止下载事件
*/
public static final String ACTION_STOP = "ACTION_STOP";
/**
* 取消下载事件
*/
public static final String ACTION_CANCEL = "ACTION_CANCEL";
/**
* 下载完成事件
*/
public static final String ACTION_COMPLETE = "ACTION_COMPLETE";
/**
* 下载失败事件
*/
public static final String ACTION_FAIL = "ACTION_FAIL";
/**
* 下载实体
*/
public static final String ENTITY = "DOWNLOAD_ENTITY";
/**
* 位置
*/
public static final String CURRENT_LOCATION = "CURRENT_LOCATION";
private List<IDownloadCommand> mCommands = new ArrayList<>();
private DownloadManager() {
}
private Context mContext;
private DownloadManager(Context context) {
mContext = context;
DownloadTarget.init(context);
DbUtil.init(context);
}
public static DownloadManager init(Context context) {
if (context instanceof Application) {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new DownloadManager(context.getApplicationContext());
}
return INSTANCE;
}
} else {
Log.e(TAG, "Context 只能为application");
}
return INSTANCE;
}
public static DownloadManager getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行下载器注册");
}
return INSTANCE;
public static DownloadManager getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行下载器注册");
}
public List<DownloadEntity> getAllDownloadEntity(){
return DbEntity.findAllData(DownloadEntity.class);
}
/**
* 设置命令
*/
public DownloadManager setCommand(IDownloadCommand command) {
mCommands.add(command);
return this;
}
/**
* 设置一组命令
*/
public DownloadManager setCommands(List<IDownloadCommand> commands) {
if (commands != null && commands.size() > 0) {
mCommands.addAll(commands);
}
return this;
return INSTANCE;
}
public List<DownloadEntity> getAllDownloadEntity() {
return DbEntity.findAllData(DownloadEntity.class);
}
/**
* 设置命令
*/
public DownloadManager setCommand(IDownloadCommand command) {
mCommands.add(command);
return this;
}
/**
* 设置一组命令
*/
public DownloadManager 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();
return this;
}
/**
* 执行所有设置的命令
*/
public synchronized void exe() {
for (IDownloadCommand command : mCommands) {
command.executeComment();
}
mCommands.clear();
}
}

@ -2,7 +2,6 @@ package com.arialyy.downloadutil.core;
import android.content.Context;
import android.util.Log;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
@ -11,105 +10,105 @@ import com.arialyy.downloadutil.util.Task;
* 下载任务调度类
*/
public class DownloadTarget extends IDownloadTarget {
private static final String TAG = "DownloadTarget";
private static final Object LOCK = new Object();
private static volatile DownloadTarget INSTANCE = null;
private Context mContext;
public static DownloadTarget getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行注册");
}
return INSTANCE;
private static final String TAG = "DownloadTarget";
private static final Object LOCK = new Object();
private static volatile DownloadTarget INSTANCE = null;
private Context mContext;
public static DownloadTarget getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行注册");
}
static DownloadTarget init(Context context) {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new DownloadTarget(context.getApplicationContext());
}
}
return INSTANCE;
return INSTANCE;
}
static DownloadTarget init(Context context) {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new DownloadTarget(context.getApplicationContext());
}
}
return INSTANCE;
}
private DownloadTarget() {
super();
}
private DownloadTarget() {
super();
}
private DownloadTarget(Context context) {
super();
mContext = context;
}
private DownloadTarget(Context context) {
super();
mContext = context;
}
@Override public void startTask(Task task) {
if (mExecutePool.putTask(task)) {
task.start();
}
@Override public void startTask(Task task) {
if (mExecutePool.putTask(task)) {
task.start();
}
@Override public void stopTask(Task task) {
if (task.isDownloading()) {
if (mExecutePool.removeTask(task)) {
task.stop();
}
}else {
task.stop();
Log.w(TAG, "停止任务失败,【任务已经停止】");
}
}
@Override public void stopTask(Task task) {
if (task.isDownloading()) {
if (mExecutePool.removeTask(task)) {
task.stop();
}
} else {
task.stop();
Log.w(TAG, "停止任务失败,【任务已经停止】");
}
}
@Override public void cancelTask(Task task) {
if (mExecutePool.removeTask(task) || mCachePool.removeTask(task)) {
task.cancel();
}
@Override public void cancelTask(Task task) {
if (mExecutePool.removeTask(task) || mCachePool.removeTask(task)) {
task.cancel();
}
}
@Override public void reTryStart(Task task) {
if (!task.isDownloading()) {
task.start();
} else {
Log.w(TAG, "任务没有完全停止,重试下载失败");
}
@Override public void reTryStart(Task task) {
if (!task.isDownloading()) {
task.start();
} else {
Log.w(TAG, "任务没有完全停止,重试下载失败");
}
@Override public Task createTask(DownloadEntity entity) {
Task task = TaskFactory.getInstance().createTask(mContext, entity, mTaskHandler);
mCachePool.putTask(task);
return task;
}
@Override public Task createTask(DownloadEntity entity) {
Task task = TaskFactory.getInstance().createTask(mContext, entity, mTaskHandler);
mCachePool.putTask(task);
return task;
}
@Override public Task getTask(DownloadEntity entity) {
Task task = mExecutePool.getTask(entity.getDownloadUrl());
if (task == null) {
task = mCachePool.getTask(entity.getDownloadUrl());
}
@Override public Task getTask(DownloadEntity entity) {
Task task = mExecutePool.getTask(entity.getDownloadUrl());
if (task == null) {
task = mCachePool.getTask(entity.getDownloadUrl());
}
return task;
return task;
}
@Override public int getTaskState(DownloadEntity entity) {
Task task = getTask(entity);
if (task == null) {
Log.e(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的下载任务");
return -1;
}
@Override 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.getDownloadEntity().getState();
}
@Override public void removeTask(DownloadEntity entity) {
Task task = mExecutePool.getTask(entity.getDownloadUrl());
if (task != null) {
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
} else {
task = mCachePool.getTask(entity.getDownloadUrl());
}
@Override public void removeTask(DownloadEntity entity) {
Task task = mExecutePool.getTask(entity.getDownloadUrl());
if (task != null) {
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
} else {
task = mCachePool.getTask(entity.getDownloadUrl());
}
if (task != null) {
Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
} else {
Log.w(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的任务");
}
if (task != null) {
Log.d(TAG, "从缓存池删除任务,删除" + (mCachePool.removeTask(task) ? "成功" : "失败"));
} else {
Log.w(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的任务");
}
}
@Override public Task getNextTask() {
return mCachePool.pollTask();
}
@Override public Task getNextTask() {
return mCachePool.pollTask();
}
}

@ -3,7 +3,6 @@ package com.arialyy.downloadutil.core;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.arialyy.downloadutil.core.inf.IDownloader;
import com.arialyy.downloadutil.core.inf.ITask;
import com.arialyy.downloadutil.core.pool.CachePool;
@ -16,212 +15,210 @@ import com.arialyy.downloadutil.util.Task;
* 任务下载器提供抽象的方法供具体的实现类操作
*/
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 static final int STOP = 2;
/**
* 任务失败
*/
public static final int FAIL = 3;
/**
* 任务取消
*/
public static final int CANCEL = 4;
/**
* 任务完成
*/
public static final int COMPLETE = 5;
public void onTaskStart(Task task);
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 onTaskStart(Task task);
/**
* 任务停止
*/
public void onTaskStop(Task task);
/**
* 任务取消
*/
public void onTaskCancel(Task task);
/**
* 任务下载失败
*/
public void onTaskFail(Task task);
/**
* 任务完成
*/
public void onTaskComplete(Task task);
public void onTaskComplete(Task task);
}
protected IDownloadTarget() {
mTaskHandler = new AutoTaskHandler(this);
}
/**
* 设置下载器监听
*
* @param targetListener {@link OnTargetListener}
*/
public void setOnTargetListener(OnTargetListener targetListener) {
this.mTargetListener = targetListener;
}
/**
* 获取任务执行池
*/
public ExecutePool getExecutePool() {
return mExecutePool;
}
/**
* 获取当前运行的任务数
*
* @return 当前正在执行的任务数
*/
public int getCurrentTaskNum() {
return mExecutePool.size();
}
/**
* 获取缓存任务数
*
* @return 获取缓存的任务数
*/
public int getCacheTaskNum() {
return mCachePool.size();
}
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() {
mTaskHandler = new AutoTaskHandler(this);
}
/**
* 设置下载器监听
*
* @param targetListener {@link OnTargetListener}
*/
public void setOnTargetListener(OnTargetListener targetListener) {
this.mTargetListener = targetListener;
@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:
case CANCEL:
case COMPLETE:
startNextTask(entity);
break;
case FAIL:
handleFailTask(entity);
break;
}
callback(msg.what, entity);
}
/**
* 获取任务执行池
* 回调
*
* @return
* @param state 状态
* @param entity 下载实体
*/
public ExecutePool getExecutePool() {
return mExecutePool;
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.onTaskComplete(task);
break;
case FAIL:
target.mTargetListener.onTaskFail(task);
break;
}
}
}
/**
* 获取当前运行的任务数
* 处理下载任务下载失败的情形
*
* @return 当前正在执行的任务数
* @param entity 失败实体
*/
public int getCurrentTaskNum() {
return mExecutePool.size();
private void handleFailTask(DownloadEntity entity) {
if (entity.getFailNum() <= target.mFailNum) {
Task task = target.getTask(entity);
target.reTryStart(task);
} else {
startNextTask(entity);
}
}
/**
* 获取缓存任务数
* 启动下一个任务条件任务停止取消下载任务完成
*
* @return 获取缓存的任务数
*/
public int getCacheTaskNum() {
return mCachePool.size();
}
public void setFailNum(int mFailNum) {
this.mFailNum = mFailNum;
}
public void setTimeOut(long timeOut) {
this.mTimeOut = timeOut;
}
/**
* 自动处理任务停止下载失败取消下载自动下载下一个任务的操作
* @param entity 通过Handler传递的下载实体
*/
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:
case CANCEL:
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.onTaskComplete(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.w(TAG, "没有下一任务");
return;
}
if (newTask.getDownloadEntity().getState() == DownloadEntity.STATE_WAIT) {
target.startTask(newTask);
}
}
private void startNextTask(DownloadEntity entity) {
target.removeTask(entity);
Task newTask = target.getNextTask();
if (newTask == null) {
Log.w(TAG, "没有下一任务");
return;
}
if (newTask.getDownloadEntity().getState() == DownloadEntity.STATE_WAIT) {
target.startTask(newTask);
}
}
}
}

@ -5,5 +5,5 @@ package com.arialyy.downloadutil.core;
* 创建任务类型
*/
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.os.Handler;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
@ -11,33 +10,33 @@ import com.arialyy.downloadutil.util.Task;
* 任务工厂
*/
public class TaskFactory {
private static final String TAG = "TaskFactory";
private static final Object LOCK = new Object();
private static volatile TaskFactory INSTANCE = null;
private static final String TAG = "TaskFactory";
private TaskFactory() {
private static final Object LOCK = new Object();
private static volatile TaskFactory INSTANCE = null;
}
private TaskFactory() {
public static TaskFactory getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new TaskFactory();
}
}
return INSTANCE;
}
}
/**
* 创建普通下载任务
*
* @param entity 下载实体
* @param handler "com.arialyy.downloadutil.core.IDownloadTarget.AutoTaskHandler"
*/
public Task createTask(Context context, DownloadEntity entity, Handler handler) {
Task.Builder builder = new Task.Builder(context, entity);
builder.setOutHandler(handler);
return builder.build();
public static TaskFactory getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new TaskFactory();
}
}
return INSTANCE;
}
/**
* 创建普通下载任务
*
* @param entity 下载实体
* @param handler "com.arialyy.downloadutil.core.IDownloadTarget.AutoTaskHandler"
*/
public Task createTask(Context context, DownloadEntity entity, Handler handler) {
Task.Builder builder = new Task.Builder(context, entity);
builder.setOutHandler(handler);
return builder.build();
}
}

@ -2,9 +2,8 @@ package com.arialyy.downloadutil.core.command;
import android.content.Context;
import android.util.Log;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
/**
* Created by lyy on 2016/8/22.
@ -12,16 +11,16 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
*/
class AddCommand extends IDownloadCommand {
AddCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
AddCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
@Override public void executeComment() {
Task task = target.getTask(mEntity);
if (task == null) {
target.createTask(mEntity);
}else {
Log.w(TAG, "添加命令执行失败,【该任务已经存在】");
}
@Override public void executeComment() {
Task task = target.getTask(mEntity);
if (task == null) {
target.createTask(mEntity);
} else {
Log.w(TAG, "添加命令执行失败,【该任务已经存在】");
}
}
}

@ -1,9 +1,8 @@
package com.arialyy.downloadutil.core.command;
import android.content.Context;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
/**
* Created by lyy on 2016/9/20.
@ -11,17 +10,17 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
*/
class CancelCommand extends IDownloadCommand {
CancelCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
CancelCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
@Override public void executeComment() {
Task task = target.getTask(mEntity);
if (task == null){
task = target.createTask(mEntity);
}
if (task != null) {
target.cancelTask(task);
}
@Override public void executeComment() {
Task task = target.getTask(mEntity);
if (task == null) {
task = target.createTask(mEntity);
}
if (task != null) {
target.cancelTask(task);
}
}
}

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.core.command;
import android.content.Context;
import com.arialyy.downloadutil.entity.DownloadEntity;
/**
@ -9,113 +8,113 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
* 命令工厂
*/
public class CommandFactory {
/**
* 创建任务
*/
public static final int TASK_CREATE = 0x122;
/**
* 启动任务
*/
public static final int TASK_START = 0x123;
/**
* 恢复任务
*/
public static final int TASK_RESUME = 0x127;
/**
* 取消任务
*/
public static final int TASK_CANCEL = 0x124;
/**
* 停止任务
*/
public static final int TASK_STOP = 0x125;
/**
* 获取任务状态
*/
public static final int TASK_STATE = 0x126;
/**
* 创建任务
*/
public static final int TASK_CREATE = 0x122;
/**
* 启动任务
*/
public static final int TASK_START = 0x123;
/**
* 恢复任务
*/
public static final int TASK_RESUME = 0x127;
/**
* 取消任务
*/
public static final int TASK_CANCEL = 0x124;
/**
* 停止任务
*/
public static final int TASK_STOP = 0x125;
/**
* 获取任务状态
*/
public static final int TASK_STATE = 0x126;
private static final Object LOCK = new Object();
private static volatile CommandFactory INSTANCE = null;
private static final Object LOCK = new Object();
private static volatile CommandFactory INSTANCE = null;
private CommandFactory() {
private CommandFactory() {
}
}
public static CommandFactory getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new CommandFactory();
}
}
return INSTANCE;
public static CommandFactory getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new CommandFactory();
}
}
return INSTANCE;
}
/**
* @param context context
* @param entity 下载实体
* @param type 命令类型{@link #TASK_CREATE}{@link #TASK_START}{@link #TASK_CANCEL}{@link
* #TASK_STOP}{@link #TASK_STATE}
*/
public IDownloadCommand createCommand(Context context, DownloadEntity entity, int type) {
switch (type) {
case TASK_CREATE:
return createAddCommand(context, entity);
case TASK_RESUME:
case TASK_START:
return createStartCommand(context, entity);
case TASK_CANCEL:
return createCancelCommand(context, entity);
case TASK_STOP:
return createStopCommand(context, entity);
case TASK_STATE:
return createStateCommand(context, entity);
default:
return null;
}
/**
* @param context context
* @param entity 下载实体
* @param type 命令类型{@link #TASK_CREATE}{@link #TASK_START}{@link #TASK_CANCEL}{@link
* #TASK_STOP}{@link #TASK_STATE}
*/
public IDownloadCommand createCommand(Context context, DownloadEntity entity, int type) {
switch (type) {
case TASK_CREATE:
return createAddCommand(context, entity);
case TASK_RESUME:
case TASK_START:
return createStartCommand(context, entity);
case TASK_CANCEL:
return createCancelCommand(context, entity);
case TASK_STOP:
return createStopCommand(context, entity);
case TASK_STATE:
return createStateCommand(context, entity);
default:
return null;
}
}
/**
* 创建获取任务状态的命令
*
* @return {@link StateCommand}
*/
private StateCommand createStateCommand(Context context, DownloadEntity entity) {
return new StateCommand(context, entity);
}
/**
* 创建获取任务状态的命令
*
* @return {@link StateCommand}
*/
private StateCommand createStateCommand(Context context, DownloadEntity entity) {
return new StateCommand(context, entity);
}
/**
* 创建停止命令
*
* @return {@link StopCommand}
*/
private StopCommand createStopCommand(Context context, DownloadEntity entity) {
return new StopCommand(context, entity);
}
/**
* 创建停止命令
*
* @return {@link StopCommand}
*/
private StopCommand createStopCommand(Context context, DownloadEntity entity) {
return new StopCommand(context, entity);
}
/**
* 创建下载任务命令
*
* @return {@link AddCommand}
*/
private AddCommand createAddCommand(Context context, DownloadEntity entity) {
return new AddCommand(context, entity);
}
/**
* 创建下载任务命令
*
* @return {@link AddCommand}
*/
private AddCommand createAddCommand(Context context, DownloadEntity entity) {
return new AddCommand(context, entity);
}
/**
* 创建启动下载命令
*
* @return {@link StartCommand}
*/
private StartCommand createStartCommand(Context context, DownloadEntity entity) {
return new StartCommand(context, entity);
}
/**
* 创建启动下载命令
*
* @return {@link StartCommand}
*/
private StartCommand createStartCommand(Context context, DownloadEntity entity) {
return new StartCommand(context, entity);
}
/**
* 创建 取消下载的命令
*
* @return {@link CancelCommand}
*/
private CancelCommand createCancelCommand(Context context, DownloadEntity entity) {
return new CancelCommand(context, entity);
}
/**
* 创建 取消下载的命令
*
* @return {@link CancelCommand}
*/
private CancelCommand createCancelCommand(Context context, DownloadEntity entity) {
return new CancelCommand(context, entity);
}
}

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.core.command;
import android.content.Context;
import com.arialyy.downloadutil.core.DownloadTarget;
import com.arialyy.downloadutil.core.IDownloadTarget;
import com.arialyy.downloadutil.entity.DownloadEntity;
@ -13,40 +12,40 @@ import com.arialyy.downloadutil.util.Util;
* 下载命令
*/
public abstract class IDownloadCommand {
protected IDownloadTarget target;
protected Context mContext;
protected DownloadEntity mEntity;
protected String TAG;
protected IDownloadTarget target;
protected Context mContext;
protected DownloadEntity mEntity;
protected String TAG;
/**
* @param context context
* @param entity 下载实体
*/
protected IDownloadCommand(Context context, DownloadEntity entity) {
if (!CheckHelp.checkDownloadEntity(entity)) {
return;
}
target = DownloadTarget.getInstance();
mContext = context;
mEntity = entity;
TAG = Util.getClassName(this);
/**
* @param context context
* @param entity 下载实体
*/
protected IDownloadCommand(Context context, DownloadEntity entity) {
if (!CheckHelp.checkDownloadEntity(entity)) {
return;
}
target = DownloadTarget.getInstance();
mContext = context;
mEntity = entity;
TAG = Util.getClassName(this);
}
public Context getContext() {
return mContext;
}
public Context getContext() {
return mContext;
}
/**
* 执行命令
*/
public abstract void executeComment();
/**
* 执行命令
*/
public abstract void executeComment();
/**
* 设置下载器
*
* @param downloadTarget {@link IDownloadTarget}
*/
public void setDownloadTarget(IDownloadTarget downloadTarget) {
target = downloadTarget;
}
/**
* 设置下载器
*
* @param downloadTarget {@link IDownloadTarget}
*/
public void setDownloadTarget(IDownloadTarget downloadTarget) {
target = downloadTarget;
}
}

@ -1,9 +1,8 @@
package com.arialyy.downloadutil.core.command;
import android.content.Context;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
/**
* Created by lyy on 2016/8/22.
@ -11,17 +10,17 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
*/
class StartCommand extends IDownloadCommand {
StartCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
StartCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
@Override public void executeComment() {
Task task = target.getTask(mEntity);
if (task == null) {
task = target.createTask(mEntity);
}
if (task != null) {
target.startTask(task);
}
@Override public void executeComment() {
Task task = target.getTask(mEntity);
if (task == null) {
task = target.createTask(mEntity);
}
if (task != null) {
target.startTask(task);
}
}
}

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.core.command;
import android.content.Context;
import com.arialyy.downloadutil.entity.DownloadEntity;
/**
@ -10,16 +9,16 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
*/
class StateCommand extends IDownloadCommand {
/**
* @param context context
* @param entity 下载实体
*/
StateCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
/**
* @param context context
* @param entity 下载实体
*/
StateCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
@Override public void executeComment() {
@Override public void executeComment() {
target.getTaskState(mEntity);
}
target.getTaskState(mEntity);
}
}

@ -2,7 +2,6 @@ package com.arialyy.downloadutil.core.command;
import android.content.Context;
import android.util.Log;
import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
@ -12,25 +11,25 @@ import com.arialyy.downloadutil.util.Task;
*/
class StopCommand extends IDownloadCommand {
/**
* @param context context
* @param entity 下载实体
*/
StopCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
/**
* @param context context
* @param entity 下载实体
*/
StopCommand(Context context, DownloadEntity entity) {
super(context, entity);
}
@Override public void executeComment() {
Task task = target.getTask(mEntity);
if (task == null) {
if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) {
task = target.createTask(mEntity);
target.stopTask(task);
} else {
Log.w(TAG, "停止命令执行失败,【调度器中没有该任务】");
}
} else {
target.stopTask(task);
}
@Override public void executeComment() {
Task task = target.getTask(mEntity);
if (task == null) {
if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) {
task = target.createTask(mEntity);
target.stopTask(task);
} else {
Log.w(TAG, "停止命令执行失败,【调度器中没有该任务】");
}
} else {
target.stopTask(task);
}
}
}

@ -7,31 +7,31 @@ import com.arialyy.downloadutil.util.Task;
* 下载功能接口
*/
public interface IDownloader {
/**
* 开始任务
*
* @param task {@link Task}
*/
public void startTask(Task task);
/**
* 开始任务
*
* @param task {@link Task}
*/
public void startTask(Task task);
/**
* 停止任务
*
* @param task {@link Task}
*/
public void stopTask(Task task);
/**
* 停止任务
*
* @param task {@link Task}
*/
public void stopTask(Task task);
/**
* 取消任务
*
* @param task {@link Task}
*/
public void cancelTask(Task task);
/**
* 取消任务
*
* @param task {@link 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,46 +7,46 @@ import com.arialyy.downloadutil.util.Task;
* 任务池
*/
public interface IPool {
/**
* 将下载任务添加到任务池中
*/
public boolean putTask(Task task);
/**
* 将下载任务添加到任务池中
*/
public boolean putTask(Task task);
/**
* 按照队列原则取出下载任务
*
* @return 返回null或者下载任务
*/
public Task pollTask();
/**
* 按照队列原则取出下载任务
*
* @return 返回null或者下载任务
*/
public Task pollTask();
/**
* 通过下载链接获取下载任务当任务不为空时队列将删除该下载任务
*
* @param downloadUrl 下载链接
* @return 返回null或者下载任务
*/
public Task getTask(String downloadUrl);
/**
* 通过下载链接获取下载任务当任务不为空时队列将删除该下载任务
*
* @param downloadUrl 下载链接
* @return 返回null或者下载任务
*/
public Task getTask(String downloadUrl);
/**
* 删除任务池中的下载任务
*
* @param task 下载任务
* @return true:移除成功
*/
public boolean removeTask(Task task);
/**
* 删除任务池中的下载任务
*
* @param task 下载任务
* @return true:移除成功
*/
public boolean removeTask(Task task);
/**
* 通过下载链接移除下载任务
*
* @param downloadUrl 下载链接
* @return true:移除成功
*/
public boolean removeTask(String downloadUrl);
/**
* 通过下载链接移除下载任务
*
* @param downloadUrl 下载链接
* @return true:移除成功
*/
public boolean removeTask(String downloadUrl);
/**
* 池子大小
*
* @return 返回缓存池或者当前任务池大小
*/
public int size();
/**
* 池子大小
*
* @return 返回缓存池或者当前任务池大小
*/
public int size();
}

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

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

@ -2,11 +2,9 @@ package com.arialyy.downloadutil.core.pool;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.core.inf.IPool;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.util.Util;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
@ -17,137 +15,137 @@ import java.util.concurrent.TimeUnit;
* 任务执行池所有当前下载任务都该任务池中默认下载大小为2
*/
public class ExecutePool implements IPool {
private static final String TAG = "ExecutePool";
private static final Object LOCK = new Object();
private static final long TIME_OUT = 1000;
private static volatile ExecutePool INSTANCE = null;
private static int SIZE = 2;
private ArrayBlockingQueue<Task> mExecuteQueue;
private Map<String, Task> mExecuteArray;
private static final String TAG = "ExecutePool";
private static final Object LOCK = new Object();
private static final long TIME_OUT = 1000;
private static volatile ExecutePool INSTANCE = null;
private static int SIZE = 2;
private ArrayBlockingQueue<Task> mExecuteQueue;
private Map<String, Task> mExecuteArray;
public static ExecutePool getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new ExecutePool();
}
}
return INSTANCE;
public static ExecutePool getInstance() {
if (INSTANCE == null) {
synchronized (LOCK) {
INSTANCE = new ExecutePool();
}
}
return INSTANCE;
}
private ExecutePool() {
mExecuteQueue = new ArrayBlockingQueue<>(SIZE);
mExecuteArray = new HashMap<>();
}
private ExecutePool() {
mExecuteQueue = new ArrayBlockingQueue<>(SIZE);
mExecuteArray = new HashMap<>();
}
@Override public boolean putTask(Task task) {
synchronized (LOCK) {
if (task == null) {
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);
}
}
}
@Override public boolean putTask(Task task) {
synchronized (LOCK) {
if (task == null) {
Log.e(TAG, "下载任务不能为空!!");
return false;
}
/**
* 添加新任务
*
* @param newTask 新下载任务
*/
private boolean putNewTask(Task newTask) {
String url = newTask.getDownloadEntity().getDownloadUrl();
boolean s = mExecuteQueue.offer(newTask);
Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】"));
if (s) {
newTask.start();
mExecuteArray.put(Util.keyToHashKey(url), newTask);
}
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 s;
}
}
return false;
}
/**
* 队列满时将移除下载队列中的第一个任务
*/
private boolean pollFirstTask() {
try {
Task oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
if (oldTask == null) {
Log.e(TAG, "移除任务失败");
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;
/**
* 添加新任务
*
* @param newTask 新下载任务
*/
private boolean putNewTask(Task newTask) {
String url = newTask.getDownloadEntity().getDownloadUrl();
boolean s = mExecuteQueue.offer(newTask);
Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】"));
if (s) {
newTask.start();
mExecuteArray.put(Util.keyToHashKey(url), newTask);
}
return s;
}
@Override public Task pollTask() {
synchronized (LOCK) {
Task task = mExecuteQueue.poll();
if (task != null) {
String url = task.getDownloadEntity().getDownloadUrl();
mExecuteArray.remove(Util.keyToHashKey(url));
}
return task;
}
/**
* 队列满时将移除下载队列中的第一个任务
*/
private boolean pollFirstTask() {
try {
Task oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
if (oldTask == null) {
Log.e(TAG, "移除任务失败");
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 public Task getTask(String downloadUrl) {
synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接");
return null;
}
String key = Util.keyToHashKey(downloadUrl);
return mExecuteArray.get(key);
}
@Override public Task pollTask() {
synchronized (LOCK) {
Task task = mExecuteQueue.poll();
if (task != null) {
String url = task.getDownloadEntity().getDownloadUrl();
mExecuteArray.remove(Util.keyToHashKey(url));
}
return task;
}
}
@Override public boolean removeTask(Task task) {
synchronized (LOCK) {
if (task == null) {
Log.e(TAG, "任务不能为空");
return false;
} else {
String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl());
mExecuteArray.remove(key);
return mExecuteQueue.remove(task);
}
}
@Override public Task getTask(String downloadUrl) {
synchronized (LOCK) {
if (TextUtils.isEmpty(downloadUrl)) {
Log.e(TAG, "请传入有效的下载链接");
return null;
}
String key = Util.keyToHashKey(downloadUrl);
return mExecuteArray.get(key);
}
}
@Override public boolean removeTask(String downloadUrl) {
synchronized (LOCK) {
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 boolean removeTask(Task task) {
synchronized (LOCK) {
if (task == null) {
Log.e(TAG, "任务不能为空");
return false;
} else {
String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl());
mExecuteArray.remove(key);
return mExecuteQueue.remove(task);
}
}
}
@Override public int size() {
return mExecuteQueue.size();
@Override public boolean removeTask(String downloadUrl) {
synchronized (LOCK) {
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.Parcelable;
import com.arialyy.downloadutil.orm.DbEntity;
import com.arialyy.downloadutil.orm.Ignore;
@ -11,179 +10,179 @@ import com.arialyy.downloadutil.orm.Ignore;
* 下载实体
*/
public class DownloadEntity extends DbEntity implements Parcelable, Cloneable {
/**
* 其它状态
*/
@Ignore public static final int STATE_OTHER = -1;
/**
* 失败状态
*/
@Ignore public static final int STATE_FAIL = 0;
/**
* 完成状态
*/
@Ignore public static final int STATE_COMPLETE = 1;
/**
* 停止状态
*/
@Ignore public static final int STATE_STOP = 2;
/**
* 未开始状态
*/
@Ignore public static final int STATE_WAIT = 3;
/**
* 下载中
*/
@Ignore public static final int STATE_DOWNLOAD_ING = 4;
/**
* 取消下载
*/
@Ignore public static final int STATE_CANCEL = 5;
private String downloadUrl = ""; //下载路径
private String downloadPath = ""; //保存路径
private String fileName = ""; //文件名
private String str = ""; //其它字段
private long completeTime; //完成时间
private long fileSize = 1;
private int state = STATE_WAIT;
private boolean isDownloadComplete = false; //是否下载完成
private long currentProgress = 0; //当前下载进度
private int failNum = 0;
public DownloadEntity() {
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int getFailNum() {
return failNum;
}
public void setFailNum(int failNum) {
this.failNum = failNum;
}
public String getDownloadUrl() {
return downloadUrl;
}
public long getCompleteTime() {
return completeTime;
}
public void setCompleteTime(long completeTime) {
this.completeTime = completeTime;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public String getDownloadPath() {
return downloadPath;
}
public void setDownloadPath(String downloadPath) {
this.downloadPath = downloadPath;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public boolean isDownloadComplete() {
return isDownloadComplete;
}
public void setDownloadComplete(boolean downloadComplete) {
isDownloadComplete = downloadComplete;
}
public long getCurrentProgress() {
return currentProgress;
}
public void setCurrentProgress(long currentProgress) {
this.currentProgress = currentProgress;
}
@Override public DownloadEntity clone() throws CloneNotSupportedException {
return (DownloadEntity) super.clone();
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.downloadUrl);
dest.writeString(this.downloadPath);
dest.writeLong(this.completeTime);
dest.writeLong(this.fileSize);
dest.writeInt(this.state);
dest.writeByte(this.isDownloadComplete ? (byte) 1 : (byte) 0);
dest.writeLong(this.currentProgress);
dest.writeInt(this.failNum);
}
protected DownloadEntity(Parcel in) {
this.downloadUrl = in.readString();
this.downloadPath = in.readString();
this.completeTime = in.readLong();
this.fileSize = in.readLong();
this.state = in.readInt();
this.isDownloadComplete = in.readByte() != 0;
this.currentProgress = in.readLong();
this.failNum = in.readInt();
}
@Ignore public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
@Override public DownloadEntity createFromParcel(Parcel source) {
return new DownloadEntity(source);
}
@Override public DownloadEntity[] newArray(int size) {
return new DownloadEntity[size];
}
};
@Override public String toString() {
return "DownloadEntity{" +
"downloadUrl='" + downloadUrl + '\'' +
", downloadPath='" + downloadPath + '\'' +
", completeTime=" + completeTime +
", fileSize=" + fileSize +
", state=" + state +
", isDownloadComplete=" + isDownloadComplete +
", currentProgress=" + currentProgress +
", failNum=" + failNum +
'}';
}
/**
* 其它状态
*/
@Ignore public static final int STATE_OTHER = -1;
/**
* 失败状态
*/
@Ignore public static final int STATE_FAIL = 0;
/**
* 完成状态
*/
@Ignore public static final int STATE_COMPLETE = 1;
/**
* 停止状态
*/
@Ignore public static final int STATE_STOP = 2;
/**
* 未开始状态
*/
@Ignore public static final int STATE_WAIT = 3;
/**
* 下载中
*/
@Ignore public static final int STATE_DOWNLOAD_ING = 4;
/**
* 取消下载
*/
@Ignore public static final int STATE_CANCEL = 5;
private String downloadUrl = ""; //下载路径
private String downloadPath = ""; //保存路径
private String fileName = ""; //文件名
private String str = ""; //其它字段
private long completeTime; //完成时间
private long fileSize = 1;
private int state = STATE_WAIT;
private boolean isDownloadComplete = false; //是否下载完成
private long currentProgress = 0; //当前下载进度
private int failNum = 0;
public DownloadEntity() {
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int getFailNum() {
return failNum;
}
public void setFailNum(int failNum) {
this.failNum = failNum;
}
public String getDownloadUrl() {
return downloadUrl;
}
public long getCompleteTime() {
return completeTime;
}
public void setCompleteTime(long completeTime) {
this.completeTime = completeTime;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public String getDownloadPath() {
return downloadPath;
}
public void setDownloadPath(String downloadPath) {
this.downloadPath = downloadPath;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public boolean isDownloadComplete() {
return isDownloadComplete;
}
public void setDownloadComplete(boolean downloadComplete) {
isDownloadComplete = downloadComplete;
}
public long getCurrentProgress() {
return currentProgress;
}
public void setCurrentProgress(long currentProgress) {
this.currentProgress = currentProgress;
}
@Override public DownloadEntity clone() throws CloneNotSupportedException {
return (DownloadEntity) super.clone();
}
@Override public int describeContents() {
return 0;
}
@Override public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.downloadUrl);
dest.writeString(this.downloadPath);
dest.writeLong(this.completeTime);
dest.writeLong(this.fileSize);
dest.writeInt(this.state);
dest.writeByte(this.isDownloadComplete ? (byte) 1 : (byte) 0);
dest.writeLong(this.currentProgress);
dest.writeInt(this.failNum);
}
protected DownloadEntity(Parcel in) {
this.downloadUrl = in.readString();
this.downloadPath = in.readString();
this.completeTime = in.readLong();
this.fileSize = in.readLong();
this.state = in.readInt();
this.isDownloadComplete = in.readByte() != 0;
this.currentProgress = in.readLong();
this.failNum = in.readInt();
}
@Ignore public static final Creator<DownloadEntity> CREATOR = new Creator<DownloadEntity>() {
@Override public DownloadEntity createFromParcel(Parcel source) {
return new DownloadEntity(source);
}
@Override public DownloadEntity[] newArray(int size) {
return new DownloadEntity[size];
}
};
@Override public String toString() {
return "DownloadEntity{" +
"downloadUrl='" + downloadUrl + '\'' +
", downloadPath='" + downloadPath + '\'' +
", completeTime=" + completeTime +
", fileSize=" + fileSize +
", state=" + state +
", isDownloadComplete=" + isDownloadComplete +
", currentProgress=" + currentProgress +
", failNum=" + failNum +
'}';
}
}

@ -3,10 +3,8 @@ package com.arialyy.downloadutil.help;
import android.content.res.Resources;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.downloadutil.R;
import com.arialyy.downloadutil.entity.DownloadEntity;
import java.io.File;
/**
@ -14,38 +12,38 @@ import java.io.File;
* 检查帮助类
*/
public class CheckHelp {
private static final String TAG = "CheckHelp";
private static final String TAG = "CheckHelp";
/**
* 检测下载实体是否合法
*
* @param entity 下载实体
* @return 合法(true)
*/
public static boolean checkDownloadEntity(DownloadEntity entity) {
if (entity == null) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_entity_null));
return false;
} else if (TextUtils.isEmpty(entity.getDownloadUrl())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_url_null));
return false;
} else if (TextUtils.isEmpty(entity.getFileName())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_file_name_null));
return false;
} else if (TextUtils.isEmpty(entity.getDownloadPath())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_path_null));
return false;
}
String fileName = entity.getFileName();
if (fileName.contains(" ")) {
fileName = fileName.replace(" ", "_");
}
String dPath = entity.getDownloadPath();
File file = new File(dPath);
if (file.isDirectory()) {
dPath += fileName;
entity.setDownloadPath(dPath);
}
return true;
/**
* 检测下载实体是否合法
*
* @param entity 下载实体
* @return 合法(true)
*/
public static boolean checkDownloadEntity(DownloadEntity entity) {
if (entity == null) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_entity_null));
return false;
} else if (TextUtils.isEmpty(entity.getDownloadUrl())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_url_null));
return false;
} else if (TextUtils.isEmpty(entity.getFileName())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_file_name_null));
return false;
} else if (TextUtils.isEmpty(entity.getDownloadPath())) {
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_path_null));
return false;
}
String fileName = entity.getFileName();
if (fileName.contains(" ")) {
fileName = fileName.replace(" ", "_");
}
String dPath = entity.getDownloadPath();
File file = new File(dPath);
if (file.isDirectory()) {
dPath += fileName;
entity.setDownloadPath(dPath);
}
return true;
}
}

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.help;
import android.os.Environment;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@ -11,53 +10,45 @@ import java.security.NoSuchAlgorithmException;
*/
public class PathHelp {
/**
* 下载链接转换保存路径
*
* @param downloadUrl 下载链接
* @return 保存路径
*/
public static String urlconvertPath(String downloadUrl) {
return Environment.getDownloadCacheDirectory().getPath() + "/" + StringToHashKey(
downloadUrl);
}
/**
* 下载链接转换保存路径
*
* @param downloadUrl 下载链接
* @return 保存路径
*/
public static String urlconvertPath(String downloadUrl) {
return Environment.getDownloadCacheDirectory().getPath() + "/" + StringToHashKey(downloadUrl);
}
/**
* 字符串转换为hash码
*
* @param str
* @return
*/
public static String StringToHashKey(String str) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(str.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(str.hashCode());
}
return cacheKey;
/**
* 字符串转换为hash码
*/
public static String StringToHashKey(String str) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(str.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(str.hashCode());
}
return cacheKey;
}
/**
* 将普通字符串转换为16位进制字符串
*
* @param src
* @return
*/
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("0x");
if (src == null || src.length <= 0) {
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();
/**
* 将普通字符串转换为16位进制字符串
*/
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("0x");
if (src == null || src.length <= 0) {
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();
}
}

@ -1,9 +1,7 @@
package com.arialyy.downloadutil.orm;
import android.support.annotation.NonNull;
import com.arialyy.downloadutil.util.Util;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@ -13,129 +11,128 @@ import java.util.List;
* 所有数据库实体父类
*/
public class DbEntity {
protected int rowID = -1;
private DbUtil mUtil = DbUtil.getInstance();
protected DbEntity() {
}
/**
* 获取所有行的rowid
*/
public int[] getRowIds() {
return mUtil.getRowId(getClass());
}
/**
* 获取rowid
*/
public int getRowId(@NonNull Object[] wheres, @NonNull Object[] values) {
return mUtil.getRowId(getClass(), wheres, values);
protected int rowID = -1;
private DbUtil mUtil = DbUtil.getInstance();
protected DbEntity() {
}
/**
* 获取所有行的rowid
*/
public int[] getRowIds() {
return mUtil.getRowId(getClass());
}
/**
* 获取rowid
*/
public int getRowId(@NonNull Object[] wheres, @NonNull Object[] values) {
return mUtil.getRowId(getClass(), wheres, values);
}
/**
* 删除当前数据
*/
public void deleteData() {
mUtil.delData(getClass(), new Object[] { "rowid" }, new Object[] { rowID });
}
/**
* 根据条件删除数据
*/
public void deleteData(@NonNull Object[] wheres, @NonNull Object[] values) {
mUtil.delData(getClass(), wheres, values);
}
/**
* 修改数据
*/
public void update() {
mUtil.modifyData(this);
}
/**
* 保存自身如果表中已经有数据则更新数据否则插入数据
*/
public void save() {
if (mUtil.tableExists(getClass()) && thisIsExist()) {
update();
} else {
insert();
}
/**
* 删除当前数据
*/
public void deleteData() {
mUtil.delData(getClass(), new Object[]{"rowid"}, new Object[]{rowID});
}
/**
* 根据条件删除数据
*/
public void deleteData(@NonNull Object[] wheres, @NonNull Object[] values) {
mUtil.delData(getClass(), wheres, values);
}
/**
* 修改数据
*/
public void update() {
mUtil.modifyData(this);
}
/**
* 保存自身如果表中已经有数据则更新数据否则插入数据
*/
public void save() {
if (mUtil.tableExists(getClass()) && thisIsExist()) {
update();
} else {
insert();
}
}
/**
* 查找数据在表中是否存在
*/
private boolean thisIsExist() {
return findData(getClass(), new String[]{"rowid"}, new String[]{rowID + ""}) != null;
}
/**
* 插入数据
*/
public void insert() {
mUtil.insertData(this);
updateRowID();
}
private void updateRowID() {
try {
Field[] fields = Util.getFields(getClass());
List<String> where = new ArrayList<>();
List<String> values = new ArrayList<>();
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
where.add(field.getName());
values.add(field.get(this) + "");
}
DbEntity entity = findData(getClass(), where.toArray(new String[where.size()]),
values.toArray(new String[values.size()]));
if (entity != null) {
rowID = entity.rowID;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
/**
* 查找数据在表中是否存在
*/
private boolean thisIsExist() {
return findData(getClass(), new String[] { "rowid" }, new String[] { rowID + "" }) != null;
}
/**
* 插入数据
*/
public void insert() {
mUtil.insertData(this);
updateRowID();
}
private void updateRowID() {
try {
Field[] fields = Util.getFields(getClass());
List<String> where = new ArrayList<>();
List<String> values = new ArrayList<>();
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
where.add(field.getName());
values.add(field.get(this) + "");
}
DbEntity entity = findData(getClass(), where.toArray(new String[where.size()]),
values.toArray(new String[values.size()]));
if (entity != null) {
rowID = entity.rowID;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
/**
* 查询所有数据
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
DbUtil util = DbUtil.getInstance();
return util.findAllData(clazz);
}
/**
* 查询一组数据
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, @NonNull String[] wheres,
@NonNull String[] values) {
DbUtil util = DbUtil.getInstance();
return util.findData(clazz, wheres, values);
}
/**
* 查询一行数据
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> T findData(Class<T> clazz, @NonNull String[] wheres,
@NonNull String[] values) {
DbUtil util = DbUtil.getInstance();
List<T> datas = util.findData(clazz, wheres, values);
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
}
}
/**
* 查询所有数据
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
DbUtil util = DbUtil.getInstance();
return util.findAllData(clazz);
}
/**
* 查询一组数据
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> List<T> findDatas(Class<T> clazz, @NonNull String[] wheres,
@NonNull String[] values) {
DbUtil util = DbUtil.getInstance();
return util.findData(clazz, wheres, values);
}
/**
* 查询一行数据
*
* @return 没有数据返回null
*/
public static <T extends DbEntity> T findData(Class<T> clazz, @NonNull String[] wheres,
@NonNull String[] values) {
DbUtil util = DbUtil.getInstance();
List<T> datas = util.findData(clazz, wheres, values);
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
}
}

@ -6,9 +6,7 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.util.Log;
import com.arialyy.downloadutil.util.Util;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
@ -19,407 +17,407 @@ import java.util.List;
* 数据库操作工具
*/
public class DbUtil {
private static final String TAG = "DbUtil";
private volatile static DbUtil INSTANCE = null;
private static final Object LOCK = new Object();
private int CREATE_TABLE = 0;
private int TABLE_EXISTS = 1;
private int INSERT_DATA = 2;
private int MODIFY_DATA = 3;
private int FIND_DATA = 4;
private int FIND_ALL_DATA = 5;
private int DEL_DATA = 6;
private int ROW_ID = 7;
private SQLiteDatabase mDb;
private SqlHelper mHelper;
private static final String TAG = "DbUtil";
private volatile static DbUtil INSTANCE = null;
private static final Object LOCK = new Object();
private int CREATE_TABLE = 0;
private int TABLE_EXISTS = 1;
private int INSERT_DATA = 2;
private int MODIFY_DATA = 3;
private int FIND_DATA = 4;
private int FIND_ALL_DATA = 5;
private int DEL_DATA = 6;
private int ROW_ID = 7;
private SQLiteDatabase mDb;
private SqlHelper mHelper;
private DbUtil() {
private DbUtil() {
}
}
public static DbUtil init(Context context) {
if (context instanceof Application) {
synchronized (LOCK) {
if (INSTANCE == null) {
INSTANCE = new DbUtil(context);
}
}
public static DbUtil init(Context context) {
if (context instanceof Application) {
synchronized (LOCK) {
if (INSTANCE == null) {
INSTANCE = new DbUtil(context);
}
return INSTANCE;
}
}
return INSTANCE;
}
private DbUtil(Context context) {
mHelper = new SqlHelper(context.getApplicationContext());
private DbUtil(Context context) {
mHelper = new SqlHelper(context.getApplicationContext());
}
protected static DbUtil getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册");
}
return INSTANCE;
}
protected static DbUtil getInstance() {
if (INSTANCE == null) {
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册");
}
return INSTANCE;
/**
* 删除某条数据
*/
synchronized <T extends DbEntity> void delData(Class<T> clazz, @NonNull Object[] wheres,
@NonNull Object[] values) {
mDb = mHelper.getWritableDatabase();
if (wheres.length <= 0 || values.length <= 0) {
Log.e(TAG, "输入删除条件");
return;
} else if (wheres.length != values.length) {
Log.e(TAG, "key 和 vaule 长度不相等");
return;
}
StringBuilder sb = new StringBuilder();
sb.append("DELETE FROM ").append(Util.getClassName(clazz)).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());
close();
}
/**
* 删除某条数据
*/
synchronized <T extends DbEntity> void delData(Class<T> clazz, @NonNull Object[] wheres,
@NonNull Object[] values) {
mDb = mHelper.getWritableDatabase();
if (wheres.length <= 0 || values.length <= 0) {
Log.e(TAG, "输入删除条件");
return;
} else if (wheres.length != values.length) {
Log.e(TAG, "key 和 vaule 长度不相等");
return;
/**
* 修改某行数据
*/
synchronized void modifyData(DbEntity dbEntity) {
mDb = mHelper.getWritableDatabase();
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;
}
StringBuilder sb = new StringBuilder();
sb.append("DELETE FROM ").append(Util.getClassName(clazz)).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++;
sb.append(i > 0 ? ", " : "");
try {
sb.append(field.getName())
.append("='")
.append(field.get(dbEntity).toString())
.append("'");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
print(DEL_DATA, sb.toString());
mDb.execSQL(sb.toString());
close();
i++;
}
sb.append(" where rowid=").append(dbEntity.rowID);
print(MODIFY_DATA, sb.toString());
mDb.execSQL(sb.toString());
}
close();
}
/**
* 修改某行数据
*/
synchronized void modifyData(DbEntity dbEntity) {
mDb = mHelper.getWritableDatabase();
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++;
}
sb.append(" where rowid=").append(dbEntity.rowID);
print(MODIFY_DATA, sb.toString());
mDb.execSQL(sb.toString());
}
close();
/**
* 遍历所有数据
*/
synchronized <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
if (!tableExists(clazz)) {
createTable(clazz);
}
mDb = mHelper.getReadableDatabase();
StringBuilder sb = new StringBuilder();
sb.append("SELECT rowid, * FROM ").append(Util.getClassName(clazz));
print(FIND_ALL_DATA, sb.toString());
Cursor cursor = mDb.rawQuery(sb.toString(), null);
return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
}
/**
* 遍历所有数据
*/
synchronized <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
if (!tableExists(clazz)) {
createTable(clazz);
}
mDb = mHelper.getReadableDatabase();
StringBuilder sb = new StringBuilder();
sb.append("SELECT rowid, * FROM ").append(Util.getClassName(clazz));
print(FIND_ALL_DATA, sb.toString());
Cursor cursor = mDb.rawQuery(sb.toString(), null);
return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
/**
* 条件查寻数据
*/
synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, @NonNull String[] wheres,
@NonNull String[] values) {
if (!tableExists(clazz)) {
createTable(clazz);
}
mDb = mHelper.getReadableDatabase();
if (wheres.length <= 0 || values.length <= 0) {
Log.e(TAG, "请输入查询条件");
return null;
} else if (wheres.length != values.length) {
Log.e(TAG, "key 和 vaule 长度不相等");
return null;
}
StringBuilder sb = new StringBuilder();
sb.append("SELECT rowid, * FROM ").append(Util.getClassName(clazz)).append(" where ");
int i = 0;
for (Object where : wheres) {
sb.append(where).append("=").append("'").append(values[i]).append("'");
sb.append(i >= wheres.length - 1 ? "" : " AND ");
i++;
}
print(FIND_DATA, sb.toString());
Cursor cursor = mDb.rawQuery(sb.toString(), null);
return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
}
/**
* 条件查寻数据
*/
synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, @NonNull String[] wheres,
@NonNull String[] values) {
if (!tableExists(clazz)) {
createTable(clazz);
/**
* 插入数据
*/
synchronized void insertData(DbEntity dbEntity) {
Class<?> clazz = dbEntity.getClass();
if (!tableExists(clazz)) {
createTable(clazz);
}
mDb = mHelper.getWritableDatabase();
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;
}
mDb = mHelper.getReadableDatabase();
if (wheres.length <= 0 || values.length <= 0) {
Log.e(TAG, "请输入查询条件");
return null;
} else if (wheres.length != values.length) {
Log.e(TAG, "key 和 vaule 长度不相等");
return null;
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;
}
StringBuilder sb = new StringBuilder();
sb.append("SELECT rowid, * FROM ").append(Util.getClassName(clazz)).append(" where ");
int i = 0;
for (Object where : wheres) {
sb.append(where).append("=").append("'").append(values[i]).append("'");
sb.append(i >= wheres.length - 1 ? "" : " AND ");
i++;
sb.append(i > 0 ? ", " : "");
sb.append("'");
try {
sb.append(field.get(dbEntity)).append("'");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
print(FIND_DATA, sb.toString());
Cursor cursor = mDb.rawQuery(sb.toString(), null);
return cursor.getCount() > 0 ? newInstanceEntity(clazz, cursor) : null;
i++;
}
sb.append(")");
print(INSERT_DATA, sb.toString());
mDb.execSQL(sb.toString());
}
close();
}
/**
* 插入数据
*/
synchronized void insertData(DbEntity dbEntity) {
Class<?> clazz = dbEntity.getClass();
if (!tableExists(clazz)) {
createTable(clazz);
}
mDb = mHelper.getWritableDatabase();
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 {
sb.append(field.get(dbEntity)).append("'");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
i++;
}
sb.append(")");
print(INSERT_DATA, sb.toString());
mDb.execSQL(sb.toString());
}
close();
/**
* 查找某张表是否存在
*/
synchronized boolean tableExists(Class clazz) {
if (mDb == null || !mDb.isOpen()) {
mDb = mHelper.getReadableDatabase();
}
/**
* 查找某张表是否存在
*/
synchronized boolean tableExists(Class clazz) {
if (mDb == null || !mDb.isOpen()) {
mDb = mHelper.getReadableDatabase();
Cursor cursor = null;
try {
StringBuilder sb = new StringBuilder();
sb.append("SELECT COUNT(*) AS c FROM sqlite_master WHERE type='table' AND name='");
sb.append(Util.getClassName(clazz));
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;
}
Cursor cursor = null;
try {
StringBuilder sb = new StringBuilder();
sb.append("SELECT COUNT(*) AS c FROM sqlite_master WHERE type='table' AND name='");
sb.append(Util.getClassName(clazz));
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();
close();
}
return false;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) cursor.close();
close();
}
return false;
}
/**
* 创建表
*/
private synchronized void createTable(Class clazz) {
if (mDb == null || !mDb.isOpen()) {
mDb = mHelper.getWritableDatabase();
/**
* 创建表
*/
private synchronized void createTable(Class clazz) {
if (mDb == null || !mDb.isOpen()) {
mDb = mHelper.getWritableDatabase();
}
Field[] fields = Util.getFields(clazz);
if (fields != null && fields.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("create table ").append(Util.getClassName(clazz)).append("(");
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
Field[] fields = Util.getFields(clazz);
if (fields != null && fields.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("create table ").append(Util.getClassName(clazz)).append("(");
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
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(",");
}
String str = sb.toString();
str = str.substring(0, str.length() - 1) + ");";
print(CREATE_TABLE, str);
mDb.execSQL(str);
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");
}
close();
sb.append(",");
}
String str = sb.toString();
str = str.substring(0, str.length() - 1) + ");";
print(CREATE_TABLE, str);
mDb.execSQL(str);
}
close();
}
/**
* 打印数据库日志
*
* @param type {@link DbUtil}
*/
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);
/**
* 打印数据库日志
*
* @param type {@link DbUtil}
*/
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);
}
/**
* 关闭数据库
*/
private synchronized void close() {
if (mDb != null) {
mDb.close();
}
/**
* 关闭数据库
*/
private synchronized void close() {
if (mDb != null) {
mDb.close();
}
}
/**
* 获取所在行Id
*/
synchronized int[] getRowId(Class clazz) {
mDb = mHelper.getReadableDatabase();
Cursor cursor = mDb.rawQuery("SELECT rowid, * FROM " + Util.getClassName(clazz), null);
int[] ids = new int[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()) {
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid"));
i++;
}
cursor.close();
close();
return ids;
/**
* 获取所在行Id
*/
synchronized int[] getRowId(Class clazz) {
mDb = mHelper.getReadableDatabase();
Cursor cursor = mDb.rawQuery("SELECT rowid, * FROM " + Util.getClassName(clazz), null);
int[] ids = new int[cursor.getCount()];
int i = 0;
while (cursor.moveToNext()) {
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid"));
i++;
}
cursor.close();
close();
return ids;
}
/**
* 获取行Id
*/
synchronized int getRowId(Class clazz, Object[] wheres, Object[] values) {
mDb = mHelper.getReadableDatabase();
if (wheres.length <= 0 || values.length <= 0) {
Log.e(TAG, "请输入删除条件");
return -1;
} else if (wheres.length != values.length) {
Log.e(TAG, "key 和 vaule 长度不相等");
return -1;
}
StringBuilder sb = new StringBuilder();
sb.append("SELECT rowid FROM ").append(Util.getClassName(clazz)).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(ROW_ID, sb.toString());
Cursor c = mDb.rawQuery(sb.toString(), null);
int id = c.getColumnIndex("rowid");
c.close();
close();
return id;
/**
* 获取行Id
*/
synchronized int getRowId(Class clazz, Object[] wheres, Object[] values) {
mDb = mHelper.getReadableDatabase();
if (wheres.length <= 0 || values.length <= 0) {
Log.e(TAG, "请输入删除条件");
return -1;
} else if (wheres.length != values.length) {
Log.e(TAG, "key 和 vaule 长度不相等");
return -1;
}
StringBuilder sb = new StringBuilder();
sb.append("SELECT rowid FROM ").append(Util.getClassName(clazz)).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(ROW_ID, sb.toString());
Cursor c = mDb.rawQuery(sb.toString(), null);
int id = c.getColumnIndex("rowid");
c.close();
close();
return id;
}
/**
* 根据数据游标创建一个具体的对象
*/
private synchronized <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) {
try {
while (cursor.moveToNext()) {
T entity = clazz.newInstance();
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
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));
}
}
entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid"));
entitys.add(entity);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
/**
* 根据数据游标创建一个具体的对象
*/
private synchronized <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) {
try {
while (cursor.moveToNext()) {
T entity = clazz.newInstance();
for (Field field : fields) {
field.setAccessible(true);
Ignore ignore = field.getAnnotation(Ignore.class);
if (ignore != null && ignore.value()) {
continue;
}
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));
}
}
entity.rowID = cursor.getInt(cursor.getColumnIndex("rowid"));
entitys.add(entity);
}
cursor.close();
close();
return entitys;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
cursor.close();
close();
return entitys;
}
}

@ -10,5 +10,5 @@ import java.lang.annotation.Target;
* 表ID字段指定
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Id {
int value() default -1;
int value() default -1;
}

@ -10,5 +10,5 @@ import java.lang.annotation.Target;
* 忽略某个字段
*/
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Ignore {
boolean value() default true;
boolean value() default true;
}

@ -10,27 +10,27 @@ import android.text.TextUtils;
* sql帮助类
*/
public class SqlHelper extends SQLiteOpenHelper {
protected static String DB_NAME;
protected static int VERSION = -1;
static {
if (TextUtils.isEmpty(DB_NAME)) {
DB_NAME = "AriaLyyDb";
}
if (VERSION == -1) {
VERSION = 1;
}
}
protected static String DB_NAME;
protected static int VERSION = -1;
public SqlHelper(Context context) {
super(context, DB_NAME, null, VERSION);
static {
if (TextUtils.isEmpty(DB_NAME)) {
DB_NAME = "AriaLyyDb";
}
if (VERSION == -1) {
VERSION = 1;
}
}
@Override public void onCreate(SQLiteDatabase db) {
public SqlHelper(Context context) {
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,9 +4,7 @@ import android.content.Context;
import android.support.annotation.NonNull;
import android.util.Log;
import android.util.SparseArray;
import com.arialyy.downloadutil.entity.DownloadEntity;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@ -21,471 +19,494 @@ import java.util.Properties;
* 下载工具类
*/
final class DownLoadUtil {
private static final String TAG = "DownLoadUtil";
//下载监听
private IDownloadListener mListener;
/**
* 线程数
*/
private static final int THREAD_NUM = 3;
private static final int TIME_OUT = 5000; //超时时间
/**
* 已经完成下载任务的线程数量
*/
private int mCompleteThreadNum = 0;
private boolean isDownloading = false;
private boolean isStop = false;
private boolean isCancel = false;
private long mCurrentLocation;
boolean isNewTask = true;
private int mCancelNum = 0;
private int mStopNum = 0;
private Context mContext;
private DownloadEntity mDownloadEntity;
public DownLoadUtil(Context context, DownloadEntity entity) {
mContext = context.getApplicationContext();
mDownloadEntity = entity;
private static final String TAG = "DownLoadUtil";
private static final Object LOCK = new Object();
//下载监听
private IDownloadListener mListener;
/**
* 线程数
*/
private static final int THREAD_NUM = 3;
private static final int TIME_OUT = 5000; //超时时间
/**
* 已经完成下载任务的线程数量
*/
private int mCompleteThreadNum = 0;
private boolean isDownloading = false;
private boolean isStop = false;
private boolean isCancel = false;
private long mCurrentLocation;
boolean isNewTask = true;
private int mCancelNum = 0;
private int mStopNum = 0;
private Context mContext;
private DownloadEntity mDownloadEntity;
public DownLoadUtil(Context context, DownloadEntity entity) {
mContext = context.getApplicationContext();
mDownloadEntity = entity;
}
public IDownloadListener getListener() {
return mListener;
}
/**
* 获取当前下载位置
*/
public long getCurrentLocation() {
return mCurrentLocation;
}
public boolean isDownloading() {
return isDownloading;
}
/**
* 取消下载
*/
public void cancelDownload() {
isCancel = true;
}
/**
* 停止下载
*/
public void stopDownload() {
isStop = true;
}
/**
* 删除下载记录文件
*/
public void delConfigFile() {
if (mContext != null && mDownloadEntity != null) {
File dFile = new File(mDownloadEntity.getDownloadPath());
File config =
new File(mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties");
if (config.exists()) {
config.delete();
}
}
public IDownloadListener getListener() {
return mListener;
}
/**
* 获取当前下载位置
*/
public long getCurrentLocation() {
return mCurrentLocation;
}
/**
* 删除temp文件
*/
public void delTempFile() {
if (mContext != null && mDownloadEntity != null) {
File dFile = new File(mDownloadEntity.getDownloadPath());
if (dFile.exists()) {
dFile.delete();
}
}
public boolean isDownloading() {
return isDownloading;
}
/**
* 多线程断点续传下载文件暂停和继续
*
* @param downloadListener 下载进度监听 {@link DownloadListener}
*/
public void start(@NonNull final IDownloadListener downloadListener) {
isDownloading = true;
mCurrentLocation = 0;
isStop = false;
isCancel = false;
mCancelNum = 0;
mStopNum = 0;
final String filePath = mDownloadEntity.getDownloadPath();
final String downloadUrl = mDownloadEntity.getDownloadUrl();
final File dFile = new File(filePath);
//读取已完成的线程数
final File configFile =
new File(mContext.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;
}
/**
* 取消下载
*/
public void cancelDownload() {
isCancel = true;
new Thread(new Runnable() {
@Override public void run() {
try {
mListener = downloadListener;
URL url = new URL(downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
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.connect();
int len = conn.getContentLength();
if (len < 0) { //网络被劫持时会出现这个问题
failDownload("下载失败,网络被劫持");
return;
}
int code = conn.getResponseCode();
if (code == 200) {
int fileLength = conn.getContentLength();
//必须建一个文件
Util.createFile(filePath);
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;
}
}
}
SparseArray<Thread> tasks = new SparseArray<>();
int blockSize = fileLength / THREAD_NUM;
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;
}
ConfigEntity entity =
new ConfigEntity(mContext, 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();
}
/**
* 多线程下载任务类,不能使用AsyncTask来进行多线程下载因为AsyncTask是串行执行的这种方式下载速度太慢了
*/
private class DownLoadTask implements Runnable {
private static final String TAG = "DownLoadTask";
private ConfigEntity dEntity;
private String configFPath;
private DownLoadTask(ConfigEntity downloadInfo) {
this.dEntity = downloadInfo;
configFPath = dEntity.context.getFilesDir().getPath()
+ "/temp/"
+ dEntity.tempFile.getName()
+ ".properties";
}
/**
* 停止下载
*/
public void stopDownload() {
isStop = true;
}
@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.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.setConnectTimeout(TIME_OUT * 4);
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);
progress(len);
currentLocation += len;
}
file.close();
is.close();
/**
* 删除下载记录文件
*/
public void delConfigFile() {
if (mContext != null && mDownloadEntity != null) {
File dFile = new File(mDownloadEntity.getDownloadPath());
File config = new File(
mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties");
if (config.exists()) {
config.delete();
}
if (isCancel) {
cancel();
return;
}
//停止状态不需要删除记录文件
if (isStop) {
stop(currentLocation);
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();
}
} catch (MalformedURLException e) {
failDownload(dEntity, currentLocation, "下载链接异常", e);
} catch (IOException e) {
failDownload(dEntity, currentLocation, "下载失败【" + dEntity.downloadUrl + "】", e);
} catch (Exception e) {
failDownload(dEntity, currentLocation, "获取流失败", e);
}
}
/**
* 删除temp文件
* 停止下载
*
* @throws IOException
*/
public void delTempFile() {
if (mContext != null && mDownloadEntity != null) {
File dFile = new File(mDownloadEntity.getDownloadPath());
if (dFile.exists()) {
dFile.delete();
}
private void stop(long currentLocation) throws IOException {
synchronized (LOCK) {
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);
}
}
}
/**
* 多线程断点续传下载文件暂停和继续
*
* @param downloadListener 下载进度监听 {@link DownloadListener}
* 取消下载
*/
public void start(@NonNull final IDownloadListener downloadListener) {
isDownloading = true;
mCurrentLocation = 0;
isStop = false;
isCancel = false;
mCancelNum = 0;
mStopNum = 0;
final String filePath = mDownloadEntity.getDownloadPath();
final String downloadUrl = mDownloadEntity.getDownloadUrl();
final File dFile = new File(filePath);
//读取已完成的线程数
final File configFile = new File(
mContext.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;
private void cancel() {
synchronized (LOCK) {
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();
}
new Thread(new Runnable() {
@Override public void run() {
try {
mListener = downloadListener;
URL url = new URL(downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Charset", "UTF-8");
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.setConnectTimeout(TIME_OUT * 4);
conn.connect();
int len = conn.getContentLength();
if (len < 0) { //网络被劫持时会出现这个问题
failDownload("下载失败,网络被劫持");
return;
}
int code = conn.getResponseCode();
if (code == 200) {
int fileLength = conn.getContentLength();
//必须建一个文件
Util.createFile(filePath);
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;
}
}
}
SparseArray<Thread> tasks = new SparseArray<>();
int blockSize = fileLength / THREAD_NUM;
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;
}
ConfigEntity entity = new ConfigEntity(mContext, 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();
private void progress(long len) {
synchronized (LOCK) {
mCurrentLocation += len;
mListener.onProgress(mCurrentLocation);
}
}
/**
* 多线程下载任务类,不能使用AsyncTask来进行多线程下载因为AsyncTask是串行执行的这种方式下载速度太慢了
* 将记录写入到配置文件
*/
private class DownLoadTask implements Runnable {
private static final String TAG = "DownLoadTask";
private ConfigEntity dEntity;
private String configFPath;
public DownLoadTask(ConfigEntity 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.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.setConnectTimeout(TIME_OUT * 4);
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();
}
}
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);
}
}
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();
}
} 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();
}
}
}
}
/**
* 将记录写入到配置文件
*/
private void writeConfig(String key, String record) throws IOException {
File configFile = new File(configFPath);
Properties pro = Util.loadConfig(configFile);
pro.setProperty(key, record);
Util.saveConfig(configFile, pro);
}
private void writeConfig(String key, String record) throws IOException {
File configFile = new File(configFPath);
Properties pro = Util.loadConfig(configFile);
pro.setProperty(key, record);
Util.saveConfig(configFile, pro);
}
/**
* 子线程下载信息类
* 下载失败
*/
private class ConfigEntity {
//文件大小
long fileSize;
String downloadUrl;
int threadId;
long startLocation;
long endLocation;
File tempFile;
Context context;
public ConfigEntity(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;
private void failDownload(ConfigEntity dEntity, long currentLocation, String msg,
Exception ex) {
synchronized (LOCK) {
try {
isDownloading = false;
isStop = true;
Log.e(TAG, msg);
if (ex != null) {
Log.e(TAG, Util.getPrintException(ex));
}
if (currentLocation != -1) {
String location = String.valueOf(currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
}
mListener.onFail();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 子线程下载信息类
*/
private class ConfigEntity {
//文件大小
long fileSize;
String downloadUrl;
int threadId;
long startLocation;
long endLocation;
File tempFile;
Context context;
public ConfigEntity(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 {
public static class DownloadListener implements IDownloadListener {
@Override public void onResume(long resumeLocation) {
@Override public void onResume(long resumeLocation) {
}
}
@Override public void onCancel() {
@Override public void onCancel() {
}
}
@Override public void onFail() {
@Override public void onFail() {
}
}
@Override public void onPreDownload(HttpURLConnection connection) {
@Override public void onPreDownload(HttpURLConnection connection) {
}
}
@Override public void onProgress(long currentLocation) {
@Override public void onProgress(long currentLocation) {
}
}
@Override public void onChildComplete(long finishLocation) {
@Override public void onChildComplete(long finishLocation) {
}
}
@Override public void onStart(long startLocation) {
@Override public void onStart(long startLocation) {
}
}
@Override public void onChildResume(long resumeLocation) {
@Override public void onChildResume(long resumeLocation) {
}
}
@Override public void onStop(long stopLocation) {
@Override public void onStop(long stopLocation) {
}
}
@Override public void onComplete() {
@Override public void onComplete() {
}
}
}
}

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

@ -5,11 +5,9 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.downloadutil.core.IDownloadTarget;
import com.arialyy.downloadutil.entity.DownloadEntity;
import java.net.HttpURLConnection;
/**
@ -17,245 +15,241 @@ import java.net.HttpURLConnection;
* 下载任务类
*/
public class Task {
public static final String TAG = "Task";
private DownloadEntity mEntity;
private IDownloadListener mListener;
private Handler mOutHandler;
private Context mContext;
private DownLoadUtil mUtil;
private Task(Context context, DownloadEntity entity) {
mContext = context.getApplicationContext();
mEntity = entity;
mUtil = new DownLoadUtil(context, entity);
public static final String TAG = "Task";
private DownloadEntity mEntity;
private IDownloadListener mListener;
private Handler mOutHandler;
private Context mContext;
private DownLoadUtil mUtil;
private Task(Context context, DownloadEntity entity) {
mContext = context.getApplicationContext();
mEntity = entity;
mUtil = new DownLoadUtil(context, entity);
}
/**
* 开始下载
*/
public void start() {
if (mUtil.isDownloading()) {
Log.d(TAG, "任务正在下载");
} else {
if (mListener == null) {
mListener = new DownloadListener(mContext, mEntity, mOutHandler);
}
mUtil.start(mListener);
}
/**
* 开始下载
*/
public void start() {
if (mUtil.isDownloading()) {
Log.d(TAG, "任务正在下载");
} else {
if (mListener == null) {
mListener = new DownloadListener(mContext, mEntity, mOutHandler);
}
mUtil.start(mListener);
}
}
public DownloadEntity getDownloadEntity() {
return mEntity;
}
/**
* 停止下载
*/
public void stop() {
if (mUtil.isDownloading()) {
mUtil.stopDownload();
} else {
mEntity.setState(DownloadEntity.STATE_STOP);
mEntity.save();
sendInState2Target(IDownloadTarget.STOP);
// 发送停止下载的广播
Intent intent = createIntent(DownloadManager.ACTION_STOP);
intent.putExtra(DownloadManager.CURRENT_LOCATION, mEntity.getCurrentProgress());
intent.putExtra(DownloadManager.ENTITY, mEntity);
mContext.sendBroadcast(intent);
}
public DownloadEntity getDownloadEntity() {
return mEntity;
}
/**
* 获取下载工具
*/
public DownLoadUtil getDownloadUtil() {
return mUtil;
}
/**
* 任务下载状态
*/
public boolean isDownloading() {
return mUtil.isDownloading();
}
/**
* 取消下载
*/
public void cancel() {
if (mUtil.isDownloading()) {
mUtil.cancelDownload();
} else {
// 如果任务不是下载状态
mUtil.cancelDownload();
mUtil.delConfigFile();
mUtil.delTempFile();
mEntity.deleteData();
sendInState2Target(IDownloadTarget.CANCEL);
//发送取消下载的广播
Intent intent = createIntent(DownloadManager.ACTION_CANCEL);
intent.putExtra(DownloadManager.ENTITY, mEntity);
mContext.sendBroadcast(intent);
}
/**
* 停止下载
*/
public void stop() {
if (mUtil.isDownloading()) {
mUtil.stopDownload();
} else {
mEntity.setState(DownloadEntity.STATE_STOP);
mEntity.save();
sendInState2Target(IDownloadTarget.STOP);
// 发送停止下载的广播
Intent intent = createIntent(DownloadManager.ACTION_STOP);
intent.putExtra(DownloadManager.CURRENT_LOCATION, mEntity.getCurrentProgress());
intent.putExtra(DownloadManager.ENTITY, mEntity);
mContext.sendBroadcast(intent);
}
}
/**
* 创建特定的Intent
*/
private Intent createIntent(String action) {
Uri.Builder builder = new Uri.Builder();
builder.scheme(mContext.getPackageName());
Uri uri = builder.build();
Intent intent = new Intent(action);
intent.setData(uri);
return intent;
}
/**
* 将任务状态发送给下载器
*
* @param state {@link IDownloadTarget#START}
*/
private void sendInState2Target(int state) {
if (mOutHandler != null) {
mOutHandler.obtainMessage(state, mEntity).sendToTarget();
}
/**
* 获取下载工具
*/
public DownLoadUtil getDownloadUtil() {
return mUtil;
}
/**
* 下载监听类
*/
private class DownloadListener extends DownLoadUtil.DownloadListener {
Handler outHandler;
Context context;
Intent sendIntent;
long INTERVAL = 1024 * 10; //10k大小的间隔
long lastLen = 0; //上一次发送长度
long lastTime = 0;
long INTERVAL_TIME = 60 * 1000; //10k大小的间隔
DownloadEntity downloadEntity;
DownloadListener(Context context, DownloadEntity downloadEntity, Handler outHandler) {
this.context = context;
this.outHandler = outHandler;
this.downloadEntity = downloadEntity;
sendIntent = createIntent(DownloadManager.ACTION_RUNNING);
sendIntent.putExtra(DownloadManager.ENTITY, downloadEntity);
}
/**
* 任务下载状态
*/
public boolean isDownloading() {
return mUtil.isDownloading();
@Override public void onPreDownload(HttpURLConnection connection) {
super.onPreDownload(connection);
long len = connection.getContentLength();
downloadEntity.setFileSize(len);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendIntent(DownloadManager.ACTION_PRE, -1);
}
/**
* 取消下载
*/
public void cancel() {
if (mUtil.isDownloading()) {
mUtil.cancelDownload();
} else {
// 如果任务不是下载状态
mUtil.cancelDownload();
mUtil.delConfigFile();
mUtil.delTempFile();
mEntity.deleteData();
sendInState2Target(IDownloadTarget.CANCEL);
//发送取消下载的广播
Intent intent = createIntent(DownloadManager.ACTION_CANCEL);
intent.putExtra(DownloadManager.ENTITY, mEntity);
mContext.sendBroadcast(intent);
}
@Override public void onResume(long resumeLocation) {
super.onResume(resumeLocation);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendIntent(DownloadManager.ACTION_RESUME, resumeLocation);
}
/**
* 创建特定的Intent
*
* @param action
* @return
*/
private Intent createIntent(String action) {
Uri.Builder builder = new Uri.Builder();
builder.scheme(mContext.getPackageName());
Uri uri = builder.build();
Intent intent = new Intent(action);
intent.setData(uri);
return intent;
@Override public void onStart(long startLocation) {
super.onStart(startLocation);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendInState2Target(IDownloadTarget.START);
sendIntent(DownloadManager.ACTION_START, startLocation);
}
/**
* 将任务状态发送给下载器
*
* @param state {@link IDownloadTarget#START}
*/
private void sendInState2Target(int state) {
if (mOutHandler != null) {
mOutHandler.obtainMessage(state, mEntity).sendToTarget();
}
@Override public void onProgress(long currentLocation) {
super.onProgress(currentLocation);
// if (currentLocation - lastLen > INTERVAL) { //不要太过于频繁发送广播
// sendIntent.putExtra(DownloadManager.CURRENT_LOCATION, currentLocation);
// lastLen = currentLocation;
// context.sendBroadcast(sendIntent);
// }
if (System.currentTimeMillis() - lastLen > INTERVAL_TIME) {
sendIntent.putExtra(DownloadManager.CURRENT_LOCATION, currentLocation);
lastTime = System.currentTimeMillis();
context.sendBroadcast(sendIntent);
}
}
/**
* 下载监听类
*/
private class DownloadListener extends DownLoadUtil.DownloadListener {
Handler outHandler;
Context context;
Intent sendIntent;
long INTERVAL = 1024 * 10; //10k大小的间隔
long lastLen = 0; //上一次发送长度
long lastTime = 0;
long INTERVAL_TIME = 60 * 1000; //10k大小的间隔
DownloadEntity downloadEntity;
DownloadListener(Context context, DownloadEntity downloadEntity,
Handler outHandler) {
this.context = context;
this.outHandler = outHandler;
this.downloadEntity = downloadEntity;
sendIntent = createIntent(DownloadManager.ACTION_RUNNING);
sendIntent.putExtra(DownloadManager.ENTITY, downloadEntity);
}
@Override public void onPreDownload(HttpURLConnection connection) {
super.onPreDownload(connection);
long len = connection.getContentLength();
downloadEntity.setFileSize(len);
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
sendIntent(DownloadManager.ACTION_PRE, -1);
}
@Override public void onResume(long resumeLocation) {
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);
sendInState2Target(IDownloadTarget.START);
sendIntent(DownloadManager.ACTION_START, startLocation);
}
@Override public void onProgress(long currentLocation) {
super.onProgress(currentLocation);
// if (currentLocation - lastLen > INTERVAL) { //不要太过于频繁发送广播
// sendIntent.putExtra(DownloadManager.CURRENT_LOCATION, currentLocation);
// lastLen = currentLocation;
// context.sendBroadcast(sendIntent);
// }
if (System.currentTimeMillis() - lastLen > INTERVAL_TIME){
sendIntent.putExtra(DownloadManager.CURRENT_LOCATION, currentLocation);
lastTime = System.currentTimeMillis();
context.sendBroadcast(sendIntent);
}
}
@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 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 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 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);
}
@Override public void onFail() {
super.onFail();
downloadEntity.setState(DownloadEntity.STATE_FAIL);
sendInState2Target(IDownloadTarget.FAIL);
sendIntent(DownloadManager.ACTION_FAIL, -1);
}
private void sendIntent(String action, long location) {
downloadEntity.setDownloadComplete(action.equals(DownloadManager.ACTION_COMPLETE));
downloadEntity.setCurrentProgress(location);
downloadEntity.update();
Intent intent = createIntent(action);
intent.putExtra(DownloadManager.ENTITY, downloadEntity);
if (location != -1) {
intent.putExtra(DownloadManager.CURRENT_LOCATION, location);
}
context.sendBroadcast(intent);
}
private void sendIntent(String action, long location) {
downloadEntity.setDownloadComplete(action.equals(DownloadManager.ACTION_COMPLETE));
downloadEntity.setCurrentProgress(location);
downloadEntity.update();
Intent intent = createIntent(action);
intent.putExtra(DownloadManager.ENTITY, 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 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(Context context, DownloadEntity downloadEntity) {
this.context = context;
this.downloadEntity = downloadEntity;
}
public Builder setDownloadListener(IDownloadListener listener) {
this.listener = listener;
return this;
}
public Builder setDownloadListener(IDownloadListener listener) {
this.listener = listener;
return this;
}
public Builder setOutHandler(Handler outHandler) {
this.outHandler = outHandler;
return this;
}
public Builder setOutHandler(Handler outHandler) {
this.outHandler = outHandler;
return this;
}
public Task build() {
Task task = new Task(context, downloadEntity);
task.mListener = listener;
task.mOutHandler = outHandler;
downloadEntity.save();
return task;
}
public Task build() {
Task task = new Task(context, downloadEntity);
task.mListener = listener;
task.mOutHandler = outHandler;
downloadEntity.save();
return task;
}
}
}

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.util;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@ -16,264 +15,261 @@ import java.util.Properties;
* Created by lyy on 2016/1/22.
*/
public class Util {
private static final String TAG = "util";
private static final String TAG = "util";
/**
* 获取类里面的所在字段
*/
public static Field[] getFields(Class clazz) {
Field[] fields = null;
fields = clazz.getDeclaredFields();
if (fields == null || fields.length == 0) {
Class superClazz = clazz.getSuperclass();
if (superClazz != null) {
fields = getFields(superClazz);
}
}
return fields;
/**
* 获取类里面的所在字段
*/
public static Field[] getFields(Class clazz) {
Field[] fields = null;
fields = clazz.getDeclaredFields();
if (fields == null || fields.length == 0) {
Class superClazz = clazz.getSuperclass();
if (superClazz != null) {
fields = getFields(superClazz);
}
}
return fields;
}
/**
* 获取类里面的指定对象如果该类没有则从父类查询
*/
public static Field getField(Class clazz, String name) {
Field field = null;
try {
field = clazz.getDeclaredField(name);
} catch (NoSuchFieldException e) {
try {
field = clazz.getField(name);
} catch (NoSuchFieldException e1) {
if (clazz.getSuperclass() == null) {
return field;
} else {
field = getField(clazz.getSuperclass(), name);
}
}
}
if (field != null) {
field.setAccessible(true);
/**
* 获取类里面的指定对象如果该类没有则从父类查询
*/
public static Field getField(Class clazz, String name) {
Field field = null;
try {
field = clazz.getDeclaredField(name);
} catch (NoSuchFieldException e) {
try {
field = clazz.getField(name);
} catch (NoSuchFieldException e1) {
if (clazz.getSuperclass() == null) {
return field;
} else {
field = getField(clazz.getSuperclass(), name);
}
return field;
}
}
/**
* 字符串转hashcode
*
* @param str
* @return
*/
public static int keyToHashCode(String str) {
int total = 0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch == '-') ch = (char) 28; // does not contain the same last 5 bits as any letter
if (ch == '\'') ch = (char) 29; // nor this
total = (total * 33) + (ch & 0x1F);
}
return total;
if (field != null) {
field.setAccessible(true);
}
return field;
}
/**
* 将key转换为16进制码
*
* @param key 缓存的key
* @return 转换后的key的值, 系统便是通过该key来读写缓存
*/
public static String keyToHashKey(String key) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
/**
* 字符串转hashcode
*/
public static int keyToHashCode(String str) {
int total = 0;
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch == '-') ch = (char) 28; // does not contain the same last 5 bits as any letter
if (ch == '\'') ch = (char) 29; // nor this
total = (total * 33) + (ch & 0x1F);
}
return total;
}
/**
* 将普通字符串转换为16位进制字符串
*/
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("0x");
if (src == null || src.length <= 0) {
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();
/**
* 将key转换为16进制码
*
* @param key 缓存的key
* @return 转换后的key的值, 系统便是通过该key来读写缓存
*/
public static String keyToHashKey(String key) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey;
}
/**
* 获取对象名
*
* @param obj 对象
* @return 对象名
*/
public static String getClassName(Object obj) {
String arrays[] = obj.getClass().getName().split("\\.");
return arrays[arrays.length - 1];
/**
* 将普通字符串转换为16位进制字符串
*/
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("0x");
if (src == null || src.length <= 0) {
return null;
}
/**
* 获取对象名
*
* @param clazz clazz
* @return 对象名
*/
public static String getClassName(Class clazz) {
String arrays[] = clazz.getName().split("\\.");
return arrays[arrays.length - 1];
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();
}
/**
* 格式化文件大小
*
* @param size file.length() 获取文件大小
*/
public static String formatFileSize(double size) {
double kiloByte = size / 1024;
if (kiloByte < 1) {
return size + "Byte(s)";
}
/**
* 获取对象名
*
* @param obj 对象
* @return 对象名
*/
public static String getClassName(Object obj) {
String arrays[] = obj.getClass().getName().split("\\.");
return arrays[arrays.length - 1];
}
double megaByte = kiloByte / 1024;
if (megaByte < 1) {
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
}
/**
* 获取对象名
*
* @param clazz clazz
* @return 对象名
*/
public static String getClassName(Class clazz) {
String arrays[] = clazz.getName().split("\\.");
return arrays[arrays.length - 1];
}
double gigaByte = megaByte / 1024;
if (gigaByte < 1) {
BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
}
/**
* 格式化文件大小
*
* @param size file.length() 获取文件大小
*/
public static String formatFileSize(double size) {
double kiloByte = size / 1024;
if (kiloByte < 1) {
return size + "Byte(s)";
}
double teraBytes = gigaByte / 1024;
if (teraBytes < 1) {
BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB";
}
BigDecimal result4 = new BigDecimal(teraBytes);
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
double megaByte = kiloByte / 1024;
if (megaByte < 1) {
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
}
/**
* 创建目录 当目录不存在的时候创建文件否则返回false
*/
public static boolean createDir(String path) {
File file = new File(path);
if (!file.exists()) {
if (!file.mkdirs()) {
Log.d(TAG, "创建失败,请检查路径和是否配置文件权限!");
return false;
}
return true;
}
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;
if (teraBytes < 1) {
BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB";
}
BigDecimal result4 = new BigDecimal(teraBytes);
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
}
/**
* 创建目录 当目录不存在的时候创建文件否则返回false
*/
public static boolean createDir(String path) {
File file = new File(path);
if (!file.exists()) {
if (!file.mkdirs()) {
Log.d(TAG, "创建失败,请检查路径和是否配置文件权限!");
return false;
}
return true;
}
return false;
}
/**
* 创建文件 当文件不存在的时候就创建一个文件否则直接返回文件
*/
public static File createFile(String path) {
File file = new File(path);
if (!file.getParentFile().exists()) {
Log.d(TAG, "目标文件所在路径不存在,准备创建……");
if (!createDir(file.getParent())) {
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();
/**
* 创建文件 当文件不存在的时候就创建一个文件否则直接返回文件
*/
public static File createFile(String path) {
File file = new File(path);
if (!file.getParentFile().exists()) {
Log.d(TAG, "目标文件所在路径不存在,准备创建……");
if (!createDir(file.getParent())) {
Log.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】");
}
}
// 创建目标文件
try {
if (!file.exists()) {
if (file.createNewFile()) {
Log.d(TAG, "创建文件成功:" + file.getAbsolutePath());
}
return null;
return file;
} else {
return file;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 设置打印的异常格式
*/
public static String getPrintException(Throwable ex) {
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();
if (cause != null) {
err.append("【Caused by】: ");
err.append(cause.toString());
err.append("\n");
StackTraceElement[] stackTrace = cause.getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
err.append(stackTraceElement.toString()).append("\n");
}
}
err.append("===================================================");
return err.toString();
/**
* 设置打印的异常格式
*/
public static String getPrintException(Throwable ex) {
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();
if (cause != null) {
err.append("【Caused by】: ");
err.append(cause.toString());
err.append("\n");
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();
}
} catch (IOException e) {
e.printStackTrace();
}
/**
* 读取下载配置文件
*/
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;
}
/**
* 保存配置文件
*/
public static void saveConfig(File file, Properties properties) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file, false);
properties.store(fos, null);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.flush();
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
/**
* 保存配置文件
*/
public static void saveConfig(File file, Properties properties) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file, false);
properties.store(fos, null);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.flush();
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

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

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