本项目完成的功能类似与迅雷等下载工具所实现的功能——实现多线程断点下载。
主要设计的技术有:
1、android中主线程与非主线程通信机制。
2、多线程的编程和管理。
3、android网络编程
4、自己设计实现设计模式-监听器模式
5、Activity、Service、数据库编程
6、android文件系统
7、缓存
博文链接:
本篇完结多线程断点下载,继续上面三篇文章的内容。
从上面三篇的内容已经全部给出了Activity界面所需要的内容,下面给出MainActivity代码:
public class MainActivity extends Activity {
private EditText loaderPath;
private Button start,stop;
private ProgressBar progressBar;
private TextView progressNum;
private final int THREADNUM = 3;
private Task task;
private static final int PROGRESS = 0;
private static final int FAILURE = 1;
private MultiThreadManager manager;
@SuppressLint("HandlerLeak")
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case PROGRESS:
// float prog = (float)progressBar.getProgress()/(float)progressBar.getMax();
float prog1 = ((float)manager.getDownedLen()/(float)manager.getFileLen())*100;
progressBar.setProgress((int)prog1);
progressNum.setText((int)(prog1)+"%"+100);
if (prog1 >= 100) {
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT)
.show();
}
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
init();
setListener();
}
private void setListener() {
start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File saveDir = Environment.getExternalStorageDirectory();
task = new Task(saveDir, loaderPath.getText().toString());
new Thread(task).start();
}else {
Toast.makeText(MainActivity.this,
"无SD卡", Toast.LENGTH_SHORT).show();
}
start.setClickable(false);
stop.setClickable(true);
}
});
stop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
exit();
start.setClickable(true);
stop.setClickable(true);
}
});
}
private void init() {
loaderPath = (EditText) findViewById(R.id.path);
start = (Button) findViewById(R.id.start_loader);
stop = (Button) findViewById(R.id.stop_loader);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressNum = (TextView) findViewById(R.id.progress_num);
progressBar.setMax(100);
}
private void exit(){
if (task != null) {
task.exit();
}
}
private class Task implements Runnable{
private String path;
private File saveDir;
public Task(File saveDir,String path){
this.saveDir = saveDir;
this.path = path;
System.out.println("MainActivity.Task.Task() 下载路径="+this.path);
}
public void exit(){
if (manager != null) {
manager.setExist(true);
}
}
@Override
public void run() {
try {
manager = new MultiThreadManager(THREADNUM,
path, saveDir, MainActivity.this);
progressBar.setMax(100);
manager.downloader(new IDownProgressing() {
@Override
public void setDownLoaderNum(int size) {
Message msg = new Message();
msg.what = PROGRESS;
msg.obj = size;
handler.sendMessage(msg);
}
});
} catch (Exception e) {
e.printStackTrace();
handler.sendMessage(handler.obtainMessage(FAILURE));
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
this.exit();
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
}
主界面就没有什么要特别说明得了,注释部分也比较详细。布局文件也非常简单:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.yin.multithreaddownloader.activity.MainActivity" >
<EditText
android:id="@+id/path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="http://192.168.2.63:8080/ds/my.mp3" />
<LinearLayout
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/path"
android:orientation="horizontal">
<Button
android:id="@+id/start_loader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始下载"
android:textSize="16sp"
/>
<Button
android:id="@+id/stop_loader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止下载"
android:textSize="16sp"
/>
</LinearLayout>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/button"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
/>
<TextView
android:id="@+id/progress_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/progressBar"
android:layout_alignParentRight="true"
android:layout_marginTop="10dp"/>
</RelativeLayout>
这里面要注意的是http://192.168.2.63:8080/ds/my.mp3这个值,这个值是服务器的地址,需要根据自己的配置进行更改的,所以不可以照搬的!
总结:
多线程断点续传下载涉及了android应用开发的大部分知识点和难点。特别是多线程管理、网络请求、文件管理、数据库编程等都是非常重要的内容。另外,如果大家对服务器开发有兴趣、或者想了解服务器开发的知识可以学习ssh框架,当然服务器框架有很多,不一定非要使用ssh,但是我个人觉得ssh还是比较简单的,特别是jsp servlet内容,需要达到比较熟悉的程度。
另外对于本项目中值得提醒的是,需要在AndroidManifest.xml配置相应的权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
洋洋洒洒写了四篇,不知道是否说的明白,大家姑且看看,如果有什么不对的地方,希望大家踊跃指正,共同交流学习!【握手】
博文链接:
时间: 2024-10-14 03:04:05