没做啥

This commit is contained in:
lyy
2016-10-14 10:01:59 +08:00
65 changed files with 3345 additions and 3422 deletions

View File

@ -63,7 +63,9 @@
</extensions> </extensions>
</Objective-C-extensions> </Objective-C-extensions>
<XML> <XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" /> <option name="XML_KEEP_LINE_BREAKS" value="false" />
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
<option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
</XML> </XML>
<codeStyleSettings language="XML"> <codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" /> <option name="FORCE_REARRANGE_MODE" value="1" />
@ -224,6 +226,6 @@
</codeStyleSettings> </codeStyleSettings>
</value> </value>
</option> </option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="aria" /> <option name="PREFERRED_PROJECT_CODE_STYLE" value="SquareAndroid" />
</component> </component>
</project> </project>

6
.idea/encodings.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

2
.idea/modules.xml generated
View File

@ -2,7 +2,7 @@
<project version="4"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/DownloadUtil.iml" filepath="$PROJECT_DIR$/DownloadUtil.iml" /> <module fileurl="file://$PROJECT_DIR$/DownloadPrj.iml" filepath="$PROJECT_DIR$/DownloadPrj.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" /> <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/downloadutil/downloadutil.iml" filepath="$PROJECT_DIR$/downloadutil/downloadutil.iml" /> <module fileurl="file://$PROJECT_DIR$/downloadutil/downloadutil.iml" filepath="$PROJECT_DIR$/downloadutil/downloadutil.iml" />
</modules> </modules>

View File

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

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

View File

@ -1,32 +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.SingleTaskActivity"--> <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>
<activity android:name=".activity.SingleTaskActivity"/> <activity android:name=".activity.SingleTaskActivity"/>
<activity android:name=".activity.MultiTaskActivity"/> <activity android:name=".activity.MultiTaskActivity"/>
</application> </application>
</manifest> </manifest>

View File

@ -6,8 +6,8 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import butterknife.Bind;
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.frame.util.show.L; import com.arialyy.frame.util.show.L;
@ -17,78 +17,75 @@ import com.arialyy.simple.base.BaseActivity;
import com.arialyy.simple.databinding.ActivityMultiBinding; import com.arialyy.simple.databinding.ActivityMultiBinding;
import com.arialyy.simple.module.DownloadModule; import com.arialyy.simple.module.DownloadModule;
import butterknife.Bind;
/** /**
* Created by Lyy on 2016/9/27. * Created by Lyy on 2016/9/27.
*/ */
public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> { public class MultiTaskActivity extends BaseActivity<ActivityMultiBinding> {
@Bind(R.id.list) RecyclerView mList; @Bind(R.id.list) RecyclerView mList;
@Bind(R.id.toolbar) Toolbar mBar; @Bind(R.id.toolbar) Toolbar mBar;
DownloadAdapter mAdapter; DownloadAdapter mAdapter;
@Override protected int setLayoutId() { @Override protected int setLayoutId() {
return R.layout.activity_multi; 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 init(Bundle savedInstanceState) { @Override protected void onResume() {
super.init(savedInstanceState); super.onResume();
setSupportActionBar(mBar); registerReceiver(mReceiver, getModule(DownloadModule.class).getDownloadFilter());
mBar.setTitle("多任务下载"); }
mAdapter = new DownloadAdapter(this, getModule(DownloadModule.class).getDownloadData());
mList.setLayoutManager(new LinearLayoutManager(this));
mList.setAdapter(mAdapter);
}
@Override protected void onDestroy() {
private BroadcastReceiver mReceiver = new BroadcastReceiver() { super.onDestroy();
long len = 0; unregisterReceiver(mReceiver);
}
@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);
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,7 +26,7 @@ public class DownloadModule extends BaseModule {
* 设置下载数据 * 设置下载数据
*/ */
public List<DownloadEntity> getDownloadData() { public List<DownloadEntity> getDownloadData() {
List<DownloadEntity> list = DownloadEntity.findAllData(DownloadEntity.class); List<DownloadEntity> list = DownloadEntity.findAllData(DownloadEntity.class);
List<DownloadEntity> newDownload = createNewDownload(); List<DownloadEntity> newDownload = createNewDownload();
if (list == null) { if (list == null) {
list = newDownload; list = newDownload;
@ -66,10 +66,11 @@ public class DownloadModule extends BaseModule {
*/ */
private List<DownloadEntity> createNewDownload() { private List<DownloadEntity> createNewDownload() {
List<DownloadEntity> list = new ArrayList<>(); List<DownloadEntity> list = new ArrayList<>();
String[] urls = getContext().getResources().getStringArray(R.array.test_apk_download_url); String[] urls =
getContext().getResources().getStringArray(R.array.test_apk_download_url);
for (String url : urls) { for (String url : urls) {
String fileName = Util.keyToHashCode(url) + ".apk"; String fileName = Util.keyToHashCode(url) + ".apk";
DownloadEntity entity = new DownloadEntity(); DownloadEntity entity = new DownloadEntity();
entity.setDownloadUrl(url); entity.setDownloadUrl(url);
entity.setDownloadPath(getDownloadPath(url)); entity.setDownloadPath(getDownloadPath(url));
entity.setFileName(fileName); entity.setFileName(fileName);

View File

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

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout <layout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
> >
<LinearLayout <LinearLayout

View File

@ -1,35 +1,34 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <layout xmlns:android="http://schemas.android.com/apk/res/android">
<android.support.design.widget.CoordinatorLayout <android.support.design.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
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_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:fitsSystemWindows="true" android:theme="@style/AppTheme.AppBarOverlay"
tools:context="com.arialyy.simple.activity.SingleTaskActivity"
> >
<android.support.design.widget.AppBarLayout <include layout="@layout/layout_bar"/>
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>
</android.support.design.widget.AppBarLayout> <include layout="@layout/content_single"/>
<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.FloatingActionButton </android.support.design.widget.CoordinatorLayout>
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> </layout>

View File

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

View File

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

View File

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

View File

@ -1,28 +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"> <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>
<!--设置导航栏内容可用--> <!--设置导航栏内容可用-->
<!--<item name="android:windowTranslucentNavigation">true</item>--> <!--<item name="android:windowTranslucentNavigation">true</item>-->
<!--设置状态栏内容可以--> <!--设置状态栏内容可以-->
<!--<item name="android:windowTranslucentStatus">true</item>--> <!--<item name="android:windowTranslucentStatus">true</item>-->
<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="android:windowIsTranslucent">true</item> <item name="android:windowIsTranslucent">true</item>
</style> </style>
</resources> </resources>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,25 +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>
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>
</style> </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>

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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, "添加命令执行失败,【该任务已经存在】");
}
} }
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 +
'}';
}
} }

View File

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

View File

@ -1,7 +1,6 @@
package com.arialyy.downloadutil.help; package com.arialyy.downloadutil.help;
import android.os.Environment; import android.os.Environment;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -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();
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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() {
}
}
} }

View File

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

View File

@ -1,17 +1,13 @@
package com.arialyy.downloadutil.util; package com.arialyy.downloadutil.util;
import android.Manifest;
import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; 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;
/** /**
@ -19,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;
}
}
} }

View File

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

View File

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

View File

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