1.用途 : 学习android4大组件的良好实例 , 关键知识点有 :
a.Activity如何与Service交互数据;
b.下载为何要使用Service?Service处于后台组件,便于与多个Activity交互,即使app没有处于当前应用页面,也能进行下载;
c.保存当前下载文件的下载量
d.Service通过BroatCast广播更新UI数据;
e.非主线程通过Handler发送消息更新UI;
f.熟悉网络连接代码及文件处理;
2.实现:
a.主界面MainActivity定义下载和暂停下载任务,及定义广播;
public class MainActivity extends AppCompatActivity {
private TextView mFileNameTv = null;
private ProgressBar mPbgressBar = null;
private Button mBtStart = null;
private Button mBtEnd = null;
BroadcastReceiver mReceiver = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFileNameTv = (TextView) findViewById(R.id.tv_fileName);
mPbgressBar = (ProgressBar) findViewById(R.id.progressBar);
mBtStart = (Button) findViewById(R.id.bt_start);
mBtEnd = (Button) findViewById(R.id.bt_end);
mPbgressBar.setMax(100);
mFileNameTv.setText("mukewang.apk");
mBtStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, DownloadService.class);
intent.setAction(DownloadService.ACTION_START);
FileInfo fileInfo = new FileInfo("http://www.imooc.com/mobile/mukewang.apk", "mukewang.apk", 0, 0);
intent.putExtra("fileInfo", fileInfo);
startService(intent);
}
});
mBtEnd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, DownloadService.class);
intent.setAction(DownloadService.ACTION_STOP);
FileInfo fileInfo = new FileInfo("http://www.imooc.com/mobile/mukewang.apk", "mukewang.apk", 0, 0);
intent.putExtra("fileInfo", fileInfo);
startService(intent);
}
});
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DownloadService.ACTION_UPDATE.equals(intent.getAction())) {
int progress = intent.getIntExtra("progress", 0);
mPbgressBar.setProgress(progress);
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(DownloadService.ACTION_UPDATE);
registerReceiver(mReceiver, filter);
}
@Override
protected void onDestroy() {
if(mReceiver!=null)
{
unregisterReceiver(mReceiver);
}
super.onDestroy();
}
}
b.定义下载文件实体类:
public class FileInfo implements Serializable{
public FileInfo(String url, String fileName, int length, int finished) {
this.url = url;
this.fileName = fileName;
this.length = length;
this.finished = finished;
}
public FileInfo() {
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int getFinished() {
return finished;
}
public void setFinished(int finished) {
this.finished = finished;
}
private String url;
private String fileName;
private int length;
private int finished;
@Override
public String toString() {
return "FileInfo{" +
"url='" + url + '\'' +
", fileName='" + fileName + '\'' +
", length=" + length +
", finished=" + finished +
'}';
}
}
c.定义任务线程下载信息:
public class ThreadInfo {
public String getUrl() {
return url;
}
public ThreadInfo() {
}
public void setUrl(String url) {
this.url = url;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getFinished() {
return finished;
}
public void setFinished(int finished) {
this.finished = finished;
}
private String url;
private int start;
private int end;
private int finished;
public ThreadInfo(String url, int start, int end, int finished) {
this.url = url;
this.start = start;
this.end = end;
this.finished = finished;
}
}
d.定义后台Service,新建下载线程:
public class ThreadInfo {
public String getUrl() {
return url;
}
public ThreadInfo() {
}
public void setUrl(String url) {
this.url = url;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getFinished() {
return finished;
}
public void setFinished(int finished) {
this.finished = finished;
}
private String url;
private int start;
private int end;
private int finished;
public ThreadInfo(String url, int start, int end, int finished) {
this.url = url;
this.start = start;
this.end = end;
this.finished = finished;
}
}
e.定义数据库帮助类:
public class DbHelper extends SQLiteOpenHelper {
public static final String DOWNLOAD_DB = "download.db";
public DbHelper(Context context) {
super(context, DOWNLOAD_DB, null, 1);
}
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL("create table thread_info(url text,start integer,end integer,finished integer)");
}
@Override
public void onUpgrade(SQLiteDatabase database, int i, int i1) {
database.execSQL("drop table thread_info");
database.execSQL("create table thread_info(url text,start integer,end integer,finished integer)");
}
}
数据访问接口:
public interface ThreadDao {
public void insertThread(ThreadInfo thread_info);
public void deleteThread(String url);
public void updateThread(String url,int finished);
public ThreadInfo getThread(String url);
}
实现数据访问接口:
public class ThreadDaoImpl implements ThreadDao {
private Context mContext;
private DbHelper mDbHelper;
public ThreadDaoImpl(Context context)
{
this.mContext = context;
mDbHelper = new DbHelper(mContext);
}
@Override
public void insertThread(ThreadInfo thread_info) {
SQLiteDatabase database = mDbHelper.getWritableDatabase();
database.execSQL("insert into thread_info (url ,start ,end ,finished) values ("+"'"+thread_info.getUrl()+"'"+","+
thread_info.getStart()+","+thread_info.getEnd()+","+thread_info.getFinished()+")");
}
@Override
public void deleteThread(String url) {
SQLiteDatabase database = mDbHelper.getWritableDatabase();
database.execSQL("delete from thread_info where url = "+"'"+url+"'");
}
@Override
public void updateThread(String url,int finished) {
SQLiteDatabase database = mDbHelper.getWritableDatabase();
database.execSQL("update thread_info set finished = "+finished +" where url = "+"'"+url+"'");
}
@Override
public ThreadInfo getThread(String url) {
SQLiteDatabase database = mDbHelper.getWritableDatabase();
Cursor cursor = database.query("thread_info", null, null, null, null, null, null);
ThreadInfo thread_info = null;
while (cursor.moveToNext()) {
thread_info = new ThreadInfo();
thread_info.setUrl(cursor.getString(0));
thread_info.setStart(cursor.getInt(1));
thread_info.setEnd(cursor.getInt(2));
thread_info.setFinished(cursor.getInt(3));
}
return thread_info;
}
}
f.下载任务线程类:
public class DownloadTask extends Thread {
private ThreadInfo mThreadInfo;
private ThreadDaoImpl mThreadDao;
private Context mContext;
private String mFileName;
private int finished;
public boolean isPause = false;
public DownloadTask(Context context, FileInfo fileInfo)
{
this.mContext = context;
mThreadDao = new ThreadDaoImpl(mContext);
this.mFileName = fileInfo.getFileName();
mThreadInfo = mThreadDao.getThread(fileInfo.getUrl());
if(mThreadInfo == null)
{
mThreadInfo = new ThreadInfo();
mThreadInfo.setUrl(fileInfo.getUrl());
mThreadInfo.setStart(0);
mThreadInfo.setEnd(fileInfo.getLength());
mThreadInfo.setFinished(0);
mThreadDao.insertThread(mThreadInfo);
}
finished = mThreadInfo.getStart() + mThreadInfo.getFinished();
}
@Override
public void run() {
//打开连接
HttpURLConnection conn = null;
RandomAccessFile accessFile = null;
InputStream isput = null;
try {
URL url = new URL(mThreadInfo.getUrl());
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(3000);
conn.setRequestMethod("GET");
//设置下载位置
conn.setRequestProperty("Range", "bytes="+(finished) + "-" + mThreadInfo.getEnd());
accessFile = new RandomAccessFile(new File(DownloadService.DOWNLOAD_PATH+mFileName), "rwd");
accessFile.seek(mThreadInfo.getStart() + mThreadInfo.getFinished());
//读取并保存下载文件
isput = conn.getInputStream();
byte[] buffer = new byte[4096];
int length = -1;
long time = System.currentTimeMillis();
while ((length = isput.read(buffer)) != -1) {
if (isPause) {
mThreadDao.updateThread(mThreadInfo.getUrl(),finished);
return;
}
accessFile.write(buffer, 0, length);
finished += length;
// 更新数据库中的下载信息
mThreadDao.updateThread(mThreadInfo.getUrl(),finished);
if(System.currentTimeMillis() - time > 500) {
time = System.currentTimeMillis();
// 用消息将下载信息传给进度条,对进度条进行更新
Intent intent = new Intent();
intent.setAction(DownloadService.ACTION_UPDATE);
intent.putExtra("progress", finished * 100 / mThreadInfo.getEnd());
mContext.sendBroadcast(intent);
}
}
mThreadDao.deleteThread(mThreadInfo.getUrl());
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
isput.close();
conn.disconnect();
accessFile.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
3.总结:通过该实例,建立宏观的android基本组件的认识;