|   廣大博友,看過后幫忙頂頂,謝謝大家?。?!   轉(zhuǎn)載請注明: http://blog.csdn.net/richway2010/article/details/6408258 【博主:各位博友,網(wǎng)友們,大家網(wǎng)上好!歡迎光臨本博客。 歡迎多多交流,多提意見,互相學(xué)習(xí),互相進(jìn)步,我們的口號是:好好學(xué)習(xí),天天向上?!? 下面就如何對Android 手機上的應(yīng)用進(jìn)行升級相關(guān)知識的講解: 一、原理及要點概述:手機軟件一般在運行時會把服務(wù)端的版本信息和當(dāng)前手機中的版本進(jìn)行比較。從而得知需不需要更新。Android上推介版本比較更新這種方式。 如果服務(wù)器端有新版本,我們需要先下載這個APK到我們的sdcard中,然后對其進(jìn)行安裝。 我們一定要保證每次安裝的keystore密鑰文件是相同的。這樣Android手機才會提醒你替換新版本。 Android區(qū)分軟件的不同是通過包名,身份的認(rèn)證是通過簽名。只有相同簽名的APK才可以安裝。不然安裝就會失敗。 
 注:如果你每次發(fā)布APK文件時都新建一個key文件會導(dǎo)致無法正確安裝,我們必須先卸載老的版本才能執(zhí)行新版本安裝。這樣你就必須要通知每個客戶去把軟件卸載后重新下載安裝。  二、接下來具體介紹一下升級步驟:簽名步驟流程講一下,很多初學(xué)者不是很清楚或容易犯錯: 
 簽名的作用: 是為了保證每個應(yīng)用程序開發(fā)商合法ID,防止部分開放商可能通過使用相同的Package Name來混淆替換已經(jīng)安裝的程序,我們需要對我們發(fā)布的APK文件進(jìn)行唯一簽名,保證我們每次發(fā)布的版本的一致性(如自動更新不會因為版本不一致而無法安裝)。 首先eclipse如圖所示打開:  
 然后設(shè)置APK名稱,一般默認(rèn)項目名稱:  
 點擊下一步,新建一個keys,輸入密鑰,:  
 注:這個密鑰很重要,每次升級都需要使用到。忘記密鑰也只能是重新生成。從而會引發(fā)后面升級的一系列問題。  下一步如圖,設(shè)置別名,組織機構(gòu)等等基本信息,根據(jù)具體情況:  
 下一步如圖選擇保存的APK目錄:  
 至此apk和密鑰文件生成完畢:  
 接下來,當(dāng)程序需要改變,我們?nèi)绾未虬堿PK文件: 第一步和上面一樣,從第二步開始講解: 注:一定要使用現(xiàn)有的密鑰,輸入之前設(shè)置的密碼,不然安裝APK將不被覆蓋。   
 下一步如圖,輸入密碼:  
 然后下一步,F(xiàn)inish掉。 至此APK升級文件創(chuàng)建好。 三、服務(wù)器端和客戶端設(shè)計服務(wù)器端設(shè)計: 
 設(shè)計方法應(yīng)該有很多,下面介紹我的一種方法: a.首先在服務(wù)器項目下建立一個文件夾來存放APK安裝文件: b.其次在src下建立一個資源文件,apkVersion.properties,屬性定義如下: 
 apkVersion=1 存版本號apkSize=550kb 大小apkPath=http://xx8080/srv/apk/Demo.apk 升級文件  
定義類:UpdateApkServlet.java  //獲取資源文件信息  static {  Properties ppt = new Properties();  try {           ppt.load(UpdateApkServlet.class .getResourceAsStream("/apkVersion.properties"));           apkVersion = ppt.getProperty("apkVersion");           apkSize = ppt.getProperty("apkSize");           apkPath = ppt.getProperty("apkPath");   }catch (Exception e) {           e.printStackTrace();  }  }   
  獲取資源,然后生成JSON字串返回客戶端處理。 注:當(dāng)客戶端版本有更新,服務(wù)器端只要把APK文件拷貝到APK目錄,然后更新apkVersion.properties文件中的信息就可以了,切記。  客戶端設(shè)計:1、 客戶端首先獲取服務(wù)器的版本信息(http方式獲取)。 2、 如何獲取本地客戶端的版本信息 如下參考代碼:  /**   * 得到本地應(yīng)用的版本信息    * @return  */  private int getAPKVersion(){      //APK版本判斷      int sdcardVersion = 0;      String apkFilePath="sdcard/demo.apk";  //安裝包路徑      PackageManager pm = getPackageManager();              PackageInfo info = pm.getPackageArchiveInfo(apkFilePath, PackageManager.GET_ACTIVITIES);           if(info != null){                   sdcardVersion=info.versionCode;       //得到版本信息                   Log.v(TAG, "Version="+sdcardVersion);          }           return sdcardVersion;  }  
  3、 版本比較,如果版本相同,則不執(zhí)行更新,不同才進(jìn)行更新操作。 這里插入客戶端版本設(shè)置介紹: 客戶端版本設(shè)置在AndroidManifest.xml文件中,里面有兩個屬性可進(jìn)行版本信息設(shè)置, android:versionCode="1" 版本號 android:versionName="1.1" 版本名稱 這個版本號需要和服務(wù)器端對應(yīng)。 4、 需要的權(quán)限設(shè)置 
 Sdcard訪問權(quán)限: uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"  訪問網(wǎng)絡(luò)權(quán)限: uses-permission android:name="android.permission.INTERNET"   
5、 更新安裝 當(dāng)用戶點擊應(yīng)用時執(zhí)行檢查更新。相關(guān)代碼參考:
  //彈出框提示 public Handler handler = new Handler() {  public void handleMessage(Message msg) {  super.handleMessage(msg);         Dialog dialog = new AlertDialog.Builder(MainActivity.this).setTitle("系統(tǒng)更新").setMessage("發(fā)現(xiàn)新版本,請更新!")   // 設(shè)置內(nèi)容.setPositiveButton("確定",// 設(shè)置確定按鈕new DialogInterface.OnClickListener() {  @Override  public void onClick(DialogInterface dialog, int which) {  pBar = new ProgressDialog(MainActivity.this);  pBar.setTitle("正在下載");pBar.setMessage("請稍候...");  pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);downFile(apkPath);}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {  public void onClick(DialogInterface dialog, int whichButton) {  // 點擊"取消"按鈕操作}}).create();// 創(chuàng)建  // 顯示對話框  dialog.show();          }  };  
   //下載 /**   * DOWNLOAD APK FILE BY URL   * @param url  */  public void downFile(final String url) {  pBar.show();  new Thread() {  public void run() {  HttpClient client = new DefaultHttpClient();  // params[0]代表連接的  urlHttpGet get = new HttpGet(url);  HttpResponse response;  try {  response = client.execute(get);  HttpEntity entity = response.getEntity();  long length = entity.getContentLength();  InputStream is = entity.getContent();  FileOutputStream fileOutputStream = null;  if (is != null) {  File file = new File(Environment.getExternalStorageDirectory(),"demo.apk");  fileOutputStream = new FileOutputStream(file);  byte[] buf = new byte[1024];  int ch = -1;  int count = 0;  while ((ch = is.read(buf)) != -1) {  // baos.write(buf, 0, ch);  fileOutputStream.write(buf, 0, ch);  count += ch;if (length > 0) {}  }  }  fileOutputStream.flush();  if (fileOutputStream != null) {  fileOutputStream.close();  }  down();  } catch (ClientProtocolException e) {  e.printStackTrace();  } catch (IOException e) {  e.printStackTrace();  }  }  }.start();  }  public void down() {  handler.post(new Runnable()   {  public void run() {  pBar.cancel();  update();  }});  }  
   //更新升級 public void update() {  Intent intent = new Intent(Intent.ACTION_VIEW);  intent.setDataAndType(Uri.fromFile(new File("/sdcard/demo.apk")),"application/vnd.android.package-archive");  startActivity(intent);  }  
結(jié)束,供參考。
 2011-5  
 |