Android应用更新-自动检测版本及自动升级

<p>步骤:</p><p>1.检测当前版本的信息AndroidManifest.xml–&gt;manifest–&gt;[Android]</p><p>2.从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面。(demo中假设需要更新)</p><p>3.当提示用户进行版本升级时,如果用户点击了&quot;更新&quot;,系统将自动从服务器上下载安装包并进行自动升级,如果点击取消将进入程序主界面。</p><p>效果图如下:</p><p></p><p><img src="/up_pic/201812/181012588689.jpg" title="181012588689.jpg"/></p><p><img src="/up_pic/201812/181012585662.jpg" title="181012585662.jpg"/></p><p><img src="/up_pic/201812/181012588879.jpg" title="181012588879.jpg"/></p><p><img src="/up_pic/201812/181012583277.jpg" title="181012583277.jpg"/></p><p>下面介绍一下代码的实现:</p><p>1.获取应用的当前版本号,我是封装了一个工具类来获取</p><p>// 获取本版本号,是否更新</p><p> int vision = Tools.getVersion(this);</p><p>获取当前版本号工具类:</p><pre class="brush:java;toolbar:false"> publicclassTools{ /** *检查是否存在SDCard * *@return */ publicstaticbooleanhasSdcard(){ Stringstate=Environment.getExternalStorageState(); if(state.equals(Environment.MEDIA_MOUNTED)){ returntrue; }else{ returnfalse; } } /** *2*获取版本号3*@return当前应用的版本号4 */ publicstaticintgetVersion(Contextcontext){ try{ PackageManagermanager=context.getPackageManager(); PackageInfoinfo=manager.getPackageInfo(context.getPackageName(), 0); Stringversion=info.versionName; intversioncode=info.versionCode; returnversioncode; }catch(Exceptione){ e.printStackTrace(); } return0; }</pre><p>2.获取服务器版本号,是否要更新(此处就是简单的网络请求拿到需要的数据即可,我是写了固定值)</p><pre class="brush:java;toolbar:false">//获取更新版本号 privatevoidgetVersion(finalintvision){ //{&quot;data&quot;:{&quot;content&quot;:&quot;其他bug修复。&quot;,&quot;id&quot;:&quot;2&quot;,&quot;api_key&quot;:&quot;android&quot;, ////&quot;version&quot;:&quot;2.1&quot;},&quot;msg&quot;:&quot;获取成功&quot;,&quot;status&quot;:1} Stringdata=&quot;&quot;; //网络请求获取当前版本号和下载链接 //实际操作是从服务器获取 //demo写死了 Stringnewversion=&quot;2.1&quot;;//更新新的版本号 Stringcontent=&quot;\n&quot;+ &quot;就不告诉你我们更新了什么-。-\n&quot;+ &quot;\n&quot;+ &quot;----------万能的分割线-----------\n&quot;+ &quot;\n&quot;+ &quot;(ㄒoㄒ)被老板打了一顿,还是来告诉你吧:\n&quot;+ &quot;1.下架商品误买了?恩。。。我搞了点小动作就不会出现了\n&quot;+ &quot;2.侧边栏、弹框优化——这个你自己去探索吧,总得留点悬念嘛-。-\n&quot;;//更新内容 Stringurl=&quot;http://openbox.mobilem.360.cn/index/d/sid/3429345&quot;;//安装包下载地址 doublenewversioncode=Double .parseDouble(newversion); intcc=(int)(newversioncode); System.out.println(newversion+&quot;v&quot;+vision+&quot;,,&quot; +cc); if(cc!=vision){ if(vision&lt;cc){ System.out.println(newversion+&quot;v&quot; +vision); //版本号不同 ShowDialog(vision,newversion,content,url); } } }</pre><p>3.接下来就是下载文件了</p><p>(1) 显示下载</p><p>此处用的是自定义按钮:</p><pre class="brush:java;toolbar:false">/** *升级系统 * *@paramcontent *@paramurl */ privatevoidShowDialog(intvision,Stringnewversion,Stringcontent, finalStringurl){ finalMaterialDialogdialog=newMaterialDialog(this); dialog.content(content).btnText(&quot;取消&quot;,&quot;更新&quot;).title(&quot;版本更新&quot;) .titleTextSize(15f).show(); dialog.setCanceledOnTouchOutside(false); dialog.setOnBtnClickL(newOnBtnClickL(){//leftbtnclicklistener @Override publicvoidonBtnClick(){ dialog.dismiss(); } },newOnBtnClickL(){//rightbtnclicklistener @Override publicvoidonBtnClick(){ dialog.dismiss(); //pBar=newProgressDialog(MainActivity.this, //R.style.dialog); pBar=newCommonProgressDialog(MainActivity.this); pBar.setCanceledOnTouchOutside(false); pBar.setTitle(&quot;正在下载&quot;); pBar.setCustomTitle(LayoutInflater.from( MainActivity.this).inflate( R.layout.title_dialog,null)); pBar.setMessage(&quot;正在下载&quot;); pBar.setIndeterminate(true); pBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pBar.setCancelable(true); //downFile(URLData.DOWNLOAD_URL); finalDownloadTaskdownloadTask=newDownloadTask( MainActivity.this); downloadTask.execute(url); pBar.setOnCancelListener(newDialogInterface.OnCancelListener(){ @Override publicvoidonCancel(DialogInterfacedialog){ downloadTask.cancel(true); } }); } }); }</pre><p>原生的按钮:</p><pre class="brush:java;toolbar:false">newandroid.app.AlertDialog.Builder(this) .setTitle(&quot;版本更新&quot;) .setMessage(content) .setPositiveButton(&quot;更新&quot;,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); pBar=newCommonProgressDialog(MainActivity.this); pBar.setCanceledOnTouchOutside(false); pBar.setTitle(&quot;正在下载&quot;); pBar.setCustomTitle(LayoutInflater.from( MainActivity.this).inflate( R.layout.title_dialog,null)); pBar.setMessage(&quot;正在下载&quot;); pBar.setIndeterminate(true); pBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pBar.setCancelable(true); //downFile(URLData.DOWNLOAD_URL); finalDownloadTaskdownloadTask=newDownloadTask( MainActivity.this); downloadTask.execute(url); pBar.setOnCancelListener(newDialogInterface.OnCancelListener(){ @Override publicvoidonCancel(DialogInterfacedialog){ downloadTask.cancel(true); } }); } }) .setNegativeButton(&quot;取消&quot;,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); } }) .show();</pre><p>(2)通过异步任务实现进度++</p><pre class="brush:java;toolbar:false">/** *下载应用 * *@authorAdministrator */ classDownloadTaskextendsAsyncTask&lt;String,Integer,String&gt;{ privateContextcontext; privatePowerManager.WakeLockmWakeLock; publicDownloadTask(Contextcontext){ this.context=context; } @Override protectedStringdoInBackground(String...sUrl){ InputStreaminput=null; OutputStreamoutput=null; HttpURLConnectionconnection=null; Filefile=null; try{ URLurl=newURL(sUrl[0]); connection=(HttpURLConnection)url.openConnection(); connection.connect(); //expectHTTP200OK,sowedon&#39;tmistakenlysaveerror //report //insteadofthefile if(connection.getResponseCode()!=HttpURLConnection.HTTP_OK){ return&quot;ServerreturnedHTTP&quot; +connection.getResponseCode()+&quot;&quot; +connection.getResponseMessage(); } //thiswillbeusefultodisplaydownloadpercentage //mightbe-1:serverdidnotreportthelength intfileLength=connection.getContentLength(); if(Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)){ file=newFile(Environment.getExternalStorageDirectory(), DOWNLOAD_NAME); if(!file.exists()){ //判断父文件夹是否存在 if(!file.getParentFile().exists()){ file.getParentFile().mkdirs(); } } }else{ Toast.makeText(MainActivity.this,&quot;sd卡未挂载&quot;, Toast.LENGTH_LONG).show(); } input=connection.getInputStream(); output=newFileOutputStream(file); bytedata[]=newbyte[4096]; longtotal=0; intcount; while((count=input.read(data))!=-1){ //allowcancelingwithbackbutton if(isCancelled()){ input.close(); returnnull; } total+=count; //publishingtheprogress.... if(fileLength&gt;0)//onlyiftotallengthisknown publishProgress((int)(total*100/fileLength)); output.write(data,0,count); } }catch(Exceptione){ System.out.println(e.toString()); returne.toString(); }finally{ try{ if(output!=null) output.close(); if(input!=null) input.close(); }catch(IOExceptionignored){ } if(connection!=null) connection.disconnect(); } returnnull; } @Override protectedvoidonPreExecute(){ super.onPreExecute(); //takeCPUlocktopreventCPUfromgoingoffiftheuser //pressesthepowerbuttonduringdownload PowerManagerpm=(PowerManager)context .getSystemService(Context.POWER_SERVICE); mWakeLock=pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName()); mWakeLock.acquire(); pBar.show(); } @Override protectedvoidonProgressUpdate(Integer...progress){ super.onProgressUpdate(progress); //ifwegethere,lengthisknown,nowsetindeterminatetofalse pBar.setIndeterminate(false); pBar.setMax(100); pBar.setProgress(progress[0]); } @Override protectedvoidonPostExecute(Stringresult){ mWakeLock.release(); pBar.dismiss(); if(result!=null){ ////申请多个权限。大神的界面 //AndPermission.with(MainActivity.this) //.requestCode(REQUEST_CODE_PERMISSION_OTHER) //.permission(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE) ////rationale作用是:用户拒绝一次权限,再次申请时先征求用户同意,再打开授权对话框,避免用户勾选不再提示。 //.rationale(newRationaleListener(){ //@Override //publicvoidshowRequestPermissionRationale(intrequestCode,Rationalerationale){ ////这里的对话框可以自定义,只要调用rationale.resume()就可以继续申请。 //AndPermission.rationaleDialog(MainActivity.this,rationale).show(); //} //} //) //.send(); //申请多个权限。 AndPermission.with(MainActivity.this) .requestCode(REQUEST_CODE_PERMISSION_SD) .permission(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE) //rationale作用是:用户拒绝一次权限,再次申请时先征求用户同意,再打开授权对话框,避免用户勾选不再提示。 .rationale(rationaleListener ) .send(); Toast.makeText(context,&quot;您未打开SD卡权限&quot;+result,Toast.LENGTH_LONG).show(); }else{ //Toast.makeText(context,&quot;Filedownloaded&quot;, //Toast.LENGTH_SHORT) //.show(); update(); } } }</pre><p>此处下载apk文件,需要获取SD的读写权限(用的是严大的权限库)</p><p>权限库GitHub:https://github.com/yanzhenjie/AndPermission</p><pre class="brush:java;toolbar:false">privatestaticfinalintREQUEST_CODE_PERMISSION_SD=101; privatestaticfinalintREQUEST_CODE_SETTING=300; privateRationaleListenerrationaleListener=newRationaleListener(){ @Override publicvoidshowRequestPermissionRationale(intrequestCode,finalRationalerationale){ //这里使用自定义对话框,如果不想自定义,用AndPermission默认对话框: //AndPermission.rationaleDialog(Context,Rationale).show(); //自定义对话框。 AlertDialog.build(MainActivity.this) .setTitle(R.string.title_dialog) .setMessage(R.string.message_permission_rationale) .setPositiveButton(R.string.btn_dialog_yes_permission,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.cancel(); rationale.resume(); } }) .setNegativeButton(R.string.btn_dialog_no_permission,newDialogInterface.OnClickListener(){ @Override publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.cancel(); rationale.cancel(); } }) .show(); } }; //----------------------------------SD权限----------------------------------// @PermissionYes(REQUEST_CODE_PERMISSION_SD) privatevoidgetMultiYes(List&lt;String&gt;grantedPermissions){ Toast.makeText(this,R.string.message_post_succeed,Toast.LENGTH_SHORT).show(); } @PermissionNo(REQUEST_CODE_PERMISSION_SD) privatevoidgetMultiNo(List&lt;String&gt;deniedPermissions){ Toast.makeText(this,R.string.message_post_failed,Toast.LENGTH_SHORT).show(); //用户否勾选了不再提示并且拒绝了权限,那么提示用户到设置中授权。 if(AndPermission.hasAlwaysDeniedPermission(this,deniedPermissions)){ AndPermission.defaultSettingDialog(this,REQUEST_CODE_SETTING) .setTitle(R.string.title_dialog) .setMessage(R.string.message_permission_failed) .setPositiveButton(R.string.btn_dialog_yes_permission) .setNegativeButton(R.string.btn_dialog_no_permission,null) .show(); //更多自定dialog,请看上面。 } } //----------------------------------权限回调处理----------------------------------// @Override publicvoidonRequestPermissionsResult(intrequestCode,@NonNullString[]permissions,@NonNullint[] grantResults){ super.onRequestPermissionsResult(requestCode,permissions,grantResults); /** *转给AndPermission分析结果。 * *@paramobject要接受结果的Activity、Fragment。 *@paramrequestCode请求码。 *@parampermissions权限数组,一个或者多个。 *@paramgrantResults请求结果。 */ AndPermission.onRequestPermissionsResult(this,requestCode,permissions,grantResults); } @Override protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){ switch(requestCode){ caseREQUEST_CODE_SETTING:{ Toast.makeText(this,R.string.message_setting_back,Toast.LENGTH_LONG).show(); //设置成功,再次请求更新 getVersion(Tools.getVersion(MainActivity.this)); break; } } }</pre><p>(3) 当apk文件下载完毕时,打开安装</p><pre class="brush:java;toolbar:false">privatevoidupdate(){ //安装应用 Intentintent=newIntent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(newFile(Environment .getExternalStorageDirectory(),DOWNLOAD_NAME)), &quot;application/vnd.android.package-archive&quot;); startActivity(intent); }</pre>
RangeTime:0.008115s
RangeMem:219.59 KB
返回顶部 留言