.自動更新的功能在實際運用中還是比較常用到的。
本文參考了大神的博客,自己複製寫了一個,加上了些註釋,也許會更好理解吧。
原文地址:http://blog.csdn.net/Android_Tutor/article/details/7015986
首先需要獲得訪問網絡和讀寫的權限
請在AndroidManifest.xml 添加以下代碼
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
兩個XML文件main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical" android:id="@+id/layout">
<TextView android:text="下載功能演示" android:id="@+id/textView1"
android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
</LinearLayout>
updateprogress.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:text="正在下載,請稍等。。。" android:id="@+id/textView1"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#fff"></TextView>
<ProgressBar style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:id="@+id/progressBar1"></ProgressBar>
<TextView android:text="文件大小:" android:id="@+id/textView2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textColor="#fff"></TextView>
</LinearLayout>
兩個java文件
Hello_worldActivity.java
package com.ccav;
import com.fjep.R;
import android.app.Activity;
import android.os.Bundle;
public class Hello_worldActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
updateClass update=new updateClass(this);
update.checkUpdateInfo();
}
}
updateClass.javapackage com.ccav;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import com.fjep.R;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
public class updateClass {
private Context mContext;
private boolean flag = false;
private ProgressBar progressBar;
// 需要下載的APK文件地址
private String apkUrl = "http://shouji.360.cn/360safesis/360MobileSafe_3.1.0.apk";
// SD卡的文件夾位置
private static final String savePath = "/sdcard/updatedemo/";
// APK在SD卡中的路徑
private static final String saveFileName = savePath + "UpdateDemo.apk";
private int progress;
private static final int START = 1;
private static final int OVER = 0;
private int numread;
private Dialog downloadDialog;
private TextView textview;
// 構造函數
public updateClass(Context context) {
mContext = context;
}
// 檢查update,在實際運用中需要有版本的判斷,但是由於這個是基礎案例演示,就沒有寫更新的版本判斷代碼,直接調用更新提示框。
public void checkUpdateInfo() {
showDialog();
}
// 所謂的更新提示框
private void showDialog() {
AlertDialog.Builder builder = new Builder(mContext);
builder.setIcon(R.drawable.happy).setTitle("親,系統檢測到更新,是否要更新呢?")
.setMessage("點擊確定立刻升級")
.setPositiveButton("立馬更新", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
updateApk();
}
}).setNegativeButton("以後再說", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 讓提示框消失
dialog.dismiss();
}
}).create().show();
}
// 顯示點擊“立馬升級”之後顯示的對話框,顯示下載進度。
protected void updateApk() {
AlertDialog.Builder builder = new Builder(mContext);
// 由於進度條是在另一個xml文件中,所以需要通過inflater方法來加載這個layout文件
LayoutInflater layout = LayoutInflater.from(mContext);
View v = layout.inflate(R.layout.updateprogress, null);
// 利用findViewById的方法找到進度條的ID,爲後面的更新進度條做準備,這裏需要注意的是需要指定View,也就是v一定需要添加否則findViewById會報錯哦。
progressBar = (ProgressBar) v.findViewById(R.id.progressBar1);
textview = (TextView) v.findViewById(R.id.textView2);
builder.setTitle("正在更新文件").setView(v)
.setNegativeButton("取消更新", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 讓提示框消失
dialog.dismiss();
// flag是一個bool型變量,這裏起得作用是停止線程,因爲如果沒有停止線程,用戶點擊取消更新後,線程還在執行下載。
flag = true;
}
});
// 這裏可以直接使用.create().show()兩個方法來讓提示框顯示,這樣看上去代碼也會更加簡潔些,但是我們需要實現讓其下載完畢之後關閉顯示下載進度進度條的那個提示窗口功能。
downloadDialog = builder.create();
downloadDialog.show();
// 開始下載apk
downloadAPK();
}
private void downloadAPK() {
// 新建一個線程
new Thread(new Runnable() {
@Override
public void run() {
try {
// 將下載路徑賦值給url
URL url = new URL(apkUrl);
// http連接的方法
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.connect();
// 獲得需要下載的文件長度
int length = conn.getContentLength();
InputStream is = conn.getInputStream();
// 檢查文件夾是否存在,不存在就創建該文件夾
File file = new File(savePath);
if (!file.exists()) {
file.mkdir();
}
FileOutputStream fos = new FileOutputStream(saveFileName);
int count = 0;
// 緩衝大小1024比較科學,如果太小下載速度很慢,即使你網速很快。
byte buf[] = new byte[1024];
do {
numread = is.read(buf);
count += numread;
// 這裏獲取進度條的進度,注意值的轉換。
progress = (int) (((float) count / length) * 100);
// 發送消息讓線程開始工作
myHandler.sendEmptyMessage(START);
if (numread <= 0) {
myHandler.sendEmptyMessage(OVER);
break;
}
// 寫入APK文件
fos.write(buf, 0, numread);
} while (!flag);// 這裏注意flag,是在flag不爲true的情況下執行while循環。之前使用flag是在用戶點擊取消按鈕的時候將flag設置爲true,這樣這個循環就被停止了,也就是線程不在發送消息給handler,同時也停止了下載工作
// 輸入輸出用完記得要關閉哦
fos.close();
is.close();
} catch (Exception e) {
Log.i("Fover", e.toString());
}
}
}).start();// 這裏要記得start讓線程開始工作
}
// Handler用於更新UI
private Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case START:
// 更新進度條的值
progressBar.setProgress(progress);
// 顯示完成度
textview.setText("已完成" + progress + "%");
break;
case OVER:
// 讓下載對話框消失
downloadDialog.dismiss();
// 安裝下載好的APK文件
installApk();
break;
default:
break;
}
}
};
protected void installApk() {
// 如果這apk文件不存在,直接返回不執行後面的代碼
File file = new File(saveFileName);
if (!file.exists()) {
return;
}
// 利用intent來啓動安裝
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(Uri.parse("file://" + saveFileName.toString()),
"application/vnd.android.package-archive");
mContext.startActivity(i);
}
}
直接複製代碼的同學,請注意R文件要和自己包裏面的相同哦,要不然會報錯。運行截圖:
PS我不是360的託,隨便找個APK的地址文件。將就着用了。