Android实现APK下载安装
来源:互联网 发布:桥梁bim软件 编辑:程序博客网 时间:2024/05/17 21:26
网上有很多种写法,也有很多坑,当然这些坑不是说代码有问题,而是Android的碎片化和各个厂商的定制造成的,例如最简单的写法DownloadManager在三星等手机上无法使用,原因是他们不支持DownloadManager。使用Thread或者IntentService或者AnsyTask其实也都可以,各有优劣。例如使用IntentService的更新UI问题,使用AnsyTask的排队问题,等等还是要看具体的需求选择最合适的实现方法。另一个问题是Android版本的问题,主要是7.0的兼容问题,不然以前的写法是要奔溃的;
兼容7.0的第一步:
在Manfist清单文件中声明一个内容提供器,当然是在Application节点内部;
<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/> </provider>
这里的applicationId占位其实是buildgradle文件中applicationId,也就是项目的包名,可以直接用项目包名代替。
而这个文件@xml/provider_paths是不存在的,是需要在res下新建的;
接下来给出一个provider_paths.xml的范例:
<?xml version="1.0" encoding="utf-8"?><paths> <external-path path="Android/data/自己的项目包名/" name="files_root" /> <external-path path="." name="external_storage_root" /></paths>
最后是android调用Apk安装:
public void installApkFile( String filePath) { //Log.e("JACK",filePath); Intent intent = new Intent(Intent.ACTION_VIEW); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri contentUri = FileProvider.getUriForFile(mContext, "com.caihongto.caihongtoforcustomer.fileprovider", new File(filePath)); intent.setDataAndType(contentUri, "application/vnd.android.package-archive"); } else { intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } mContext.startActivity(intent); }
有一点需要注意的是:
这里的命名必须和清单文件的命名一致;
下面是下载与安装代码:
public class DownloadAsyncTask extends AsyncTask<String, Integer, Boolean> { private Context mContext; int per = 0; private ProgressDialog perDialog = null; private String fullPath = null; //private File apkFile; public DownloadAsyncTask(Context context){ mContext=context; } @Override protected Boolean doInBackground(String... params) { fullPath = params[1] + params[2]; try { URL url = new URL(params[0]); HttpURLConnection huc = (HttpURLConnection) url .openConnection(); huc.setConnectTimeout(10 * 1000); huc.connect(); if (huc.getResponseCode() == 200) { perDialog.setMax(huc.getContentLength()); File path = new File(params[1]); if (!path.exists()) { path.mkdirs(); } File apkFile = new File(path, params[2]); if (!apkFile.exists()) { apkFile.createNewFile(); } InputStream is = huc.getInputStream(); FileOutputStream fos = new FileOutputStream(apkFile); byte[] buf = new byte[1024]; int readSize; while (true) { readSize = is.read(buf); if (readSize <= 0) { break; } per += readSize; this.publishProgress(per); fos.write(buf, 0, readSize); } fos.close(); is.close(); return true; } else { return false; } } catch (MalformedURLException e) { return false; } catch (IOException e) { return false; } } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); perDialog.dismiss(); if (result) { Toast.makeText(mContext, "下载完成", Toast.LENGTH_SHORT) .show(); installApkFile(fullPath); } else { Toast.makeText(mContext, "下载失败", Toast.LENGTH_SHORT) .show(); } } @Override protected void onPreExecute() { super.onPreExecute(); perDialog = new ProgressDialog(mContext); perDialog.setMessage("正在下载..."); perDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);// 设置水平进度条 perDialog.setCancelable(true);// 设置是否可以通过点击Back键取消 perDialog.setCanceledOnTouchOutside(false);// 设置在点击Dialog外是否取消Dialog进度条 perDialog.show(); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); perDialog.setProgress(values[0]); } public void installApkFile( String filePath) { Intent intent = new Intent(Intent.ACTION_VIEW); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri contentUri = FileProvider.getUriForFile(mContext, "com.caihongto.caihongtoforcustomer.fileprovider", new File(filePath)); intent.setDataAndType(contentUri, "application/vnd.android.package-archive"); } else { intent.setDataAndType(Uri.fromFile(new File(filePath)), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } mContext.startActivity(intent); }}
最后看下怎么调用的吧;
String[] params = new String[] { "http://www.caihongto.com/public/androidapk/6cc043563be7528213bbfa585245a5f9.apk",Environment.getExternalStorageDirectory() + "/pistol/app/", "caihongto_.apk" }; new DownloadAsyncTask(MainActivity.this).execute(params);
就这样吧,如果有什么同类的问题,大家可以留言;
另外附上一种大神的写法:
首先定义一个将Apk的存储File 转换为Uri的方法,代码如下:
public static Uri getFileExternalContentUri(Context context, File externalFile) { String filePath = externalFile.getAbsolutePath(); Cursor cursor = context.getContentResolver().query(MediaStore.Files.getContentUri("external"), new String[]{MediaStore.Files.FileColumns._ID}, MediaStore.Files.FileColumns.DATA + "=? ", new String[]{filePath}, null); if (cursor != null && cursor.moveToFirst()) { int id = cursor.getInt(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID)); cursor.close(); return Uri.withAppendedPath(MediaStore.Files.getContentUri("external"), "" + id); } else { if (externalFile.exists()) { ContentValues values = new ContentValues(); values.put(MediaStore.Files.FileColumns.DATA, filePath); return context.getContentResolver().insert(MediaStore.Files.getContentUri("external"), values); } else { return null; } } }
然后在完成下载之后调用这个方法,并实现安装逻辑:
public static boolean installApp(File apkFile, final Context context) { LogUtil.i(TAG, "开始安装apk 文件包:"); if (apkFile != null && apkFile.exists() && apkFile.isFile()) { if (context != null) { // 通过Intent安装APK文件 final Intent instalInstant = new Intent(Intent.ACTION_VIEW); instalInstant.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { instalInstant.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); instalInstant.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); Uri apkFileURI = ResUtil.getFileExternalContentUri(context,apkFile); instalInstant.setDataAndType(apkFileURI, "application/vnd.android.package-archive"); if (context != null) { context.startActivity(instalInstant); } } else { instalInstant.setDataAndType(Uri.parse("file://" + apkFile.getAbsolutePath()), "application/vnd.android.package-archive"); } return true; } else { LogUtil.e(TAG, "installApp() --> context is null !!! "); } } else { LogUtil.e(TAG, "installApp() --> apkFile exists = false !!! "); } return false; }
先这样吧
1 0
- Android实现APK下载安装
- Android 下载安装APK
- Android 下载安装APK
- android下载安装APK
- android下载安装APK
- android下载安装APK
- Android 下载APK 安装APK 打开APK
- Android 下载APK 安装APK 打开APK
- Android 下载APK 安装APK 打开APK
- Android 下载APK 安装APK 打开APK
- Android实现应用下载并自动安装apk包
- Android实现应用下载并自动安装apk包
- Android实现应用下载并自动安装apk包
- Android实现应用下载并自动安装apk包
- Android实现应用下载并自动安装apk包
- Android 实现apk文件下载并自动安装
- Android 实现apk文件下载并自动安装
- Android实现文件下载并自动安装apk包
- C# Serializable对象序列化的作用
- org.apache.jasper.JasperException --The JSP specification requires that an attribute name is precede
- UIView
- 正确应对系统内存不足,使用OnLowMemory和OnTrimMemory回调
- 关于WEB页面刷新重复提交问题
- Android实现APK下载安装
- 下载 m3u8 视频脚本
- 递推递归练习——H
- 【论文笔记】CHI '16 Embracing Error to Enable Rapid CrowdSourcing
- work——python下载文件
- 存储器概念理解
- android 隐藏顶部标题栏
- loss weight
- jsp基础