Android 程序自动更新


之前帮别人定制的一个android应用需要加个自动更新的功能。在 Market 里的应用是无需操心此事的,但像我这种定制的程序就需要自己实现。

原理相当简单,检查更新的时候,通过指定的URL获取服务器端版本信息。比较版本,如果更新,访问服务器端返回的apk的URL地址,下载,安装。各种 Makert 也是通过类似的机制实现的。原理搞清楚了,代码就相当简单了。

获取apk的VesionName,即AndroidManifest.xml中定义的android:versionName

1
2
3
4
5
6
7
8
9
10
public String getVesionName(Context context) {
	String versionName = null;
	try {
		versionName = context.getPackageManager().getPackageInfo("net.vpntunnel", 0).versionName;
	} catch (NameNotFoundException e) {
		Log.e(TAG, e.getMessage());
	}
 
	return versionName;
}

更新以及安装程序需要的权限,在AndroidManifest.xml中添加

1
2
3
4
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
<uses-permission android:name="android.permission.INSTALL_PACKAGES"></uses-permission>

获取apk的versionCode,即AndroidManifest.xml中定义的android:versionCode

1
2
3
4
5
6
7
8
9
10
public int getVersionCode(Context context) {
	int versionCode = 0;
	try {
		versionCode = context.getPackageManager().getPackageInfo("net.vpntunnel", 0).versionCode;
	} catch (NameNotFoundException e) {
		Log.e(TAG, e.getMessage());
	}
 
	return versionCode;
}

服务器端version.JSON,包含apk路径以及版本信息

1
2
3
4
5
6
{
    "ApkName":"NAME",
    "ApkFullName":"NAME_1.0.5.apk",
    "VersionName":"1.0.5",
    "VersionCode":3
}

获取远程服务器的版本信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void getRemoteJSON(string host) throws ClientProtocolException, IOException, JSONException {
	String url = String.format("http://%s/%s", host, VER_JSON);
	StringBuilder sb = new StringBuilder();
	HttpClient client = new DefaultHttpClient();
	HttpParams httpParams = client.getParams();
	HttpConnectionParams.setConnectionTimeout(httpParams, 3000);
	HttpConnectionParams.setSoTimeout(httpParams, 5000);
	HttpResponse response = client.execute(new HttpGet(url));
	HttpEntity entity = response.getEntity();
	if (entity != null) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"), 8192);
 
		String line = null;
		while ((line = reader.readLine()) != null) {
			sb.append(line + "\n");
		}
		reader.close();
	}
 
	JSONObject object = (JSONObject) new JSONTokener(sb.toString()).nextValue();
	this.apkFullName = object.getString("ApkFullName");
	this.versionName = object.getString("VersionName");
	this.versionCode = Integer.valueOf(object.getInt("VersionCode"));
}

发现更新的提醒窗口,通过AlertDialog实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void shoVersionUpdate(String newVersion, final String updateURL) {
	String message = String.format("%s: %s, %s", mContext.getString(R.string.found_newversion), newVersion, mContext.getString(R.string.need_update));
	AlertDialog dialog = new AlertDialog.Builder(mContext).setTitle(mContext.getString(R.string.alertdialog_title)).setMessage(message)
	// update
			.setPositiveButton(mContext.getString(R.string.alertdialog_update_button), new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					pBar = new ProgressDialog(mContext);
					pBar.setTitle(mContext.getString(R.string.progressdialog_title));
					pBar.setMessage(mContext.getString(R.string.progressdialog_message));
					pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
					dialog.dismiss();
					downFile(updateURL);
				}
				// cancel
			}).setNegativeButton(mContext.getString(R.string.alertdialog_cancel_button), new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					dialog.dismiss();
				}
			}).create();
	dialog.show();
}

下载新版的apk文件,存放地址可以放到SD卡中。通过Environment.getExternalStorageDirectory()获取SD卡中的路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
private void downFile(final String url) {
	pBar.show();
	new Thread() {
		public void run() {
			HttpClient client = new DefaultHttpClient();
			HttpGet 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 f = new File(UPDATE_DIR);
					if (!f.exists()) {
						f.mkdirs();
					}
					fileOutputStream = new FileOutputStream(new File(UPDATE_DIR, updateFileName));
 
					byte[] buf = new byte[1024];
					int ch = -1;
					int count = 0;
					while ((ch = is.read(buf)) != -1) {
						fileOutputStream.write(buf, 0, ch);
						count += ch;
						Log.d(TAG, String.valueOf(count));
						if (length > 0) {
						}
					}
				}
				fileOutputStream.flush();
				if (fileOutputStream != null) {
					fileOutputStream.close();
				}
 
				handler.post(new Runnable() {
					public void run() {
						pBar.cancel();
						installUpdate();
					}
				});
			} catch (Exception e) {
				pBar.cancel();
				Log.e(TAG, e.getMessage());
			}
		}
 
	}.start();
}

安装更新

1
2
3
4
5
private void installUpdate() {
	Intent intent = new Intent(Intent.ACTION_VIEW);
	intent.setDataAndType(Uri.fromFile(new File(UPDATE_DIR, updateFileName)), "application/vnd.android.package-archive");
	mContext.startActivity(intent);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值