700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android实用功能开发——版本更新(适配6.0权限管理 7.0安装外部APK)

Android实用功能开发——版本更新(适配6.0权限管理 7.0安装外部APK)

时间:2020-03-07 07:27:37

相关推荐

Android实用功能开发——版本更新(适配6.0权限管理 7.0安装外部APK)

我在去年写过一篇博客,叫《Android实用功能分享——应用版本的更新实例》,那个时候APP限制很少,不需要手动申请文件权限和安装的权限,随着Android系统的安全性的提高,这篇博客下面的技术就显得不够用了,因为我决定更新一下技术,以适应时代发展。

众所周知,在Anroid 6.0以后,对于操作文件的权限已经变了,需要我们在应用运行时手动请求以下权限

<!--往sdcard中写入数据的权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><!--在sdcard中创建/删除文件的权限 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"tools:ignore="ProtectedPermissions" />

另外,在Anroid 7.0以后,安装外部APP也需要申请权限

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

大方向说完以后,咱们来具体实施一下项目,首先在build.gradle文件下配置两个外部依赖

//权限申请框架implementation 'pub.devrel:easypermissions:0.3.0'//APP注解框架implementation 'org.xutils:xutils:3.3.36'

然后在自定义MyAPP里面初始化下xutils的框架

/***@Description* @author 小瓶盖* @return* @createTime /9/16 0016 16:38* 更新日志*/public class MyAPP extends Application {@Overridepublic void onCreate() {super.onCreate();//网络注解框架x.Ext.init(this);}}

接下来就在Activity里面编写程序

import android.content.Intent;import android.os.Bundle;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.view.View;import com.ltl.update.base.BasePermissionActivity;import com.ltl.update.utils.UpDateStatus;import com.ltl.update.utils.UpdateHelper;import org.xutils.view.annotation.ContentView;import org.xutils.view.annotation.Event;import org.xutils.x;import java.util.List;@ContentView(R.layout.activity_main)public class MainActivity extends BasePermissionActivity implements UpDateStatus {private UpdateHelper mUpdateHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);x.view().inject(this);mUpdateHelper = new UpdateHelper(this);mUpdateHelper.setUpDateStatus(this);}@Overridepublic void updateNewVersion(boolean needUpdate) {//是否强更}@Overridepublic void cancelUpdate() {//取消更新}@Overridepublic void cancelJurisdiction() {//取消授权}@Event(R.id.id_update)private void onClick(View view) {//申请文件权限onRequestPermissions(file, RC_FILE, FILE_TIPS);}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {boolean b = mUpdateHelper.onRequestPermissionsResult(requestCode, grantResults);if (!b) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);}}/*** 文件操作权限获取成功* @param requestCode 申请权限时的请求码* @param perms 申请成功的权限集合*/@Overridepublic void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {super.onPermissionsGranted(requestCode, perms);mUpdateHelper.getVersion();}@Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == UpdateHelper.INSTALL_APK_REQUESTCODE) {//打开授权设置返回的时候检查一下权限mUpdateHelper.onActivityResult(requestCode, resultCode, data);}}}

代码其实比较好懂,重点讲一下我自定义的一个版本更新工具类,代码如下

import android.Manifest;import android.app.Activity;import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.content.pm.PackageManager;import .Uri;import android.os.Build;import android.provider.Settings;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.text.TextUtils;import com.ltl.update.UpdataDialog;import org.json.JSONObject;import org.xutils.http.RequestParams;import org.xutils.x;import java.io.File;import java.util.Map;/*** @author 小瓶盖* @Description* @return* @createTime /9/16 0016 16:38* 更新日志*/public class UpdateHelper extends UpDateVersionImpl {public static final int INSTALL_APK_REQUESTCODE = 1531;private UpdateModel mModel;public void setUpDateStatus(UpDateStatus upDateStatus) {mUpDateStatus = upDateStatus;}private UpDateStatus mUpDateStatus;public static boolean isLoaded = false;public static boolean HAVE_NEW_VERSION = false;private String path = "";public UpdateHelper(Context mContext) {super(mContext);mModel = new UpdateModel();File pathFile = new File(FileUtils.writeApkSaveList(), "update" + (AppUtils.getVersionCode(mContext) + 1) + ".apk");path = pathFile.getPath();}@Overridepublic void downloadAPK(String url) {RequestParams requestParams = new RequestParams(url);requestParams.setSaveFilePath(path);x.http().get(requestParams, new DownFile());}class DownFile extends DownFileImpl {UpdataDialog progressDialog;public DownFile() {progressDialog = new UpdataDialog(mContext);}@Overridepublic void onStarted() {progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);progressDialog.setMessage("亲,努力下载中。。。");progressDialog.show();}@Overridepublic void onLoading(long total, long current, boolean isDownloading) {if (isDownloading) {progressDialog.setMax((int) (total / 1024f / 1024f));progressDialog.setProgress((int) ((current / 1024f / 1024f)));}}@Overridepublic void onSuccess(File result) {try {installApk(result);} catch (Exception e) {e.printStackTrace();toastMsg("安装失败,请前往应用市场更新");}progressDialog.dismiss();}@Overridepublic void onError(Throwable ex, boolean isOnCallback) {ex.printStackTrace();toastMsg("下载失败,请检查网络和SD卡");progressDialog.dismiss();}}@Overridepublic void installApk(File file) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 7.0+以上版本Uri apkUri = FileUtils.getUriForFile(mContext, 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");}mContext.startActivity(intent);((Activity) mContext).finish();}@Overridepublic void getVersion() {mModel = getModel(new JSONObject());if (mModel.getVersionNo() > getVersionCode() && !TextUtils.isEmpty(mModel.getUrl())) {//要更新了HAVE_NEW_VERSION = true;judgePermissions(mModel);}}@Overridepublic void judgePermissions(UpdateModel model) {if (model != null) {if (Build.VERSION.SDK_INT >= 26) {//来判断应用是否有权限安装apkboolean installAllowed = mActivity.getPackageManager().canRequestPackageInstalls();//有权限if (installAllowed) {//直接前往下载onVersionUpdate(model);} else {//无权限 申请权限ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, INSTALL_APK_REQUESTCODE);}} else {//直接前往下载onVersionUpdate(model);}}}@Overridepublic void onVersionUpdate(final UpdateModel model) {AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);dialog.setCancelable(false);dialog.setTitle("温馨提示");dialog.setMessage(model.getInstructions());dialog.setPositiveButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();if (mUpDateStatus != null) {mUpDateStatus.cancelUpdate();}if (model.isForceUpdate()) {isLoaded = false;mActivity.finish();System.exit(0);}}});dialog.setNeutralButton("马上更新", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {isLoaded = false;downloadAPK(model.getUrl());}});dialog.show();}@Overridepublic UpdateModel getModel(JSONObject object) {//模拟数据UpdateModel mModel = new UpdateModel();//拼多多的下载链接mModel.setUrl("https://imtt./16891/apk/3BB6A311C926A75A15FBCF29BC3FF2CF.apk");mModel.setVersionNo(2);mModel.setInstructions("新版本更新啦");return mModel;}@Overridepublic int getVersionCode() {return AppUtils.getVersionCode(mContext);}@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == INSTALL_APK_REQUESTCODE) {judgePermissions(mModel);}}@Overridepublic boolean onRequestPermissionsResult(int requestCode, @NonNull int[] grantResults) {if (requestCode == INSTALL_APK_REQUESTCODE) {if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {onVersionUpdate(mModel);} else {//将用户引导至安装未知应用界面。showInstallApkTips();}return true;}return false;}/***没有权限需要提示更新*/public void showInstallApkTips() {AlertDialog.Builder dialog = new AlertDialog.Builder(mContext);dialog.setCancelable(false);dialog.setTitle("温馨提示");dialog.setMessage("有新的版本要更新,请打开允许安装外部应用权限后重试");dialog.setPositiveButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();if (mUpDateStatus != null) {mUpDateStatus.cancelJurisdiction();}if (mModel.isForceUpdate()) {Intent intent = new Intent();intent.setAction("android.intent.action.VIEW");Uri content_url = Uri.parse(mModel.getUrl());intent.setData(content_url);mActivity.startActivity(intent);isLoaded = false;mActivity.finish();System.exit(0);}}});dialog.setNeutralButton("前往设置", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {isLoaded = false;Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);intent.setData(Uri.parse("package:" + mContext.getPackageName()));mActivity.startActivityForResult(intent, INSTALL_APK_REQUESTCODE);}});dialog.show();}}

具体的,代码的注释已经很清楚,主要是权限申请和处理,这里面每一步都至关重要,其中 installApk(File file) 方法,是调起系统安装APP的方法,到此,基本上就完成操作了。如果没有权限,调起是会报严重错误的。

public void installApk(File file) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 7.0+以上版本Uri apkUri = FileUtils.getUriForFile(mContext, 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");}mContext.startActivity(intent);((Activity) mContext).finish();}

以上就是部分代码,有些细节的接口类会在下面的源码中贴出,欢迎下载源码体验。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。