編輯:關於Android編程
版本更新是每個項目必備的功能,思路大概都差不多,首先獲取到客戶端的版本號與服務器上最新的版本進行比較,如果需要進行更新,則返回下載的鏈接,進行下載安裝,直接上代碼:
MainActivity:
package com.home.update; import android.os.Bundle; import android.app.Activity; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); UpdateManager um = new UpdateManager(MainActivity.this); um.checkUpdateInfo(); } }
版本更新工具類:
package com.home.update; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONException; import org.json.JSONObject; import android.app.AlertDialog; import android.app.Dialog; import android.app.AlertDialog.Builder; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.DialogInterface.OnClickListener; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.widget.ProgressBar; public class UpdateManager { private Context context; // 發起版本檢測的url private final static String CHECKURL = "http://...."; // 服務器返回的apk安裝包下載路徑 private static String downloadUrl = ""; private Dialog noticeDialog; private ProgressBar mProgress; private boolean interceptFlag = false; private Dialog downloadDialog; private static final int DOWN_UPDATE = 1; private static final int DOWN_OVER = 2; private int progress; // 下載包安裝本地存放路徑 private static final String savePath = Environment .getExternalStorageDirectory() + "/guyun/update/"; private static final String saveFileName = savePath + "sport.apk"; public UpdateManager(Context context) { this.context = context; } /** * 更新UI的Handler */ private Handler handler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case DOWN_UPDATE: mProgress.setProgress(progress); break; case DOWN_OVER: if (downloadDialog != null) downloadDialog.dismiss(); installApk(); break; default: break; } }; }; /** * 版本更新接口 */ public void checkUpdateInfo() { // 向服務器發出檢查請求,如果需要更新則彈出提示對話框 if (isNeedUpdate()) { // 顯示提示對話框 showNoticeDialog(); } } /** * 檢查當前版本是否需要更新 * * @return */ private boolean isNeedUpdate() { String versionName = getVersionName(context); boolean isNeedUpdate = testVersion(versionName); return isNeedUpdate; } /** * 獲取本地版本名稱 * * @param context * @return */ private String getVersionName(Context context) { String versionName = ""; try { // 包名改為自己應用的包名即可 versionName = context.getPackageManager().getPackageInfo( "com.home.update", 1).versionName; } catch (NameNotFoundException e) { e.printStackTrace(); } return versionName; } /** * 向服務器發起版本檢測請求,服務器根據提交的版本參數和服務器上的當前版本進行比較 如果符合更新要求,返回最新版本號和下載URL * * @param versionName * @return */ private boolean testVersion(String version) { boolean isNeedUpdate = false; // 這裡的url具體拼裝方式應根據服務器需要的格式而定 String url = CHECKURL + "?version=" + version; String result = get(url); try { // 這裡的具體解析方式應根據自己服務器返回的數據而定 JSONObject jsonObj = new JSONObject(result); int code = jsonObj.getInt("code"); if (code == 0) { JSONObject valueObj = jsonObj.getJSONObject("value"); String lastVersion = valueObj.getString("version"); downloadUrl = valueObj.getString("url"); if (version.equals(lastVersion)) { isNeedUpdate = false; } else { isNeedUpdate = true; } } else { isNeedUpdate = false; } } catch (JSONException e) { e.printStackTrace(); } return isNeedUpdate; } /** * 以get方式發送請求 * * @param url * @return */ private String get(String url) { BufferedReader reader = null; StringBuffer sb = null; String result = ""; HttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(url); request.addHeader("Content-Type", " text/json"); try { // 發送請求,得到響應 HttpResponse response = client.execute(request); // 如果請求成功 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { reader = new BufferedReader(new InputStreamReader(response .getEntity().getContent())); sb = new StringBuffer(); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } else if (response.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE) { result = "維護或繁忙"; } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (reader != null) { reader.close(); reader = null; } } catch (IOException e) { result = "維護或繁忙"; e.printStackTrace(); } } if (sb != null) { result = sb.toString(); } return result; } /** * 彈出更新提示對話框 */ private void showNoticeDialog() { AlertDialog.Builder builder = new Builder(context); builder.setTitle("軟件版本更新"); builder.setMessage("版本可以更新哦"); builder.setPositiveButton("下載", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); showDownloadDialog(); } }); builder.setNegativeButton("以後再說", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); noticeDialog = builder.create(); noticeDialog.show(); // 設置彈出對話框大小屬性 WindowManager.LayoutParams lp = noticeDialog.getWindow() .getAttributes(); lp.width = 400; lp.height = 500; noticeDialog.getWindow().setAttributes(lp); } /** * 下載進度對話框 */ private void showDownloadDialog() { AlertDialog.Builder builder = new Builder(context); builder.setTitle("正在下載,請稍後..."); final LayoutInflater inflater = LayoutInflater.from(context); View v = inflater.inflate(R.layout.progress, null); mProgress = (ProgressBar) v.findViewById(R.id.progress); builder.setView(v); builder.setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); interceptFlag = true; } }); downloadDialog = builder.create(); downloadDialog.show(); downloadApk(); } /** * 啟動線程下載apk */ private void downloadApk() { Thread downLoadThread = new Thread(downApkRunnable); downLoadThread.start(); } /** * 安裝包下載線程 */ private Runnable downApkRunnable = new Runnable() { @Override public void run() { try { URL url = new URL(downloadUrl); 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(); } String apkFile = saveFileName; File ApkFile = new File(apkFile); FileOutputStream fos = new FileOutputStream(ApkFile); int count = 0; byte buf[] = new byte[1024]; do { int numread = is.read(buf); count += numread; progress = (int) (((float) count / length) * 100); // 更新進度 handler.sendEmptyMessage(DOWN_UPDATE); if (numread <= 0) { // 下載完成通知安裝 handler.sendEmptyMessage(DOWN_OVER); break; } fos.write(buf, 0, numread); } while (!interceptFlag);// 點擊取消就停止下載. fos.close(); is.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; /** * 安裝APK */ private void installApk() { File apkfile = new File(saveFileName); if (!apkfile.exists()) { return; } Intent i = new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive"); context.startActivity(i); } }
如果是在4.0以上版本,不能在主線程訪問網絡,部分功能需要作相應調整開啟異步子線程。
一、前言現在要說的就是最後一篇了,如何應對Android中一些加固apk安全防護,在之前的兩篇破解文章中,我們可以看到一個是針對於Java層的破解,一個是針對於nativ
兩個人共嘗一個痛苦只有半個痛苦,兩個人共享一個歡樂卻有兩個歡樂。 本講內容:Gallery仿圖像集浏覽 一、基本原理 在 Activity 中實現 OnGest
相信不少朋友在平常的學習和工作當中都會用到SD存儲卡,雖然它具有是很強大的存儲功能,但同時也是非常脆弱的。一旦SD卡罷工,真是欲哭無淚。那麼到底sd卡壞了怎
若有這樣的需求或場景,要求每次啟動Activity時都清空原有的任務棧,也就是finish掉原任務棧中的所有Activity,有沒有一種鸠占鵲巢的趕腳?下面介紹的這個方法