Android 9 安装更新 apk,适用于android 9及以下安卓版本。
16lz
2021-01-23
Android应用中apk下载更新,适用于android 9及以下安卓版本。
直接上代码:
一、在主配置文件中写权限。
//在此加入 //在res文件夹下新建package命名为xml,新建xml文件命名为files_paths
二、创建 files_paths.xml
<?xml version="1.0" encoding="utf-8"?>
三、创建 UpdateVersionController.java
public class UpdateVersionController { private Button cancelBtn; private Context context; private int info; private int info3; private int versionCode;//当前版本号 private Dialog dialog; //提示用户更新的dialog private ProgressDialog pd; //下载进度条 public static UpdateVersionController getInstance(Context context) { return new UpdateVersionController(context); } public UpdateVersionController(Context context) { this.context = context; } /* * 记得运行该方法 */ public void forceCheckUpdateInfo(){ //获取版本号,这个版本号为未更新的版本号 versionCode = getVerCode(context); //获取app新版版本信息,添加网络请求 new Thread(new Runnable() { @Override public void run() { /* *用的Volley框架,Volley可以自己搜索下载jar包,下面是使用Volley获取GET请求的方法 */ RequestQueue mQueue= Volley.newRequestQueue(context); JsonObjectRequest mreq=new JsonObjectRequest(Request.Method.GET,“获取版本号的网址”,new Response.Listener() { @Override public void onResponse(JSONObject jsonObject) { String tt=jsonObject.toString(); //把获取的jsonObject转为String类型 Gson gson=new Gson(); //这里我用的是Gson解析,可以自己搜索gson的jar包下载使用 AppVersion nt=gson.fromJson(tt, AppVersion.class); //这里的AppVersion是网络获取版本号的网址中json数据的实体类,tt是网络获取的数据,用该方法实现json解析 //关于实体类:从服务器网址获取的json数据,通过搜索json自动生成实体类下载复制。并 implement Serializable ,添加构造方法 info=nt.getVNumber(); //通过nt获取实体类里的版本号,为String类型 info3=nt.getIsForce(); //通过nt获取是否强制更新,为String类型 Log.e("版本",""+versionCode);//建议输出一下版本号,进行对比 //更新app版本号比对,info新版本号和当前的版本号versionCode做对比,如果新版本号大于本版本就运行更新方法showUpdataDialog() if ( info > versionCode) { showUpdataDialog(); } else { } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { Log.e("*****", String.valueOf(volleyError)); } }); mQueue.add(mreq); } }).start(); } /** * 弹出对话框提示用户更新 */ protected void showUpdataDialog() { dialog = new Dialog(context, android.R.style.Theme_Dialog); dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); dialog.setContentView(R.layout.activity_updater); dialog.setCanceledOnTouchOutside(false); dialog.setCancelable(false); ((TextView) dialog.findViewById(R.id.content)).setText("是否进行更新?"); cancelBtn = (Button) dialog.findViewById(R.id.cancel); cancelBtn.setVisibility("0".equals(info3) ? View.GONE : View.VISIBLE); // 取消更新 cancelBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); // 确认更新 dialog.findViewById(R.id.ok).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); downLoadApk(); } }); dialog.show(); } /** * 步骤三:下载文件 */ private void downLoadApk() { // 进度条对话框 pd = new ProgressDialog(context); pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); pd.setMessage("下载中..."); pd.setCanceledOnTouchOutside(false); pd.setCancelable(false); // 监听返回键--防止下载的时候点击返回 pd.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { Toast.makeText(context, "正在下载请稍后", Toast.LENGTH_SHORT).show(); return true; } else { return false; } } }); // Sdcard不可用 if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(context, "SD卡不可用", Toast.LENGTH_SHORT).show(); } else { pd.show(); //下载的子线程 new Thread() { @Override public void run() { try { // 在子线程中下载APK文件 File file = getFileFromServer(“下载apk的网址 ”, pd); sleep(1000); // 安装APK文件 OpenFileUtil.openFileByPath(context,file.toString()); pd.dismiss(); // 结束掉进度条对话框 } catch (Exception e) { Toast.makeText(context, "文件下载失败了", Toast.LENGTH_SHORT).show(); pd.dismiss(); e.printStackTrace(); } } }.start(); } } /** * 从服务器下载apk */ public File getFileFromServer(String path, ProgressDialog pd) throws Exception { // 如果相等的话表示当前的sdcard挂载在手机上并且是可用的 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); // 获取到文件的大小 pd.setMax(conn.getContentLength() / 1024); InputStream is = conn.getInputStream(); String p = PathUtils.path; File file = new File(p+ "/update/aaaa.apk"); Log.e("File路径",""+file); //判断文件夹是否被创建 boolean mkdirs; if (!file.getParentFile().exists()) { mkdirs = file.getParentFile().mkdirs(); } FileOutputStream fos = new FileOutputStream(file); BufferedInputStream bis = new BufferedInputStream(is); byte[] buffer = new byte[1024]; int len; int total = 0; while ((len = bis.read(buffer)) != -1) { fos.write(buffer, 0, len); total += len; // 获取当前下载量 pd.setProgress(total / 1024); } fos.close(); bis.close(); is.close(); return file; } else { return null; } } /** * 获取版本号 */ public static int getVerCode(Context context) { int verCode = -1; try { // 获取packagemanager的实例 PackageManager packageManager = context.getPackageManager(); // getPackageName()是你当前类的包名,0代表是获取版本信息 PackageInfo packInfo = packageManager.getPackageInfo( context.getPackageName(), 0); verCode = packInfo.versionCode; } catch (Exception e) { e.printStackTrace(); } return verCode; }}
三、创建OpenFileUtil.java 打开任意文件也可以使用该类
public class OpenFileUtil { private static final String[][] MATCH_ARRAY={ //{后缀名, 文件类型} {".3gp", "video/3gpp"}, {".apk", "application/vnd.android.package-archive"}, {".asf", "video/x-ms-asf"}, {".avi", "video/x-msvideo"}, {".bin", "application/octet-stream"}, {".bmp", "image/bmp"}, {".c", "text/plain"}, {".class", "application/octet-stream"}, {".conf", "text/plain"}, {".cpp", "text/plain"}, {".doc", "application/msword"}, {".docx", "application/msword"}, {".xls", "application/msword"}, {".xlsx", "application/msword"}, {".exe", "application/octet-stream"}, {".gif", "image/gif"}, {".gtar", "application/x-gtar"}, {".gz", "application/x-gzip"}, {".h", "text/plain"}, {".htm", "text/html"}, {".html", "text/html"}, {".jar", "application/java-archive"}, {".java", "text/plain"}, {".jpeg", "image/jpeg"}, {".jpg", "image/jpeg"}, {".js", "application/x-javascript"}, {".log", "text/plain"}, {".m3u", "audio/x-mpegurl"}, {".m4a", "audio/mp4a-latm"}, {".m4b", "audio/mp4a-latm"}, {".m4p", "audio/mp4a-latm"}, {".m4u", "video/vnd.mpegurl"}, {".m4v", "video/x-m4v"}, {".mov", "video/quicktime"}, {".mp2", "audio/x-mpeg"}, {".mp3", "audio/x-mpeg"}, {".mp4", "video/mp4"}, {".mpc", "application/vnd.mpohun.certificate"}, {".mpe", "video/mpeg"}, {".mpeg", "video/mpeg"}, {".mpg", "video/mpeg"}, {".mpg4", "video/mp4"}, {".mpga", "audio/mpeg"}, {".msg", "application/vnd.ms-outlook"}, {".ogg", "audio/ogg"}, {".pdf", "application/pdf"}, {".png", "image/png"}, {".pps", "application/vnd.ms-powerpoint"}, {".ppt", "application/vnd.ms-powerpoint"}, {".prop", "text/plain"}, {".rar", "application/x-rar-compressed"}, {".rc", "text/plain"}, {".rmvb", "audio/x-pn-realaudio"}, {".rtf", "application/rtf"}, {".sh", "text/plain"}, {".tar", "application/x-tar"}, {".tgz", "application/x-compressed"}, {".txt", "text/plain"}, {".wav", "audio/x-wav"}, {".wma", "audio/x-ms-wma"}, {".wmv", "audio/x-ms-wmv"}, {".wps", "application/vnd.ms-works"}, {".xml", "text/plain"}, {".z", "application/x-compress"}, {".zip", "application/zip"}, {"", "*/*"} }; /** * 根据路径打开文件 * @param context 上下文 * @param path 文件路径 */ public static void openFileByPath(Context context, String path) { if(context==null||path==null) return; Intent intent = new Intent(); //设置intent的Action属性 intent.setAction(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addCategory(Intent.CATEGORY_DEFAULT); //文件的类型 String type = ""; for(int i =0;i < MATCH_ARRAY.length;i++){ //判断文件的格式 if(path.contains(MATCH_ARRAY[i][0])){ type = MATCH_ARRAY[i][1]; break; } } try { File out = new File(path); Uri fileURI; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 由于7.0以后文件访问权限,可以通过定义xml在androidmanifest中申请,也可以直接跳过权限 // 通过定义xml在androidmanifest中申请// fileURI = FileProvider.getUriForFile(context,// "com.lonelypluto.zyw_test.provider",// out); // 直接跳过权限 StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.setVmPolicy(builder.build()); fileURI = Uri.fromFile(out); }else{ fileURI = Uri.fromFile(out); } //设置intent的data和Type属性 intent.setDataAndType(fileURI, type); //跳转 if (context.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { context.startActivity(intent); } else { Toast.makeText(context, "没有找到对应的程序", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { //当系统没有携带文件打开软件,提示 Toast.makeText(context, "无法打开该格式文件", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } }}
三、PathUtils .java
public class PathUtils { public static String path = null;}
四、程序入口MainActivity.java
private UpdateVersionController controller=new UpdateVersionController(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); PathUtils.path = getExternalFilesDir(null).toString(); controller.forceCheckUpdateInfo();//运行该方法 if (Build.VERSION.SDK_INT>=23&&checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){ requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},1); requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO},1); requestPermissions(new String[]{Manifest.permission.INTERNET},1); requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1); requestPermissions(new String[]{Manifest.permission.ACCESS_NETWORK_STATE},1); requestPermissions(new String[]{Manifest.permission.ACCESS_WIFI_STATE},1); requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE},1); requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1); requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},1); requestPermissions(new String[]{Manifest.permission.CAMERA},1); requestPermissions(new String[]{Manifest.permission.GET_TASKS},1); requestPermissions(new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES},1); requestPermissions(new String[]{Manifest.permission.READ_CONTACTS},1); } }
完成了。
更多相关文章
- 【Android】1.6版本所有权限
- android+spring boot 选择,上传,下载文件
- Android 危险权限与所有权限大全
- Eclipse下Android工程无法自动产生R文件解决
- [置顶] Android中资源文件的详解和android中的单位介绍
- android(drawable文件夹)图片适配
- Android资源文件使用经验