Android(安卓)提示版本更新的实现
16lz
2021-01-25
步骤:
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大写了,改小写后解决;
更多相关文章
- 万字长文带你了解最常用的开源 Squid 代理服务器
- Nginx系列教程(一)| 手把手教你在Linux环境下搭建Nginx服务
- Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
- 创建非阻塞的Socket服务器
- [置顶] 【android】通过User-Agent,解决httppost从服务器上获取的
- Android常用控件及其属性
- Android中通过AsyncTask类来制作炫酷进度条的实例教程
- Android进度条 多线程登录或下载
- 当Android遇见HTTP缓存代理服务器