2014年6月12日 星期四

Android Apk Download Install Update 下載安裝 更新 APP

大陸更新app方法從網路上找到這篇http://mft.iteye.com/blog/1686524
基本上就是把apk檔跟一個文件檔(版本資訊)放在雲端上面,但就卡在版本資訊,上面連結沒有寫這部分,於是我找到了要用json,這裡卡超久,最後找到此連結http://blog.it4fun.net/archives/112 
,接著出現問題2,android改版後網路要求變嚴格,會出現android.os.NetworkOnMainThreadException問題,解決此參考http://goo.gl/yFbGdR
,接著還有問題3 ,java.lang.string cannot be converted to jsonarray,解決方法http://goo.gl/Qv0mym
就是不能用POST,要用GET。

1.MainActivity.java
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.util.Log;
import android.widget.Toast;

public class MainActivity extends Activity {
 /* update */
 protected static final int UPDATA_CLIENT = 0;
 protected static final int CHECK_UPDATE = 1;
 protected static final int DOWN_ERROR = 0;
 /** Called when the activity is first created. */
 private int serverVersion = 1; // 現在版本
 private int newServerVersion; // 最新版本
 private String downLoadApkUrl = "https://dl.dropbox.com/s/vahfdayyluk151z/Android.apk"; // 放置最新檔案網址

 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  /* update */
  /* 加入StrictMode避免發生 android.os.NetworkOnMainThreadException */
  StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
    .detectDiskReads().detectDiskWrites().detectNetwork()
    .penaltyLog().build());
  StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
    .detectLeakedSqlLiteObjects().detectLeakedClosableObjects()
    .penaltyLog().penaltyDeath().build());

  JSONArray obj = getJson("http://terryyamg.github.io/myweb/update_verson.json"); // 更新版本文件檔位置
  Log.i("obj:", obj + "");
  try {
   for (int i = 0; i < obj.length(); i++) {
    JSONObject data = obj.getJSONObject(i);
    newServerVersion = Integer.parseInt(data.getString("code")); // code為名稱,抓出來newServerVersion為值
   }
  } catch (JSONException e) {

  } catch (NullPointerException e) {
   Log.i("data", "NullPointException");
  }

  new Thread(new Runnable() {
   public void run() {
    try {
     Message msg = new Message();
     msg.what = CHECK_UPDATE;
     handler.sendMessage(msg);

    } catch (NumberFormatException e) {
     // TODO Auto-generated catch block

    } catch (Exception e) {
     // TODO Auto-generated catch block

    }

   }
  }).start();
 }

 /* update */
 public static JSONArray getJson(String url) {
  InputStream is = null;
  String result = "";
  // 若線上資料為陣列,則使用JSONArray
  JSONArray jsonArray = null;
  // 若線上資料為單筆資料,則使用JSONObject
  // JSONObject jsonObj = null;
  // 透過HTTP連線取得回應
  try {
   HttpClient httpclient = new DefaultHttpClient(); // for port 80
   HttpGet httppost = new HttpGet(url); // 要用Get,用Post會出現
             // java.lang.string cannot
             // be converted to jsonarray
   HttpResponse response = httpclient.execute(httppost);
   Log.i("response:", response + ""); // 沒有值會catch錯誤,加入前面StrictMode就可以
   HttpEntity entity = response.getEntity();
   Log.i("entity:", entity + "");
   is = entity.getContent();
   Log.i("is:", is + "");
  } catch (Exception e) {
   e.printStackTrace();
  }
  // 讀取回應
  try {
   BufferedReader reader = new BufferedReader(new InputStreamReader(
     is, "utf8"), 9999999); // 99999為傳流大小,若資料很大,可自行調整
   StringBuilder sb = new StringBuilder();
   String line = null;
   while ((line = reader.readLine()) != null) {
    // 逐行取得資料
    sb.append(line + "\n");
   }
   is.close();
   result = sb.toString();
   Log.i("result:", result + ""); // LogCat會印出json ex:[{"code":"1"}]
  } catch (Exception e) {
   e.printStackTrace();
  }
  // 轉換文字為JSONArray
  try {
   jsonArray = new JSONArray(result);
  } catch (JSONException e) {
   e.printStackTrace();
  }
  return jsonArray;
 }

 public void showUpdateDialog() {

  @SuppressWarnings("unused")
  AlertDialog alert = new AlertDialog.Builder(MainActivity.this)
    .setTitle("更新提示").setIcon(android.R.drawable.ic_dialog_info)
    .setMessage("最新優惠出來啦,快來下載更新")
    .setPositiveButton("下載", new DialogInterface.OnClickListener() {

     public void onClick(DialogInterface dialog, int which) {
      dialog.dismiss(); // 關閉對話框
      downLoadApk();
     }

    }).show();

 }

 protected void downLoadApk() {
  final ProgressDialog pd; // 進度條對話框
  pd = new ProgressDialog(this);
  pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
  pd.setMessage("正在下載更新");
  pd.show();
  new Thread() {
   @Override
   public void run() {
    try {
     File file = getFileFromServer(downLoadApkUrl, pd);
     sleep(3000);
     installApk(file);
     pd.dismiss(); // 結束進度條對話框
    } catch (Exception e) {
     pd.dismiss();
     Message msg = new Message();
     msg.what = DOWN_ERROR;
     handler.sendMessage(msg);
     e.printStackTrace();
    }
   }
  }.start();
 }

 public static File getFileFromServer(String path, ProgressDialog pd)
   throws Exception {
  /* 如果相等的話表示當前的SDcard掛載在手機上並且是可用的 */
  if (Environment.getExternalStorageState().equals(
    Environment.MEDIA_MOUNTED)) {
   URL url = new URL(path);
   HttpURLConnection conn = (HttpURLConnection) url.openConnection();
   conn.setConnectTimeout(5000);
   pd.setMax(conn.getContentLength()); // 獲取副本文件大小
   InputStream is = conn.getInputStream();
   File file = new File(Environment.getExternalStorageDirectory(),
     "update.apk");
   FileOutputStream fos = new FileOutputStream(file);
   BufferedInputStream bis = new BufferedInputStream(is);
   byte[] buffer = new byte[1024];
   int len;
   int total = 0;
   while ((len = bis.read(buffer)) != -1) {
    fos.write(buffer, 0, len);
    total += len;
    pd.setProgress(total); // 獲取當前下載量
   }
   fos.close();
   bis.close();
   is.close();
   return file;
  } else {
   return null;
  }
 }

 /* 安裝APK */
 protected void installApk(File file) {
  Intent intent = new Intent();
  intent.setAction(Intent.ACTION_VIEW); // 執行動作
  intent.setDataAndType(Uri.fromFile(file),
    "application/vnd.android.package-archive"); // 執行的數據類型
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //2015.05.28 update 安裝完成後啟動app
  startActivity(intent);
 }

 Handler handler = new Handler() {

  @Override
  public void handleMessage(Message msg) {
   // TODO Auto-generated method stub
   super.handleMessage(msg);
   switch (msg.what) {
   case DOWN_ERROR:
    // 下載APK失敗
    Toast.makeText(getApplicationContext(), "下載新版本失敗", 1).show();
    break;
   case CHECK_UPDATE:
    // 檢查更新

    if (serverVersion == 0) {
     serverVersion = newServerVersion;
    }

    if (serverVersion != newServerVersion) {
     Log.i("serverVersion:", serverVersion + ""); // 顯示現在版本
     Log.i("newServerVersion:", newServerVersion + ""); // 顯示最新版本
     showUpdateDialog(); // 執行更新
    }
    break;
   }
  }
 };
}
2.AndroidManifest.xml
加入使用網路權限

3.update_verson.json
[{"code":"1"}]

沒有留言 :

張貼留言