標籤:android 多線程 網路編程 斷點下載 資料庫
本項目完成的功能類似與迅雷等下載工具所實現的功能——實現多線程斷點下載。
主要設計的技術有:
1、android中主線程與非主線程通訊機制。
2、多線程的編程和管理。
3、android網路編程
4、自己設計實現設計模式-監聽器模式
5、Activity、Service、資料庫編程
6、android檔案系統
7、緩衝
博文連結:
Android-多線程斷點下載詳解及源碼下載(一)
Android-多線程斷點下載詳解及源碼下載(二)
Android-多線程斷點下載詳解及源碼下載(三)
本篇完結多線程斷點下載,繼續上面三篇文章的內容。
從上面三篇的內容已經全部給出了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"/>
洋洋洒洒寫了四篇,不知道是否說的明白,大家姑且看看,如果有什麼不對的地方,希望大家踴躍指正,共同交流學習!【握手】
博文連結:
Android-多線程斷點下載詳解及源碼下載(一)
Android-多線程斷點下載詳解及源碼下載(二)
Android-多線程斷點下載詳解及源碼下載(三)
源碼下載(伺服器端和用戶端代碼)
Android-多線程斷點下載詳解及源碼下載(四)