安装权限申请:
1. AdroidManifest.xml
以下放在 application内
2. 在资源文件夹res/xml下新建file_provider.xml文件
name
:是一个虚设的文件名(可以自由命名),对外可见路径的一部分,隐藏真实文件目录
path
:是一个相对目录,相对于当前的子标签根目录,表示内部内存卡根目录,对应根目录等价于Context.getFilesDir()
3. 版本更新工具类:
public class VersionUtil extends AppCompatActivity {
private static Activity recieveActivity;
private static String result, downloadURL, version = "";
/**
* 获取当前程序的版本号
*/
private static void getAPKVersion(Boolean isNeed) {
try {
//获取packagemanager的实例
PackageManager packageManager = recieveActivity.getPackageManager();
//getPackageName()是当前类的包名,0代表是获取版本信息
PackageInfo packInfo = packageManager.getPackageInfo(recieveActivity.getPackageName(), 0);
Log.i("TAG", "版本号" + packInfo.versionCode);
Log.i("TAG", "版本名" + packInfo.versionName);
version = String.valueOf(packInfo.versionCode);
checkVersion(isNeed);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 提示版本更新的对话框
*/
private static void showDialogUpdate() {
// 这里的属性可以一直设置,因为每次设置后返回的是一个builder对象
AlertDialog.Builder builder = new AlertDialog.Builder(recieveActivity);
// 设置提示框的标题
builder.setTitle("提示");
// 设置要显示的信息
builder.setMessage("检查到新版本,确定下载并更新吗?");
// 设置确定按钮
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
boolean isPermit = getPersimmionsRsult();
if (isPermit) {
downloadAPK();
}
}
});
// 设置取消按钮
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
return;
}
});
// 显示对话框
builder.show();
}
@TargetApi(23)
private static void getPersimmions() {
int SDK_PERMISSION_REQUEST = 127;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ArrayList permissions = new ArrayList();
/***
* 用户如果禁止,则每次进入都会申请
*/
//读写权限
if (recieveActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ToastUtil.showToast(recieveActivity, "安装app需要您勾选读写权限");
permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (permissions.size() > 0) {
ActivityCompat.requestPermissions(recieveActivity, permissions.toArray(new String[permissions.size()]), SDK_PERMISSION_REQUEST);
}
}
}
@TargetApi(23)
private static boolean getPersimmionsRsult() {
boolean isPermit = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (recieveActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
isPermit = false;
ToastUtil.showToast(recieveActivity, "未勾选读写权限");
} else {
isPermit = true;
}
}
return isPermit;
}
private static void downloadAPK() {
final ProgressDialog pd; //进度条对话框
pd = new ProgressDialog(recieveActivity);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("正在下载更新");
pd.show();
//启动子线程下载任务
new Thread() {
@Override
public void run() {
try {
File file = getFileFromServer(downloadURL, pd);
sleep(3000);
installApk(file);
pd.dismiss(); //结束掉进度条对话框
} catch (Exception e) {
//下载apk失败
ToastUtil.showToast(recieveActivity, "下载新版本失败");
e.printStackTrace();
}
}
}.start();
}
/**
* 从服务器获取apk文件的代码
* 传入网址uri,进度条对象即可获得一个File文件
* (要在子线程中执行)
* @param uri
* @param pd
* @return
* @throws Exception
*/
private static File getFileFromServer(String uri, ProgressDialog pd) throws Exception {
//如果相等的话表示当前的sdcard挂载在手机上并且是可用的
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
URL url = new URL(uri);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
//获取到文件的大小
pd.setMax(conn.getContentLength() / 1024);
InputStream is = conn.getInputStream();
long time = System.currentTimeMillis();//当前时间的毫秒数
File file = new File(Environment.getExternalStorageDirectory(), time + "updata.apk");
FileOutputStream fos = new FileOutputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len;
int total = 0;
while ((len = bis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
total += len;
//获取当前下载量
pd.setProgress(total / 1024);
}
fos.close();
bis.close();
is.close();
return file;
} else {
return null;
}
}
/**
* 安装apk
* @param file
*/
private static void installApk(File file) {
if (!file.exists()) {
return;
}
try {
Intent intent = new Intent();
//执行动作
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//版本在7.0以上是不能直接通过uri访问的
//兼容7.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(recieveActivity.getApplication().getApplicationContext(), recieveActivity.getPackageName() + ".fileprovider", file); //recieveActivity.getPackageName() 取得包名
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
//兼容8.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
boolean hasInstallPermission = recieveActivity.getPackageManager().canRequestPackageInstalls();
if (!hasInstallPermission) {
ToastUtil.showToast(recieveActivity, "安装app需要您勾选允许安装未知应用权限");
startInstallPermissionSettingActivity();
//return;
}
}
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
}
if (recieveActivity.getPackageManager().queryIntentActivities(intent, 0).size() > 0) {
recieveActivity.startActivity(intent);
}
//如果不加,最后不会提示完成、打开。
android.os.Process.killProcess(android.os.Process.myPid());
} catch (Throwable e) {
e.printStackTrace();
ToastUtil.showToast(recieveActivity, "未知应用权限开启失败,请重启应用");
}
}
/** * 跳转到设置-允许安装未知来源-页面 */
@RequiresApi(api = Build.VERSION_CODES.O)
private static void startInstallPermissionSettingActivity() {
//注意这个是8.0新API
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
recieveActivity.startActivityForResult(intent, 99);
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.i("VersionUtil", "此处重写失败,未解决。。。"); //在本功能暂不影响使用
}
}