1.首先清单文件中加入权限
<!--安装包相关权限--> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
2. application中加入, 注意 android:authorities="${applicationId}.provider" 这部分要和后面使用对应上
<provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>3.进行逻辑上相关判断, 8.0以上要设置未知来源的权限, targetSdkVersion需要设置要大于等于26, 否则 haveInstallPermission 只能获取到false
boolean haveInstallPermission; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { haveInstallPermission = getPackageManager().canRequestPackageInstalls(); if (!haveInstallPermission) { //没有未知来源安装权限权限 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setTitle("提示"); builder.setMessage("安装应用需要打开未知来源权限,请去设置中开启应用权限,以允许安装来自此来源的应用"); builder.setPositiveButton("去设置", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startInstallPermissionSettingActivity(); } } }); builder.show(); return;//防止系统执行默认的方法会跳转页面后弹窗提示,所以会重复 return 掉 }else { showProgressDialog("正在下载:0%"); ToolUtils.downloadApk(MainActivity.this, verUrl); } }else { showProgressDialog("正在下载:0%"); ToolUtils.downloadApk(MainActivity.this, verUrl); } @RequiresApi(api = Build.VERSION_CODES.O) private void startInstallPermissionSettingActivity() { //注意这个是8.0新API Uri packageURI = Uri.parse("package:" + getPackageName()); Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI); startActivityForResult(intent, REQUEST_CODE_INSTALL_PERMISSION); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_INSTALL_PERMISSION) { showProgressDialog("正在下载:0%"); ToolUtils.downloadApk(MainActivity.this, verUrl);//再次执行安装流程,包含权限判等 } }4.下载处理相关:
public static void downloadApk(final Context context, final String fileUrl) { ((BaseActivity) context).showProgressDialog("正在下载:" + 0 + "%"); String mPath; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { mPath = Environment.getExternalStorageDirectory() + "/download"; final File dir = new File(mPath); dir.getAbsolutePath().toString(); if (!dir.exists()) { dir.mkdir(); } final File apkFile = new File(dir, getFileName(fileUrl)); if (apkFile.exists()) { apkFile.delete(); } // 请求Api new AsyncTask<Void, Integer, String>() { @Override protected String doInBackground(Void... voids) { try { // 构造URL URL url = new URL(fileUrl); // 打开连接 URLConnection con = url.openConnection(); //获得文件的长度 int contentLength = con.getContentLength(); System.out.println("长度 :" + contentLength); // 输入流 InputStream is = con.getInputStream(); // 1K的数据缓冲 byte[] bs = new byte[1024]; // 读取到的数据长度 int len; // 输出的文件流 OutputStream os = new FileOutputStream(apkFile); // 开始读取 int count = 0; while ((len = is.read(bs)) != -1) { os.write(bs, 0, len); count += len; if (count == contentLength) { ((BaseActivity) context).cancelProgressDialog(); } publishProgress((int) ((count / (float) contentLength) * 100)); } // 完毕,关闭所有链接 os.close(); is.close(); installApk(context, apkFile); } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onProgressUpdate(Integer... integers) { ((BaseActivity) context).showProgressDialog("正在下载:" + integers[0] + "%"); } @Override protected void onPostExecute(String result) { } }.execute(); } } //安装 public static void installApk(Context context, File apkFile) { Intent intent = new Intent(Intent.ACTION_VIEW); //兼容7.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); FileProvider7.setIntentDataAndType(context, intent, "application/vnd.android.package-archive", apkFile, true); } else { intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } if (context.getPackageManager().queryIntentActivities(intent, 0).size() > 0) { context.startActivity(intent); } context.startActivity(intent); android.os.Process.killProcess(android.os.Process.myPid()); }5.工具类
import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Build; import java.io.File; import java.util.List; /** * Created by zhanghongyang01 on 17/5/31. */ public class FileProvider7 { public static Uri getUriForFile(Context context, File file) { Uri fileUri = null; if (Build.VERSION.SDK_INT >= 24) { fileUri = getUriForFile24(context, file); } else { fileUri = Uri.fromFile(file); } return fileUri; } public static Uri getUriForFile24(Context context, File file) { Uri fileUri = android.support.v4.content.FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file); return fileUri; } public static void setIntentDataAndType(Context context, Intent intent, String type, File file, boolean writeAble) { if (Build.VERSION.SDK_INT >= 24) { intent.setDataAndType(getUriForFile(context, file), type); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); if (writeAble) { intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } } else { intent.setDataAndType(Uri.fromFile(file), type); } } public static void setIntentData(Context context, Intent intent, File file, boolean writeAble) { if (Build.VERSION.SDK_INT >= 24) { intent.setData(getUriForFile(context, file)); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); if (writeAble) { intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } } else { intent.setData(Uri.fromFile(file)); } } public static void grantPermissions(Context context, Intent intent, Uri uri, boolean writeAble) { int flag = Intent.FLAG_GRANT_READ_URI_PERMISSION; if (writeAble) { flag |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION; } intent.addFlags(flag); List<ResolveInfo> resInfoList = context.getPackageManager() .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; context.grantUriPermission(packageName, uri, flag); } } }
