android 实现检测版本,下载apk更新(附源码)
其实这不是什么难事了,都有热更新的技术了,只是记录一下,大神勿嘲笑。
先说下思路,首先要有更新的接口,只要进入app,就监测一下接口,是否更新,更新的话,检测本地版本是否低于接口返回的版本,低的话,就根据返回的路径下载apk更新。接口返回的字段起码有 更新标志、更新版本,更新描述,apk下载地址。
更新标志应该有三种状态,更新,询问更新,强制更新,可以启动一个Service(不要忘记在清单文件中注册)来进行检查更新以及下载的工作;
这下面就是 Service里的全部代码,也不是很难理解,重要的地方都有注释。写好Service后,在代码中 startService()启动就可以了。
这里面弹出了一个讯问框,需要在清单文件中 加入权限, <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />,这是弹出全局讯问框的权限。
import android.app.AlertDialog; import android.app.Dialog; import android.app.Service; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Color; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.support.annotation.Nullable; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.widget.ProgressBar; import android.widget.TextView; import com.example.sdtz.wenmingweifang.R; import com.example.sdtz.wenmingweifang.Tool.OkHttpUtil; import com.example.sdtz.wenmingweifang.Util.App; import com.example.sdtz.wenmingweifang.Util.MyUrl; import org.json.JSONException; import org.json.JSONObject; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; /** * Created by sdtz on 2017/7/1. */ public class UpdateService extends Service { private ProgressBar mProgressBar;//进度条 private TextView tv1; private TextView tv2; private String url = MyUrl.Httpurl; private String VersionCode; private String result; private App app; private String mSavePath;//apk保存地址 private String mVersion_path; private String mVersion_name = "app.apk";//apk名 private float length; private Dialog mDownloadDialog;//对话框 private int mProgress;//进度值 private static final int DOWNLOADING = 1;//apk下载中 private static final int DOWNLOAD_FINISH = 2;//apk下载完毕 private boolean mIsCancel = false;//是否取消下载标示符 @Nullable @Override public IBinder onBind(Intent intent) { return null; } private Handler mUpdateProgressHandler = new Handler(){ public void handleMessage(Message msg) { switch (msg.what){ case DOWNLOADING: // 设置进度条 mProgressBar.setProgress(mProgress); tv1.setText( mProgress + "/100"); float len = length/1024/1024;//将length转换为M单位 float b = (float)(Math.round(len*100))/100;//保留两位小数点 tv2.setText( b+"M"); break; case DOWNLOAD_FINISH: // 隐藏当前下载对话框 mDownloadDialog.dismiss(); // 安装 APK 文件 installAPK(); break; default: break; } }; }; @Override public int onStartCommand(Intent intent, int flags, int startId) { try { VersionCode = getVersionName(); /* getJsonReuslt();*/ new OkHttpUtil().getJson(MyUrl.appdown, new OkHttpUtil.HttpCallBack() { @Override public void onSusscess(String data) throws JSONException { JSONObject jo1 = new JSONObject(data); app = new App(); app.setVersion(jo1.getString("version").toString()); app.setDescription(jo1.getString("description").toString()); app.setUrl(MyUrl.Httpurl+jo1.getString("url").toString()); app.setUpdate_flag(jo1.getString("update_flag").toString()); mVersion_path = app.getUrl(); //手机当前版本 String phoneVersion = VersionCode.substring(0,VersionCode.lastIndexOf(".")); Double jiekou = Double.parseDouble(app.getVersion()); Double bendi = null; try { bendi = Double.parseDouble(getVersionName()); } catch (Exception e) { e.printStackTrace(); } Log.d("==","接口:"+jiekou+"本地:"+bendi+"::"+app.toString()); //本地版本 与 接口返回版本 不一致,并且 更新标志为1 ,则更新 if( !VersionCode.equals(app.getVersion()) && (jiekou>bendi) && app.getUpdate_flag().equals("1")){ Log.d("==","::进入"); showDialog(app.getDescription()); }else if( !VersionCode.equals(app.getVersion()) && (jiekou>bendi) && app.getUpdate_flag().equals("2")){ showDownloadDialog(); } } }); } catch (Exception e) { e.printStackTrace(); } catch (Throwable throwable) { throwable.printStackTrace(); } return super.onStartCommand(intent, flags, startId); } /* * 获取当前程序的版本号 */ private String getVersionName() throws Exception{ //获取packagemanager的实例 PackageManager packageManager = getPackageManager(); //getPackageName()是你当前类的包名,0代表是获取版本信息 PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0); return packInfo.versionName; } private void showDialog(String drc) { final AlertDialog.Builder builder = new AlertDialog.Builder(this,AlertDialog.THEME_HOLO_LIGHT); builder.setMessage(drc); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { showDownloadDialog(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); } }); AlertDialog alertDialog = builder.create(); alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); alertDialog.setCanceledOnTouchOutside(true); alertDialog.show(); alertDialog.getButton(alertDialog.BUTTON_POSITIVE).setTextColor(Color.GREEN); alertDialog.getButton(alertDialog.BUTTON_NEGATIVE).setTextColor(Color.RED); } /* * 开启新线程下载文件 */ private void downloadAPK() { new Thread(new Runnable() { @Override public void run() { try{//检查sd是否挂载 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ String sdPath = Environment.getExternalStorageDirectory() + "/"; mSavePath = sdPath + "WenmingDownload"; File dir = new File(mSavePath); if (!dir.exists()) dir.mkdir(); // 下载文件 HttpURLConnection conn = (HttpURLConnection) new URL(mVersion_path).openConnection(); conn.connect(); InputStream is = conn.getInputStream(); length = conn.getContentLength(); File apkFile = new File(mSavePath, mVersion_name); FileOutputStream fos = new FileOutputStream(apkFile); int count = 0; byte[] buffer = new byte[1024]; while (!mIsCancel){ int numread = is.read(buffer); count += numread; // 计算进度条的当前位置 mProgress = (int) ((count/length) * 100); // 更新进度条 mUpdateProgressHandler.sendEmptyMessage(DOWNLOADING); // 下载完成 if (numread < 0){ mUpdateProgressHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } fos.write(buffer, 0, numread); } fos.close(); is.close(); } }catch(Exception e){ e.printStackTrace(); } } }).start(); } /* * 下载到本地后执行安装 */ protected void installAPK() { File apkFile = new File(mSavePath, mVersion_name); if (!apkFile.exists()) return; Intent intent = new Intent(Intent.ACTION_VIEW); Uri uri = Uri.parse("file://" + apkFile.toString()); intent.setDataAndType(uri, "application/vnd.android.package-archive"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); this.startActivity(intent); } /* * 显示正在下载对话框 */ protected void showDownloadDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("版本更新,下载中。。。"); View view = LayoutInflater.from(this).inflate(R.layout.dialog_progress, null); mProgressBar = (ProgressBar) view.findViewById(R.id.id_progress); tv1 = (TextView) view.findViewById(R.id.tv1); tv2 = (TextView) view.findViewById(R.id.tv2); builder.setView(view); mDownloadDialog = builder.create(); mDownloadDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); mDownloadDialog.show(); // 下载文件 downloadAPK(); } }