步骤:
1.检测当前版本的信息AndroidManifest.xml-->manifest-->android:versionName。
2.从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面。
3.当提示用户进行版本升级时,如果用户点击了确定,系统将自动从服务器上下载并进行自动升级,如果点击取消将进入程序主界面。
01 | 获取当前程序的版本号: |
02 |
03 | 1 . /* |
04 | 2. * 获取当前程序的版本号 |
05 | 3. */ |
06 | 4 . private String getVersionName() throws Exception{ |
07 | 5 . //获取packagemanager的实例 |
08 | 6 . PackageManager packageManager = getPackageManager(); |
09 | 7 . //getPackageName()是你当前类的包名,0代表是获取版本信息 |
10 | 8 . PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0 ); |
11 | 9 . return packInfo.versionName; |
12 | 10 .} |
01 | 获取服务器端的版本号: |
02 | 1 . /* |
03 | 2. * 用pull解析器解析服务器返回的xml文件 (xml封装了版本号) |
04 | 3. */ |
05 | 4 . public static UpdataInfo getUpdataInfo(InputStream is) throws Exception{ |
06 | 5 . XmlPullParser parser = Xml.newPullParser(); |
07 | 6 . parser.setInput(is, "utf-8" ); //设置解析的数据源 |
08 | 7 . int type = parser.getEventType(); |
09 | 8 . UpdataInfo info = new UpdataInfo(); //实体 |
10 | 9 . while (type != XmlPullParser.END_DOCUMENT ){ |
11 | 10 . switch (type) { |
12 | 11 . case XmlPullParser.START_TAG: |
13 | 12 . if ( "version" .equals(parser.getName())){ |
14 | 13 . info.setVersion(parser.nextText()); //获取版本号 |
15 | 14 . } else if ( "url" .equals(parser.getName())){ |
16 | 15 . info.setUrl(parser.nextText()); //获取要升级的APK文件 |
17 | 16 . } else if ( "description" .equals(parser.getName())){ |
18 | 17 . info.setDescription(parser.nextText()); //获取该文件的信息 |
19 | 18 . } |
20 | 19 . break ; |
21 | 20 . } |
22 | 21 . type = parser.next(); |
23 | 22 . } |
24 | 23 . return info; |
25 | 24 .} |
01 | 从服务器下载apk: |
02 | 1 . public static File getFileFromServer(String path, ProgressDialog pd) throws Exception{ |
03 | 2 . //如果相等的话表示当前的sdcard挂载在手机上并且是可用的 |
04 | 3 . if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ |
05 | 4 . URL url = new URL(path); |
06 | 5 . HttpURLConnection conn = (HttpURLConnection) url.openConnection(); |
07 | 6 . conn.setConnectTimeout( 5000 ); |
08 | 7 . //获取到文件的大小 |
09 | 8 . pd.setMax(conn.getContentLength()); |
10 | 9 . InputStream is = conn.getInputStream(); |
11 | 10 . File file = new File(Environment.getExternalStorageDirectory(), "updata.apk" ); |
12 | 11 . FileOutputStream fos = new FileOutputStream(file); |
13 | 12 . BufferedInputStream bis = new BufferedInputStream(is); |
14 | 13 . byte [] buffer = new byte [ 1024 ]; |
15 | 14 . int len ; |
16 | 15 . int total= 0 ; |
17 | 16 . while ((len =bis.read(buffer))!=- 1 ){ |
18 | 17 . fos.write(buffer, 0 , len); |
19 | 18 . total+= len; |
20 | 19 . //获取当前下载量 |
21 | 20 . pd.setProgress(total); |
22 | 21 . } |
23 | 22 . fos.close(); |
24 | 23 . bis.close(); |
25 | 24 . is.close(); |
26 | 25 . return file; |
27 | 26 . } |
28 | 27 . else { |
29 | 28 . return null ; |
30 | 29 . } |
31 | 30 .} |
匹配、下载、自动安装:
01 | /* |
02 | * 从服务器获取xml解析并进行比对版本号 |
03 | */ |
04 | public class CheckVersionTask implements Runnable{ |
05 | |
06 | public void run() { |
07 | try { |
08 | //从资源文件获取服务器 地址 |
09 | String path = getResources().getString(R.string.serverurl); |
10 | //包装成url的对象 |
11 | URL url = new URL(path); |
12 | HttpURLConnection conn = (HttpURLConnection) url.openConnection(); |
13 | conn.setConnectTimeout( 5000 ); |
14 | InputStream is =conn.getInputStream(); |
15 | info = UpdataInfoParser.getUpdataInfo(is); |
16 | |
17 | if (info.getVersion().equals(versionname)){ |
18 | Log.i(TAG, "版本号相同无需升级" ); |
19 | LoginMain(); |
20 | } else { |
21 | Log.i(TAG, "版本号不同 ,提示用户升级 " ); |
22 | Message msg = new Message(); |
23 | msg.what = UPDATA_CLIENT; |
24 | handler.sendMessage(msg); |
25 | } |
26 | } catch (Exception e) { |
27 | // 待处理 |
28 | Message msg = new Message(); |
29 | msg.what = GET_UNDATAINFO_ERROR; |
30 | handler.sendMessage(msg); |
31 | e.printStackTrace(); |
32 | } |
33 | } |
34 | } |
01 | Handler handler = new Handler(){ |
02 | @Override |
03 | public void handleMessage(Message msg) { |
04 | // TODO Auto-generated method stub |
05 | super .handleMessage(msg); |
06 | switch (msg.what) { |
07 | case UPDATA_CLIENT: |
08 | //对话框通知用户升级程序 |
09 | showUpdataDialog(); |
10 | break ; |
11 | case GET_UNDATAINFO_ERROR: |
12 | //服务器超时 |
13 | Toast.makeText(getApplicationContext(), "获取服务器更新信息失败" , 1 ).show(); |
14 | LoginMain(); |
15 | break ; |
16 | case DOWN_ERROR: |
17 | //下载apk失败 |
18 | Toast.makeText(getApplicationContext(), "下载新版本失败" , 1 ).show(); |
19 | LoginMain(); |
20 | break ; |
21 | } |
22 | } |
23 | }; |
01 | /* |
02 | * |
03 | * 弹出对话框通知用户更新程序 |
04 | * |
05 | * 弹出对话框的步骤: |
06 | * 1.创建alertDialog的builder. |
07 | * 2.要给builder设置属性, 对话框的内容,样式,按钮 |
08 | * 3.通过builder 创建一个对话框 |
09 | * 4.对话框show()出来 |
10 | */ |
11 | protected void showUpdataDialog() { |
12 | AlertDialog.Builder builer = new Builder( this ) ; |
13 | builer.setTitle( "版本升级" ); |
14 | builer.setMessage(info.getDescription()); |
15 | //当点确定按钮时从服务器上下载 新的apk 然后安装 |
16 | builer.setPositiveButton( "确定" , new OnClickListener() { |
17 | public void onClick(DialogInterface dialog, int which) { |
18 | Log.i(TAG, "下载apk,更新" ); |
19 | downLoadApk(); |
20 | } |
21 | }); |
22 | //当点取消按钮时进行登录 |
23 | builer.setNegativeButton( "取消" , new OnClickListener() { |
24 | public void onClick(DialogInterface dialog, int which) { |
25 | // TODO Auto-generated method stub |
26 | LoginMain(); |
27 | } |
28 | }); |
29 | AlertDialog dialog = builer.create(); |
30 | dialog.show(); |
31 | } |
01 | /* |
02 | * 从服务器中下载APK |
03 | */ |
04 | protected void downLoadApk() { |
05 | final ProgressDialog pd; //进度条对话框 |
06 | pd = new ProgressDialog( this ); |
07 | pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); |
08 | pd.setMessage( "正在下载更新" ); |
09 | pd.show(); |
10 | new Thread(){ |
11 | @Override |
12 | public void run() { |
13 | try { |
14 | File file = DownLoadManager.getFileFromServer(info.getUrl(), pd); |
15 | sleep( 3000 ); |
16 | installApk(file); |
17 | pd.dismiss(); //结束掉进度条对话框 |
18 | } catch (Exception e) { |
19 | Message msg = new Message(); |
20 | msg.what = DOWN_ERROR; |
21 | handler.sendMessage(msg); |
22 | e.printStackTrace(); |
23 | } |
24 | }}.start(); |
25 | } |
1 | //安装apk |
2 | protected void installApk(File file) { |
3 | Intent intent = new Intent(); |
4 | //执行动作 |
5 | intent.setAction(Intent.ACTION_VIEW); |
6 | //执行的数据类型 |
7 | intent.setDataAndType(Uri.fromFile(file), "application/vnd.Android.package-archive" ); //编者按:此处Android应为android,否则造成安装不了 |
8 | startActivity(intent); |
9 | } |
1 | /* |
2 | * 进入程序的主界面 |
3 | */ |
4 | private void LoginMain(){ |
5 | Intent intent = new Intent( this ,MainActivity. class ); |
6 | startActivity(intent); |
7 | //结束掉当前的activity |
8 | this .finish(); |
9 | } |
二、参考后使用情况:
1.可以下载apk,但安装失败:
1)以为配置文件中需定义了android.permission.INSTALL_PACKAGES,其实不需;
2)以为是要在执行安装的activity中配置
1 | < intent-filter > |
2 | < action android:name = "android.intent.action.VIEW" /> |
3 | < category android:name = "android.intent.category.DEFAULT" /> |
4 | </ intent-filter > |
,其实不是;
3)代码中application/vnd.Android.package-archive有一个字母A大写了,改小写后解决;