Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android實現在線更新的過程案例

Android實現在線更新的過程案例

編輯:關於Android編程

一、更新軟件的准備
在線更新軟件的話需要我們有簽名的應用,我們需要把簽過名之後的軟件放入到服務器中,我的如下:
這裡寫圖片描述
其中apk是有簽名的更新版本!
updateinfo.html代碼如下:

{version:2.0,description:有全新版本,請下載!,apkurl:hhtp://172.23.252.89:8080/MobileSafe2.0.apk}

二、具體客戶端軟件的實現

項目結構如下:

這裡寫圖片描述

主要的業務邏輯在這裡SplashActivity.java<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;"> package com.xuliugen.mobilesafe; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import net.tsz.afinal.FinalHttp; import net.tsz.afinal.http.AjaxCallBack; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.Intent; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.animation.AlphaAnimation; import android.widget.TextView; import android.widget.Toast; /** * splash界面的作用 * 1、用來展現產品的Logo; * 2、應用程序初始化的操作; * 3、檢查應用程序的版本; * 4、檢查當前應用程序是否合法注冊; * * * 更新安裝的話要使用簽名 * @author xuliugen * */ public class SplashActivity extends Activity { protected static final int SHOW_UPDATE_DIALOG = 0; protected static final int ENTER_HOME = 1; protected static final int URL_ERROR = 2; protected static final int NETWORK_ERROR = 3; protected static final int JSON_ERROR = 40; private TextView tv_splash_version; private TextView tv_update_info;//升級進度 private String description;// 版本信息的描述 private String apkurl;// 版本更新的地址 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); tv_splash_version = (TextView) this.findViewById(R.id.tv_splash_version); tv_update_info = (TextView) findViewById(R.id.tv_update_info); tv_splash_version.setText(版本號: + getVersionName()); // 檢查更新 checkUpdate(); // 設置動畫 AlphaAnimation alphaAnimation = new AlphaAnimation(0.2f, 1.0f); alphaAnimation.setDuration(3000);// 設置動畫的時長 //執行動畫 findViewById(R.id.rl_root_splash).startAnimation(alphaAnimation); } /** * 由於更新界面是在主線程中操作 * * 所以可以使用handler,當子線程中運行結束的時候們可以通知主線程進行相關的操作 */ private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); //得到handler發送的message消息進行處理 switch (msg.what) { case SHOW_UPDATE_DIALOG:// 顯示升級的對話框 showUpdateDialog(); break; case ENTER_HOME:// 進入主頁面 enterHome(); break; case URL_ERROR:// URL錯誤 enterHome(); Toast.makeText(getApplicationContext(), URL錯誤, 0).show(); break; case NETWORK_ERROR:// 網絡異常 enterHome(); Toast.makeText(SplashActivity.this, 網絡異常, 0).show(); break; case JSON_ERROR:// JSON解析出錯 enterHome(); Toast.makeText(SplashActivity.this, JSON解析出錯, 0).show(); break; default: break; } } }; /** * 檢查是否有新版本 * * 需要請求網絡,一般在子線程中使用 */ private void checkUpdate() { new Thread() { public void run() { // URL:http://172.23.252.89:8080/updateinfo.json Message message = Message.obtain();// 得到一個存在的信息,用於存放更新的信息 long startTime = System.currentTimeMillis(); try { URL url = new URL(getString(R.string.serverurl)); //URL url = new URL(http://172.23.252.89:8080/updateinfo.json); // 聯網操作 HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod(GET);//設置請求方式 httpURLConnection.setConnectTimeout(4000);//設置超時時間 int code = httpURLConnection.getResponseCode();// 獲得響應碼 if (code == 200) {// 成功 InputStream inputStream = httpURLConnection.getInputStream(); //把流轉換為一個String類型 ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while((len = inputStream.read(buffer))!=-1){ baos.write(buffer, 0, len); } inputStream.close(); String result = baos.toString();//得到string類型的數據 baos.close(); //因為得到的數據是一個json的string所以要json解析 JSONObject jsonObj = new JSONObject(result); //得到服務器的版本信息 String version = (String) jsonObj.get(version); description = (String) jsonObj.get(description); apkurl = (String) jsonObj.get(apkurl); //校驗是否有新版本 if (getVersionName().equals(version)) {// 版本一致,進入主界面 message.what = ENTER_HOME; } else {// 有新版本,彈出一個升級對話框 message.what = SHOW_UPDATE_DIALOG; } } } catch (MalformedURLException e) { message.what = URL_ERROR; e.printStackTrace(); } catch (IOException e) { message.what = NETWORK_ERROR; e.printStackTrace(); } catch (JSONException e) { message.what = JSON_ERROR; e.printStackTrace(); } finally { long endTime = System.currentTimeMillis(); long dTime = endTime-startTime;//花費的時間 //在界面中停留3秒 if(dTime < 3000){ try { Thread.sleep(3000-dTime); } catch (InterruptedException e) { e.printStackTrace(); } } handler.sendMessage(message);// 將消息發送出去 } } }.start(); } /** * 得到應用層序的版本名稱 * * @return */ private String getVersionName() { // 用於管理安裝的apk和未安裝的apk PackageManager packageManager = getPackageManager(); try { // 得到apk的功能清單文件:為了防止出錯直接使用getPackageName()方法獲得包名 // packageManager.getPackageInfo(com.xuliugen.mobilesafe, 0); PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0); //返回版本名稱 return packageInfo.versionName; } catch (NameNotFoundException e) { e.printStackTrace(); return ; } } /** * 彈出升級對話框 */ protected void showUpdateDialog() { AlertDialog.Builder builder = new Builder(this); builder.setTitle(提示升級); // builder.setCancelable(false);//強制升級:就是不讓用戶取消 builder.setMessage(description);//為dialog設置信息 builder.setOnCancelListener(new OnCancelListener() { // @Override public void onCancel(DialogInterface dialog) { // 進入主頁面 enterHome(); dialog.dismiss(); // 取消顯示對話框 } }); builder.setNegativeButton(下次再說, new OnClickListener() {// 取消 @Override public void onClick(DialogInterface dialog, int which) { // 進入主頁面 enterHome(); dialog.dismiss(); // 取消顯示對話框 } }); builder.setPositiveButton(立刻升級, new OnClickListener() {//確認 @Override public void onClick(DialogInterface dialog, int which) { // 下載APK,並且替換安裝 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {//得到sd卡的狀態 // sdcard存在 // 使用afnal下載apk文件 FinalHttp finalhttp = new FinalHttp(); // 得到sdcard路徑 String SDCARD_PATH = Environment .getExternalStorageDirectory() .getAbsolutePath() + /mobilesafe2.0.apk; finalhttp.download(apkurl, SDCARD_PATH, new AjaxCallBack() { @Override public void onFailure(Throwable t, int errorNo, String strMsg) { t.printStackTrace(); Toast.makeText(getApplicationContext(), 下載失敗, 1).show(); super.onFailure(t, errorNo, strMsg); } /** * count:為總的大小 * current:為當前下載的大小 */ @Override public void onLoading(long count, long current) {//正在下載 super.onLoading(count, current); tv_update_info.setVisibility(View.VISIBLE); //當前下載百分比 int progress = (int) (current * 100 / count); tv_update_info.setText(下載進度:+progress+%); } /** * file t:表示文件的路徑 */ @Override public void onSuccess(File t) { super.onSuccess(t); //成功的時候要安裝apk installAPK(t); } /** * 安裝APK * @param t :文件下載的路徑 */ private void installAPK(File t) { Intent intent = new Intent(); intent.setAction(android.intent.action.VIEW); intent.addCategory(android.intent.category.DEFAULT); intent.setDataAndType(Uri.fromFile(t), application/vnd.android.package-archive); startActivity(intent); } }); } else {// sdcard不存在 Toast.makeText(getApplicationContext(), 沒有sdcard,請安裝上在試,0).show(); return; } } }); builder.show(); } /** * 進入主界面 */ protected void enterHome() { Intent intent = new Intent(this, HomeActivity.class); startActivity(intent); // 關閉當前頁面 finish(); } }

其中使用的把流轉化為一個String類型的方法可以封裝為一個工具類:
StreamTools.java

package com.xuliugen.mobilesafe.utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 把流轉換為一個String類型
 * 
 * @author xuliugen
 * 
 */
public class StreamTools {
    /**
     * @param is  輸入流
     * @return String 返回的字符串
     * @throws IOException
     */
    public static String readFromStream(InputStream is) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1) {
            baos.write(buffer, 0, len);
        }
        is.close();
        String result = baos.toString();
        baos.close();
        return result;
    }
}

 

注意:我們的簽名一定要牢記,但是如果忘記也有方法解決:
(1)改簽名:這將無法覆蓋安裝,這是包名不變的情況,這就要求用戶先卸載以前的應用,體驗不佳!
(2)改包名:重新簽名,這就相當於手機安裝兩個應用,但是可以用技術卸載第一個應用。

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