安卓使用http下載文件

在安卓中,可以直接用java的java.net.URL包訪問網絡下載數據。不同的是,安卓程序需要權限,需要在AndroidManifest.xml文件中聲明權限

 <!-- 網絡權限 -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- 操作sd卡權限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

不過有個需要注意的是,我使用的是最新的adt安卓開發集成eclipse的安裝包,在使用網絡服務的時候,處理網絡請求的代碼,不能在主線程中進行,不然安卓會提示錯誤。

但是,有些組件設置值,他必須是在主線程的循環中,纔可以。

Looper loop = Looper.getMainLooper();
handler = new Handler(loop){
	@Override
	public void handleMessage(Message msg) {
		// TODO Auto-generated method stub
		super.handleMessage(msg);
		switch (msg.what) {
			case SETTEXT:
				//主線程ui更新text值
				text.setText(msg.obj.toString());
				break;
		}
	}
};
		
download.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View arg0) {
		//新線程下載
		new Thread(new Runnable() {
			@Override
			public void run() {
				//新建一個下載
				Download load = new Download(url);
				String value = load.downloadAsString();
				Message msg = handler.obtainMessage();
				msg.obj = value;
				msg.what = SETTEXT;
				msg.sendToTarget();
			}
		}).start();
	}
});

Download類:

package com.example.org.suju.download;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import android.os.Environment;
import android.util.Log;


public class Download {
	/** 連接url */
	private String urlstr;
	/** sd卡目錄路徑 */
	private String sdcard;
	/** http連接管理類 */
	private HttpURLConnection urlcon;
	
	public Download(String url)
	{
		this.urlstr = url;
		//獲取設備sd卡目錄
		this.sdcard = Environment.getExternalStorageDirectory() + "/";
		urlcon = getConnection();
	}
	
	/*
	 * 讀取網絡文本
	 */
	public String downloadAsString()
	{
		StringBuilder sb = new StringBuilder();
		String temp = null;
		try {
			InputStream is = urlcon.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			while ((temp = br.readLine()) != null) {
				sb.append(temp);
			}
			br.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sb.toString();
	}
	
	/*
	 * 獲取http連接處理類HttpURLConnection
	 */
	private HttpURLConnection getConnection()
	{
		URL url;
		HttpURLConnection urlcon = null;
		try {
			url = new URL(urlstr);
			urlcon = (HttpURLConnection) url.openConnection();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return urlcon;
	}
	
	/*
	 * 獲取連接文件長度。
	 */
	public int getLength()
	{
		return urlcon.getContentLength();
	}
	
	/*
	 * 寫文件到sd卡 demo
	 * 前提需要設置模擬器sd卡容量,否則會引發EACCES異常
	 * 先創建文件夾,在創建文件
	 */
	public int down2sd(String dir, String filename, downhandler handler)
	{
		StringBuilder sb = new StringBuilder(sdcard)
							.append(dir);
		File file = new File(sb.toString());
		if (!file.exists()) {
			file.mkdirs();
			//創建文件夾
			Log.d("log", sb.toString());
		}
		//獲取文件全名
		sb.append(filename);
		file = new File(sb.toString());
		
		FileOutputStream fos = null;
		try {
			InputStream is = urlcon.getInputStream();
			//創建文件
			file.createNewFile();
			fos = new FileOutputStream(file);
			byte[] buf = new byte[1024];
			while ((is.read(buf)) != -1) {
				fos.write(buf);
				//同步更新數據
				handler.setSize(buf.length);
			}
			is.close();
		} catch (Exception e) {
			return 0;
		} finally {
			try {
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return 1;
	}
	
	/*
	 * 內部回調接口類
	 */
	public abstract class downhandler
	{
		public abstract void setSize(int size);
	}
}

線程下載提示Activity:

用一個線程循環處理網絡下載,並使用下載類回調函數,發送處理消息給主線程消息處理方法,同步更新滾動條值。

        @Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.download);
		
		text = (TextView) findViewById(R.id.label);
		load = (ProgressBar) findViewById(R.id.load);

		//獲取傳遞的Intent的Bundle的url鍵值
		final String url = getIntent().getExtras().getString("url");
		
		final Handler handler = new Handler(){
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				//這裏就一條消息
				int pro = load.getProgress() + msg.arg1;
				load.setProgress(pro);
				text.setText(Integer.toString(pro));
				if (pro >= load.getMax()) {
					finish();	//結束下載進度框
				}
			}
		};

		new Thread(new Runnable() {
			@Override
			public void run() {
				//另起線程執行下載,安卓最新sdk規範,網絡操作不能再主線程。
				Download l = new Download(url);
				load.setMax(l.getLength());
				
				/**
				 * 下載文件到sd卡,虛擬設備必須要開始設置sd卡容量
				 * downhandler是Download的內部類,作爲回調接口實時顯示下載數據
				 */
				int status = l.down2sd("downtemp/", "1.ddd", l.new downhandler() {
					@Override
					public void setSize(int size) {
						Message msg = handler.obtainMessage();
						msg.arg1 = size;
						msg.sendToTarget();
						Log.d("log", Integer.toString(size));
					}
				});
				//log輸出
				Log.d("log", Integer.toString(status));
				
			}
		}).start();
	}


對話框模式的Activity需要設置一個屬性android:theme。

<activity 
android:name="com.example.org.suju.download.DownloadActivity"
android:theme="@android:style/Theme.Dialog"
            ></activity>

使用一個按鈕啓動下載對話框Activity,並傳遞數據

down2sd.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View arg0) {
		Intent intent = new Intent();
		intent.setClass(MainActivity.this, DownloadActivity.class);
		Bundle bundle = new Bundle();
		bundle.putString("url", urlstr.getText().toString());
		intent.putExtras(bundle);
		startActivity(intent);
	}
});


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章