<p>步骤:</p><p>1.检测当前版本的信息AndroidManifest.xml–>manifest–>[Android]</p><p>2.从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面。(demo中假设需要更新)</p><p>3.当提示用户进行版本升级时,如果用户点击了"更新",系统将自动从服务器上下载安装包并进行自动升级,如果点击取消将进入程序主界面。</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){
//{"data":{"content":"其他bug修复。","id":"2","api_key":"android",
////"version":"2.1"},"msg":"获取成功","status":1}
Stringdata="";
//网络请求获取当前版本号和下载链接
//实际操作是从服务器获取
//demo写死了
Stringnewversion="2.1";//更新新的版本号
Stringcontent="\n"+
"就不告诉你我们更新了什么-。-\n"+
"\n"+
"----------万能的分割线-----------\n"+
"\n"+
"(ㄒoㄒ)被老板打了一顿,还是来告诉你吧:\n"+
"1.下架商品误买了?恩。。。我搞了点小动作就不会出现了\n"+
"2.侧边栏、弹框优化——这个你自己去探索吧,总得留点悬念嘛-。-\n";//更新内容
Stringurl="http://openbox.mobilem.360.cn/index/d/sid/3429345";//安装包下载地址
doublenewversioncode=Double
.parseDouble(newversion);
intcc=(int)(newversioncode);
System.out.println(newversion+"v"+vision+",,"
+cc);
if(cc!=vision){
if(vision<cc){
System.out.println(newversion+"v"
+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("取消","更新").title("版本更新")
.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("正在下载");
pBar.setCustomTitle(LayoutInflater.from(
MainActivity.this).inflate(
R.layout.title_dialog,null));
pBar.setMessage("正在下载");
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("版本更新")
.setMessage(content)
.setPositiveButton("更新",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
dialog.dismiss();
pBar=newCommonProgressDialog(MainActivity.this);
pBar.setCanceledOnTouchOutside(false);
pBar.setTitle("正在下载");
pBar.setCustomTitle(LayoutInflater.from(
MainActivity.this).inflate(
R.layout.title_dialog,null));
pBar.setMessage("正在下载");
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("取消",newDialogInterface.OnClickListener(){
@Override
publicvoidonClick(DialogInterfacedialog,intwhich){
dialog.dismiss();
}
})
.show();</pre><p>(2)通过异步任务实现进度++</p><pre class="brush:java;toolbar:false">/**
*下载应用
*
*@authorAdministrator
*/
classDownloadTaskextendsAsyncTask<String,Integer,String>{
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'tmistakenlysaveerror
//report
//insteadofthefile
if(connection.getResponseCode()!=HttpURLConnection.HTTP_OK){
return"ServerreturnedHTTP"
+connection.getResponseCode()+""
+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,"sd卡未挂载",
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>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,"您未打开SD卡权限"+result,Toast.LENGTH_LONG).show();
}else{
//Toast.makeText(context,"Filedownloaded",
//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<String>grantedPermissions){
Toast.makeText(this,R.string.message_post_succeed,Toast.LENGTH_SHORT).show();
}
@PermissionNo(REQUEST_CODE_PERMISSION_SD)
privatevoidgetMultiNo(List<String>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)),
"application/vnd.android.package-archive");
startActivity(intent);
}</pre>