废话:bugly这些也挺好用的,偶尔需要自己写...
1.请求安装未知应用来源的权限
//配置权限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
btnInstall.setOnClickListener(v -> {
if (Build.VERSION.SDK_INT >= 26) {
boolean b = getPackageManager().canRequestPackageInstalls();
if (b) {
//存储权限申请
requestWriteExternalStorage();
} else {
//请求安装未知应用来源的权限
showDialogRequestInstall();
}
} else {
requestWriteExternalStorage();
}
});
//跳转让用户手动开启权限
private void showDialogRequestInstall() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("权限管理")
.setMessage("请开启允许应用安装权限")
.setPositiveButton("确定", (dialog, which) -> {
dialog.dismiss();
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
startActivityForResult(intent, Constant.REQUECT_INSTALL_PERMISSION);
});
builder.show();
}
2.权限请求
//随便搜一下 有很多框架可以使用 这里使用
implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'
//配置权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
private void requestWriteExternalStorage() {
PermissionManager.newBuilder(this)
.setPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
.callBack(new PermissionManager.PermissionRequestCallBack() {
@Override
public void successCallBack() {
//请求成功回调
downloadApk();
}
@Override
public void failureCallBack() {
//请求失败回调
//提示用户自己去权限管理处开启权限
showGetPermissionDialog();
}
});
}
public static void showGetPermissionDialog(Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("权限管理")
.setMessage("请前往权限管理开启相应权限")
.setPositiveButton("前往", (dialogInterface, i) -> {
dialogInterface.dismiss();
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse(ConstantObject.PACKAGE_URL_SCHEME + context.getPackageName()));
context.startActivity(intent);
})
.setNegativeButton("取消", (dialogInterface, i) -> dialogInterface.dismiss());
builder.setCancelable(false);
builder.show();
}
//权限请求的工具类 可能有未知问题的 emmmm
public class PermissionManager {
private static PermissionManager mPermissionManager;
private static RxPermissions rxPermissions;
private String permission;
private PermissionManager() {
}
public static PermissionManager newBuilder(Activity activity) {
mPermissionManager = new PermissionManager();
rxPermissions = new RxPermissions(activity);
return mPermissionManager;
}
public PermissionManager setPermission(String permission){
this.permission = permission;
return this;
}
public void callBack(final PermissionRequestCallBack callBack) {
rxPermissions.request(permission)
.filter(it -> callBack!=null)
.subscribe(aBoolean -> {
if (aBoolean) {
callBack.successCallBack();
} else {
callBack.failureCallBack();
}
}, t-> t.printStackTrace());
}
public interface PermissionRequestCallBack {
void successCallBack();
void failureCallBack();
}
}
3.下载
//一般网络请求框架都能下载文件的 这里使用:
implementation 'com.liulishuo.filedownloader:library:1.7.4'
//配置权限
<uses-permission android:name="android.permission.INTERNET" />
//在Application里初始化 FileDownloader.init(this);
//下载链接
private String apkUrl ="";
//下载存储路径 根目录下的apk文件夹
private String apkPath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/apk/"+"yingyongming.apk";
private void downloadApk() {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setMessage("下载中0%...");
alertDialog.setCancelable(false);
alertDialog.show();
FileDownloader.getImpl().create(apkUrl)
.setPath(apkPath)
.setListener(new FileDownloadListener() {
@Override
protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
}
@Override
protected void connected(BaseDownloadTask task, String etag, boolean isContinue, int soFarBytes, int totalBytes) {
}
@Override
protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
alertDialog.setMessage("下载中"+(int)((double) soFarBytes / (double) totalBytes * 100)+"%...");
}
@Override
protected void blockComplete(BaseDownloadTask task) {
}
@Override
protected void retry(final BaseDownloadTask task, final Throwable ex, final int retryingTimes, final int soFarBytes) {
}
@Override
protected void completed(BaseDownloadTask task) {
alertDialog.setMessage("下载中100%...");
alertDialog.dismiss();
installApp(context, "包名", apkPath);
}
@Override
protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
}
@Override
protected void error(BaseDownloadTask task, Throwable e) {
alertDialog.dismiss();
e.printStackTrace();
}
@Override
protected void warn(BaseDownloadTask task) {
}
}).start();
}
4.安装 需要注意7.0之后文件的访问是通过FileProvider
在res文件下创建xml文件夹 创建共享的目录文件 xxx.xml
其中
<files-path>:内部存储空间应用私有目录下的 files/ 目录,等同于 Context.getFilesDir() 所获取的目录路径;
<cache-path>:内部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getCacheDir() 所获取的目录路径;
<external-path>:外部存储空间根目录,等同于 Environment.getExternalStorageDirectory() 所获取的目录路径;
<external-files-path>:外部存储空间应用私有目录下的 files/ 目录,等同于 Context.getExternalFilesDir(null) 所获取的目录路径;
<external-cache-path>:外部存储空间应用私有目录下的 cache/ 目录,等同于 Context.getExternalCacheDir();
//在AndroidManifest.xml 中配置 FileProvider
<application>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.yourname"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
public static void installApp(Context context,String packageName,String mUrl) {
File appFile = new File(mUrl);
if (!appFile.getParentFile().exists()) {
appFile.getParentFile().mkdir();
}
//判断版本是否在7.0以上
//跳转到新版本应用安装页面
if (Build.VERSION.SDK_INT >= 24) {
//yourname 是定义在xxxx.xml中的值
Uri apkUri = FileProvider.getUriForFile(context, packageName+".yourname", appFile);//在AndroidManifest中的android:authorities值
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
context.startActivity(install);
} else {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.fromFile(appFile), "application/vnd.android.package-archive");
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
System.exit(0);
}
5.效果图
6.告辞