下载工具死锁修复

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. 5
      app/src/main/AndroidManifest.xml
  11. 78
      app/src/main/java/com/arialyy/simple/activity/MainActivity.java
  12. 91
      app/src/main/java/com/arialyy/simple/activity/MultiTaskActivity.java
  13. 248
      app/src/main/java/com/arialyy/simple/activity/SimpleTestActivity.java
  14. 241
      app/src/main/java/com/arialyy/simple/activity/SingleTaskActivity.java
  15. 21
      app/src/main/java/com/arialyy/simple/adapter/DownloadAdapter.java
  16. 1
      app/src/main/java/com/arialyy/simple/base/BaseActivity.java
  17. 1
      app/src/main/java/com/arialyy/simple/base/BaseApplication.java
  18. 1
      app/src/main/java/com/arialyy/simple/base/BaseModule.java
  19. 52
      app/src/main/java/com/arialyy/simple/module/DownloadModule.java
  20. 39
      app/src/main/java/com/arialyy/simple/widget/HorizontalProgressBarWithNumber.java
  21. 24
      app/src/main/res/layout/activity_main.xml
  22. 20
      app/src/main/res/layout/activity_multi.xml
  23. 42
      app/src/main/res/layout/activity_simple.xml
  24. 34
      app/src/main/res/layout/activity_single.xml
  25. 72
      app/src/main/res/layout/content_simple.xml
  26. 72
      app/src/main/res/layout/content_single.xml
  27. 10
      app/src/main/res/layout/layout_bar.xml
  28. 16
      app/src/main/res/values-v21/styles.xml
  29. 2
      app/src/main/res/values/styles.xml
  30. 14
      app/src/test/java/com/example/arial/downloaddemo/ExampleUnitTest.java
  31. 0
      cache/build/mPro.properties
  32. 3
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadManager.java
  33. 1
      downloadutil/src/main/java/com/arialyy/downloadutil/core/DownloadTarget.java
  34. 3
      downloadutil/src/main/java/com/arialyy/downloadutil/core/IDownloadTarget.java
  35. 1
      downloadutil/src/main/java/com/arialyy/downloadutil/core/TaskFactory.java
  36. 3
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/AddCommand.java
  37. 3
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/CancelCommand.java
  38. 1
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/CommandFactory.java
  39. 1
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/IDownloadCommand.java
  40. 3
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/StartCommand.java
  41. 1
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/StateCommand.java
  42. 1
      downloadutil/src/main/java/com/arialyy/downloadutil/core/command/StopCommand.java
  43. 2
      downloadutil/src/main/java/com/arialyy/downloadutil/core/inf/ITask.java
  44. 2
      downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/CachePool.java
  45. 4
      downloadutil/src/main/java/com/arialyy/downloadutil/core/pool/ExecutePool.java
  46. 1
      downloadutil/src/main/java/com/arialyy/downloadutil/entity/DownloadEntity.java
  47. 2
      downloadutil/src/main/java/com/arialyy/downloadutil/help/CheckHelp.java
  48. 11
      downloadutil/src/main/java/com/arialyy/downloadutil/help/PathHelp.java
  49. 3
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/DbEntity.java
  50. 8
      downloadutil/src/main/java/com/arialyy/downloadutil/orm/DbUtil.java
  51. 187
      downloadutil/src/main/java/com/arialyy/downloadutil/util/DownLoadUtil.java
  52. 8
      downloadutil/src/main/java/com/arialyy/downloadutil/util/Task.java
  53. 4
      downloadutil/src/main/java/com/arialyy/downloadutil/util/Util.java
  54. 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="Add" />
<ConfirmationsSetting value="0" id="Remove" /> <ConfirmationsSetting value="0" id="Remove" />
</component> </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" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

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

@ -13,7 +13,7 @@
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<!--android:name=".activity.SimpleTestActivity"--> <!--android:name=".activity.SingleTaskActivity"-->
<activity <activity
android:name=".activity.MainActivity" android:name=".activity.MainActivity"
android:label="@string/app_name" android:label="@string/app_name"
@ -24,6 +24,9 @@
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".activity.SingleTaskActivity"/>
<activity android:name=".activity.MultiTaskActivity"/>
</application> </application>
</manifest> </manifest>

@ -1,29 +1,19 @@
package com.arialyy.simple.activity; package com.arialyy.simple.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.Toolbar;
import android.support.v7.widget.RecyclerView; import android.view.View;
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.R;
import com.arialyy.simple.adapter.DownloadAdapter;
import com.arialyy.simple.base.BaseActivity; import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityMainBinding; 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> { public class MainActivity extends BaseActivity<ActivityMainBinding> {
@Bind(R.id.list) RecyclerView mList; @Bind(R.id.toolbar) Toolbar mBar;
DownloadAdapter mAdapter;
@Override protected int setLayoutId() { @Override protected int setLayoutId() {
return R.layout.activity_main; return R.layout.activity_main;
@ -31,60 +21,18 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
@Override protected void init(Bundle savedInstanceState) { @Override protected void init(Bundle savedInstanceState) {
super.init(savedInstanceState); super.init(savedInstanceState);
mAdapter = new DownloadAdapter(this, getModule(DownloadModule.class).getDownloadData()); setSupportActionBar(mBar);
mList.setLayoutManager(new LinearLayoutManager(this)); mBar.setTitle("多线程多任务下载");
mList.setAdapter(mAdapter);
} }
public void onClick(View view) {
private BroadcastReceiver mReceiver = new BroadcastReceiver() { switch (view.getId()) {
long len = 0; case R.id.single_task:
startActivity(new Intent(this, SingleTaskActivity.class));
@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; break;
case DownloadManager.ACTION_RUNNING: case R.id.multi_task:
long current = intent.getLongExtra(DownloadManager.CURRENT_LOCATION, 0); startActivity(new Intent(this, MultiTaskActivity.class));
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; break;
} }
} }
};
@Override protected void onResume() {
super.onResume();
registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter());
}
@Override protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
} }

@ -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.content.res.Resources;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import butterknife.Bind;
import com.arialyy.absadapter.common.AbsHolder; import com.arialyy.absadapter.common.AbsHolder;
import com.arialyy.absadapter.recycler_view.AbsRVAdapter; import com.arialyy.absadapter.recycler_view.AbsRVAdapter;
import com.arialyy.downloadutil.core.DownloadManager; import com.arialyy.downloadutil.core.DownloadManager;
@ -14,15 +14,12 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.frame.util.show.L; import com.arialyy.frame.util.show.L;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.widget.HorizontalProgressBarWithNumber; import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import butterknife.Bind;
/** /**
* Created by Lyy on 2016/9/27. * Created by Lyy on 2016/9/27.
* 下载列表适配器 * 下载列表适配器
@ -145,24 +142,24 @@ public class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapte
private void start(DownloadEntity entity) { private void start(DownloadEntity entity) {
List<IDownloadCommand> commands = new ArrayList<>(); List<IDownloadCommand> commands = new ArrayList<>();
IDownloadCommand addCommand = mFactory.createCommand(getContext(), entity, IDownloadCommand addCommand =
CommandFactory.TASK_CREATE); mFactory.createCommand(getContext(), entity, CommandFactory.TASK_CREATE);
IDownloadCommand startCommand = mFactory.createCommand(getContext(), entity, IDownloadCommand startCommand =
CommandFactory.TASK_START); mFactory.createCommand(getContext(), entity, CommandFactory.TASK_START);
commands.add(addCommand); commands.add(addCommand);
commands.add(startCommand); commands.add(startCommand);
mManager.setCommands(commands).exe(); mManager.setCommands(commands).exe();
} }
private void stop(DownloadEntity entity) { private void stop(DownloadEntity entity) {
IDownloadCommand stopCommand = mFactory.createCommand(getContext(), entity, IDownloadCommand stopCommand =
CommandFactory.TASK_STOP); mFactory.createCommand(getContext(), entity, CommandFactory.TASK_STOP);
mManager.setCommand(stopCommand).exe(); mManager.setCommand(stopCommand).exe();
} }
private void cancel(DownloadEntity entity) { private void cancel(DownloadEntity entity) {
IDownloadCommand cancelCommand = mFactory.createCommand(getContext(), entity, IDownloadCommand cancelCommand =
CommandFactory.TASK_CANCEL); mFactory.createCommand(getContext(), entity, CommandFactory.TASK_CANCEL);
mManager.setCommand(cancelCommand).exe(); mManager.setCommand(cancelCommand).exe();
} }
} }

@ -2,7 +2,6 @@ package com.arialyy.simple.base;
import android.databinding.ViewDataBinding; import android.databinding.ViewDataBinding;
import android.os.Bundle; import android.os.Bundle;
import com.arialyy.frame.core.AbsActivity; import com.arialyy.frame.core.AbsActivity;
/** /**

@ -1,7 +1,6 @@
package com.arialyy.simple.base; package com.arialyy.simple.base;
import android.app.Application; import android.app.Application;
import com.arialyy.downloadutil.core.DownloadManager; import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.frame.core.AbsFrame; import com.arialyy.frame.core.AbsFrame;

@ -1,7 +1,6 @@
package com.arialyy.simple.base; package com.arialyy.simple.base;
import android.content.Context; import android.content.Context;
import com.arialyy.frame.module.AbsModule; import com.arialyy.frame.module.AbsModule;
/** /**

@ -3,7 +3,6 @@ package com.arialyy.simple.module;
import android.content.Context; import android.content.Context;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.Environment; import android.os.Environment;
import com.arialyy.downloadutil.core.DownloadManager; import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Util; 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.frame.util.StringUtil;
import com.arialyy.simple.R; import com.arialyy.simple.R;
import com.arialyy.simple.base.BaseModule; import com.arialyy.simple.base.BaseModule;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -26,21 +24,50 @@ public class DownloadModule extends BaseModule {
/** /**
* 设置下载数据 * 设置下载数据
*
* @return
*/ */
public List<DownloadEntity> getDownloadData() { public List<DownloadEntity> getDownloadData() {
List<DownloadEntity> list = DownloadEntity.findAllData(DownloadEntity.class); List<DownloadEntity> list = DownloadEntity.findAllData(DownloadEntity.class);
List<DownloadEntity> newDownload = createNewDownload();
if (list == null) { if (list == null) {
list = createNewDownload(); list = newDownload;
} else {
list = filter(list, newDownload);
} }
return list; return list;
} }
/**
* 过滤任务
*
* @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;
}
count++;
if (count == sqlEntity.size()) {
list.add(cEntity);
}
}
}
return list;
}
/**
* 创建下载列表
*/
private List<DownloadEntity> createNewDownload() { private List<DownloadEntity> createNewDownload() {
List<DownloadEntity> list = new ArrayList<>(); List<DownloadEntity> list = new ArrayList<>();
String[] urls = getContext().getResources() String[] urls =
.getStringArray(R.array.test_apk_download_url); getContext().getResources().getStringArray(R.array.test_apk_download_url);
for (String url : urls) { for (String url : urls) {
String fileName = Util.keyToHashCode(url) + ".apk"; String fileName = Util.keyToHashCode(url) + ".apk";
DownloadEntity entity = new DownloadEntity(); DownloadEntity entity = new DownloadEntity();
@ -54,8 +81,6 @@ public class DownloadModule extends BaseModule {
/** /**
* 下载广播过滤器 * 下载广播过滤器
*
* @return
*/ */
public IntentFilter getDownloadFilter() { public IntentFilter getDownloadFilter() {
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
@ -71,10 +96,13 @@ public class DownloadModule extends BaseModule {
return filter; return filter;
} }
/**
* 设置下载队列
*/
private String getDownloadPath(String url) { private String getDownloadPath(String url) {
String path = Environment.getExternalStorageDirectory() String path =
.getPath() + "/" + AndroidUtils.getAppName(getContext()) + "downloads/" + StringUtil Environment.getExternalStorageDirectory().getPath() + "/" + AndroidUtils.getAppName(
.keyToHashKey(url) + ".apk"; getContext()) + "downloads/" + StringUtil.keyToHashKey(url) + ".apk";
File file = new File(path); File file = new File(path);
if (!file.getParentFile().exists()) { if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs(); file.getParentFile().mkdirs();

@ -7,7 +7,6 @@ import android.graphics.Paint;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.TypedValue; import android.util.TypedValue;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import com.arialyy.simple.R; import com.arialyy.simple.R;
public class HorizontalProgressBarWithNumber extends ProgressBar { public class HorizontalProgressBarWithNumber extends ProgressBar {
@ -32,13 +31,13 @@ public class HorizontalProgressBarWithNumber extends ProgressBar {
/** /**
* offset of draw progress * offset of draw progress
*/ */
protected int mTextOffset = dp2px( protected int mTextOffset =
DEFAULT_SIZE_TEXT_OFFSET); dp2px(DEFAULT_SIZE_TEXT_OFFSET);
/** /**
* height of reached progress bar * height of reached progress bar
*/ */
protected int mReachedProgressBarHeight = dp2px( protected int mReachedProgressBarHeight =
DEFAULT_HEIGHT_REACHED_PROGRESS_BAR); dp2px(DEFAULT_HEIGHT_REACHED_PROGRESS_BAR);
/** /**
* color of reached bar * color of reached bar
*/ */
@ -50,8 +49,8 @@ public class HorizontalProgressBarWithNumber extends ProgressBar {
/** /**
* height of unreached progress bar * height of unreached progress bar
*/ */
protected int mUnReachedProgressBarHeight = dp2px( protected int mUnReachedProgressBarHeight =
DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR); dp2px(DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR);
/** /**
* view width except padding * view width except padding
*/ */
@ -86,9 +85,7 @@ public class HorizontalProgressBarWithNumber extends ProgressBar {
} else { } else {
float textHeight = (mPaint.descent() - mPaint.ascent()); float textHeight = (mPaint.descent() - mPaint.ascent());
result = (int) (getPaddingTop() + getPaddingBottom() + Math.max( result = (int) (getPaddingTop() + getPaddingBottom() + Math.max(
Math.max(mReachedProgressBarHeight, mUnReachedProgressBarHeight), Math.max(mReachedProgressBarHeight, mUnReachedProgressBarHeight), Math.abs(textHeight)));
Math.abs(textHeight))
);
if (specMode == MeasureSpec.AT_MOST) { if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize); result = Math.min(result, specSize);
} }
@ -101,17 +98,18 @@ public class HorizontalProgressBarWithNumber extends ProgressBar {
*/ */
private void obtainStyledAttributes(AttributeSet attrs) { private void obtainStyledAttributes(AttributeSet attrs) {
// init values from custom attributes // init values from custom attributes
final TypedArray attributes = getContext().obtainStyledAttributes(attrs, final TypedArray attributes =
R.styleable.HorizontalProgressBarWithNumber); getContext().obtainStyledAttributes(attrs, R.styleable.HorizontalProgressBarWithNumber);
mTextColor = attributes.getColor( mTextColor =
R.styleable.HorizontalProgressBarWithNumber_progress_text_color, attributes.getColor(R.styleable.HorizontalProgressBarWithNumber_progress_text_color,
DEFAULT_TEXT_COLOR); DEFAULT_TEXT_COLOR);
mTextSize = (int) attributes.getDimension( mTextSize = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_text_size, mTextSize); R.styleable.HorizontalProgressBarWithNumber_progress_text_size, mTextSize);
mReachedBarColor = attributes.getColor( mReachedBarColor =
R.styleable.HorizontalProgressBarWithNumber_progress_reached_color, mTextColor); attributes.getColor(R.styleable.HorizontalProgressBarWithNumber_progress_reached_color,
mUnReachedBarColor = attributes.getColor( mTextColor);
R.styleable.HorizontalProgressBarWithNumber_progress_unreached_color, mUnReachedBarColor =
attributes.getColor(R.styleable.HorizontalProgressBarWithNumber_progress_unreached_color,
DEFAULT_COLOR_UNREACHED_COLOR); DEFAULT_COLOR_UNREACHED_COLOR);
mReachedProgressBarHeight = (int) attributes.getDimension( mReachedProgressBarHeight = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height, R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height,
@ -121,8 +119,9 @@ public class HorizontalProgressBarWithNumber extends ProgressBar {
mUnReachedProgressBarHeight); mUnReachedProgressBarHeight);
mTextOffset = (int) attributes.getDimension( mTextOffset = (int) attributes.getDimension(
R.styleable.HorizontalProgressBarWithNumber_progress_text_offset, mTextOffset); R.styleable.HorizontalProgressBarWithNumber_progress_text_offset, mTextOffset);
int textVisible = attributes.getInt( int textVisible =
R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility, VISIBLE); attributes.getInt(R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility,
VISIBLE);
if (textVisible != VISIBLE) { if (textVisible != VISIBLE) {
mIfDrawText = false; mIfDrawText = false;
} }

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

@ -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>

@ -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"
/>

@ -9,4 +9,20 @@
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item> <item name="colorAccent">@color/colorAccent</item>
</style> </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> </resources>

@ -6,6 +6,8 @@
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item> <item name="colorAccent">@color/colorAccent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style> </style>
<style name="AppTheme.NoActionBar"> <style name="AppTheme.NoActionBar">

@ -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);
}
}

@ -3,13 +3,10 @@ package com.arialyy.downloadutil.core;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.command.IDownloadCommand; import com.arialyy.downloadutil.core.command.IDownloadCommand;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.orm.DbEntity; import com.arialyy.downloadutil.orm.DbEntity;
import com.arialyy.downloadutil.orm.DbUtil; import com.arialyy.downloadutil.orm.DbUtil;
import com.arialyy.downloadutil.util.Task;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

@ -2,7 +2,6 @@ package com.arialyy.downloadutil.core;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task; import com.arialyy.downloadutil.util.Task;

@ -3,7 +3,6 @@ package com.arialyy.downloadutil.core;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.inf.IDownloader; import com.arialyy.downloadutil.core.inf.IDownloader;
import com.arialyy.downloadutil.core.inf.ITask; import com.arialyy.downloadutil.core.inf.ITask;
import com.arialyy.downloadutil.core.pool.CachePool; import com.arialyy.downloadutil.core.pool.CachePool;
@ -100,8 +99,6 @@ public abstract class IDownloadTarget implements IDownloader, ITask {
/** /**
* 获取任务执行池 * 获取任务执行池
*
* @return
*/ */
public ExecutePool getExecutePool() { public ExecutePool getExecutePool() {
return mExecutePool; return mExecutePool;

@ -2,7 +2,6 @@ package com.arialyy.downloadutil.core;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task; import com.arialyy.downloadutil.util.Task;

@ -2,9 +2,8 @@ package com.arialyy.downloadutil.core.command;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
/** /**
* Created by lyy on 2016/8/22. * Created by lyy on 2016/8/22.

@ -1,9 +1,8 @@
package com.arialyy.downloadutil.core.command; package com.arialyy.downloadutil.core.command;
import android.content.Context; import android.content.Context;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
/** /**
* Created by lyy on 2016/9/20. * Created by lyy on 2016/9/20.

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.core.command; package com.arialyy.downloadutil.core.command;
import android.content.Context; import android.content.Context;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
/** /**

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.core.command; package com.arialyy.downloadutil.core.command;
import android.content.Context; import android.content.Context;
import com.arialyy.downloadutil.core.DownloadTarget; import com.arialyy.downloadutil.core.DownloadTarget;
import com.arialyy.downloadutil.core.IDownloadTarget; import com.arialyy.downloadutil.core.IDownloadTarget;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;

@ -1,9 +1,8 @@
package com.arialyy.downloadutil.core.command; package com.arialyy.downloadutil.core.command;
import android.content.Context; import android.content.Context;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
/** /**
* Created by lyy on 2016/8/22. * Created by lyy on 2016/8/22.

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.core.command; package com.arialyy.downloadutil.core.command;
import android.content.Context; import android.content.Context;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
/** /**

@ -2,7 +2,6 @@ package com.arialyy.downloadutil.core.command;
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task; import com.arialyy.downloadutil.util.Task;

@ -1,7 +1,7 @@
package com.arialyy.downloadutil.core.inf; package com.arialyy.downloadutil.core.inf;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import com.arialyy.downloadutil.util.Task;
/** /**
* Created by lyy on 2016/8/16. * Created by lyy on 2016/8/16.

@ -2,11 +2,9 @@ package com.arialyy.downloadutil.core.pool;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.inf.IPool; import com.arialyy.downloadutil.core.inf.IPool;
import com.arialyy.downloadutil.util.Task; import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.util.Util; import com.arialyy.downloadutil.util.Util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;

@ -2,11 +2,9 @@ package com.arialyy.downloadutil.core.pool;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.core.inf.IPool; import com.arialyy.downloadutil.core.inf.IPool;
import com.arialyy.downloadutil.util.Task;
import com.arialyy.downloadutil.util.Util; import com.arialyy.downloadutil.util.Util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;

@ -2,7 +2,6 @@ package com.arialyy.downloadutil.entity;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import com.arialyy.downloadutil.orm.DbEntity; import com.arialyy.downloadutil.orm.DbEntity;
import com.arialyy.downloadutil.orm.Ignore; import com.arialyy.downloadutil.orm.Ignore;

@ -3,10 +3,8 @@ package com.arialyy.downloadutil.help;
import android.content.res.Resources; import android.content.res.Resources;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.R; import com.arialyy.downloadutil.R;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import java.io.File; import java.io.File;
/** /**

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.help; package com.arialyy.downloadutil.help;
import android.os.Environment; import android.os.Environment;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -18,15 +17,11 @@ public class PathHelp {
* @return 保存路径 * @return 保存路径
*/ */
public static String urlconvertPath(String downloadUrl) { public static String urlconvertPath(String downloadUrl) {
return Environment.getDownloadCacheDirectory().getPath() + "/" + StringToHashKey( return Environment.getDownloadCacheDirectory().getPath() + "/" + StringToHashKey(downloadUrl);
downloadUrl);
} }
/** /**
* 字符串转换为hash码 * 字符串转换为hash码
*
* @param str
* @return
*/ */
public static String StringToHashKey(String str) { public static String StringToHashKey(String str) {
String cacheKey; String cacheKey;
@ -42,9 +37,6 @@ public class PathHelp {
/** /**
* 将普通字符串转换为16位进制字符串 * 将普通字符串转换为16位进制字符串
*
* @param src
* @return
*/ */
public static String bytesToHexString(byte[] src) { public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("0x"); StringBuilder stringBuilder = new StringBuilder("0x");
@ -59,5 +51,4 @@ public class PathHelp {
} }
return stringBuilder.toString(); return stringBuilder.toString();
} }
} }

@ -1,9 +1,7 @@
package com.arialyy.downloadutil.orm; package com.arialyy.downloadutil.orm;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import com.arialyy.downloadutil.util.Util; import com.arialyy.downloadutil.util.Util;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -55,7 +53,6 @@ public class DbEntity {
mUtil.modifyData(this); mUtil.modifyData(this);
} }
/** /**
* 保存自身如果表中已经有数据则更新数据否则插入数据 * 保存自身如果表中已经有数据则更新数据否则插入数据
*/ */

@ -6,9 +6,7 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.util.Util; import com.arialyy.downloadutil.util.Util;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -375,7 +373,8 @@ public class DbUtil {
/** /**
* 根据数据游标创建一个具体的对象 * 根据数据游标创建一个具体的对象
*/ */
private synchronized <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz, Cursor cursor) { private synchronized <T extends DbEntity> List<T> newInstanceEntity(Class<T> clazz,
Cursor cursor) {
Field[] fields = Util.getFields(clazz); Field[] fields = Util.getFields(clazz);
List<T> entitys = new ArrayList<>(); List<T> entitys = new ArrayList<>();
if (fields != null && fields.length > 0) { if (fields != null && fields.length > 0) {
@ -401,8 +400,7 @@ public class DbUtil {
} else if (type == long.class || type == Long.class) { } else if (type == long.class || type == Long.class) {
field.setLong(entity, cursor.getLong(column)); field.setLong(entity, cursor.getLong(column));
} else if (type == boolean.class || type == Boolean.class) { } else if (type == boolean.class || type == Boolean.class) {
field.setBoolean(entity, field.setBoolean(entity, !cursor.getString(column).equalsIgnoreCase("false"));
!cursor.getString(column).equalsIgnoreCase("false"));
} else if (type == java.util.Date.class || type == java.sql.Date.class) { } else if (type == java.util.Date.class || type == java.sql.Date.class) {
field.set(entity, new Date(cursor.getString(column))); field.set(entity, new Date(cursor.getString(column)));
} else if (type == byte[].class) { } else if (type == byte[].class) {

@ -4,9 +4,7 @@ import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -22,6 +20,7 @@ import java.util.Properties;
*/ */
final class DownLoadUtil { final class DownLoadUtil {
private static final String TAG = "DownLoadUtil"; private static final String TAG = "DownLoadUtil";
private static final Object LOCK = new Object();
//下载监听 //下载监听
private IDownloadListener mListener; private IDownloadListener mListener;
/** /**
@ -43,7 +42,6 @@ final class DownLoadUtil {
private Context mContext; private Context mContext;
private DownloadEntity mDownloadEntity; private DownloadEntity mDownloadEntity;
public DownLoadUtil(Context context, DownloadEntity entity) { public DownLoadUtil(Context context, DownloadEntity entity) {
mContext = context.getApplicationContext(); mContext = context.getApplicationContext();
mDownloadEntity = entity; mDownloadEntity = entity;
@ -84,8 +82,8 @@ final class DownLoadUtil {
public void delConfigFile() { public void delConfigFile() {
if (mContext != null && mDownloadEntity != null) { if (mContext != null && mDownloadEntity != null) {
File dFile = new File(mDownloadEntity.getDownloadPath()); File dFile = new File(mDownloadEntity.getDownloadPath());
File config = new File( File config =
mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties"); new File(mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties");
if (config.exists()) { if (config.exists()) {
config.delete(); config.delete();
} }
@ -120,8 +118,8 @@ final class DownLoadUtil {
final String downloadUrl = mDownloadEntity.getDownloadUrl(); final String downloadUrl = mDownloadEntity.getDownloadUrl();
final File dFile = new File(filePath); final File dFile = new File(filePath);
//读取已完成的线程数 //读取已完成的线程数
final File configFile = new File( final File configFile =
mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties"); new File(mContext.getFilesDir().getPath() + "/temp/" + dFile.getName() + ".properties");
try { try {
if (!configFile.exists()) { //记录文件被删除,则重新下载 if (!configFile.exists()) { //记录文件被删除,则重新下载
isNewTask = true; isNewTask = true;
@ -142,11 +140,11 @@ final class DownLoadUtil {
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET"); conn.setRequestMethod("GET");
conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Charset", "UTF-8");
conn.setConnectTimeout(TIME_OUT * 4);
conn.setRequestProperty("User-Agent", 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)"); "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", 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, */*"); "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(); conn.connect();
int len = conn.getContentLength(); int len = conn.getContentLength();
if (len < 0) { //网络被劫持时会出现这个问题 if (len < 0) { //网络被劫持时会出现这个问题
@ -207,8 +205,9 @@ final class DownLoadUtil {
} }
//分配下载位置 //分配下载位置
Object record = pro.getProperty(dFile.getName() + "_record_" + i); Object record = pro.getProperty(dFile.getName() + "_record_" + i);
if (!isNewTask && record != null && Long.parseLong( if (!isNewTask
record + "") > 0) { //如果有记录,则恢复下载 && record != null
&& Long.parseLong(record + "") > 0) { //如果有记录,则恢复下载
Long r = Long.parseLong(record + ""); Long r = Long.parseLong(record + "");
mCurrentLocation += r - startL; mCurrentLocation += r - startL;
Log.d(TAG, "++++++++++ 线程_" + i + "_恢复下载 ++++++++++"); Log.d(TAG, "++++++++++ 线程_" + i + "_恢复下载 ++++++++++");
@ -227,9 +226,8 @@ final class DownLoadUtil {
//如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度 //如果整个文件的大小不为线程个数的整数倍,则最后一个线程的结束位置即为文件的总长度
endL = fileLength; endL = fileLength;
} }
ConfigEntity entity = new ConfigEntity(mContext, fileLength, ConfigEntity entity =
downloadUrl, dFile, i, startL, new ConfigEntity(mContext, fileLength, downloadUrl, dFile, i, startL, endL);
endL);
DownLoadTask task = new DownLoadTask(entity); DownLoadTask task = new DownLoadTask(entity);
tasks.put(i, new Thread(task)); tasks.put(i, new Thread(task));
} }
@ -249,9 +247,12 @@ final class DownLoadUtil {
failDownload("下载失败,返回码:" + code); failDownload("下载失败,返回码:" + code);
} }
} catch (IOException e) { } catch (IOException e) {
failDownload( failDownload("下载失败【downloadUrl:"
"下载失败【downloadUrl:" + downloadUrl + "】\n【filePath:" + filePath + "】" + Util + downloadUrl
.getPrintException(e)); + "】\n【filePath:"
+ filePath
+ "】"
+ Util.getPrintException(e));
} }
} }
}).start(); }).start();
@ -272,17 +273,25 @@ final class DownLoadUtil {
private ConfigEntity dEntity; private ConfigEntity dEntity;
private String configFPath; private String configFPath;
public DownLoadTask(ConfigEntity downloadInfo) { private DownLoadTask(ConfigEntity downloadInfo) {
this.dEntity = downloadInfo; this.dEntity = downloadInfo;
configFPath = dEntity.context.getFilesDir() configFPath = dEntity.context.getFilesDir().getPath()
.getPath() + "/temp/" + dEntity.tempFile.getName() + ".properties"; + "/temp/"
+ dEntity.tempFile.getName()
+ ".properties";
} }
@Override public void run() { @Override public void run() {
long currentLocation = 0; long currentLocation = 0;
try { try {
Log.d(TAG, Log.d(TAG, "线程_"
"线程_" + dEntity.threadId + "_正在下载【" + "开始位置 : " + dEntity.startLocation + ",结束位置:" + dEntity.endLocation + "】"); + dEntity.threadId
+ "_正在下载【"
+ "开始位置 : "
+ dEntity.startLocation
+ ",结束位置:"
+ dEntity.endLocation
+ "】");
URL url = new URL(dEntity.downloadUrl); URL url = new URL(dEntity.downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//在头里面请求下载开始位置和结束位置 //在头里面请求下载开始位置和结束位置
@ -315,48 +324,19 @@ final class DownLoadUtil {
} }
//把下载数据数据写入文件 //把下载数据数据写入文件
file.write(buffer, 0, len); file.write(buffer, 0, len);
synchronized (DownLoadUtil.this) { progress(len);
mCurrentLocation += len;
mListener.onProgress(mCurrentLocation);
}
currentLocation += len; currentLocation += len;
} }
file.close(); file.close();
is.close(); is.close();
if (isCancel) { if (isCancel) {
synchronized (DownLoadUtil.this) { cancel();
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; return;
} }
//停止状态不需要删除记录文件 //停止状态不需要删除记录文件
if (isStop) { if (isStop) {
synchronized (DownLoadUtil.this) { stop(currentLocation);
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; return;
} }
Log.i(TAG, "线程【" + dEntity.threadId + "】下载完毕"); Log.i(TAG, "线程【" + dEntity.threadId + "】下载完毕");
@ -372,41 +352,58 @@ final class DownLoadUtil {
mListener.onComplete(); mListener.onComplete();
} }
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
e.printStackTrace(); failDownload(dEntity, currentLocation, "下载链接异常", e);
isDownloading = false; } catch (IOException e) {
synchronized (DownLoadUtil.this) { failDownload(dEntity, currentLocation, "下载失败【" + dEntity.downloadUrl + "】", e);
try { } catch (Exception e) {
String location = String.valueOf(currentLocation); failDownload(dEntity, currentLocation, "获取流失败", e);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId,
location);
failDownload("下载链接异常");
} catch (IOException e1) {
e1.printStackTrace();
} }
} }
} catch (IOException e) {
synchronized (DownLoadUtil.this) { /**
try { * 停止下载
*
* @throws IOException
*/
private void stop(long currentLocation) throws IOException {
synchronized (LOCK) {
mStopNum++;
String location = String.valueOf(currentLocation); String location = String.valueOf(currentLocation);
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, Log.i(TAG, "thread_" + dEntity.threadId + "_stop, stop location ==> " + currentLocation);
location); writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
failDownload( if (mStopNum == THREAD_NUM) {
"下载失败【" + dEntity.downloadUrl + "】" + Util.getPrintException(e)); Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
} catch (IOException e1) { isDownloading = false;
e1.printStackTrace(); mListener.onStop(mCurrentLocation);
} }
} }
} catch (Exception e) { }
synchronized (DownLoadUtil.this) {
try { /**
String location = String.valueOf(currentLocation); * 取消下载
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, */
location); private void cancel() {
failDownload("获取流失败" + Util.getPrintException(e)); synchronized (LOCK) {
} catch (IOException e1) { mCancelNum++;
e1.printStackTrace(); 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();
}
} }
} }
private void progress(long len) {
synchronized (LOCK) {
mCurrentLocation += len;
mListener.onProgress(mCurrentLocation);
} }
} }
@ -419,6 +416,30 @@ final class DownLoadUtil {
pro.setProperty(key, record); pro.setProperty(key, record);
Util.saveConfig(configFile, pro); Util.saveConfig(configFile, pro);
} }
/**
* 下载失败
*/
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();
}
}
}
} }
/** /**
@ -434,8 +455,8 @@ final class DownLoadUtil {
File tempFile; File tempFile;
Context context; Context context;
public ConfigEntity(Context context, long fileSize, String downloadUrl, File file, public ConfigEntity(Context context, long fileSize, String downloadUrl, File file, int threadId,
int threadId, long startLocation, long endLocation) { long startLocation, long endLocation) {
this.fileSize = fileSize; this.fileSize = fileSize;
this.downloadUrl = downloadUrl; this.downloadUrl = downloadUrl;
this.tempFile = file; this.tempFile = file;

@ -5,11 +5,9 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.util.Log; import android.util.Log;
import com.arialyy.downloadutil.core.DownloadManager; import com.arialyy.downloadutil.core.DownloadManager;
import com.arialyy.downloadutil.core.IDownloadTarget; import com.arialyy.downloadutil.core.IDownloadTarget;
import com.arialyy.downloadutil.entity.DownloadEntity; import com.arialyy.downloadutil.entity.DownloadEntity;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
/** /**
@ -105,9 +103,6 @@ public class Task {
/** /**
* 创建特定的Intent * 创建特定的Intent
*
* @param action
* @return
*/ */
private Intent createIntent(String action) { private Intent createIntent(String action) {
Uri.Builder builder = new Uri.Builder(); Uri.Builder builder = new Uri.Builder();
@ -142,8 +137,7 @@ public class Task {
long INTERVAL_TIME = 60 * 1000; //10k大小的间隔 long INTERVAL_TIME = 60 * 1000; //10k大小的间隔
DownloadEntity downloadEntity; DownloadEntity downloadEntity;
DownloadListener(Context context, DownloadEntity downloadEntity, DownloadListener(Context context, DownloadEntity downloadEntity, Handler outHandler) {
Handler outHandler) {
this.context = context; this.context = context;
this.outHandler = outHandler; this.outHandler = outHandler;
this.downloadEntity = downloadEntity; this.downloadEntity = downloadEntity;

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.util; package com.arialyy.downloadutil.util;
import android.util.Log; import android.util.Log;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -59,9 +58,6 @@ public class Util {
/** /**
* 字符串转hashcode * 字符串转hashcode
*
* @param str
* @return
*/ */
public static int keyToHashCode(String str) { public static int keyToHashCode(String str) {
int total = 0; int total = 0;

@ -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