Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 【黑馬Android】(07)多線程下載的原理/開源項目xutils/顯示意圖/隱式意圖/人品計算器/開啟activity獲取返回值

【黑馬Android】(07)多線程下載的原理/開源項目xutils/顯示意圖/隱式意圖/人品計算器/開啟activity獲取返回值

編輯:關於Android編程

多線程下載的原理

司馬光砸缸,多開幾個小水管,搶救小朋友。

\

\

 

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class MutileThreadDownload {
	/**
	 * 線程的數量
	 */
	private static int threadCount = 3;

	/**
	 * 每個下載區塊的大小
	 */
	private static long blocksize;

	/**
	 * 正在運行的線程的數量
	 */
	private static int runningThreadCount;

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		// 服務器文件的路徑
		String path = "http://192.168.1.100:8080/ff.exe";
		URL url = new URL(path);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setRequestMethod("GET");
		conn.setConnectTimeout(5000);
		int code = conn.getResponseCode();
		if (code == 200) {
			long size = conn.getContentLength();// 得到服務端返回的文件的大小
			System.out.println("服務器文件的大小:" + size);
			blocksize = size / threadCount;
			// 1.首先在本地創建一個大小跟服務器一模一樣的空白文件。
			File file = new File("temp.exe");
			RandomAccessFile raf = new RandomAccessFile(file, "rw");
			raf.setLength(size);
			// 2.開啟若干個子線程分別去下載對應的資源。
			runningThreadCount = threadCount;
			for (int i = 1; i <= threadCount; i++) {
				long startIndex = (i - 1) * blocksize;
				long endIndex = i * blocksize - 1;
				if (i == threadCount) {
					// 最後一個線程
					endIndex = size - 1;
				}
				System.out.println("開啟線程:" + i + "下載的位置:" + startIndex + "~"
						+ endIndex);
				new DownloadThread(path, i, startIndex, endIndex).start();
			}
		}
		conn.disconnect();
	}

	private static class DownloadThread extends Thread {
		private int threadId;
		private long startIndex;
		private long endIndex;
		private String path;

		public DownloadThread(String path, int threadId, long startIndex,
				long endIndex) {
			this.path = path;
			this.threadId = threadId;
			this.startIndex = startIndex;
			this.endIndex = endIndex;
		}

		@Override
		public void run() {
			try {
				// 當前線程下載的總大小
				int total = 0;
				File positionFile = new File(threadId + ".txt");
				URL url = new URL(path);
				HttpURLConnection conn = (HttpURLConnection) url
						.openConnection();
				conn.setRequestMethod("GET");
				// 接著從上一次的位置繼續下載數據
				if (positionFile.exists() && positionFile.length() > 0) {// 判斷是否有記錄
					FileInputStream fis = new FileInputStream(positionFile);
					BufferedReader br = new BufferedReader(
							new InputStreamReader(fis));
					// 獲取當前線程上次下載的總大小是多少
					String lasttotalstr = br.readLine();
					int lastTotal = Integer.valueOf(lasttotalstr);
					System.out.println("上次線程" + threadId + "下載的總大小:"
							+ lastTotal);
					startIndex += lastTotal;
					total += lastTotal;// 加上上次下載的總大小。
					fis.close();
				}

				conn.setRequestProperty("Range", "bytes=" + startIndex + "-"
						+ endIndex);
				conn.setConnectTimeout(5000);
				int code = conn.getResponseCode();
				System.out.println("code=" + code);
				InputStream is = conn.getInputStream();
				File file = new File("temp.exe");
				RandomAccessFile raf = new RandomAccessFile(file, "rw");
				// 指定文件開始寫的位置。
				raf.seek(startIndex);
				System.out.println("第" + threadId + "個線程:寫文件的開始位置:"
						+ String.valueOf(startIndex));
				int len = 0;
				byte[] buffer = new byte[512];
				while ((len = is.read(buffer)) != -1) {
					RandomAccessFile rf = new RandomAccessFile(positionFile,
							"rwd");
					raf.write(buffer, 0, len);
					total += len;
					rf.write(String.valueOf(total).getBytes());
					rf.close();
				}
				is.close();
				raf.close();

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				// 只有所有的線程都下載完畢後 才可以刪除記錄文件。
				synchronized (MutileThreadDownload.class) {
					System.out.println("線程" + threadId + "下載完畢了");
					runningThreadCount--;
					if (runningThreadCount < 1) {
						System.out.println("所有的線程都工作完畢了。刪除臨時記錄的文件");
						for (int i = 1; i <= threadCount; i++) {
							File f = new File(i + ".txt");
							System.out.println(f.delete());
						}
					}
				}

			}
		}
	}
}

 

多線程斷點下載的原理

 

同上

多線程斷點下載的移植

\

 




    
    
    

    
        
            
                

                
            
        
    



    

    

    

    

 

pb.xml



package com.itheima.mutilethread;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;

public class MainActivity extends Activity {
	protected static final int DOWNLOAD_ERROR = 1;
	private static final int THREAD_ERROR = 2;
	public static final int DWONLOAD_FINISH = 3;
	private EditText et_path;
	private EditText et_count;
	/**
	 * 存放進度條的布局
	 */
	private LinearLayout ll_container;
	
	/**
	 * 進度條的集合
	 */
	private List pbs;
	
	/**
	 * android下的消息處理器,在主線程創建,才可以更新ui
	 */
	private Handler handler = new Handler(){
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case DOWNLOAD_ERROR:
				Toast.makeText(getApplicationContext(), "下載失敗", 0).show();
				break;
			case THREAD_ERROR:
				Toast.makeText(getApplicationContext(), "下載失敗,請重試", 0).show();
				break;
			case DWONLOAD_FINISH:
				Toast.makeText(getApplicationContext(), "下載完成", 0).show();
				break;
			}
		};
	};
	
	/**
	 * 線程的數量
	 */
	private int threadCount = 3;

	/**
	 * 每個下載區塊的大小
	 */
	private long blocksize;

	/**
	 * 正在運行的線程的數量
	 */
	private  int runningThreadCount;


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		et_path = (EditText) findViewById(R.id.et_path);
		et_count = (EditText) findViewById(R.id.et_count);
		ll_container = (LinearLayout) findViewById(R.id.ll_container);
	}

	/**
	 * 下載按鈕的點擊事件
	 * @param view
	 */
	public void downLoad(View view){
		//下載文件的路徑
		final String path = et_path.getText().toString().trim();
		if(TextUtils.isEmpty(path)){
			Toast.makeText(this, "對不起下載路徑不能為空", 0).show();
			return;
		}
		String count = et_count.getText().toString().trim();
		if(TextUtils.isEmpty(path)){
			Toast.makeText(this, "對不起,線程數量不能為空", 0).show();
			return;
		}
		threadCount = Integer.parseInt(count);
		//清空掉舊的進度條
		ll_container.removeAllViews();
		//在界面裡面添加count個進度條
		pbs = new ArrayList();
		for(int j=0;j 0) {// 判斷是否有記錄
					FileInputStream fis = new FileInputStream(positionFile);
					BufferedReader br = new BufferedReader(
							new InputStreamReader(fis));
					// 獲取當前線程上次下載的總大小是多少
					String lasttotalstr = br.readLine();
					int lastTotal = Integer.valueOf(lasttotalstr);
					System.out.println("上次線程" + threadId + "下載的總大小:"
							+ lastTotal);
					startIndex += lastTotal;
					total += lastTotal;// 加上上次下載的總大小。
					fis.close();
					//存數據庫。
					//_id path threadid total
				}

				conn.setRequestProperty("Range", "bytes=" + startIndex + "-"
						+ endIndex);
			
				conn.setConnectTimeout(5000);
				int code = conn.getResponseCode();
				System.out.println("code=" + code);
				InputStream is = conn.getInputStream();
				File file = new File(Environment.getExternalStorageDirectory(),getFileName(path));
				RandomAccessFile raf = new RandomAccessFile(file, "rw");
				// 指定文件開始寫的位置。
				raf.seek(startIndex);
				System.out.println("第" + threadId + "個線程:寫文件的開始位置:"
						+ String.valueOf(startIndex));
				int len = 0;
				byte[] buffer = new byte[1024];
				while ((len = is.read(buffer)) != -1) {
					RandomAccessFile rf = new RandomAccessFile(positionFile,
							"rwd");
					raf.write(buffer, 0, len);
					total += len;
					rf.write(String.valueOf(total).getBytes());
					rf.close();
					pbs.get(threadId-1).setProgress(total);
				}
				is.close();
				raf.close();

			} catch (Exception e) {
				e.printStackTrace();
				Message msg = Message.obtain();
				msg.what = THREAD_ERROR;
				handler.sendMessage(msg);
			} finally {
				// 只有所有的線程都下載完畢後 才可以刪除記錄文件。
				synchronized (MainActivity.class) {
					System.out.println("線程" + threadId + "下載完畢了");
					runningThreadCount--;
					if (runningThreadCount < 1) {
						System.out.println("所有的線程都工作完畢了。刪除臨時記錄的文件");
						for (int i = 1; i <= threadCount; i++) {
							File f = new File(Environment.getExternalStorageDirectory(),getFileName(path)+ i + ".txt");
							System.out.println(f.delete());
						}
						Message msg = Message.obtain();
						msg.what = DWONLOAD_FINISH;
						handler.sendMessage(msg);
					}
				}

			}
		}
	}
	//http://192.168.1.100:8080/aa.exe
	private String getFileName(String path){
		int start = path.lastIndexOf("/")+1;
		return path.substring(start);
	}
	
}

開源項目xutils

xUtils-master.zip

\

 



    

 

xUtils-2.4.7.jar

package com.itheima.download2;

import java.io.File;

import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.HttpHandler;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;

public class MainActivity extends Activity {
	private EditText et_path;
	private TextView tv_info;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		et_path = (EditText) findViewById(R.id.et_path);
		tv_info = (TextView) findViewById(R.id.tv_info);
	}

	public void download(View view) {
		String path = et_path.getText().toString().trim();
		if (TextUtils.isEmpty(path)) {
			Toast.makeText(this, "請輸入下載的路徑", 0).show();
			return;
		} else {
			HttpUtils http = new HttpUtils();
			HttpHandler handler = http.download(path, "/sdcard/abc.mp3", true, // 如果目標文件存在,接著未完成的部分繼續下載。服務器不支持RANGE時將從新下載。
					true, // 如果從請求返回信息中獲取到文件名,下載完成後自動重命名。
					new RequestCallBack() {

						@Override
						public void onStart() {
							tv_info.setText("conn...");
						}

						@Override
						public void onLoading(long total, long current,
								boolean isUploading) {
							tv_info.setText(current + "/" + total);
						}

						@Override
						public void onSuccess(ResponseInfo responseInfo) {
							tv_info.setText("downloaded:"
									+ responseInfo.result.getPath());
						}

						@Override
						public void onFailure(HttpException error, String msg) {
							tv_info.setText(msg);
						}
					});
		}
	}
}

顯示意圖

人品計算器的案例

隱式意圖




    

    
        
            
                

                
            
        
        
            
                

                

                
                
            
     
        
    




    

package com.itheima.intent2;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	public void click(View view) {
		// 打 action
		// 人 數據
		// 附件的數據 Category 類別
		Intent intent = new Intent();
		intent.setAction("com.itheima.intent2.open2");
		intent.addCategory(Intent.CATEGORY_DEFAULT);

		// URL:統一資源定位符 http https ftp rtsp: URI:統一資源標識符 url是uri的一個子集
		// intent.setData(Uri.parse("jianren:張三"));
		// intent.setType("application/person");
		intent.setDataAndType(Uri.parse("jianren:張三"), "application/person");
		startActivity(intent);
	}
}
package com.itheima.intent2;

import android.app.Activity;
import android.os.Bundle;

public class SecondActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_second);
	}
}

打開浏覽器

\

 




    

    
        
            
                

                
            
        
    

package com.itheima.openbrowser;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}

	
	
	public void click(View view){
//        
//        
//        
//        
//        
//        
//        
		Intent intent = new Intent();
		intent.setAction("android.intent.action.VIEW");
		intent.addCategory("android.intent.category.DEFAULT");
		intent.addCategory("android.intent.category.BROWSABLE");
		intent.setData(Uri.parse("http://www.baidu.com"));
		startActivity(intent);
	}

}

 

人品計算器




    

    
        
            
                

                
            
        
        
        
    



    

package com.itheima.rpcalc;

import java.util.Random;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class CalcActivity extends Activity {
	private TextView tv_result;

	//當activity被創建的時候調用的方法
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_calc);
		tv_result = (TextView) findViewById(R.id.tv_result);
		Intent intent = getIntent();
		String name = intent.getStringExtra("name");
		byte[] result = name.getBytes();
		int number = 0;
		for(byte b :result){
			 number += b&0xff;
		}
		int sorce = Math.abs(number)%100;
		tv_result.setText(name+"的人品:"+sorce);
	}
}
package com.itheima.rpcalc;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
	private EditText et_name;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		et_name = (EditText) findViewById(R.id.et_name);
	}
	
	
	//顯式意圖  :必須指定要激活的組件的完整包名和類名 (應用程序之間耦合在一起)
	// 一般激活自己應用的組件的時候 采用顯示意圖
	
	//隱式意圖: 只需要指定要動作和數據就可以 ( 好處應用程序之間沒有耦合)
	//激活別人寫的應用  隱式意圖, 不需要關心對方的包名和類名
	
	
	
	public void enter(View view){
		String name = et_name.getText().toString().trim();
		if(TextUtils.isEmpty(name)){
			Toast.makeText(this, "請輸入姓名", 0).show();
			return;
		}
		//意圖     開電視  打人  打醬油
		Intent intent = new Intent(this, CalcActivity.class);
		intent.putExtra("name", name);
		//顯式意圖
		//intent.setClassName(getPackageName(), "com.itheima.rpcalc.CalcActivity");//不指定動作,也不指定數據 直接指定要激活的組件
		startActivity(intent);
		//隱式意圖
		//intent.setAction(action);
		//intent.setData(data);
	}
}

開啟activity獲取返回值

\

 

 




    
    

    
        
            
                

                
            
        
        
        
         
        
    

 

sms_item.xml




    

activity_sms.xml




    
    

activity_main.xml



    

    
package com.itheima.smshelper;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class ListNumberActivity extends Activity {
	private ListView lv;
	private String[] objects = {
			"1234","34324","5643543","32424" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_sms);
		lv = (ListView) findViewById(R.id.lv);
		lv.setAdapter(new ArrayAdapter(this, R.layout.sms_item,
				R.id.tv_info, objects));
		
		lv.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView parent, View view,
					int position, long id) {
				String smsinfo = objects[position];
				Intent data = new Intent();
				data.putExtra("smsinfo", smsinfo);
				//設置數據。
				setResult(1, data);
				//關閉掉當前的activity,並且回傳數據 onActivityResult().
				finish();
			}
		});
	}
}
package com.itheima.smshelper;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class ListSmsActivity extends Activity {
	private ListView lv;
	private String[] objects = {
			"玫瑰香香,情人黏黏,情話甜甜,情歌綿綿;花燈燦燦,禮花點點,好運連連,好夢圓圓。情人節喜逢元宵節,喜鵲登枝蝴蝶成雙鴛鴦成對雙喜臨門祝雙節快樂,合家團團圓圓,甜甜蜜蜜,開開心心,幸幸福福",
			"情人節快到了,我精心挑選玫瑰花、百合花和滿天星,扎成一束鮮花隨短信送給你,火紅的玫瑰代表熱烈奔放,潔白的百合代表百年好合,小小的滿天星代表幸福美好。願你的情人節熱烈奔放,你們的愛情百年好合,你們的生活幸福美滿。預祝情人節快樂",
			"^o^滿天星光,最愛你許過願望的那一顆,鮮花綻放,最愛你摘下微笑的那一朵,曼妙旋律,最愛你感動落淚的那一段,親愛的,情人節快樂,愛你。 ",
			"^o^寶貝,情人節到了,送你一束玫瑰,用真心塑料紙包扎,系上快樂彩帶,噴點愛的香水,插一張真情卡片,寫著:寶貝,願我的愛能帶給你一生的快樂!" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_sms);
		lv = (ListView) findViewById(R.id.lv);
		lv.setAdapter(new ArrayAdapter(this, R.layout.sms_item,
				R.id.tv_info, objects));
		
		lv.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView parent, View view,
					int position, long id) {
				String smsinfo = objects[position];
				Intent data = new Intent();
				data.putExtra("smsinfo", smsinfo);
				//設置數據。
				setResult(0, data);
				//關閉掉當前的activity,並且回傳數據 onActivityResult().
				finish();
			}
		});
	}
}
package com.itheima.smshelper;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {
	private EditText et_content;
	private EditText et_number;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		et_content = (EditText) findViewById(R.id.et_content);
		et_number = (EditText) findViewById(R.id.et_number);
	}

	public void selectSms(View view) {
		Intent intent = new Intent(this, ListSmsActivity.class);
		// 開啟一個新的界面,並且獲取界面的返回值
		// startActivity(intent);
		// int requestCode 請求碼
		startActivityForResult(intent, 0);
	}

	public void selectNumber(View view) {
		Intent intent = new Intent(this, ListNumberActivity.class);
		// 開啟一個新的界面,並且獲取界面的返回值
		// startActivity(intent);
		// int requestCode 請求碼
		startActivityForResult(intent, 1);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (data != null) {
			String smsinfo = data.getStringExtra("smsinfo");
			if (resultCode == 0) {
				et_content.setText(smsinfo);
			} else if (resultCode == 1) {
				et_number.setText(smsinfo);
			}
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	
	public void sendSms(View view){
		String content = et_content.getText().toString().trim();
		String number = et_number.getText().toString().trim();
		SmsManager.getDefault().sendTextMessage(number, null, content, null, null);
		Toast.makeText(this, "發送成功", 0).show();
	}
}

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved