下载工具死锁修复
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
229
.idea/codeStyleSettings.xml
generated
Normal file
229
.idea/codeStyleSettings.xml
generated
Normal file
@ -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>
|
3
.idea/dictionaries/AriaL.xml
generated
Normal file
3
.idea/dictionaries/AriaL.xml
generated
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<component name="ProjectDictionaryState">
|
||||||
|
<dictionary name="AriaL" />
|
||||||
|
</component>
|
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -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 {
|
||||||
|
@ -7,7 +7,7 @@ import android.test.ApplicationTestCase;
|
|||||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||||
*/
|
*/
|
||||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||||
public ApplicationTest() {
|
public ApplicationTest() {
|
||||||
super(Application.class);
|
super(Application.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,29 +1,32 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<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.MOUNT_UNMOUNT_FILESYSTEMS"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".base.BaseApplication"
|
android:name=".base.BaseApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
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:label="@string/app_name"
|
||||||
android:supportsRtl="true"
|
android:theme="@style/AppTheme.NoActionBar">
|
||||||
android:theme="@style/AppTheme">
|
<intent-filter>
|
||||||
<!--android:name=".activity.SimpleTestActivity"-->
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<activity
|
|
||||||
android:name=".activity.MainActivity"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:theme="@style/AppTheme.NoActionBar">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
|
||||||
|
<activity android:name=".activity.SingleTaskActivity"/>
|
||||||
|
<activity android:name=".activity.MultiTaskActivity"/>
|
||||||
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -1,90 +1,38 @@
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@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) {
|
||||||
|
switch (view.getId()) {
|
||||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
case R.id.single_task:
|
||||||
long len = 0;
|
startActivity(new Intent(this, SingleTaskActivity.class));
|
||||||
|
break;
|
||||||
@Override public void onReceive(Context context, Intent intent) {
|
case R.id.multi_task:
|
||||||
String action = intent.getAction();
|
startActivity(new Intent(this, MultiTaskActivity.class));
|
||||||
DownloadEntity entity = intent.getParcelableExtra(DownloadManager.ENTITY);
|
break;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,165 +14,162 @@ 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.
|
||||||
* 下载列表适配器
|
* 下载列表适配器
|
||||||
*/
|
*/
|
||||||
public class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapter.MyHolder> {
|
public class DownloadAdapter extends AbsRVAdapter<DownloadEntity, DownloadAdapter.MyHolder> {
|
||||||
private static final String TAG = "DownloadAdapter";
|
private static final String TAG = "DownloadAdapter";
|
||||||
private DownloadManager mManager;
|
private DownloadManager mManager;
|
||||||
private CommandFactory mFactory;
|
private CommandFactory mFactory;
|
||||||
private Map<String, Long> mProgress = new HashMap<>();
|
private Map<String, Long> mProgress = new HashMap<>();
|
||||||
private Map<String, Integer> mPositions = new HashMap<>();
|
private Map<String, Integer> mPositions = new HashMap<>();
|
||||||
|
|
||||||
public DownloadAdapter(Context context, List<DownloadEntity> data) {
|
public DownloadAdapter(Context context, List<DownloadEntity> data) {
|
||||||
super(context, data);
|
super(context, data);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (DownloadEntity entity : data) {
|
for (DownloadEntity entity : data) {
|
||||||
mProgress.put(entity.getDownloadUrl(), entity.getCurrentProgress());
|
mProgress.put(entity.getDownloadUrl(), entity.getCurrentProgress());
|
||||||
mPositions.put(entity.getDownloadUrl(), i);
|
mPositions.put(entity.getDownloadUrl(), i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
mFactory = CommandFactory.getInstance();
|
mFactory = CommandFactory.getInstance();
|
||||||
mManager = DownloadManager.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BtClickListener implements View.OnClickListener {
|
||||||
|
private DownloadEntity entity;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
BtClickListener(int position, DownloadEntity entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
this.position = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected MyHolder getViewHolder(View convertView, int viewType) {
|
@Override public void onClick(View v) {
|
||||||
return new MyHolder(convertView);
|
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 int setLayoutId(int type) {
|
private void start(DownloadEntity entity) {
|
||||||
return R.layout.item_download;
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateState(DownloadEntity entity) {
|
private void stop(DownloadEntity entity) {
|
||||||
notifyItemChanged(indexItem(entity.getDownloadUrl()));
|
IDownloadCommand stopCommand =
|
||||||
|
mFactory.createCommand(getContext(), entity, CommandFactory.TASK_STOP);
|
||||||
|
mManager.setCommand(stopCommand).exe();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setProgress(String url, long currentPosition) {
|
private void cancel(DownloadEntity entity) {
|
||||||
mProgress.put(url, currentPosition);
|
IDownloadCommand cancelCommand =
|
||||||
// int index = indexItem(url);
|
mFactory.createCommand(getContext(), entity, CommandFactory.TASK_CANCEL);
|
||||||
// L.d(TAG, "index ==> " + index);
|
mManager.setCommand(cancelCommand).exe();
|
||||||
// notifyItemChanged(index);
|
|
||||||
notifyItemChanged(indexItem(url));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized int indexItem(String url) {
|
class MyHolder extends AbsHolder {
|
||||||
Set set = mPositions.entrySet();
|
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber progress;
|
||||||
for (Object aSet : set) {
|
@Bind(R.id.bt) Button bt;
|
||||||
Map.Entry entry = (Map.Entry) aSet;
|
|
||||||
if (entry.getKey().equals(url)) {
|
MyHolder(View itemView) {
|
||||||
return (int) entry.getValue();
|
super(itemView);
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyHolder extends AbsHolder {
|
|
||||||
@Bind(R.id.progressBar) HorizontalProgressBarWithNumber progress;
|
|
||||||
@Bind(R.id.bt) Button bt;
|
|
||||||
|
|
||||||
MyHolder(View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,17 @@ 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Lyy on 2016/9/27.
|
* Created by Lyy on 2016/9/27.
|
||||||
*/
|
*/
|
||||||
public abstract class BaseActivity<VB extends ViewDataBinding> extends AbsActivity<VB> {
|
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) {
|
@Override protected void init(Bundle savedInstanceState) {
|
||||||
super.init(savedInstanceState);
|
super.init(savedInstanceState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -9,9 +8,9 @@ import com.arialyy.frame.core.AbsFrame;
|
|||||||
* Created by Lyy on 2016/9/27.
|
* Created by Lyy on 2016/9/27.
|
||||||
*/
|
*/
|
||||||
public class BaseApplication extends Application {
|
public class BaseApplication extends Application {
|
||||||
@Override public void onCreate() {
|
@Override public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
AbsFrame.init(this);
|
AbsFrame.init(this);
|
||||||
DownloadManager.init(this);
|
DownloadManager.init(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Lyy on 2016/9/27.
|
* Created by Lyy on 2016/9/27.
|
||||||
*/
|
*/
|
||||||
public class BaseModule extends AbsModule {
|
public class BaseModule extends AbsModule {
|
||||||
public BaseModule(Context context) {
|
public BaseModule(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -20,65 +18,95 @@ import java.util.List;
|
|||||||
* Created by Lyy on 2016/9/27.
|
* Created by Lyy on 2016/9/27.
|
||||||
*/
|
*/
|
||||||
public class DownloadModule extends BaseModule {
|
public class DownloadModule extends BaseModule {
|
||||||
public DownloadModule(Context context) {
|
public DownloadModule(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置下载数据
|
* 设置下载数据
|
||||||
*
|
*/
|
||||||
* @return
|
public List<DownloadEntity> getDownloadData() {
|
||||||
*/
|
List<DownloadEntity> list = DownloadEntity.findAllData(DownloadEntity.class);
|
||||||
public List<DownloadEntity> getDownloadData() {
|
List<DownloadEntity> newDownload = createNewDownload();
|
||||||
List<DownloadEntity> list = DownloadEntity.findAllData(DownloadEntity.class);
|
if (list == null) {
|
||||||
if (list == null) {
|
list = newDownload;
|
||||||
list = createNewDownload();
|
} else {
|
||||||
|
list = filter(list, newDownload);
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
return list;
|
count++;
|
||||||
}
|
if (count == sqlEntity.size()) {
|
||||||
|
list.add(cEntity);
|
||||||
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;
|
}
|
||||||
}
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载广播过滤器
|
* 创建下载列表
|
||||||
*
|
*/
|
||||||
* @return
|
private List<DownloadEntity> createNewDownload() {
|
||||||
*/
|
List<DownloadEntity> list = new ArrayList<>();
|
||||||
public IntentFilter getDownloadFilter() {
|
String[] urls =
|
||||||
IntentFilter filter = new IntentFilter();
|
getContext().getResources().getStringArray(R.array.test_apk_download_url);
|
||||||
filter.addDataScheme(getContext().getPackageName());
|
for (String url : urls) {
|
||||||
filter.addAction(DownloadManager.ACTION_PRE);
|
String fileName = Util.keyToHashCode(url) + ".apk";
|
||||||
filter.addAction(DownloadManager.ACTION_RESUME);
|
DownloadEntity entity = new DownloadEntity();
|
||||||
filter.addAction(DownloadManager.ACTION_START);
|
entity.setDownloadUrl(url);
|
||||||
filter.addAction(DownloadManager.ACTION_RUNNING);
|
entity.setDownloadPath(getDownloadPath(url));
|
||||||
filter.addAction(DownloadManager.ACTION_STOP);
|
entity.setFileName(fileName);
|
||||||
filter.addAction(DownloadManager.ACTION_CANCEL);
|
list.add(entity);
|
||||||
filter.addAction(DownloadManager.ACTION_COMPLETE);
|
|
||||||
filter.addAction(DownloadManager.ACTION_FAIL);
|
|
||||||
return filter;
|
|
||||||
}
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
private String getDownloadPath(String url) {
|
/**
|
||||||
String path = Environment.getExternalStorageDirectory()
|
* 下载广播过滤器
|
||||||
.getPath() + "/" + AndroidUtils.getAppName(getContext()) + "downloads/" + StringUtil
|
*/
|
||||||
.keyToHashKey(url) + ".apk";
|
public IntentFilter getDownloadFilter() {
|
||||||
File file = new File(path);
|
IntentFilter filter = new IntentFilter();
|
||||||
if (!file.getParentFile().exists()) {
|
filter.addDataScheme(getContext().getPackageName());
|
||||||
file.getParentFile().mkdirs();
|
filter.addAction(DownloadManager.ACTION_PRE);
|
||||||
}
|
filter.addAction(DownloadManager.ACTION_RESUME);
|
||||||
return path;
|
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.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 {
|
||||||
private static final int DEFAULT_TEXT_SIZE = 10;
|
private static final int DEFAULT_TEXT_SIZE = 10;
|
||||||
private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1;
|
private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1;
|
||||||
private static final int DEFAULT_COLOR_UNREACHED_COLOR = 0xFFd3d6da;
|
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_REACHED_PROGRESS_BAR = 2;
|
||||||
private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2;
|
private static final int DEFAULT_HEIGHT_UNREACHED_PROGRESS_BAR = 2;
|
||||||
private static final int DEFAULT_SIZE_TEXT_OFFSET = 10;
|
private static final int DEFAULT_SIZE_TEXT_OFFSET = 10;
|
||||||
/**
|
/**
|
||||||
* painter of all drawing things
|
* painter of all drawing things
|
||||||
*/
|
*/
|
||||||
protected Paint mPaint = new Paint();
|
protected Paint mPaint = new Paint();
|
||||||
/**
|
/**
|
||||||
* color of progress number
|
* color of progress number
|
||||||
*/
|
*/
|
||||||
protected int mTextColor = DEFAULT_TEXT_COLOR;
|
protected int mTextColor = DEFAULT_TEXT_COLOR;
|
||||||
/**
|
/**
|
||||||
* size of text (sp)
|
* size of text (sp)
|
||||||
*/
|
*/
|
||||||
protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
|
protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
protected int mReachedBarColor = DEFAULT_TEXT_COLOR;
|
protected int mReachedBarColor = DEFAULT_TEXT_COLOR;
|
||||||
/**
|
/**
|
||||||
* color of unreached bar
|
* color of unreached bar
|
||||||
*/
|
*/
|
||||||
protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR;
|
protected int mUnReachedBarColor = DEFAULT_COLOR_UNREACHED_COLOR;
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
protected int mRealWidth;
|
protected int mRealWidth;
|
||||||
protected boolean mIfDrawText = true;
|
protected boolean mIfDrawText = true;
|
||||||
protected static final int VISIBLE = 0;
|
protected static final int VISIBLE = 0;
|
||||||
|
|
||||||
public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) {
|
public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs) {
|
||||||
this(context, attrs, 0);
|
this(context, attrs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs, int defStyle) {
|
public HorizontalProgressBarWithNumber(Context context, AttributeSet attrs, int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
obtainStyledAttributes(attrs);
|
obtainStyledAttributes(attrs);
|
||||||
mPaint.setTextSize(mTextSize);
|
mPaint.setTextSize(mTextSize);
|
||||||
mPaint.setColor(mTextColor);
|
mPaint.setColor(mTextColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
@Override protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
int width = MeasureSpec.getSize(widthMeasureSpec);
|
int width = MeasureSpec.getSize(widthMeasureSpec);
|
||||||
int height = measureHeight(heightMeasureSpec);
|
int height = measureHeight(heightMeasureSpec);
|
||||||
setMeasuredDimension(width, height);
|
setMeasuredDimension(width, height);
|
||||||
mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft();
|
mRealWidth = getMeasuredWidth() - getPaddingRight() - getPaddingLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int measureHeight(int measureSpec) {
|
private int measureHeight(int measureSpec) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int specMode = MeasureSpec.getMode(measureSpec);
|
int specMode = MeasureSpec.getMode(measureSpec);
|
||||||
int specSize = MeasureSpec.getSize(measureSpec);
|
int specSize = MeasureSpec.getSize(measureSpec);
|
||||||
if (specMode == MeasureSpec.EXACTLY) {
|
if (specMode == MeasureSpec.EXACTLY) {
|
||||||
result = specSize;
|
result = specSize;
|
||||||
} 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) {
|
||||||
);
|
result = Math.min(result, specSize);
|
||||||
if (specMode == MeasureSpec.AT_MOST) {
|
}
|
||||||
result = Math.min(result, specSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the styled attributes
|
* get the styled attributes
|
||||||
*/
|
*/
|
||||||
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 =
|
||||||
DEFAULT_COLOR_UNREACHED_COLOR);
|
attributes.getColor(R.styleable.HorizontalProgressBarWithNumber_progress_unreached_color,
|
||||||
mReachedProgressBarHeight = (int) attributes.getDimension(
|
DEFAULT_COLOR_UNREACHED_COLOR);
|
||||||
R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height,
|
mReachedProgressBarHeight = (int) attributes.getDimension(
|
||||||
mReachedProgressBarHeight);
|
R.styleable.HorizontalProgressBarWithNumber_progress_reached_bar_height,
|
||||||
mUnReachedProgressBarHeight = (int) attributes.getDimension(
|
mReachedProgressBarHeight);
|
||||||
R.styleable.HorizontalProgressBarWithNumber_progress_unreached_bar_height,
|
mUnReachedProgressBarHeight = (int) attributes.getDimension(
|
||||||
mUnReachedProgressBarHeight);
|
R.styleable.HorizontalProgressBarWithNumber_progress_unreached_bar_height,
|
||||||
mTextOffset = (int) attributes.getDimension(
|
mUnReachedProgressBarHeight);
|
||||||
R.styleable.HorizontalProgressBarWithNumber_progress_text_offset, mTextOffset);
|
mTextOffset = (int) attributes.getDimension(
|
||||||
int textVisible = attributes.getInt(
|
R.styleable.HorizontalProgressBarWithNumber_progress_text_offset, mTextOffset);
|
||||||
R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility, VISIBLE);
|
int textVisible =
|
||||||
if (textVisible != VISIBLE) {
|
attributes.getInt(R.styleable.HorizontalProgressBarWithNumber_progress_text_visibility,
|
||||||
mIfDrawText = false;
|
VISIBLE);
|
||||||
}
|
if (textVisible != VISIBLE) {
|
||||||
attributes.recycle();
|
mIfDrawText = false;
|
||||||
}
|
}
|
||||||
|
attributes.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
@Override protected synchronized void onDraw(Canvas canvas) {
|
@Override protected synchronized void onDraw(Canvas canvas) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
canvas.translate(getPaddingLeft(), getHeight() / 2);
|
canvas.translate(getPaddingLeft(), getHeight() / 2);
|
||||||
boolean noNeedBg = false;
|
boolean noNeedBg = false;
|
||||||
float radio = getProgress() * 1.0f / getMax();
|
float radio = getProgress() * 1.0f / getMax();
|
||||||
float progressPosX = (int) (mRealWidth * radio);
|
float progressPosX = (int) (mRealWidth * radio);
|
||||||
String text = getProgress() + "%";
|
String text = getProgress() + "%";
|
||||||
// mPaint.getTextBounds(text, 0, text.length(), mTextBound);
|
// mPaint.getTextBounds(text, 0, text.length(), mTextBound);
|
||||||
float textWidth = mPaint.measureText(text);
|
float textWidth = mPaint.measureText(text);
|
||||||
float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;
|
float textHeight = (mPaint.descent() + mPaint.ascent()) / 2;
|
||||||
if (progressPosX + textWidth > mRealWidth) {
|
if (progressPosX + textWidth > mRealWidth) {
|
||||||
progressPosX = mRealWidth - textWidth;
|
progressPosX = mRealWidth - textWidth;
|
||||||
noNeedBg = true;
|
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();
|
|
||||||
}
|
}
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dp 2 px
|
* dp 2 px
|
||||||
*/
|
*/
|
||||||
protected int dp2px(int dpVal) {
|
protected int dp2px(int dpVal) {
|
||||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
|
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
|
||||||
getResources().getDisplayMetrics());
|
getResources().getDisplayMetrics());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sp 2 px
|
* sp 2 px
|
||||||
*/
|
*/
|
||||||
protected int sp2px(int spVal) {
|
protected int sp2px(int spVal) {
|
||||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
|
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
|
||||||
getResources().getDisplayMetrics());
|
getResources().getDisplayMetrics());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,18 +1,32 @@
|
|||||||
<?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_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
>
|
||||||
|
|
||||||
|
<include layout="@layout/layout_bar"/>
|
||||||
|
|
||||||
|
<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:orientation="vertical"
|
android:onClick="onClick"
|
||||||
>
|
android:text="单任务下载"
|
||||||
|
style="?buttonBarButtonStyle"
|
||||||
|
/>
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<Button
|
||||||
android:id="@+id/list"
|
android:id="@+id/multi_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"
|
||||||
|
/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</layout>
|
</layout>
|
||||||
|
20
app/src/main/res/layout/activity_multi.xml
Normal file
20
app/src/main/res/layout/activity_multi.xml
Normal file
@ -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>
|
|
34
app/src/main/res/layout/activity_single.xml
Normal file
34
app/src/main/res/layout/activity_single.xml
Normal file
@ -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>
|
|
72
app/src/main/res/layout/content_single.xml
Normal file
72
app/src/main/res/layout/content_single.xml
Normal file
@ -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"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
>
|
>
|
||||||
|
|
||||||
<com.arialyy.simple.widget.HorizontalProgressBarWithNumber
|
<com.arialyy.simple.widget.HorizontalProgressBarWithNumber
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/progressBar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_toLeftOf="@+id/bt"
|
android:layout_toLeftOf="@+id/bt"
|
||||||
android:max="100"
|
android:max="100"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/bt"
|
android:id="@+id/bt"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:text="开始"
|
android:text="开始"
|
||||||
style="?buttonBarButtonStyle"
|
style="?buttonBarButtonStyle"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
10
app/src/main/res/layout/layout_bar.xml
Normal file
10
app/src/main/res/layout/layout_bar.xml
Normal file
@ -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"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context="com.example.arial.downloaddemo.com.arialyy.simple.MainActivity">
|
tools:context="com.example.arial.downloaddemo.com.arialyy.simple.MainActivity">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_settings"
|
android:id="@+id/action_settings"
|
||||||
android:title="@string/action_settings"
|
android:title="@string/action_settings"
|
||||||
android:orderInCategory="100"
|
android:orderInCategory="100"
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
</menu>
|
</menu>
|
||||||
|
@ -1,12 +1,28 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="AppTheme.NoActionBar">
|
<style name="AppTheme.NoActionBar">
|
||||||
<item name="windowActionBar">false</item>
|
<item name="windowActionBar">false</item>
|
||||||
<item name="windowNoTitle">true</item>
|
<item name="windowNoTitle">true</item>
|
||||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||||
<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>
|
||||||
</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>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
|
<!-- 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
|
(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). -->
|
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
|
||||||
<dimen name="activity_horizontal_margin">64dp</dimen>
|
<dimen name="activity_horizontal_margin">64dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<declare-styleable name="HorizontalProgressBarWithNumber">
|
<declare-styleable name="HorizontalProgressBarWithNumber">
|
||||||
<attr name="progress_unreached_color" format="color"/>
|
<attr name="progress_unreached_color" format="color"/>
|
||||||
<attr name="progress_reached_color" format="color"/>
|
<attr name="progress_reached_color" format="color"/>
|
||||||
<attr name="progress_reached_bar_height" format="dimension"/>
|
<attr name="progress_reached_bar_height" format="dimension"/>
|
||||||
<attr name="progress_unreached_bar_height" format="dimension"/>
|
<attr name="progress_unreached_bar_height" format="dimension"/>
|
||||||
<attr name="progress_text_size" format="dimension"/>
|
<attr name="progress_text_size" format="dimension"/>
|
||||||
<attr name="progress_text_color" format="color"/>
|
<attr name="progress_text_color" format="color"/>
|
||||||
<attr name="progress_text_offset" format="dimension"/>
|
<attr name="progress_text_offset" format="dimension"/>
|
||||||
<attr name="progress_text_visibility" format="enum">
|
<attr name="progress_text_visibility" format="enum">
|
||||||
<enum name="visible" value="0"/>
|
<enum name="visible" value="0"/>
|
||||||
<enum name="invisible" value="1"/>
|
<enum name="invisible" value="1"/>
|
||||||
</attr>
|
</attr>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
</resources>
|
</resources>
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="colorPrimary">#3F51B5</color>
|
<color name="colorPrimary">#3F51B5</color>
|
||||||
<color name="colorPrimaryDark">#303F9F</color>
|
<color name="colorPrimaryDark">#303F9F</color>
|
||||||
<color name="colorAccent">#FF4081</color>
|
<color name="colorAccent">#FF4081</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
<dimen name="fab_margin">16dp</dimen>
|
<dimen name="fab_margin">16dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">DownloadDemo</string>
|
<string name="app_name">DownloadDemo</string>
|
||||||
<string name="action_settings">Settings</string>
|
<string name="action_settings">Settings</string>
|
||||||
|
|
||||||
<string-array name="test_apk_download_url">
|
<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/22/94/822260b849944492caadd2983f9bb624.apk</item> <!--300M的文件-->
|
||||||
<item>http://static.gaoshouyou.com/d/21/e8/61218d78d0e8b79df68dbc18dd484c97.apk</item>
|
<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/12/0d/7f120f50c80d2e7b8c4ba24ece4f9cdd.apk</item>
|
||||||
<item>http://static.gaoshouyou.com/d/d4/4f/d6d48db3794fb9ecf47e83c346570881.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/18/cf/ba18113bc6cf56c1c5863e761e717003.apk</item>-->
|
||||||
<!--<item>http://static.gaoshouyou.com/d/60/17/2460921367173ea7145f11194a6f2587.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/32/e0/1a32123ecbe0ee010d35479df248f90f.apk</item>-->
|
||||||
<!--<item>http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.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/e6/f5/4de6329f9cf5dc3a1d1e6bbcca0d003c.apk</item>-->
|
||||||
<!--<item>http://static.gaoshouyou.com/d/6e/e5/ff6ecaaf45e532e6d07747af82357472.apk</item>-->
|
<!--<item>http://static.gaoshouyou.com/d/6e/e5/ff6ecaaf45e532e6d07747af82357472.apk</item>-->
|
||||||
<!--<item>http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk</item>-->
|
<!--<item>http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk</item>-->
|
||||||
</string-array>
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<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>
|
||||||
</style>
|
<item name="windowActionBar">false</item>
|
||||||
|
<item name="windowNoTitle">true</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.NoActionBar">
|
<style name="AppTheme.NoActionBar">
|
||||||
<item name="windowActionBar">false</item>
|
<item name="windowActionBar">false</item>
|
||||||
<item name="windowNoTitle">true</item>
|
<item name="windowNoTitle">true</item>
|
||||||
<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>
|
||||||
</style>
|
</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>
|
</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);
|
|
||||||
}
|
|
||||||
}
|
|
0
cache/build/mPro.properties
vendored
Normal file
0
cache/build/mPro.properties
vendored
Normal file
@ -7,7 +7,7 @@ import android.test.ApplicationTestCase;
|
|||||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||||
*/
|
*/
|
||||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||||
public ApplicationTest() {
|
public ApplicationTest() {
|
||||||
super(Application.class);
|
super(Application.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.arialyy.downloadutil">
|
package="com.arialyy.downloadutil">
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:supportsRtl="true">
|
android:supportsRtl="true">
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -18,122 +15,122 @@ import java.util.List;
|
|||||||
* 下载管理器,通过命令的方式控制下载
|
* 下载管理器,通过命令的方式控制下载
|
||||||
*/
|
*/
|
||||||
public class DownloadManager {
|
public class DownloadManager {
|
||||||
private static final String TAG = "DownloadManager";
|
private static final String TAG = "DownloadManager";
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
private static volatile DownloadManager INSTANCE = null;
|
private static volatile DownloadManager INSTANCE = null;
|
||||||
/**
|
/**
|
||||||
* 下载开始前事件
|
* 下载开始前事件
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_PRE = "ACTION_PRE";
|
public static final String ACTION_PRE = "ACTION_PRE";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始下载事件
|
* 开始下载事件
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_START = "ACTION_START";
|
public static final String ACTION_START = "ACTION_START";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 恢复下载事件
|
* 恢复下载事件
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_RESUME = "ACTION_RESUME";
|
public static final String ACTION_RESUME = "ACTION_RESUME";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 正在下载事件
|
* 正在下载事件
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_RUNNING = "ACTION_RUNNING";
|
public static final String ACTION_RUNNING = "ACTION_RUNNING";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止下载事件
|
* 停止下载事件
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_STOP = "ACTION_STOP";
|
public static final String ACTION_STOP = "ACTION_STOP";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消下载事件
|
* 取消下载事件
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_CANCEL = "ACTION_CANCEL";
|
public static final String ACTION_CANCEL = "ACTION_CANCEL";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载完成事件
|
* 下载完成事件
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_COMPLETE = "ACTION_COMPLETE";
|
public static final String ACTION_COMPLETE = "ACTION_COMPLETE";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载失败事件
|
* 下载失败事件
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_FAIL = "ACTION_FAIL";
|
public static final String ACTION_FAIL = "ACTION_FAIL";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载实体
|
* 下载实体
|
||||||
*/
|
*/
|
||||||
public static final String ENTITY = "DOWNLOAD_ENTITY";
|
public static final String ENTITY = "DOWNLOAD_ENTITY";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 位置
|
* 位置
|
||||||
*/
|
*/
|
||||||
public static final String CURRENT_LOCATION = "CURRENT_LOCATION";
|
public static final String CURRENT_LOCATION = "CURRENT_LOCATION";
|
||||||
|
|
||||||
private List<IDownloadCommand> mCommands = new ArrayList<>();
|
private List<IDownloadCommand> mCommands = new ArrayList<>();
|
||||||
|
|
||||||
private DownloadManager() {
|
private DownloadManager() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
private DownloadManager(Context context) {
|
private DownloadManager(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
DownloadTarget.init(context);
|
DownloadTarget.init(context);
|
||||||
DbUtil.init(context);
|
DbUtil.init(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DownloadManager init(Context context) {
|
public static DownloadManager init(Context context) {
|
||||||
if (context instanceof Application) {
|
if (context instanceof Application) {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
INSTANCE = new DownloadManager(context.getApplicationContext());
|
INSTANCE = new DownloadManager(context.getApplicationContext());
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.e(TAG, "Context 只能为application");
|
|
||||||
}
|
}
|
||||||
return INSTANCE;
|
}
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Context 只能为application");
|
||||||
}
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
public static DownloadManager getInstance() {
|
public static DownloadManager getInstance() {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
throw new NullPointerException("请在Application中调用init进行下载器注册");
|
throw new NullPointerException("请在Application中调用init进行下载器注册");
|
||||||
}
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
public List<DownloadEntity> getAllDownloadEntity(){
|
public List<DownloadEntity> getAllDownloadEntity() {
|
||||||
return DbEntity.findAllData(DownloadEntity.class);
|
return DbEntity.findAllData(DownloadEntity.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置命令
|
* 设置命令
|
||||||
*/
|
*/
|
||||||
public DownloadManager setCommand(IDownloadCommand command) {
|
public DownloadManager setCommand(IDownloadCommand command) {
|
||||||
mCommands.add(command);
|
mCommands.add(command);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置一组命令
|
* 设置一组命令
|
||||||
*/
|
*/
|
||||||
public DownloadManager setCommands(List<IDownloadCommand> commands) {
|
public DownloadManager setCommands(List<IDownloadCommand> commands) {
|
||||||
if (commands != null && commands.size() > 0) {
|
if (commands != null && commands.size() > 0) {
|
||||||
mCommands.addAll(commands);
|
mCommands.addAll(commands);
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行所有设置的命令
|
* 执行所有设置的命令
|
||||||
*/
|
*/
|
||||||
public synchronized void exe() {
|
public synchronized void exe() {
|
||||||
for (IDownloadCommand command : mCommands) {
|
for (IDownloadCommand command : mCommands) {
|
||||||
command.executeComment();
|
command.executeComment();
|
||||||
}
|
|
||||||
mCommands.clear();
|
|
||||||
}
|
}
|
||||||
|
mCommands.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
@ -11,105 +10,105 @@ import com.arialyy.downloadutil.util.Task;
|
|||||||
* 下载任务调度类
|
* 下载任务调度类
|
||||||
*/
|
*/
|
||||||
public class DownloadTarget extends IDownloadTarget {
|
public class DownloadTarget extends IDownloadTarget {
|
||||||
private static final String TAG = "DownloadTarget";
|
private static final String TAG = "DownloadTarget";
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
private static volatile DownloadTarget INSTANCE = null;
|
private static volatile DownloadTarget INSTANCE = null;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
public static DownloadTarget getInstance() {
|
public static DownloadTarget getInstance() {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
throw new NullPointerException("请在Application中调用init进行注册");
|
throw new NullPointerException("请在Application中调用init进行注册");
|
||||||
}
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
static DownloadTarget init(Context context) {
|
static DownloadTarget init(Context context) {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
INSTANCE = new DownloadTarget(context.getApplicationContext());
|
INSTANCE = new DownloadTarget(context.getApplicationContext());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
private DownloadTarget() {
|
private DownloadTarget() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DownloadTarget(Context context) {
|
private DownloadTarget(Context context) {
|
||||||
super();
|
super();
|
||||||
mContext = context;
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void startTask(Task task) {
|
@Override public void startTask(Task task) {
|
||||||
if (mExecutePool.putTask(task)) {
|
if (mExecutePool.putTask(task)) {
|
||||||
task.start();
|
task.start();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public void stopTask(Task task) {
|
@Override public void stopTask(Task task) {
|
||||||
if (task.isDownloading()) {
|
if (task.isDownloading()) {
|
||||||
if (mExecutePool.removeTask(task)) {
|
if (mExecutePool.removeTask(task)) {
|
||||||
task.stop();
|
task.stop();
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
task.stop();
|
task.stop();
|
||||||
Log.w(TAG, "停止任务失败,【任务已经停止】");
|
Log.w(TAG, "停止任务失败,【任务已经停止】");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public void cancelTask(Task task) {
|
@Override public void cancelTask(Task task) {
|
||||||
if (mExecutePool.removeTask(task) || mCachePool.removeTask(task)) {
|
if (mExecutePool.removeTask(task) || mCachePool.removeTask(task)) {
|
||||||
task.cancel();
|
task.cancel();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public void reTryStart(Task task) {
|
@Override public void reTryStart(Task task) {
|
||||||
if (!task.isDownloading()) {
|
if (!task.isDownloading()) {
|
||||||
task.start();
|
task.start();
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "任务没有完全停止,重试下载失败");
|
Log.w(TAG, "任务没有完全停止,重试下载失败");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public Task createTask(DownloadEntity entity) {
|
@Override public Task createTask(DownloadEntity entity) {
|
||||||
Task task = TaskFactory.getInstance().createTask(mContext, entity, mTaskHandler);
|
Task task = TaskFactory.getInstance().createTask(mContext, entity, mTaskHandler);
|
||||||
mCachePool.putTask(task);
|
mCachePool.putTask(task);
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public Task getTask(DownloadEntity entity) {
|
@Override public Task getTask(DownloadEntity entity) {
|
||||||
Task task = mExecutePool.getTask(entity.getDownloadUrl());
|
Task task = mExecutePool.getTask(entity.getDownloadUrl());
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
task = mCachePool.getTask(entity.getDownloadUrl());
|
task = mCachePool.getTask(entity.getDownloadUrl());
|
||||||
}
|
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public int getTaskState(DownloadEntity entity) {
|
@Override public int getTaskState(DownloadEntity entity) {
|
||||||
Task task = getTask(entity);
|
Task task = getTask(entity);
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
Log.e(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的下载任务");
|
Log.e(TAG, "没有找到下载链接为【" + entity.getDownloadUrl() + "】的下载任务");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
return task.getDownloadEntity().getState();
|
|
||||||
}
|
}
|
||||||
|
return task.getDownloadEntity().getState();
|
||||||
|
}
|
||||||
|
|
||||||
@Override public void removeTask(DownloadEntity entity) {
|
@Override public void removeTask(DownloadEntity entity) {
|
||||||
Task task = mExecutePool.getTask(entity.getDownloadUrl());
|
Task task = mExecutePool.getTask(entity.getDownloadUrl());
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
|
Log.d(TAG, "从执行池删除任务,删除" + (mExecutePool.removeTask(task) ? "成功" : "失败"));
|
||||||
} else {
|
} else {
|
||||||
task = mCachePool.getTask(entity.getDownloadUrl());
|
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() {
|
@Override public Task getNextTask() {
|
||||||
return mCachePool.pollTask();
|
return mCachePool.pollTask();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package com.arialyy.downloadutil.core;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.arialyy.downloadutil.core.inf.IDownloader;
|
import com.arialyy.downloadutil.core.inf.IDownloader;
|
||||||
import com.arialyy.downloadutil.core.inf.ITask;
|
import com.arialyy.downloadutil.core.inf.ITask;
|
||||||
import com.arialyy.downloadutil.core.pool.CachePool;
|
import com.arialyy.downloadutil.core.pool.CachePool;
|
||||||
@ -16,212 +15,210 @@ import com.arialyy.downloadutil.util.Task;
|
|||||||
* 任务下载器,提供抽象的方法供具体的实现类操作
|
* 任务下载器,提供抽象的方法供具体的实现类操作
|
||||||
*/
|
*/
|
||||||
public abstract class IDownloadTarget implements IDownloader, ITask {
|
public abstract class IDownloadTarget implements IDownloader, ITask {
|
||||||
|
/**
|
||||||
|
* 任务开始
|
||||||
|
*/
|
||||||
|
public static final int START = 1;
|
||||||
|
/**
|
||||||
|
* 任务停止
|
||||||
|
*/
|
||||||
|
public static final int STOP = 2;
|
||||||
|
/**
|
||||||
|
* 任务失败
|
||||||
|
*/
|
||||||
|
public static final int FAIL = 3;
|
||||||
|
/**
|
||||||
|
* 任务取消
|
||||||
|
*/
|
||||||
|
public static final int CANCEL = 4;
|
||||||
|
/**
|
||||||
|
* 任务完成
|
||||||
|
*/
|
||||||
|
public static final int COMPLETE = 5;
|
||||||
|
|
||||||
|
protected CachePool mCachePool = CachePool.getInstance();
|
||||||
|
protected ExecutePool mExecutePool = ExecutePool.getInstance();
|
||||||
|
protected AutoTaskHandler mTaskHandler;
|
||||||
|
/**
|
||||||
|
* 下载失败次数
|
||||||
|
*/
|
||||||
|
protected int mFailNum = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超时时间
|
||||||
|
*/
|
||||||
|
protected long mTimeOut = 10000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载器任务监听
|
||||||
|
*/
|
||||||
|
protected OnTargetListener mTargetListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Target处理任务监听
|
||||||
|
*/
|
||||||
|
public interface OnTargetListener {
|
||||||
/**
|
/**
|
||||||
* 任务开始
|
* 任务开始
|
||||||
*/
|
*/
|
||||||
public static final int START = 1;
|
public void onTaskStart(Task task);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务停止
|
* 任务停止
|
||||||
*/
|
*/
|
||||||
public static final int STOP = 2;
|
public void onTaskStop(Task task);
|
||||||
/**
|
|
||||||
* 任务失败
|
|
||||||
*/
|
|
||||||
public static final int FAIL = 3;
|
|
||||||
/**
|
/**
|
||||||
* 任务取消
|
* 任务取消
|
||||||
*/
|
*/
|
||||||
public static final int CANCEL = 4;
|
public void onTaskCancel(Task task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务下载失败
|
||||||
|
*/
|
||||||
|
public void onTaskFail(Task task);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务完成
|
* 任务完成
|
||||||
*/
|
*/
|
||||||
public static final int COMPLETE = 5;
|
public void onTaskComplete(Task task);
|
||||||
|
}
|
||||||
|
|
||||||
protected CachePool mCachePool = CachePool.getInstance();
|
protected IDownloadTarget() {
|
||||||
protected ExecutePool mExecutePool = ExecutePool.getInstance();
|
mTaskHandler = new AutoTaskHandler(this);
|
||||||
protected AutoTaskHandler mTaskHandler;
|
}
|
||||||
/**
|
|
||||||
* 下载失败次数
|
|
||||||
*/
|
|
||||||
protected int mFailNum = 10;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 超时时间
|
* 设置下载器监听
|
||||||
*/
|
*
|
||||||
protected long mTimeOut = 10000;
|
* @param targetListener {@link OnTargetListener}
|
||||||
|
*/
|
||||||
|
public void setOnTargetListener(OnTargetListener targetListener) {
|
||||||
|
this.mTargetListener = targetListener;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载器任务监听
|
* 获取任务执行池
|
||||||
*/
|
*/
|
||||||
protected OnTargetListener mTargetListener;
|
public ExecutePool getExecutePool() {
|
||||||
|
return mExecutePool;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target处理任务监听
|
* 获取当前运行的任务数
|
||||||
*/
|
*
|
||||||
public interface OnTargetListener {
|
* @return 当前正在执行的任务数
|
||||||
/**
|
*/
|
||||||
* 任务开始
|
public int getCurrentTaskNum() {
|
||||||
*/
|
return mExecutePool.size();
|
||||||
public void onTaskStart(Task task);
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务停止
|
* 获取缓存任务数
|
||||||
*/
|
*
|
||||||
public void onTaskStop(Task task);
|
* @return 获取缓存的任务数
|
||||||
|
*/
|
||||||
|
public int getCacheTaskNum() {
|
||||||
|
return mCachePool.size();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
public void setFailNum(int mFailNum) {
|
||||||
* 任务取消
|
this.mFailNum = mFailNum;
|
||||||
*/
|
}
|
||||||
public void onTaskCancel(Task task);
|
|
||||||
|
|
||||||
/**
|
public void setTimeOut(long timeOut) {
|
||||||
* 任务下载失败
|
this.mTimeOut = timeOut;
|
||||||
*/
|
}
|
||||||
public void onTaskFail(Task task);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任务完成
|
* 自动处理任务停止,下载失败,取消下载,自动下载下一个任务的操作
|
||||||
*/
|
*/
|
||||||
public void onTaskComplete(Task task);
|
private static class AutoTaskHandler extends Handler {
|
||||||
|
private static final String TAG = "AutoTaskHandler";
|
||||||
|
IDownloadTarget target;
|
||||||
|
|
||||||
|
public AutoTaskHandler(IDownloadTarget target) {
|
||||||
|
this.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IDownloadTarget() {
|
@Override public void handleMessage(Message msg) {
|
||||||
mTaskHandler = new AutoTaskHandler(this);
|
super.handleMessage(msg);
|
||||||
|
DownloadEntity entity = (DownloadEntity) msg.obj;
|
||||||
|
if (entity == null) {
|
||||||
|
Log.e(TAG, "请传入下载实体DownloadEntity");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (msg.what) {
|
||||||
|
case STOP:
|
||||||
|
case CANCEL:
|
||||||
|
case COMPLETE:
|
||||||
|
startNextTask(entity);
|
||||||
|
break;
|
||||||
|
case FAIL:
|
||||||
|
handleFailTask(entity);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
callback(msg.what, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置下载器监听
|
* 回调
|
||||||
*
|
*
|
||||||
* @param targetListener {@link OnTargetListener}
|
* @param state 状态
|
||||||
|
* @param entity 下载实体
|
||||||
*/
|
*/
|
||||||
public void setOnTargetListener(OnTargetListener targetListener) {
|
private void callback(int state, DownloadEntity entity) {
|
||||||
this.mTargetListener = targetListener;
|
if (target.mTargetListener != null) {
|
||||||
|
Task task = target.getTask(entity);
|
||||||
|
switch (state) {
|
||||||
|
case START:
|
||||||
|
target.mTargetListener.onTaskStart(task);
|
||||||
|
break;
|
||||||
|
case STOP:
|
||||||
|
target.mTargetListener.onTaskStop(task);
|
||||||
|
break;
|
||||||
|
case CANCEL:
|
||||||
|
target.mTargetListener.onTaskCancel(task);
|
||||||
|
break;
|
||||||
|
case COMPLETE:
|
||||||
|
target.mTargetListener.onTaskComplete(task);
|
||||||
|
break;
|
||||||
|
case FAIL:
|
||||||
|
target.mTargetListener.onTaskFail(task);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取任务执行池
|
* 处理下载任务下载失败的情形
|
||||||
*
|
*
|
||||||
* @return
|
* @param entity 失败实体
|
||||||
*/
|
*/
|
||||||
public ExecutePool getExecutePool() {
|
private void handleFailTask(DownloadEntity entity) {
|
||||||
return mExecutePool;
|
if (entity.getFailNum() <= target.mFailNum) {
|
||||||
|
Task task = target.getTask(entity);
|
||||||
|
target.reTryStart(task);
|
||||||
|
} else {
|
||||||
|
startNextTask(entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前运行的任务数
|
* 启动下一个任务,条件:任务停止,取消下载,任务完成
|
||||||
*
|
*
|
||||||
* @return 当前正在执行的任务数
|
* @param entity 通过Handler传递的下载实体
|
||||||
*/
|
*/
|
||||||
public int getCurrentTaskNum() {
|
private void startNextTask(DownloadEntity entity) {
|
||||||
return mExecutePool.size();
|
target.removeTask(entity);
|
||||||
}
|
Task newTask = target.getNextTask();
|
||||||
|
if (newTask == null) {
|
||||||
/**
|
Log.w(TAG, "没有下一任务");
|
||||||
* 获取缓存任务数
|
return;
|
||||||
*
|
}
|
||||||
* @return 获取缓存的任务数
|
if (newTask.getDownloadEntity().getState() == DownloadEntity.STATE_WAIT) {
|
||||||
*/
|
target.startTask(newTask);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,5 @@ package com.arialyy.downloadutil.core;
|
|||||||
* 创建任务类型
|
* 创建任务类型
|
||||||
*/
|
*/
|
||||||
public enum TaskEnum {
|
public enum TaskEnum {
|
||||||
ORDINARY, NO_USR_CALLBACK
|
ORDINARY, NO_USR_CALLBACK
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package com.arialyy.downloadutil.core;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
||||||
import com.arialyy.downloadutil.entity.DownloadEntity;
|
import com.arialyy.downloadutil.entity.DownloadEntity;
|
||||||
import com.arialyy.downloadutil.util.Task;
|
import com.arialyy.downloadutil.util.Task;
|
||||||
|
|
||||||
@ -11,33 +10,33 @@ import com.arialyy.downloadutil.util.Task;
|
|||||||
* 任务工厂
|
* 任务工厂
|
||||||
*/
|
*/
|
||||||
public class TaskFactory {
|
public class TaskFactory {
|
||||||
private static final String TAG = "TaskFactory";
|
private static final String TAG = "TaskFactory";
|
||||||
|
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
private static volatile TaskFactory INSTANCE = null;
|
private static volatile TaskFactory INSTANCE = null;
|
||||||
|
|
||||||
private TaskFactory() {
|
private TaskFactory() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TaskFactory getInstance() {
|
||||||
|
if (INSTANCE == null) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
INSTANCE = new TaskFactory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
public static TaskFactory getInstance() {
|
/**
|
||||||
if (INSTANCE == null) {
|
* 创建普通下载任务
|
||||||
synchronized (LOCK) {
|
*
|
||||||
INSTANCE = new TaskFactory();
|
* @param entity 下载实体
|
||||||
}
|
* @param handler "com.arialyy.downloadutil.core.IDownloadTarget.AutoTaskHandler"
|
||||||
}
|
*/
|
||||||
return INSTANCE;
|
public Task createTask(Context context, DownloadEntity entity, Handler handler) {
|
||||||
}
|
Task.Builder builder = new Task.Builder(context, entity);
|
||||||
|
builder.setOutHandler(handler);
|
||||||
/**
|
return builder.build();
|
||||||
* 创建普通下载任务
|
}
|
||||||
*
|
|
||||||
* @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.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.
|
||||||
@ -12,16 +11,16 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
|
|||||||
*/
|
*/
|
||||||
class AddCommand extends IDownloadCommand {
|
class AddCommand extends IDownloadCommand {
|
||||||
|
|
||||||
AddCommand(Context context, DownloadEntity entity) {
|
AddCommand(Context context, DownloadEntity entity) {
|
||||||
super(context, entity);
|
super(context, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void executeComment() {
|
@Override public void executeComment() {
|
||||||
Task task = target.getTask(mEntity);
|
Task task = target.getTask(mEntity);
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
target.createTask(mEntity);
|
target.createTask(mEntity);
|
||||||
}else {
|
} else {
|
||||||
Log.w(TAG, "添加命令执行失败,【该任务已经存在】");
|
Log.w(TAG, "添加命令执行失败,【该任务已经存在】");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
@ -11,17 +10,17 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
|
|||||||
*/
|
*/
|
||||||
class CancelCommand extends IDownloadCommand {
|
class CancelCommand extends IDownloadCommand {
|
||||||
|
|
||||||
CancelCommand(Context context, DownloadEntity entity) {
|
CancelCommand(Context context, DownloadEntity entity) {
|
||||||
super(context, entity);
|
super(context, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void executeComment() {
|
@Override public void executeComment() {
|
||||||
Task task = target.getTask(mEntity);
|
Task task = target.getTask(mEntity);
|
||||||
if (task == null){
|
if (task == null) {
|
||||||
task = target.createTask(mEntity);
|
task = target.createTask(mEntity);
|
||||||
}
|
|
||||||
if (task != null) {
|
|
||||||
target.cancelTask(task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (task != null) {
|
||||||
|
target.cancelTask(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,113 +8,113 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
|
|||||||
* 命令工厂
|
* 命令工厂
|
||||||
*/
|
*/
|
||||||
public class CommandFactory {
|
public class CommandFactory {
|
||||||
/**
|
/**
|
||||||
* 创建任务
|
* 创建任务
|
||||||
*/
|
*/
|
||||||
public static final int TASK_CREATE = 0x122;
|
public static final int TASK_CREATE = 0x122;
|
||||||
/**
|
/**
|
||||||
* 启动任务
|
* 启动任务
|
||||||
*/
|
*/
|
||||||
public static final int TASK_START = 0x123;
|
public static final int TASK_START = 0x123;
|
||||||
/**
|
/**
|
||||||
* 恢复任务
|
* 恢复任务
|
||||||
*/
|
*/
|
||||||
public static final int TASK_RESUME = 0x127;
|
public static final int TASK_RESUME = 0x127;
|
||||||
/**
|
/**
|
||||||
* 取消任务
|
* 取消任务
|
||||||
*/
|
*/
|
||||||
public static final int TASK_CANCEL = 0x124;
|
public static final int TASK_CANCEL = 0x124;
|
||||||
/**
|
/**
|
||||||
* 停止任务
|
* 停止任务
|
||||||
*/
|
*/
|
||||||
public static final int TASK_STOP = 0x125;
|
public static final int TASK_STOP = 0x125;
|
||||||
/**
|
/**
|
||||||
* 获取任务状态
|
* 获取任务状态
|
||||||
*/
|
*/
|
||||||
public static final int TASK_STATE = 0x126;
|
public static final int TASK_STATE = 0x126;
|
||||||
|
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
private static volatile CommandFactory INSTANCE = null;
|
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) {
|
* @param context context
|
||||||
synchronized (LOCK) {
|
* @param entity 下载实体
|
||||||
INSTANCE = new CommandFactory();
|
* @param type 命令类型{@link #TASK_CREATE}、{@link #TASK_START}、{@link #TASK_CANCEL}、{@link
|
||||||
}
|
* #TASK_STOP}、{@link #TASK_STATE}
|
||||||
}
|
*/
|
||||||
return INSTANCE;
|
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
|
* @return {@link StateCommand}
|
||||||
* #TASK_STOP}、{@link #TASK_STATE}
|
*/
|
||||||
*/
|
private StateCommand createStateCommand(Context context, DownloadEntity entity) {
|
||||||
public IDownloadCommand createCommand(Context context, DownloadEntity entity, int type) {
|
return new StateCommand(context, entity);
|
||||||
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}
|
* @return {@link StopCommand}
|
||||||
*/
|
*/
|
||||||
private StateCommand createStateCommand(Context context, DownloadEntity entity) {
|
private StopCommand createStopCommand(Context context, DownloadEntity entity) {
|
||||||
return new StateCommand(context, entity);
|
return new StopCommand(context, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建停止命令
|
* 创建下载任务命令
|
||||||
*
|
*
|
||||||
* @return {@link StopCommand}
|
* @return {@link AddCommand}
|
||||||
*/
|
*/
|
||||||
private StopCommand createStopCommand(Context context, DownloadEntity entity) {
|
private AddCommand createAddCommand(Context context, DownloadEntity entity) {
|
||||||
return new StopCommand(context, entity);
|
return new AddCommand(context, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建下载任务命令
|
* 创建启动下载命令
|
||||||
*
|
*
|
||||||
* @return {@link AddCommand}
|
* @return {@link StartCommand}
|
||||||
*/
|
*/
|
||||||
private AddCommand createAddCommand(Context context, DownloadEntity entity) {
|
private StartCommand createStartCommand(Context context, DownloadEntity entity) {
|
||||||
return new AddCommand(context, entity);
|
return new StartCommand(context, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建启动下载命令
|
* 创建 取消下载的命令
|
||||||
*
|
*
|
||||||
* @return {@link StartCommand}
|
* @return {@link CancelCommand}
|
||||||
*/
|
*/
|
||||||
private StartCommand createStartCommand(Context context, DownloadEntity entity) {
|
private CancelCommand createCancelCommand(Context context, DownloadEntity entity) {
|
||||||
return new StartCommand(context, 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;
|
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;
|
||||||
@ -13,40 +12,40 @@ import com.arialyy.downloadutil.util.Util;
|
|||||||
* 下载命令
|
* 下载命令
|
||||||
*/
|
*/
|
||||||
public abstract class IDownloadCommand {
|
public abstract class IDownloadCommand {
|
||||||
protected IDownloadTarget target;
|
protected IDownloadTarget target;
|
||||||
protected Context mContext;
|
protected Context mContext;
|
||||||
protected DownloadEntity mEntity;
|
protected DownloadEntity mEntity;
|
||||||
protected String TAG;
|
protected String TAG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param context context
|
* @param context context
|
||||||
* @param entity 下载实体
|
* @param entity 下载实体
|
||||||
*/
|
*/
|
||||||
protected IDownloadCommand(Context context, DownloadEntity entity) {
|
protected IDownloadCommand(Context context, DownloadEntity entity) {
|
||||||
if (!CheckHelp.checkDownloadEntity(entity)) {
|
if (!CheckHelp.checkDownloadEntity(entity)) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
target = DownloadTarget.getInstance();
|
|
||||||
mContext = context;
|
|
||||||
mEntity = entity;
|
|
||||||
TAG = Util.getClassName(this);
|
|
||||||
}
|
}
|
||||||
|
target = DownloadTarget.getInstance();
|
||||||
|
mContext = context;
|
||||||
|
mEntity = entity;
|
||||||
|
TAG = Util.getClassName(this);
|
||||||
|
}
|
||||||
|
|
||||||
public Context getContext() {
|
public Context getContext() {
|
||||||
return mContext;
|
return mContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行命令
|
* 执行命令
|
||||||
*/
|
*/
|
||||||
public abstract void executeComment();
|
public abstract void executeComment();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置下载器
|
* 设置下载器
|
||||||
*
|
*
|
||||||
* @param downloadTarget {@link IDownloadTarget}
|
* @param downloadTarget {@link IDownloadTarget}
|
||||||
*/
|
*/
|
||||||
public void setDownloadTarget(IDownloadTarget downloadTarget) {
|
public void setDownloadTarget(IDownloadTarget downloadTarget) {
|
||||||
target = downloadTarget;
|
target = downloadTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
@ -11,17 +10,17 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
|
|||||||
*/
|
*/
|
||||||
class StartCommand extends IDownloadCommand {
|
class StartCommand extends IDownloadCommand {
|
||||||
|
|
||||||
StartCommand(Context context, DownloadEntity entity) {
|
StartCommand(Context context, DownloadEntity entity) {
|
||||||
super(context, entity);
|
super(context, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void executeComment() {
|
@Override public void executeComment() {
|
||||||
Task task = target.getTask(mEntity);
|
Task task = target.getTask(mEntity);
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
task = target.createTask(mEntity);
|
task = target.createTask(mEntity);
|
||||||
}
|
|
||||||
if (task != null) {
|
|
||||||
target.startTask(task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (task != null) {
|
||||||
|
target.startTask(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,16 +9,16 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
|
|||||||
*/
|
*/
|
||||||
class StateCommand extends IDownloadCommand {
|
class StateCommand extends IDownloadCommand {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param context context
|
* @param context context
|
||||||
* @param entity 下载实体
|
* @param entity 下载实体
|
||||||
*/
|
*/
|
||||||
StateCommand(Context context, DownloadEntity entity) {
|
StateCommand(Context context, DownloadEntity entity) {
|
||||||
super(context, 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.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;
|
||||||
|
|
||||||
@ -12,25 +11,25 @@ import com.arialyy.downloadutil.util.Task;
|
|||||||
*/
|
*/
|
||||||
class StopCommand extends IDownloadCommand {
|
class StopCommand extends IDownloadCommand {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param context context
|
* @param context context
|
||||||
* @param entity 下载实体
|
* @param entity 下载实体
|
||||||
*/
|
*/
|
||||||
StopCommand(Context context, DownloadEntity entity) {
|
StopCommand(Context context, DownloadEntity entity) {
|
||||||
super(context, entity);
|
super(context, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void executeComment() {
|
@Override public void executeComment() {
|
||||||
Task task = target.getTask(mEntity);
|
Task task = target.getTask(mEntity);
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) {
|
if (mEntity.getState() == DownloadEntity.STATE_DOWNLOAD_ING) {
|
||||||
task = target.createTask(mEntity);
|
task = target.createTask(mEntity);
|
||||||
target.stopTask(task);
|
target.stopTask(task);
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG, "停止命令执行失败,【调度器中没有该任务】");
|
Log.w(TAG, "停止命令执行失败,【调度器中没有该任务】");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
target.stopTask(task);
|
target.stopTask(task);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,31 +7,31 @@ import com.arialyy.downloadutil.util.Task;
|
|||||||
* 下载功能接口
|
* 下载功能接口
|
||||||
*/
|
*/
|
||||||
public interface IDownloader {
|
public interface IDownloader {
|
||||||
/**
|
/**
|
||||||
* 开始任务
|
* 开始任务
|
||||||
*
|
*
|
||||||
* @param task {@link Task}
|
* @param task {@link Task}
|
||||||
*/
|
*/
|
||||||
public void startTask(Task task);
|
public void startTask(Task task);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止任务
|
* 停止任务
|
||||||
*
|
*
|
||||||
* @param task {@link Task}
|
* @param task {@link Task}
|
||||||
*/
|
*/
|
||||||
public void stopTask(Task task);
|
public void stopTask(Task task);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消任务
|
* 取消任务
|
||||||
*
|
*
|
||||||
* @param task {@link Task}
|
* @param task {@link Task}
|
||||||
*/
|
*/
|
||||||
public void cancelTask(Task task);
|
public void cancelTask(Task task);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重试下载
|
* 重试下载
|
||||||
*
|
*
|
||||||
* @param task {@link Task}
|
* @param task {@link Task}
|
||||||
*/
|
*/
|
||||||
public void reTryStart(Task task);
|
public void reTryStart(Task task);
|
||||||
}
|
}
|
||||||
|
@ -7,46 +7,46 @@ import com.arialyy.downloadutil.util.Task;
|
|||||||
* 任务池
|
* 任务池
|
||||||
*/
|
*/
|
||||||
public interface IPool {
|
public interface IPool {
|
||||||
/**
|
/**
|
||||||
* 将下载任务添加到任务池中
|
* 将下载任务添加到任务池中
|
||||||
*/
|
*/
|
||||||
public boolean putTask(Task task);
|
public boolean putTask(Task task);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按照队列原则取出下载任务
|
* 按照队列原则取出下载任务
|
||||||
*
|
*
|
||||||
* @return 返回null或者下载任务
|
* @return 返回null或者下载任务
|
||||||
*/
|
*/
|
||||||
public Task pollTask();
|
public Task pollTask();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过下载链接获取下载任务,当任务不为空时,队列将删除该下载任务
|
* 通过下载链接获取下载任务,当任务不为空时,队列将删除该下载任务
|
||||||
*
|
*
|
||||||
* @param downloadUrl 下载链接
|
* @param downloadUrl 下载链接
|
||||||
* @return 返回null或者下载任务
|
* @return 返回null或者下载任务
|
||||||
*/
|
*/
|
||||||
public Task getTask(String downloadUrl);
|
public Task getTask(String downloadUrl);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除任务池中的下载任务
|
* 删除任务池中的下载任务
|
||||||
*
|
*
|
||||||
* @param task 下载任务
|
* @param task 下载任务
|
||||||
* @return true:移除成功
|
* @return true:移除成功
|
||||||
*/
|
*/
|
||||||
public boolean removeTask(Task task);
|
public boolean removeTask(Task task);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过下载链接移除下载任务
|
* 通过下载链接移除下载任务
|
||||||
*
|
*
|
||||||
* @param downloadUrl 下载链接
|
* @param downloadUrl 下载链接
|
||||||
* @return true:移除成功
|
* @return true:移除成功
|
||||||
*/
|
*/
|
||||||
public boolean removeTask(String downloadUrl);
|
public boolean removeTask(String downloadUrl);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 池子大小
|
* 池子大小
|
||||||
*
|
*
|
||||||
* @return 返回缓存池或者当前任务池大小
|
* @return 返回缓存池或者当前任务池大小
|
||||||
*/
|
*/
|
||||||
public int size();
|
public int size();
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
@ -9,41 +9,41 @@ import com.arialyy.downloadutil.entity.DownloadEntity;
|
|||||||
*/
|
*/
|
||||||
public interface ITask {
|
public interface ITask {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建一个新的下载任务,创建时只是将新任务存储到缓存池
|
* 创建一个新的下载任务,创建时只是将新任务存储到缓存池
|
||||||
*
|
*
|
||||||
* @param entity 下载实体{@link DownloadEntity}
|
* @param entity 下载实体{@link DownloadEntity}
|
||||||
* @return {@link Task}
|
* @return {@link Task}
|
||||||
*/
|
*/
|
||||||
public Task createTask(DownloadEntity entity);
|
public Task createTask(DownloadEntity entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过下载链接从缓存池或任务池搜索下载任务,如果缓存池或任务池都没有任务,则创建新任务
|
* 通过下载链接从缓存池或任务池搜索下载任务,如果缓存池或任务池都没有任务,则创建新任务
|
||||||
*
|
*
|
||||||
* @param entity 下载实体{@link DownloadEntity}
|
* @param entity 下载实体{@link DownloadEntity}
|
||||||
* @return {@link Task}
|
* @return {@link Task}
|
||||||
*/
|
*/
|
||||||
public Task getTask(DownloadEntity entity);
|
public Task getTask(DownloadEntity entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过下载链接搜索下载任务
|
* 通过下载链接搜索下载任务
|
||||||
*
|
*
|
||||||
* @param entity 下载实体{@link DownloadEntity}
|
* @param entity 下载实体{@link DownloadEntity}
|
||||||
* @return {@code -1 ==> 错误},{@link com.arialyy.downloadutil.entity.DownloadEntity#STATE_FAIL}
|
* @return {@code -1 ==> 错误},{@link com.arialyy.downloadutil.entity.DownloadEntity#STATE_FAIL}
|
||||||
*/
|
*/
|
||||||
public int getTaskState(DownloadEntity entity);
|
public int getTaskState(DownloadEntity entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过下载链接删除任务
|
* 通过下载链接删除任务
|
||||||
*
|
*
|
||||||
* @param entity 下载实体{@link DownloadEntity}
|
* @param entity 下载实体{@link DownloadEntity}
|
||||||
*/
|
*/
|
||||||
public void removeTask(DownloadEntity entity);
|
public void removeTask(DownloadEntity entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取缓存池的下一个任务
|
* 获取缓存池的下一个任务
|
||||||
*
|
*
|
||||||
* @return 下载任务 or null
|
* @return 下载任务 or null
|
||||||
*/
|
*/
|
||||||
public Task getNextTask();
|
public Task getNextTask();
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ package com.arialyy.downloadutil.core.pool;
|
|||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.arialyy.downloadutil.core.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;
|
||||||
@ -16,97 +14,97 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
* 任务缓存池,所有下载任务最先缓存在这个池中
|
* 任务缓存池,所有下载任务最先缓存在这个池中
|
||||||
*/
|
*/
|
||||||
public class CachePool implements IPool {
|
public class CachePool implements IPool {
|
||||||
private static final String TAG = "CachePool";
|
private static final String TAG = "CachePool";
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
|
private static final int MAX_NUM = Integer.MAX_VALUE; //最大下载任务数
|
||||||
private static volatile CachePool INSTANCE = null;
|
private static volatile CachePool INSTANCE = null;
|
||||||
private Map<String, Task> mCacheArray;
|
private Map<String, Task> mCacheArray;
|
||||||
private LinkedBlockingQueue<Task> mCacheQueue;
|
private LinkedBlockingQueue<Task> mCacheQueue;
|
||||||
|
|
||||||
public static CachePool getInstance() {
|
public static CachePool getInstance() {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
INSTANCE = new CachePool();
|
INSTANCE = new CachePool();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 INSTANCE;
|
return s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CachePool() {
|
@Override public Task pollTask() {
|
||||||
mCacheQueue = new LinkedBlockingQueue<>(MAX_NUM);
|
synchronized (LOCK) {
|
||||||
mCacheArray = new HashMap<>();
|
Task task = mCacheQueue.poll();
|
||||||
|
if (task != null) {
|
||||||
|
String url = task.getDownloadEntity().getDownloadUrl();
|
||||||
|
mCacheArray.remove(Util.keyToHashKey(url));
|
||||||
|
}
|
||||||
|
return task;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean putTask(Task task) {
|
@Override public Task getTask(String downloadUrl) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
if (task == null) {
|
if (TextUtils.isEmpty(downloadUrl)) {
|
||||||
Log.e(TAG, "下载任务不能为空!!");
|
Log.e(TAG, "请传入有效的下载链接");
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
String url = task.getDownloadEntity().getDownloadUrl();
|
String key = Util.keyToHashKey(downloadUrl);
|
||||||
if (mCacheQueue.contains(task)) {
|
return mCacheArray.get(key);
|
||||||
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() {
|
@Override public boolean removeTask(Task task) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
Task task = mCacheQueue.poll();
|
if (task == null) {
|
||||||
if (task != null) {
|
Log.e(TAG, "任务不能为空");
|
||||||
String url = task.getDownloadEntity().getDownloadUrl();
|
return false;
|
||||||
mCacheArray.remove(Util.keyToHashKey(url));
|
} else {
|
||||||
}
|
String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl());
|
||||||
return task;
|
mCacheArray.remove(key);
|
||||||
}
|
return mCacheQueue.remove(task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public Task getTask(String downloadUrl) {
|
@Override public boolean removeTask(String downloadUrl) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
if (TextUtils.isEmpty(downloadUrl)) {
|
if (TextUtils.isEmpty(downloadUrl)) {
|
||||||
Log.e(TAG, "请传入有效的下载链接");
|
Log.e(TAG, "请传入有效的下载链接");
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
String key = Util.keyToHashKey(downloadUrl);
|
String key = Util.keyToHashKey(downloadUrl);
|
||||||
return mCacheArray.get(key);
|
Task task = mCacheArray.get(key);
|
||||||
}
|
mCacheArray.remove(key);
|
||||||
|
return mCacheQueue.remove(task);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean removeTask(Task task) {
|
@Override public int size() {
|
||||||
synchronized (LOCK) {
|
return mCacheQueue.size();
|
||||||
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 int size() {
|
|
||||||
return mCacheQueue.size();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ package com.arialyy.downloadutil.core.pool;
|
|||||||
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.arialyy.downloadutil.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;
|
||||||
@ -17,137 +15,137 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* 任务执行池,所有当前下载任务都该任务池中,默认下载大小为2
|
* 任务执行池,所有当前下载任务都该任务池中,默认下载大小为2
|
||||||
*/
|
*/
|
||||||
public class ExecutePool implements IPool {
|
public class ExecutePool implements IPool {
|
||||||
private static final String TAG = "ExecutePool";
|
private static final String TAG = "ExecutePool";
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
private static final long TIME_OUT = 1000;
|
private static final long TIME_OUT = 1000;
|
||||||
private static volatile ExecutePool INSTANCE = null;
|
private static volatile ExecutePool INSTANCE = null;
|
||||||
private static int SIZE = 2;
|
private static int SIZE = 2;
|
||||||
private ArrayBlockingQueue<Task> mExecuteQueue;
|
private ArrayBlockingQueue<Task> mExecuteQueue;
|
||||||
private Map<String, Task> mExecuteArray;
|
private Map<String, Task> mExecuteArray;
|
||||||
|
|
||||||
public static ExecutePool getInstance() {
|
public static ExecutePool getInstance() {
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
INSTANCE = new ExecutePool();
|
INSTANCE = new ExecutePool();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
private ExecutePool() {
|
private ExecutePool() {
|
||||||
mExecuteQueue = new ArrayBlockingQueue<>(SIZE);
|
mExecuteQueue = new ArrayBlockingQueue<>(SIZE);
|
||||||
mExecuteArray = new HashMap<>();
|
mExecuteArray = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean putTask(Task task) {
|
@Override public boolean putTask(Task task) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
if (task == null) {
|
if (task == null) {
|
||||||
Log.e(TAG, "下载任务不能为空!!");
|
Log.e(TAG, "下载任务不能为空!!");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String url = task.getDownloadEntity().getDownloadUrl();
|
|
||||||
if (mExecuteQueue.contains(task)) {
|
|
||||||
Log.e(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】");
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
if (mExecuteQueue.size() >= SIZE) {
|
|
||||||
if (pollFirstTask()) {
|
|
||||||
return putNewTask(task);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return putNewTask(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
String url = task.getDownloadEntity().getDownloadUrl();
|
||||||
/**
|
if (mExecuteQueue.contains(task)) {
|
||||||
* 添加新任务
|
Log.e(TAG, "队列中已经包含了该任务,任务下载链接【" + url + "】");
|
||||||
*
|
return false;
|
||||||
* @param newTask 新下载任务
|
} else {
|
||||||
*/
|
if (mExecuteQueue.size() >= SIZE) {
|
||||||
private boolean putNewTask(Task newTask) {
|
if (pollFirstTask()) {
|
||||||
String url = newTask.getDownloadEntity().getDownloadUrl();
|
return putNewTask(task);
|
||||||
boolean s = mExecuteQueue.offer(newTask);
|
}
|
||||||
Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】"));
|
} else {
|
||||||
if (s) {
|
return putNewTask(task);
|
||||||
newTask.start();
|
|
||||||
mExecuteArray.put(Util.keyToHashKey(url), newTask);
|
|
||||||
}
|
}
|
||||||
return s;
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 队列满时,将移除下载队列中的第一个任务
|
* 添加新任务
|
||||||
*/
|
*
|
||||||
private boolean pollFirstTask() {
|
* @param newTask 新下载任务
|
||||||
try {
|
*/
|
||||||
Task oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
private boolean putNewTask(Task newTask) {
|
||||||
if (oldTask == null) {
|
String url = newTask.getDownloadEntity().getDownloadUrl();
|
||||||
Log.e(TAG, "移除任务失败");
|
boolean s = mExecuteQueue.offer(newTask);
|
||||||
return false;
|
Log.w(TAG, "任务添加" + (s ? "成功" : "失败,【" + url + "】"));
|
||||||
}
|
if (s) {
|
||||||
oldTask.stop();
|
newTask.start();
|
||||||
// wait(200);
|
mExecuteArray.put(Util.keyToHashKey(url), newTask);
|
||||||
String key = Util.keyToHashKey(oldTask.getDownloadEntity().getDownloadUrl());
|
|
||||||
mExecuteArray.remove(key);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
@Override public Task pollTask() {
|
/**
|
||||||
synchronized (LOCK) {
|
* 队列满时,将移除下载队列中的第一个任务
|
||||||
Task task = mExecuteQueue.poll();
|
*/
|
||||||
if (task != null) {
|
private boolean pollFirstTask() {
|
||||||
String url = task.getDownloadEntity().getDownloadUrl();
|
try {
|
||||||
mExecuteArray.remove(Util.keyToHashKey(url));
|
Task oldTask = mExecuteQueue.poll(TIME_OUT, TimeUnit.MICROSECONDS);
|
||||||
}
|
if (oldTask == null) {
|
||||||
return task;
|
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) {
|
@Override public Task pollTask() {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
if (TextUtils.isEmpty(downloadUrl)) {
|
Task task = mExecuteQueue.poll();
|
||||||
Log.e(TAG, "请传入有效的下载链接");
|
if (task != null) {
|
||||||
return null;
|
String url = task.getDownloadEntity().getDownloadUrl();
|
||||||
}
|
mExecuteArray.remove(Util.keyToHashKey(url));
|
||||||
String key = Util.keyToHashKey(downloadUrl);
|
}
|
||||||
return mExecuteArray.get(key);
|
return task;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean removeTask(Task task) {
|
@Override public Task getTask(String downloadUrl) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
if (task == null) {
|
if (TextUtils.isEmpty(downloadUrl)) {
|
||||||
Log.e(TAG, "任务不能为空");
|
Log.e(TAG, "请传入有效的下载链接");
|
||||||
return false;
|
return null;
|
||||||
} else {
|
}
|
||||||
String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl());
|
String key = Util.keyToHashKey(downloadUrl);
|
||||||
mExecuteArray.remove(key);
|
return mExecuteArray.get(key);
|
||||||
return mExecuteQueue.remove(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean removeTask(String downloadUrl) {
|
@Override public boolean removeTask(Task task) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
if (TextUtils.isEmpty(downloadUrl)) {
|
if (task == null) {
|
||||||
Log.e(TAG, "请传入有效的下载链接");
|
Log.e(TAG, "任务不能为空");
|
||||||
return false;
|
return false;
|
||||||
}
|
} else {
|
||||||
String key = Util.keyToHashKey(downloadUrl);
|
String key = Util.keyToHashKey(task.getDownloadEntity().getDownloadUrl());
|
||||||
Task task = mExecuteArray.get(key);
|
mExecuteArray.remove(key);
|
||||||
mExecuteArray.remove(key);
|
return mExecuteQueue.remove(task);
|
||||||
return mExecuteQueue.remove(task);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override public int size() {
|
@Override public boolean removeTask(String downloadUrl) {
|
||||||
return mExecuteQueue.size();
|
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.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;
|
||||||
|
|
||||||
@ -11,179 +10,179 @@ import com.arialyy.downloadutil.orm.Ignore;
|
|||||||
* 下载实体
|
* 下载实体
|
||||||
*/
|
*/
|
||||||
public class DownloadEntity extends DbEntity implements Parcelable, Cloneable {
|
public class DownloadEntity extends DbEntity implements Parcelable, Cloneable {
|
||||||
/**
|
/**
|
||||||
* 其它状态
|
* 其它状态
|
||||||
*/
|
*/
|
||||||
@Ignore public static final int STATE_OTHER = -1;
|
@Ignore public static final int STATE_OTHER = -1;
|
||||||
/**
|
/**
|
||||||
* 失败状态
|
* 失败状态
|
||||||
*/
|
*/
|
||||||
@Ignore public static final int STATE_FAIL = 0;
|
@Ignore public static final int STATE_FAIL = 0;
|
||||||
/**
|
/**
|
||||||
* 完成状态
|
* 完成状态
|
||||||
*/
|
*/
|
||||||
@Ignore public static final int STATE_COMPLETE = 1;
|
@Ignore public static final int STATE_COMPLETE = 1;
|
||||||
/**
|
/**
|
||||||
* 停止状态
|
* 停止状态
|
||||||
*/
|
*/
|
||||||
@Ignore public static final int STATE_STOP = 2;
|
@Ignore public static final int STATE_STOP = 2;
|
||||||
/**
|
/**
|
||||||
* 未开始状态
|
* 未开始状态
|
||||||
*/
|
*/
|
||||||
@Ignore public static final int STATE_WAIT = 3;
|
@Ignore public static final int STATE_WAIT = 3;
|
||||||
/**
|
/**
|
||||||
* 下载中
|
* 下载中
|
||||||
*/
|
*/
|
||||||
@Ignore public static final int STATE_DOWNLOAD_ING = 4;
|
@Ignore public static final int STATE_DOWNLOAD_ING = 4;
|
||||||
/**
|
/**
|
||||||
* 取消下载
|
* 取消下载
|
||||||
*/
|
*/
|
||||||
@Ignore public static final int STATE_CANCEL = 5;
|
@Ignore public static final int STATE_CANCEL = 5;
|
||||||
|
|
||||||
private String downloadUrl = ""; //下载路径
|
private String downloadUrl = ""; //下载路径
|
||||||
private String downloadPath = ""; //保存路径
|
private String downloadPath = ""; //保存路径
|
||||||
private String fileName = ""; //文件名
|
private String fileName = ""; //文件名
|
||||||
private String str = ""; //其它字段
|
private String str = ""; //其它字段
|
||||||
private long completeTime; //完成时间
|
private long completeTime; //完成时间
|
||||||
private long fileSize = 1;
|
private long fileSize = 1;
|
||||||
private int state = STATE_WAIT;
|
private int state = STATE_WAIT;
|
||||||
private boolean isDownloadComplete = false; //是否下载完成
|
private boolean isDownloadComplete = false; //是否下载完成
|
||||||
private long currentProgress = 0; //当前下载进度
|
private long currentProgress = 0; //当前下载进度
|
||||||
private int failNum = 0;
|
private int failNum = 0;
|
||||||
|
|
||||||
public DownloadEntity() {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStr() {
|
@Override public DownloadEntity[] newArray(int size) {
|
||||||
return str;
|
return new DownloadEntity[size];
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public void setStr(String str) {
|
@Override public String toString() {
|
||||||
this.str = str;
|
return "DownloadEntity{" +
|
||||||
}
|
"downloadUrl='" + downloadUrl + '\'' +
|
||||||
|
", downloadPath='" + downloadPath + '\'' +
|
||||||
public String getFileName() {
|
", completeTime=" + completeTime +
|
||||||
return fileName;
|
", fileSize=" + fileSize +
|
||||||
}
|
", state=" + state +
|
||||||
|
", isDownloadComplete=" + isDownloadComplete +
|
||||||
public void setFileName(String fileName) {
|
", currentProgress=" + currentProgress +
|
||||||
this.fileName = fileName;
|
", failNum=" + failNum +
|
||||||
}
|
'}';
|
||||||
|
}
|
||||||
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.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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,38 +12,38 @@ import java.io.File;
|
|||||||
* 检查帮助类
|
* 检查帮助类
|
||||||
*/
|
*/
|
||||||
public class CheckHelp {
|
public class CheckHelp {
|
||||||
private static final String TAG = "CheckHelp";
|
private static final String TAG = "CheckHelp";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检测下载实体是否合法
|
* 检测下载实体是否合法
|
||||||
*
|
*
|
||||||
* @param entity 下载实体
|
* @param entity 下载实体
|
||||||
* @return 合法(true)
|
* @return 合法(true)
|
||||||
*/
|
*/
|
||||||
public static boolean checkDownloadEntity(DownloadEntity entity) {
|
public static boolean checkDownloadEntity(DownloadEntity entity) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
Log.w(TAG, Resources.getSystem().getString(R.string.error_entity_null));
|
Log.w(TAG, Resources.getSystem().getString(R.string.error_entity_null));
|
||||||
return false;
|
return false;
|
||||||
} else if (TextUtils.isEmpty(entity.getDownloadUrl())) {
|
} else if (TextUtils.isEmpty(entity.getDownloadUrl())) {
|
||||||
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_url_null));
|
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_url_null));
|
||||||
return false;
|
return false;
|
||||||
} else if (TextUtils.isEmpty(entity.getFileName())) {
|
} else if (TextUtils.isEmpty(entity.getFileName())) {
|
||||||
Log.w(TAG, Resources.getSystem().getString(R.string.error_file_name_null));
|
Log.w(TAG, Resources.getSystem().getString(R.string.error_file_name_null));
|
||||||
return false;
|
return false;
|
||||||
} else if (TextUtils.isEmpty(entity.getDownloadPath())) {
|
} else if (TextUtils.isEmpty(entity.getDownloadPath())) {
|
||||||
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_path_null));
|
Log.w(TAG, Resources.getSystem().getString(R.string.error_download_path_null));
|
||||||
return false;
|
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;
|
|
||||||
}
|
}
|
||||||
|
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;
|
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;
|
||||||
|
|
||||||
@ -11,53 +10,45 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
*/
|
*/
|
||||||
public class PathHelp {
|
public class PathHelp {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载链接转换保存路径
|
* 下载链接转换保存路径
|
||||||
*
|
*
|
||||||
* @param downloadUrl 下载链接
|
* @param downloadUrl 下载链接
|
||||||
* @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
|
public static String StringToHashKey(String str) {
|
||||||
* @return
|
String cacheKey;
|
||||||
*/
|
try {
|
||||||
public static String StringToHashKey(String str) {
|
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
|
||||||
String cacheKey;
|
mDigest.update(str.getBytes());
|
||||||
try {
|
cacheKey = bytesToHexString(mDigest.digest());
|
||||||
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
|
} catch (NoSuchAlgorithmException e) {
|
||||||
mDigest.update(str.getBytes());
|
cacheKey = String.valueOf(str.hashCode());
|
||||||
cacheKey = bytesToHexString(mDigest.digest());
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
cacheKey = String.valueOf(str.hashCode());
|
|
||||||
}
|
|
||||||
return cacheKey;
|
|
||||||
}
|
}
|
||||||
|
return cacheKey;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将普通字符串转换为16位进制字符串
|
* 将普通字符串转换为16位进制字符串
|
||||||
*
|
*/
|
||||||
* @param src
|
public static String bytesToHexString(byte[] src) {
|
||||||
* @return
|
StringBuilder stringBuilder = new StringBuilder("0x");
|
||||||
*/
|
if (src == null || src.length <= 0) {
|
||||||
public static String bytesToHexString(byte[] src) {
|
return null;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
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;
|
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;
|
||||||
@ -13,129 +11,128 @@ import java.util.List;
|
|||||||
* 所有数据库实体父类
|
* 所有数据库实体父类
|
||||||
*/
|
*/
|
||||||
public class DbEntity {
|
public class DbEntity {
|
||||||
protected int rowID = -1;
|
protected int rowID = -1;
|
||||||
private DbUtil mUtil = DbUtil.getInstance();
|
private DbUtil mUtil = DbUtil.getInstance();
|
||||||
|
|
||||||
protected DbEntity() {
|
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();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有行的rowid
|
* 查找数据在表中是否存在
|
||||||
*/
|
*/
|
||||||
public int[] getRowIds() {
|
private boolean thisIsExist() {
|
||||||
return mUtil.getRowId(getClass());
|
return findData(getClass(), new String[] { "rowid" }, new String[] { rowID + "" }) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取rowid
|
* 插入数据
|
||||||
*/
|
*/
|
||||||
public int getRowId(@NonNull Object[] wheres, @NonNull Object[] values) {
|
public void insert() {
|
||||||
return mUtil.getRowId(getClass(), wheres, values);
|
mUtil.insertData(this);
|
||||||
}
|
updateRowID();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
private void updateRowID() {
|
||||||
* 删除当前数据
|
try {
|
||||||
*/
|
Field[] fields = Util.getFields(getClass());
|
||||||
public void deleteData() {
|
List<String> where = new ArrayList<>();
|
||||||
mUtil.delData(getClass(), new Object[]{"rowid"}, new Object[]{rowID});
|
List<String> values = new ArrayList<>();
|
||||||
}
|
for (Field field : fields) {
|
||||||
|
field.setAccessible(true);
|
||||||
/**
|
Ignore ignore = field.getAnnotation(Ignore.class);
|
||||||
* 根据条件删除数据
|
if (ignore != null && ignore.value()) {
|
||||||
*/
|
continue;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
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 没有数据返回null
|
||||||
return findData(getClass(), new String[]{"rowid"}, new String[]{rowID + ""}) != null;
|
*/
|
||||||
}
|
public static <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
|
||||||
|
DbUtil util = DbUtil.getInstance();
|
||||||
|
return util.findAllData(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插入数据
|
* 查询一组数据
|
||||||
*/
|
*
|
||||||
public void insert() {
|
* @return 没有数据返回null
|
||||||
mUtil.insertData(this);
|
*/
|
||||||
updateRowID();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
private void updateRowID() {
|
/**
|
||||||
try {
|
* 查询一行数据
|
||||||
Field[] fields = Util.getFields(getClass());
|
*
|
||||||
List<String> where = new ArrayList<>();
|
* @return 没有数据返回null
|
||||||
List<String> values = new ArrayList<>();
|
*/
|
||||||
for (Field field : fields) {
|
public static <T extends DbEntity> T findData(Class<T> clazz, @NonNull String[] wheres,
|
||||||
field.setAccessible(true);
|
@NonNull String[] values) {
|
||||||
Ignore ignore = field.getAnnotation(Ignore.class);
|
DbUtil util = DbUtil.getInstance();
|
||||||
if (ignore != null && ignore.value()) {
|
List<T> datas = util.findData(clazz, wheres, values);
|
||||||
continue;
|
return datas == null ? null : datas.size() > 0 ? datas.get(0) : null;
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -19,407 +17,407 @@ import java.util.List;
|
|||||||
* 数据库操作工具
|
* 数据库操作工具
|
||||||
*/
|
*/
|
||||||
public class DbUtil {
|
public class DbUtil {
|
||||||
private static final String TAG = "DbUtil";
|
private static final String TAG = "DbUtil";
|
||||||
private volatile static DbUtil INSTANCE = null;
|
private volatile static DbUtil INSTANCE = null;
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
private int CREATE_TABLE = 0;
|
private int CREATE_TABLE = 0;
|
||||||
private int TABLE_EXISTS = 1;
|
private int TABLE_EXISTS = 1;
|
||||||
private int INSERT_DATA = 2;
|
private int INSERT_DATA = 2;
|
||||||
private int MODIFY_DATA = 3;
|
private int MODIFY_DATA = 3;
|
||||||
private int FIND_DATA = 4;
|
private int FIND_DATA = 4;
|
||||||
private int FIND_ALL_DATA = 5;
|
private int FIND_ALL_DATA = 5;
|
||||||
private int DEL_DATA = 6;
|
private int DEL_DATA = 6;
|
||||||
private int ROW_ID = 7;
|
private int ROW_ID = 7;
|
||||||
private SQLiteDatabase mDb;
|
private SQLiteDatabase mDb;
|
||||||
private SqlHelper mHelper;
|
private SqlHelper mHelper;
|
||||||
|
|
||||||
private DbUtil() {
|
private DbUtil() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DbUtil init(Context context) {
|
public static DbUtil init(Context context) {
|
||||||
if (context instanceof Application) {
|
if (context instanceof Application) {
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
if (INSTANCE == null) {
|
|
||||||
INSTANCE = new DbUtil(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private DbUtil(Context context) {
|
|
||||||
mHelper = new SqlHelper(context.getApplicationContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static DbUtil getInstance() {
|
|
||||||
if (INSTANCE == null) {
|
if (INSTANCE == null) {
|
||||||
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册");
|
INSTANCE = new DbUtil(context);
|
||||||
}
|
}
|
||||||
return INSTANCE;
|
}
|
||||||
}
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
private DbUtil(Context context) {
|
||||||
* 删除某条数据
|
mHelper = new SqlHelper(context.getApplicationContext());
|
||||||
*/
|
}
|
||||||
synchronized <T extends DbEntity> void delData(Class<T> clazz, @NonNull Object[] wheres,
|
|
||||||
@NonNull Object[] values) {
|
protected static DbUtil getInstance() {
|
||||||
mDb = mHelper.getWritableDatabase();
|
if (INSTANCE == null) {
|
||||||
if (wheres.length <= 0 || values.length <= 0) {
|
throw new NullPointerException("请在Application中调用init进行数据库工具注册注册");
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改某行数据
|
* 删除某条数据
|
||||||
*/
|
*/
|
||||||
synchronized void modifyData(DbEntity dbEntity) {
|
synchronized <T extends DbEntity> void delData(Class<T> clazz, @NonNull Object[] wheres,
|
||||||
mDb = mHelper.getWritableDatabase();
|
@NonNull Object[] values) {
|
||||||
Class<?> clazz = dbEntity.getClass();
|
mDb = mHelper.getWritableDatabase();
|
||||||
Field[] fields = Util.getFields(clazz);
|
if (wheres.length <= 0 || values.length <= 0) {
|
||||||
if (fields != null && fields.length > 0) {
|
Log.e(TAG, "输入删除条件");
|
||||||
StringBuilder sb = new StringBuilder();
|
return;
|
||||||
sb.append("UPDATE ").append(Util.getClassName(dbEntity)).append(" SET ");
|
} else if (wheres.length != values.length) {
|
||||||
int i = 0;
|
Log.e(TAG, "key 和 vaule 长度不相等");
|
||||||
for (Field field : fields) {
|
return;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
/**
|
sb.append("DELETE FROM ").append(Util.getClassName(clazz)).append(" WHERE ");
|
||||||
* 遍历所有数据
|
int i = 0;
|
||||||
*/
|
for (Object where : wheres) {
|
||||||
synchronized <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
|
sb.append(where).append("=").append("'").append(values[i]).append("'");
|
||||||
if (!tableExists(clazz)) {
|
sb.append(i >= wheres.length - 1 ? "" : ",");
|
||||||
createTable(clazz);
|
i++;
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
print(DEL_DATA, sb.toString());
|
||||||
|
mDb.execSQL(sb.toString());
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 条件查寻数据
|
* 修改某行数据
|
||||||
*/
|
*/
|
||||||
synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, @NonNull String[] wheres,
|
synchronized void modifyData(DbEntity dbEntity) {
|
||||||
@NonNull String[] values) {
|
mDb = mHelper.getWritableDatabase();
|
||||||
if (!tableExists(clazz)) {
|
Class<?> clazz = dbEntity.getClass();
|
||||||
createTable(clazz);
|
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;
|
||||||
}
|
}
|
||||||
mDb = mHelper.getReadableDatabase();
|
sb.append(i > 0 ? ", " : "");
|
||||||
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 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();
|
|
||||||
}
|
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
try {
|
||||||
StringBuilder sb = new StringBuilder();
|
sb.append(field.getName())
|
||||||
sb.append("SELECT COUNT(*) AS c FROM sqlite_master WHERE type='table' AND name='");
|
.append("='")
|
||||||
sb.append(Util.getClassName(clazz));
|
.append(field.get(dbEntity).toString())
|
||||||
sb.append("'");
|
.append("'");
|
||||||
print(TABLE_EXISTS, sb.toString());
|
} catch (IllegalAccessException e) {
|
||||||
cursor = mDb.rawQuery(sb.toString(), null);
|
e.printStackTrace();
|
||||||
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;
|
i++;
|
||||||
|
}
|
||||||
|
sb.append(" where rowid=").append(dbEntity.rowID);
|
||||||
|
print(MODIFY_DATA, sb.toString());
|
||||||
|
mDb.execSQL(sb.toString());
|
||||||
}
|
}
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建表
|
* 遍历所有数据
|
||||||
*/
|
*/
|
||||||
private synchronized void createTable(Class clazz) {
|
synchronized <T extends DbEntity> List<T> findAllData(Class<T> clazz) {
|
||||||
if (mDb == null || !mDb.isOpen()) {
|
if (!tableExists(clazz)) {
|
||||||
mDb = mHelper.getWritableDatabase();
|
createTable(clazz);
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
close();
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打印数据库日志
|
* 条件查寻数据
|
||||||
*
|
*/
|
||||||
* @param type {@link DbUtil}
|
synchronized <T extends DbEntity> List<T> findData(Class<T> clazz, @NonNull String[] wheres,
|
||||||
*/
|
@NonNull String[] values) {
|
||||||
private void print(int type, String sql) {
|
if (!tableExists(clazz)) {
|
||||||
String str = "";
|
createTable(clazz);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
mDb = mHelper.getReadableDatabase();
|
||||||
/**
|
if (wheres.length <= 0 || values.length <= 0) {
|
||||||
* 关闭数据库
|
Log.e(TAG, "请输入查询条件");
|
||||||
*/
|
return null;
|
||||||
private synchronized void close() {
|
} else if (wheres.length != values.length) {
|
||||||
if (mDb != null) {
|
Log.e(TAG, "key 和 vaule 长度不相等");
|
||||||
mDb.close();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所在行Id
|
* 插入数据
|
||||||
*/
|
*/
|
||||||
synchronized int[] getRowId(Class clazz) {
|
synchronized void insertData(DbEntity dbEntity) {
|
||||||
mDb = mHelper.getReadableDatabase();
|
Class<?> clazz = dbEntity.getClass();
|
||||||
Cursor cursor = mDb.rawQuery("SELECT rowid, * FROM " + Util.getClassName(clazz), null);
|
if (!tableExists(clazz)) {
|
||||||
int[] ids = new int[cursor.getCount()];
|
createTable(clazz);
|
||||||
int i = 0;
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建表
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭数据库
|
||||||
|
*/
|
||||||
|
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, 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()) {
|
while (cursor.moveToNext()) {
|
||||||
ids[i] = cursor.getInt(cursor.getColumnIndex("rowid"));
|
T entity = clazz.newInstance();
|
||||||
i++;
|
for (Field field : fields) {
|
||||||
}
|
field.setAccessible(true);
|
||||||
cursor.close();
|
Ignore ignore = field.getAnnotation(Ignore.class);
|
||||||
close();
|
if (ignore != null && ignore.value()) {
|
||||||
return ids;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取行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();
|
|
||||||
}
|
}
|
||||||
|
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();
|
} catch (InstantiationException e) {
|
||||||
close();
|
e.printStackTrace();
|
||||||
return entitys;
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
cursor.close();
|
||||||
|
close();
|
||||||
|
return entitys;
|
||||||
|
}
|
||||||
}
|
}
|
@ -10,5 +10,5 @@ import java.lang.annotation.Target;
|
|||||||
* 表ID字段指定
|
* 表ID字段指定
|
||||||
*/
|
*/
|
||||||
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface 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 {
|
@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帮助类
|
* sql帮助类
|
||||||
*/
|
*/
|
||||||
public class SqlHelper extends SQLiteOpenHelper {
|
public class SqlHelper extends SQLiteOpenHelper {
|
||||||
protected static String DB_NAME;
|
protected static String DB_NAME;
|
||||||
protected static int VERSION = -1;
|
protected static int VERSION = -1;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
if (TextUtils.isEmpty(DB_NAME)) {
|
if (TextUtils.isEmpty(DB_NAME)) {
|
||||||
DB_NAME = "AriaLyyDb";
|
DB_NAME = "AriaLyyDb";
|
||||||
}
|
|
||||||
if (VERSION == -1) {
|
|
||||||
VERSION = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (VERSION == -1) {
|
||||||
public SqlHelper(Context context) {
|
VERSION = 1;
|
||||||
super(context, DB_NAME, null, VERSION);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@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.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;
|
||||||
@ -21,471 +19,494 @@ 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;
|
||||||
* 线程数
|
/**
|
||||||
*/
|
* 线程数
|
||||||
private static final int THREAD_NUM = 3;
|
*/
|
||||||
private static final int TIME_OUT = 5000; //超时时间
|
private static final int THREAD_NUM = 3;
|
||||||
/**
|
private static final int TIME_OUT = 5000; //超时时间
|
||||||
* 已经完成下载任务的线程数量
|
/**
|
||||||
*/
|
* 已经完成下载任务的线程数量
|
||||||
private int mCompleteThreadNum = 0;
|
*/
|
||||||
private boolean isDownloading = false;
|
private int mCompleteThreadNum = 0;
|
||||||
private boolean isStop = false;
|
private boolean isDownloading = false;
|
||||||
private boolean isCancel = false;
|
private boolean isStop = false;
|
||||||
private long mCurrentLocation;
|
private boolean isCancel = false;
|
||||||
boolean isNewTask = true;
|
private long mCurrentLocation;
|
||||||
private int mCancelNum = 0;
|
boolean isNewTask = true;
|
||||||
private int mStopNum = 0;
|
private int mCancelNum = 0;
|
||||||
private Context mContext;
|
private int mStopNum = 0;
|
||||||
private DownloadEntity mDownloadEntity;
|
private Context mContext;
|
||||||
|
private DownloadEntity mDownloadEntity;
|
||||||
|
|
||||||
|
public DownLoadUtil(Context context, DownloadEntity entity) {
|
||||||
|
mContext = context.getApplicationContext();
|
||||||
|
mDownloadEntity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
public DownLoadUtil(Context context, DownloadEntity entity) {
|
public IDownloadListener getListener() {
|
||||||
mContext = context.getApplicationContext();
|
return mListener;
|
||||||
mDownloadEntity = entity;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前下载位置
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除temp文件
|
||||||
|
*/
|
||||||
|
public void delTempFile() {
|
||||||
|
if (mContext != null && mDownloadEntity != null) {
|
||||||
|
File dFile = new File(mDownloadEntity.getDownloadPath());
|
||||||
|
if (dFile.exists()) {
|
||||||
|
dFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多线程断点续传下载文件,暂停和继续
|
||||||
|
*
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
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 IDownloadListener getListener() {
|
@Override public void run() {
|
||||||
return mListener;
|
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();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前下载位置
|
* 停止下载
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public long getCurrentLocation() {
|
private void stop(long currentLocation) throws IOException {
|
||||||
return mCurrentLocation;
|
synchronized (LOCK) {
|
||||||
}
|
mStopNum++;
|
||||||
|
String location = String.valueOf(currentLocation);
|
||||||
public boolean isDownloading() {
|
Log.i(TAG, "thread_" + dEntity.threadId + "_stop, stop location ==> " + currentLocation);
|
||||||
return isDownloading;
|
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
|
||||||
|
if (mStopNum == THREAD_NUM) {
|
||||||
|
Log.d(TAG, "++++++++++++++++ onStop +++++++++++++++++");
|
||||||
|
isDownloading = false;
|
||||||
|
mListener.onStop(mCurrentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消下载
|
* 取消下载
|
||||||
*/
|
*/
|
||||||
public void cancelDownload() {
|
private void cancel() {
|
||||||
isCancel = true;
|
synchronized (LOCK) {
|
||||||
}
|
mCancelNum++;
|
||||||
|
if (mCancelNum == THREAD_NUM) {
|
||||||
/**
|
File configFile = new File(configFPath);
|
||||||
* 停止下载
|
if (configFile.exists()) {
|
||||||
*/
|
configFile.delete();
|
||||||
public void stopDownload() {
|
}
|
||||||
isStop = true;
|
if (dEntity.tempFile.exists()) {
|
||||||
}
|
dEntity.tempFile.delete();
|
||||||
|
}
|
||||||
/**
|
Log.d(TAG, "++++++++++++++++ onCancel +++++++++++++++++");
|
||||||
* 删除下载记录文件
|
isDownloading = false;
|
||||||
*/
|
mListener.onCancel();
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void progress(long len) {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
mCurrentLocation += len;
|
||||||
|
mListener.onProgress(mCurrentLocation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除temp文件
|
* 将记录写入到配置文件
|
||||||
*/
|
*/
|
||||||
public void delTempFile() {
|
private void writeConfig(String key, String record) throws IOException {
|
||||||
if (mContext != null && mDownloadEntity != null) {
|
File configFile = new File(configFPath);
|
||||||
File dFile = new File(mDownloadEntity.getDownloadPath());
|
Properties pro = Util.loadConfig(configFile);
|
||||||
if (dFile.exists()) {
|
pro.setProperty(key, record);
|
||||||
dFile.delete();
|
Util.saveConfig(configFile, pro);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多线程断点续传下载文件,暂停和继续
|
* 下载失败
|
||||||
*
|
|
||||||
* @param downloadListener 下载进度监听 {@link DownloadListener}
|
|
||||||
*/
|
*/
|
||||||
public void start(@NonNull final IDownloadListener downloadListener) {
|
private void failDownload(ConfigEntity dEntity, long currentLocation, String msg,
|
||||||
isDownloading = true;
|
Exception ex) {
|
||||||
mCurrentLocation = 0;
|
synchronized (LOCK) {
|
||||||
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 {
|
try {
|
||||||
if (!configFile.exists()) { //记录文件被删除,则重新下载
|
isDownloading = false;
|
||||||
isNewTask = true;
|
isStop = true;
|
||||||
Util.createFile(configFile.getPath());
|
Log.e(TAG, msg);
|
||||||
} else {
|
if (ex != null) {
|
||||||
isNewTask = !dFile.exists();
|
Log.e(TAG, Util.getPrintException(ex));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
if (currentLocation != -1) {
|
||||||
e.printStackTrace();
|
String location = String.valueOf(currentLocation);
|
||||||
failDownload("下载失败,记录文件被删除");
|
writeConfig(dEntity.tempFile.getName() + "_record_" + dEntity.threadId, location);
|
||||||
return;
|
}
|
||||||
|
mListener.onFail();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
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");
|
private class ConfigEntity {
|
||||||
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)");
|
long fileSize;
|
||||||
conn.setRequestProperty("Accept",
|
String downloadUrl;
|
||||||
"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, */*");
|
int threadId;
|
||||||
conn.setConnectTimeout(TIME_OUT * 4);
|
long startLocation;
|
||||||
conn.connect();
|
long endLocation;
|
||||||
int len = conn.getContentLength();
|
File tempFile;
|
||||||
if (len < 0) { //网络被劫持时会出现这个问题
|
Context context;
|
||||||
failDownload("下载失败,网络被劫持");
|
|
||||||
return;
|
public ConfigEntity(Context context, long fileSize, String downloadUrl, File file, int threadId,
|
||||||
}
|
long startLocation, long endLocation) {
|
||||||
int code = conn.getResponseCode();
|
this.fileSize = fileSize;
|
||||||
if (code == 200) {
|
this.downloadUrl = downloadUrl;
|
||||||
int fileLength = conn.getContentLength();
|
this.tempFile = file;
|
||||||
//必须建一个文件
|
this.threadId = threadId;
|
||||||
Util.createFile(filePath);
|
this.startLocation = startLocation;
|
||||||
RandomAccessFile file = new RandomAccessFile(filePath, "rwd");
|
this.endLocation = endLocation;
|
||||||
//设置文件长度
|
this.context = context;
|
||||||
file.setLength(fileLength);
|
}
|
||||||
mListener.onPreDownload(conn);
|
}
|
||||||
//分配每条线程的下载区间
|
|
||||||
Properties pro = null;
|
public static class DownloadListener implements IDownloadListener {
|
||||||
pro = Util.loadConfig(configFile);
|
|
||||||
if (pro.isEmpty()) {
|
@Override public void onResume(long resumeLocation) {
|
||||||
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) {
|
@Override public void onCancel() {
|
||||||
Log.e(TAG, msg);
|
|
||||||
isDownloading = false;
|
|
||||||
stopDownload();
|
|
||||||
mListener.onFail();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override public void onFail() {
|
||||||
* 多线程下载任务类,不能使用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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override public void onPreDownload(HttpURLConnection connection) {
|
||||||
* 子线程下载信息类
|
|
||||||
*/
|
|
||||||
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 {
|
@Override public void onProgress(long currentLocation) {
|
||||||
|
|
||||||
@Override public void onResume(long resumeLocation) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onCancel() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFail() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onPreDownload(HttpURLConnection connection) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onProgress(long currentLocation) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onChildComplete(long finishLocation) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onStart(long startLocation) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onChildResume(long resumeLocation) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onStop(long stopLocation) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onComplete() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void onChildComplete(long finishLocation) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void onStart(long startLocation) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void onChildResume(long resumeLocation) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void onStop(long stopLocation) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void onComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -6,53 +6,53 @@ import java.net.HttpURLConnection;
|
|||||||
* 下载监听
|
* 下载监听
|
||||||
*/
|
*/
|
||||||
public interface IDownloadListener {
|
public interface IDownloadListener {
|
||||||
/**
|
/**
|
||||||
* 取消下载
|
* 取消下载
|
||||||
*/
|
*/
|
||||||
public void onCancel();
|
public void onCancel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载失败
|
* 下载失败
|
||||||
*/
|
*/
|
||||||
public void onFail();
|
public void onFail();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载预处理,可通过HttpURLConnection获取文件长度
|
* 下载预处理,可通过HttpURLConnection获取文件长度
|
||||||
*/
|
*/
|
||||||
public void onPreDownload(HttpURLConnection connection);
|
public void onPreDownload(HttpURLConnection connection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载监听
|
* 下载监听
|
||||||
*/
|
*/
|
||||||
public void onProgress(long currentLocation);
|
public void onProgress(long currentLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单一线程的结束位置
|
* 单一线程的结束位置
|
||||||
*/
|
*/
|
||||||
public void onChildComplete(long finishLocation);
|
public void onChildComplete(long finishLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始
|
* 开始
|
||||||
*/
|
*/
|
||||||
public void onStart(long startLocation);
|
public void onStart(long startLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 子程恢复下载的位置
|
* 子程恢复下载的位置
|
||||||
*/
|
*/
|
||||||
public void onChildResume(long resumeLocation);
|
public void onChildResume(long resumeLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 恢复位置
|
* 恢复位置
|
||||||
*/
|
*/
|
||||||
public void onResume(long resumeLocation);
|
public void onResume(long resumeLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 停止
|
* 停止
|
||||||
*/
|
*/
|
||||||
public void onStop(long stopLocation);
|
public void onStop(long stopLocation);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载完成
|
* 下载完成
|
||||||
*/
|
*/
|
||||||
public void onComplete();
|
public void onComplete();
|
||||||
}
|
}
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,245 +15,241 @@ import java.net.HttpURLConnection;
|
|||||||
* 下载任务类
|
* 下载任务类
|
||||||
*/
|
*/
|
||||||
public class Task {
|
public class Task {
|
||||||
public static final String TAG = "Task";
|
public static final String TAG = "Task";
|
||||||
|
|
||||||
private DownloadEntity mEntity;
|
private DownloadEntity mEntity;
|
||||||
private IDownloadListener mListener;
|
private IDownloadListener mListener;
|
||||||
private Handler mOutHandler;
|
private Handler mOutHandler;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private DownLoadUtil mUtil;
|
private DownLoadUtil mUtil;
|
||||||
|
|
||||||
private Task(Context context, DownloadEntity entity) {
|
private Task(Context context, DownloadEntity entity) {
|
||||||
mContext = context.getApplicationContext();
|
mContext = context.getApplicationContext();
|
||||||
mEntity = entity;
|
mEntity = entity;
|
||||||
mUtil = new DownLoadUtil(context, 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 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 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建特定的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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载监听类
|
||||||
|
*/
|
||||||
|
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();
|
||||||
public void start() {
|
downloadEntity.setFileSize(len);
|
||||||
if (mUtil.isDownloading()) {
|
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
|
||||||
Log.d(TAG, "任务正在下载");
|
sendIntent(DownloadManager.ACTION_PRE, -1);
|
||||||
} else {
|
|
||||||
if (mListener == null) {
|
|
||||||
mListener = new DownloadListener(mContext, mEntity, mOutHandler);
|
|
||||||
}
|
|
||||||
mUtil.start(mListener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DownloadEntity getDownloadEntity() {
|
@Override public void onResume(long resumeLocation) {
|
||||||
return mEntity;
|
super.onResume(resumeLocation);
|
||||||
|
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
|
||||||
|
sendIntent(DownloadManager.ACTION_RESUME, resumeLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override public void onStart(long startLocation) {
|
||||||
* 停止下载
|
super.onStart(startLocation);
|
||||||
*/
|
downloadEntity.setState(DownloadEntity.STATE_DOWNLOAD_ING);
|
||||||
public void stop() {
|
sendInState2Target(IDownloadTarget.START);
|
||||||
if (mUtil.isDownloading()) {
|
sendIntent(DownloadManager.ACTION_START, startLocation);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override public void onProgress(long currentLocation) {
|
||||||
* 获取下载工具
|
super.onProgress(currentLocation);
|
||||||
*/
|
// if (currentLocation - lastLen > INTERVAL) { //不要太过于频繁发送广播
|
||||||
public DownLoadUtil getDownloadUtil() {
|
// sendIntent.putExtra(DownloadManager.CURRENT_LOCATION, currentLocation);
|
||||||
return mUtil;
|
// 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);
|
||||||
public boolean isDownloading() {
|
sendInState2Target(IDownloadTarget.STOP);
|
||||||
return mUtil.isDownloading();
|
sendIntent(DownloadManager.ACTION_STOP, stopLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override public void onCancel() {
|
||||||
* 取消下载
|
super.onCancel();
|
||||||
*/
|
downloadEntity.setState(DownloadEntity.STATE_CANCEL);
|
||||||
public void cancel() {
|
sendInState2Target(IDownloadTarget.CANCEL);
|
||||||
if (mUtil.isDownloading()) {
|
sendIntent(DownloadManager.ACTION_CANCEL, -1);
|
||||||
mUtil.cancelDownload();
|
downloadEntity.deleteData();
|
||||||
} 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 onComplete() {
|
||||||
* 创建特定的Intent
|
super.onComplete();
|
||||||
*
|
downloadEntity.setState(DownloadEntity.STATE_COMPLETE);
|
||||||
* @param action
|
downloadEntity.setDownloadComplete(true);
|
||||||
* @return
|
sendInState2Target(IDownloadTarget.COMPLETE);
|
||||||
*/
|
sendIntent(DownloadManager.ACTION_COMPLETE, -1);
|
||||||
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 onFail() {
|
||||||
* 将任务状态发送给下载器
|
super.onFail();
|
||||||
*
|
downloadEntity.setState(DownloadEntity.STATE_FAIL);
|
||||||
* @param state {@link IDownloadTarget#START}
|
sendInState2Target(IDownloadTarget.FAIL);
|
||||||
*/
|
sendIntent(DownloadManager.ACTION_FAIL, -1);
|
||||||
private void sendInState2Target(int state) {
|
|
||||||
if (mOutHandler != null) {
|
|
||||||
mOutHandler.obtainMessage(state, mEntity).sendToTarget();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void sendIntent(String action, long location) {
|
||||||
* 下载监听类
|
downloadEntity.setDownloadComplete(action.equals(DownloadManager.ACTION_COMPLETE));
|
||||||
*/
|
downloadEntity.setCurrentProgress(location);
|
||||||
private class DownloadListener extends DownLoadUtil.DownloadListener {
|
downloadEntity.update();
|
||||||
Handler outHandler;
|
Intent intent = createIntent(action);
|
||||||
Context context;
|
intent.putExtra(DownloadManager.ENTITY, downloadEntity);
|
||||||
Intent sendIntent;
|
if (location != -1) {
|
||||||
long INTERVAL = 1024 * 10; //10k大小的间隔
|
intent.putExtra(DownloadManager.CURRENT_LOCATION, location);
|
||||||
long lastLen = 0; //上一次发送长度
|
}
|
||||||
long lastTime = 0;
|
context.sendBroadcast(intent);
|
||||||
long INTERVAL_TIME = 60 * 1000; //10k大小的间隔
|
}
|
||||||
DownloadEntity downloadEntity;
|
}
|
||||||
|
|
||||||
DownloadListener(Context context, DownloadEntity downloadEntity,
|
public static class Builder {
|
||||||
Handler outHandler) {
|
DownloadEntity downloadEntity;
|
||||||
this.context = context;
|
IDownloadListener listener;
|
||||||
this.outHandler = outHandler;
|
Handler outHandler;
|
||||||
this.downloadEntity = downloadEntity;
|
Context context;
|
||||||
sendIntent = createIntent(DownloadManager.ACTION_RUNNING);
|
|
||||||
sendIntent.putExtra(DownloadManager.ENTITY, downloadEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onPreDownload(HttpURLConnection connection) {
|
public Builder(Context context, DownloadEntity downloadEntity) {
|
||||||
super.onPreDownload(connection);
|
this.context = context;
|
||||||
long len = connection.getContentLength();
|
this.downloadEntity = downloadEntity;
|
||||||
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 onCancel() {
|
|
||||||
super.onCancel();
|
|
||||||
downloadEntity.setState(DownloadEntity.STATE_CANCEL);
|
|
||||||
sendInState2Target(IDownloadTarget.CANCEL);
|
|
||||||
sendIntent(DownloadManager.ACTION_CANCEL, -1);
|
|
||||||
downloadEntity.deleteData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onComplete() {
|
|
||||||
super.onComplete();
|
|
||||||
downloadEntity.setState(DownloadEntity.STATE_COMPLETE);
|
|
||||||
downloadEntity.setDownloadComplete(true);
|
|
||||||
sendInState2Target(IDownloadTarget.COMPLETE);
|
|
||||||
sendIntent(DownloadManager.ACTION_COMPLETE, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFail() {
|
|
||||||
super.onFail();
|
|
||||||
downloadEntity.setState(DownloadEntity.STATE_FAIL);
|
|
||||||
sendInState2Target(IDownloadTarget.FAIL);
|
|
||||||
sendIntent(DownloadManager.ACTION_FAIL, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
public Builder setDownloadListener(IDownloadListener listener) {
|
||||||
DownloadEntity downloadEntity;
|
this.listener = listener;
|
||||||
IDownloadListener listener;
|
return this;
|
||||||
Handler outHandler;
|
|
||||||
Context context;
|
|
||||||
|
|
||||||
public Builder(Context context, DownloadEntity downloadEntity) {
|
|
||||||
this.context = context;
|
|
||||||
this.downloadEntity = downloadEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setDownloadListener(IDownloadListener listener) {
|
|
||||||
this.listener = listener;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setOutHandler(Handler outHandler) {
|
|
||||||
this.outHandler = outHandler;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task build() {
|
|
||||||
Task task = new Task(context, downloadEntity);
|
|
||||||
task.mListener = listener;
|
|
||||||
task.mOutHandler = outHandler;
|
|
||||||
downloadEntity.save();
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -16,264 +15,261 @@ import java.util.Properties;
|
|||||||
* Created by lyy on 2016/1/22.
|
* Created by lyy on 2016/1/22.
|
||||||
*/
|
*/
|
||||||
public class Util {
|
public class Util {
|
||||||
private static final String TAG = "util";
|
private static final String TAG = "util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取类里面的所在字段
|
* 获取类里面的所在字段
|
||||||
*/
|
*/
|
||||||
public static Field[] getFields(Class clazz) {
|
public static Field[] getFields(Class clazz) {
|
||||||
Field[] fields = null;
|
Field[] fields = null;
|
||||||
fields = clazz.getDeclaredFields();
|
fields = clazz.getDeclaredFields();
|
||||||
if (fields == null || fields.length == 0) {
|
if (fields == null || fields.length == 0) {
|
||||||
Class superClazz = clazz.getSuperclass();
|
Class superClazz = clazz.getSuperclass();
|
||||||
if (superClazz != null) {
|
if (superClazz != null) {
|
||||||
fields = getFields(superClazz);
|
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);
|
||||||
}
|
}
|
||||||
return fields;
|
}
|
||||||
|
}
|
||||||
|
if (field != null) {
|
||||||
|
field.setAccessible(true);
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将普通字符串转换为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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对象名
|
||||||
|
*
|
||||||
|
* @param obj 对象
|
||||||
|
* @return 对象名
|
||||||
|
*/
|
||||||
|
public static String getClassName(Object obj) {
|
||||||
|
String arrays[] = obj.getClass().getName().split("\\.");
|
||||||
|
return arrays[arrays.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对象名
|
||||||
|
*
|
||||||
|
* @param clazz clazz
|
||||||
|
* @return 对象名
|
||||||
|
*/
|
||||||
|
public static String getClassName(Class clazz) {
|
||||||
|
String arrays[] = clazz.getName().split("\\.");
|
||||||
|
return arrays[arrays.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化文件大小
|
||||||
|
*
|
||||||
|
* @param size file.length() 获取文件大小
|
||||||
|
*/
|
||||||
|
public static String formatFileSize(double size) {
|
||||||
|
double kiloByte = size / 1024;
|
||||||
|
if (kiloByte < 1) {
|
||||||
|
return size + "Byte(s)";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
double megaByte = kiloByte / 1024;
|
||||||
* 获取类里面的指定对象,如果该类没有则从父类查询
|
if (megaByte < 1) {
|
||||||
*/
|
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
|
||||||
public static Field getField(Class clazz, String name) {
|
return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
|
||||||
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);
|
|
||||||
}
|
|
||||||
return field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
double gigaByte = megaByte / 1024;
|
||||||
* 字符串转hashcode
|
if (gigaByte < 1) {
|
||||||
*
|
BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
|
||||||
* @param str
|
return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
|
||||||
* @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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
double teraBytes = gigaByte / 1024;
|
||||||
* 将key转换为16进制码
|
if (teraBytes < 1) {
|
||||||
*
|
BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
|
||||||
* @param key 缓存的key
|
return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB";
|
||||||
* @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;
|
|
||||||
}
|
}
|
||||||
|
BigDecimal result4 = new BigDecimal(teraBytes);
|
||||||
|
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将普通字符串转换为16位进制字符串
|
* 创建目录 当目录不存在的时候创建文件,否则返回false
|
||||||
*/
|
*/
|
||||||
public static String bytesToHexString(byte[] src) {
|
public static boolean createDir(String path) {
|
||||||
StringBuilder stringBuilder = new StringBuilder("0x");
|
File file = new File(path);
|
||||||
if (src == null || src.length <= 0) {
|
if (!file.exists()) {
|
||||||
return null;
|
if (!file.mkdirs()) {
|
||||||
}
|
Log.d(TAG, "创建失败,请检查路径和是否配置文件权限!");
|
||||||
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 obj 对象
|
|
||||||
* @return 对象名
|
|
||||||
*/
|
|
||||||
public static String getClassName(Object obj) {
|
|
||||||
String arrays[] = obj.getClass().getName().split("\\.");
|
|
||||||
return arrays[arrays.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取对象名
|
|
||||||
*
|
|
||||||
* @param clazz clazz
|
|
||||||
* @return 对象名
|
|
||||||
*/
|
|
||||||
public static String getClassName(Class clazz) {
|
|
||||||
String arrays[] = clazz.getName().split("\\.");
|
|
||||||
return arrays[arrays.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 格式化文件大小
|
|
||||||
*
|
|
||||||
* @param size file.length() 获取文件大小
|
|
||||||
*/
|
|
||||||
public static String formatFileSize(double size) {
|
|
||||||
double kiloByte = size / 1024;
|
|
||||||
if (kiloByte < 1) {
|
|
||||||
return size + "Byte(s)";
|
|
||||||
}
|
|
||||||
|
|
||||||
double megaByte = kiloByte / 1024;
|
|
||||||
if (megaByte < 1) {
|
|
||||||
BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
|
|
||||||
return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
|
|
||||||
}
|
|
||||||
|
|
||||||
double gigaByte = megaByte / 1024;
|
|
||||||
if (gigaByte < 1) {
|
|
||||||
BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
|
|
||||||
return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
|
|
||||||
}
|
|
||||||
|
|
||||||
double teraBytes = gigaByte / 1024;
|
|
||||||
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;
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建文件 当文件不存在的时候就创建一个文件,否则直接返回文件
|
* 创建文件 当文件不存在的时候就创建一个文件,否则直接返回文件
|
||||||
*/
|
*/
|
||||||
public static File createFile(String path) {
|
public static File createFile(String path) {
|
||||||
File file = new File(path);
|
File file = new File(path);
|
||||||
if (!file.getParentFile().exists()) {
|
if (!file.getParentFile().exists()) {
|
||||||
Log.d(TAG, "目标文件所在路径不存在,准备创建……");
|
Log.d(TAG, "目标文件所在路径不存在,准备创建……");
|
||||||
if (!createDir(file.getParent())) {
|
if (!createDir(file.getParent())) {
|
||||||
Log.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】");
|
Log.d(TAG, "创建目录文件所在的目录失败!文件路径【" + path + "】");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// 创建目标文件
|
|
||||||
try {
|
|
||||||
if (!file.exists()) {
|
|
||||||
if (file.createNewFile()) {
|
|
||||||
Log.d(TAG, "创建文件成功:" + file.getAbsolutePath());
|
|
||||||
}
|
|
||||||
return file;
|
|
||||||
} else {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
// 创建目标文件
|
||||||
|
try {
|
||||||
|
if (!file.exists()) {
|
||||||
|
if (file.createNewFile()) {
|
||||||
|
Log.d(TAG, "创建文件成功:" + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
} else {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置打印的异常格式
|
* 设置打印的异常格式
|
||||||
*/
|
*/
|
||||||
public static String getPrintException(Throwable ex) {
|
public static String getPrintException(Throwable ex) {
|
||||||
StringBuilder err = new StringBuilder();
|
StringBuilder err = new StringBuilder();
|
||||||
err.append("ExceptionDetailed:\n");
|
err.append("ExceptionDetailed:\n");
|
||||||
err.append("====================Exception Info====================\n");
|
err.append("====================Exception Info====================\n");
|
||||||
err.append(ex.toString());
|
err.append(ex.toString());
|
||||||
err.append("\n");
|
err.append("\n");
|
||||||
StackTraceElement[] stack = ex.getStackTrace();
|
StackTraceElement[] stack = ex.getStackTrace();
|
||||||
for (StackTraceElement stackTraceElement : stack) {
|
for (StackTraceElement stackTraceElement : stack) {
|
||||||
err.append(stackTraceElement.toString()).append("\n");
|
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();
|
|
||||||
}
|
}
|
||||||
|
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) {
|
public static Properties loadConfig(File file) {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
FileInputStream fis = null;
|
FileInputStream fis = null;
|
||||||
try {
|
try {
|
||||||
fis = new FileInputStream(file);
|
fis = new FileInputStream(file);
|
||||||
properties.load(fis);
|
properties.load(fis);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (fis != null) {
|
if (fis != null) {
|
||||||
fis.close();
|
fis.close();
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return properties;
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存配置文件
|
* 保存配置文件
|
||||||
*/
|
*/
|
||||||
public static void saveConfig(File file, Properties properties) {
|
public static void saveConfig(File file, Properties properties) {
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
try {
|
try {
|
||||||
fos = new FileOutputStream(file, false);
|
fos = new FileOutputStream(file, false);
|
||||||
properties.store(fos, null);
|
properties.store(fos, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (fos != null) {
|
if (fos != null) {
|
||||||
fos.flush();
|
fos.flush();
|
||||||
fos.close();
|
fos.close();
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">DownloadUtil</string>
|
<string name="app_name">DownloadUtil</string>
|
||||||
|
|
||||||
<string name="error_entity_null">下载实体不能为空</string>
|
<string name="error_entity_null">下载实体不能为空</string>
|
||||||
<string name="error_download_url_null">下载链接不能为空</string>
|
<string name="error_download_url_null">下载链接不能为空</string>
|
||||||
<string name="error_download_path_null">存储地址不能为空</string>
|
<string name="error_download_path_null">存储地址不能为空</string>
|
||||||
<string name="error_file_name_null">文件名不能为空</string>
|
<string name="error_file_name_null">文件名不能为空</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user