一看啥都会 一敲啥都醉 真的是各种坑
首先附上代码 下面在一一介绍:(现在博客更新的加入代码的背景颜色为白色 好chou啊 实名吐槽 哈哈哈)
//显示 showDownloadProgressDialog
private void showDownloadProgressDialog(Context context) {
ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setTitle("提示");
progressDialog.setMessage("正在下载...");
progressDialog.setIndeterminate(false);
progressDialog.setMax(100);
progressDialog.setCancelable(false); //设置不可点击界面之外的区域让对话框小时
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //进度条类型
progressDialog.show();
new DownloadAPK(progressDialog).execute(urlApk);//urlApk为apk路径
}
@Override
protected Object doInBackground(Object[] objects) {
URL url;
HttpURLConnection conn;
BufferedInputStream bis = null;
FileOutputStream fos = null;
try {
url = new URL((String) objects[0]);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int fileLength = conn.getContentLength();
bis = new BufferedInputStream(conn.getInputStream());
//这个为在本地创建文件的路径
//创建的文件路径:路径+名字.apk
String fileName = Environment.getExternalStorageDirectory().getPath() + "/sysf.apk";
file = new File(fileName);
if (!file.exists()) {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
}
fos = new FileOutputStream(file);
byte data[] = new byte[4 * 1024];
long total = 0;
int count;
while ((count = bis.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
fos.write(data, 0, count);
fos.flush();
}
fos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bis != null) {
bis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onProgressUpdate(Object[] values) {
super.onProgressUpdate(values);
// 这里 改变ProgressDialog的进度值
progressDialog.setProgress((int) values[0]);
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
openFile(file); //打开安装apk文件操作
progressDialog.dismiss(); //关闭对话框
}
private void openFile(File file) {
if (file != null) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//判读版本是否在7.0以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri apkUri = FileProvider.getUriForFile(getContext(), getPackageName() + ".FileProvider", file);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
startActivity(intent);
}
}
}
注意点一:
注意点二:
这里要有个版本的判断 否则高版本的手机无法安装
注意点三:《清单文件》
除了读写的权限还应该加上安装的权限 这个就是高版本安装的权限设置
<!-- 读取数据 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 写入数据 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--安装 高版本安装apk权限申请-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
到这里 一切看着都完美无缺 谁能想到运行时会报一个这样的错误:
Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference
解决:清单文件 《application》中加入:
<!--文件的路径 会把具体的路径给你换成你的包名-->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.*.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
注意authorities :包名.fileprovider
否则安装失败
res--xml--file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--
name属性的值可以随便写,别名
path属性的值表示共享的具体位置,设置空就表示将整个SD卡进行共享
-->
<external-path
name="external_files"
path="." />
<!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
<external-path
name="beta_external_path"
path="Download/" />
<!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
<external-path
name="beta_external_files_path"
path="Android/data/" />
</paths>
有缺陷,建议使用服务进行下载