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