今天做了自動更新功能,現在把趟過的坑介紹一下:
自動更新步驟:獲取當前版本號,然後去和服務器版本號對比,如果不一樣就說明有升級,提示用戶升級,用戶點擊確定後自動後臺下載新APK並且安裝。聽起來是不是很簡單?做起來也很簡單,只是有一些坑而已。
我是在LoginActivity()中寫的自動更新功能,在用戶準備登陸時判斷一下是否有新版本,如果有的話就自動更新(我做的是強制性更新),沒有不做處理,當然可以有更人性化的處理,給用戶選擇是否升級的權利
private int versionCode;//當前版本號
private String version_info;//版本信息
private Context mContext;
private int version_netcode;//服務端當前版本號
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); initView(); mContext = this; Log.e("tag", "11111111111111111111111"); // 獲取當前版本號 try { getVersonCode();// } catch (Exception e) { e.printStackTrace(); } //獲取服務端的版本號 getNetVersonCode();// } /** * 獲取當前程序版本號// * * @return * @throws Exception */ private int getVersonCode() throws Exception { PackageManager packageManager = getPackageManager(); //getPackageName()是你當前類的包名,0代表是獲取版本信息 PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0); versionCode = packageInfo.versionCode;
Log.e(“TTTTTTT”, versionCode + “”);
return versionCode;
}
/**
* 獲取服務端的版本號
*/
private void getNetVersonCode() {
String url = "http://crm.taxchina.com/wcm/inside/gkk/interface/AndroidUpdate.aspx ";//各自公司後臺提供,裏面存儲APK基本信息
OkHttpUtils
.get()
.url(url)
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e) {
}
@Override
public void onResponse(String response) {
//請求網絡成功解析數據
Log.e("888888888888888888888", "聯網成功");
processData(response);
}
});
}
private void processData(String response) {
VersonModel versonModel = new Gson().fromJson(response, VersonModel.class);
version_netcode = Integer.parseInt(String.valueOf(versonModel.getVersion_code()));
version_info = versonModel.getVersion_info();
Log.e("tttttt", version_netcode + "");
//比較兩個版本是否一致
CheckVersionTask();
}
private void CheckVersionTask() {
if (versionCode == version_netcode) {
Log.e("tagggggg", "版本號相同無需升級");
} else {
//提示用戶升級
Message msg = Message.obtain();
msg.what = UPDATA_CLIENT;
handler.sendMessage(msg);
}
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case UPDATA_CLIENT:
//提示用戶升級的對話框
showUpdataDialog();
break;
}
}
};
private void showUpdataDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("版本升級");
builder.setMessage(version_info);
//用戶點擊確定按鈕下載新的apk
builder.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.e("tag000000000", "下載apk,更新");
downLoadApk();
}
});
builder.show();
}
/**
* 從服務器中下載apk
*/
private void downLoadApk() {
final String path = "http://crm.taxchina.com/wcm/resource/UploadApk/taxSign.apk";//下載APK的路徑也是公司後臺服務端給接口
final ProgressDialog pd;
pd = new ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("正在下載更新");
pd.show();
new Thread() {
@Override
public void run() {
super.run();
//下載安裝apk
try {
Utils.getFileFromServer(mContext,path,pd);*強調內容*重點內容**
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
//下面放上utils工具包代碼,也是核心代碼
/**
* 從服務器下載apk:
*
* @param context
* @param path
* @param pd
* @throws Exception
*/
public static void getFileFromServer(Context context, String path,
ProgressDialog pd) throws Exception {
String downloadPath = Environment.getExternalStorageDirectory()
.getPath() + "/download_cache";
File file = new File(downloadPath);
if (!file.exists())
file.mkdir();
URL url = new URL(path);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(5 * 1000);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
try {
if (urlConnection.getResponseCode() == 200) {
InputStream is = urlConnection.getInputStream();
// 開始下載apk文件
FileOutputStream fos = new FileOutputStream(downloadPath
+ "/action.apk");
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[5120];
int total = 0;
int count = 0;
while ((count = bis.read(buffer)) != -1) {
fos.write(buffer, 0, count);
total += count;
// 獲取當前下載量
pd.setProgress(total);
}
fos.close();
bis.close();
is.close();
urlConnection.disconnect();
pd.dismiss();
// 安裝 apk 文件
installApk(context, downloadPath + "/action.apk");
}
} catch (Exception e) {
pd.dismiss();
}
}
/**
* 安裝apk
*
* @param context
* @param filename
*/
protected static void installApk(Context context, String filename) {
File file = new File(filename);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW); // 瀏覽網頁的Action(動作)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
String type = "application/vnd.android.package-archive";
intent.setDataAndType(Uri.fromFile(file), type); // 設置數據類型
context.startActivity(intent);
}
好了,到此爲止自動更新功能就添加完成了,就會自動下載安裝了。
此處有兩個坑:1、 String type = “application/vnd.android.package-archive”; android必須都是小寫
2、 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);加上此句纔會有安裝運行新應用窗口提示
最後一個大坑是用真機測試的時候,卻提示“未安裝應用程序”。
說明:這裏的要升級的文件已經正常下載到手機上了,權限也都加好了。
產生這種現象的原因就是:手機上已經安裝好的apk和正在安裝的apk包名都是一樣的,可是簽名不一樣,所以它會提示你安裝不成功。在服務器上的升級包是做好籤名的,而我在測試的時候是用真機測試的,也就是說電腦上的android程序直接運行在了手機上,而沒有經過打包簽名,最後導致的結果就是文件正常下載到手機上,可是安裝不成功。
其實解決方法也很簡單了:把簽名的安裝包安裝到手機上,再測試升級的功能,這樣就沒有問題了。
這是我的一些個人理解,由於水平有限,如果有問題我會及時改正,歡迎大家指正錯誤。