前言
- 在android应用开发中经常会遇到应用升级和下载第三方应用的需求。
- 这篇博客介绍了关于下apk获取写入权限问题。和7.0以及7.0以上版本的手机读取不到apk而无法安装的问题。
- 该下载方式适应各种版本,处理了一系列遇到的问题。
正文
Activity类
/**
*
* 这demo有两个地方比较重要
* 1,下载apk的地址,这里决定了6.0和以上的额版本是否需要使用动态写入权限。
* 2,在DownloadManagerUtil类里面的StrictMode的使用。这将决定7.0以及7.0以上的系统是否能读取到apk文件并启动安装。
*/
public class MainActivity extends Activity {
private String url = "http://p.gdown.baidu.com/2c94946f0e26ae462034226fde89692a269f6bdf2aa6e9c8767d772124c9f7c7d260e6931fef78f570c881e16b38ef5c2078652c803b022fe844fb87d68c894ddbef8a9694a05f1e0ff373231ca712808c4440578d04145cdba6bc15f63a58840b47586cd429087098129921afed1197f1295b0f2cf49ff9250a04c0d4ef1ae92fdb5712c98e32f6be819bd5d37ee48e968923ef76a8cc7fb9742033e72b07c84dd4e14dc8d7931011e1242b1a867296948cf07eaea2a39a3dfd57541fe83eade2e5b448b9ba397e0a84fc90bc2405b969c9634da0803afc6b0464e4a7e333bb0c7072bd418e99312b5457043c33f156a13660aba0be6f15";//较小的apk文件
private String url2 = "http://mhhy.dl.gxpan.cn/apk/ml/MBGYD092101/Gardenscapes-ledou-MBGYD092101.apk";//梦幻花园游戏包体较大,可以很好的查看下载效果
private String title = "应用宝";//这里可以写应用名
private String desc = "大量优质应用,尽在应用宝。";//这里填写一些对应用的介绍
long downloadId = 0;
DownloadManagerUtil downloadManagerUtil;
private boolean isRegisterReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PublicUtile.getInstance().setmActivity(this);
setReceiver();
RelativeLayout rlParentContainer = new RelativeLayout(this.getApplicationContext());
setContentView(rlParentContainer);
RelativeLayout.LayoutParams rlp_tv = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
rlp_tv.addRule(RelativeLayout.CENTER_HORIZONTAL);
TextView tv = new TextView(this.getApplicationContext());
tv.setText("DownLoadManager Test");
rlParentContainer.addView(tv, rlp_tv);
RelativeLayout.LayoutParams rlp_button = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
rlp_button.addRule(RelativeLayout.CENTER_IN_PARENT);
Button download = new Button(this.getApplicationContext());
download.setText("开始下载...");
rlParentContainer.addView(download, rlp_button);
downloadManagerUtil = new DownloadManagerUtil(this);
download.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//调起系统下载功能
if (downloadId != 0) {
downloadManagerUtil.clearCurrentTask(downloadId);
}
downloadId = downloadManagerUtil.download(url, title, desc);
}
});
}
/**
* 注册下载成功的广播监听
*/
private void setReceiver() {
if (!isRegisterReceiver) {
DownloadReceiver receiver = new DownloadReceiver();
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
this.registerReceiver(receiver, intentFilter);
isRegisterReceiver = true;
}
}}
/**
* Created by lenovo on 2018/6/17.
* 下载成功广播类
*/
public class DownloadReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
installApk(context, id, PublicUtile.getApkDownPath(context) + PublicUtile.TestApkName);
} else if (intent.getAction().equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
//处理 如果还未完成下载,用户点击Notification ,跳转到下载中心
Intent viewDownloadIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
viewDownloadIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(viewDownloadIntent);
}
}
/**
* 启动安装
*
* @param context
* @param downloadApkId
* @param apkPath
*/
private static void installApk(Context context, long downloadApkId, String apkPath) {
DownloadManager dManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Intent install = new Intent(Intent.ACTION_VIEW);
Uri downloadFileUri = dManager.getUriForDownloadedFile(downloadApkId);
if (downloadFileUri != null) {
Log.e("DownloadManager", downloadFileUri.toString());
install.setDataAndType(Uri.parse("file://" + apkPath), "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
} else {
Log.e("DownloadManager", "download error");
}
}
}
/**
* Created by lenovo on 2018/6/17.
* 下载类
*/
public class DownloadManagerUtil {
private Context mContext;
public DownloadManagerUtil(Context context) {
mContext = context;
}
// //简单的下载功能
// public long download(String url, String title, String desc) {
// Uri uri = Uri.parse(url);
// DownloadManager.Request req = new DownloadManager.Request(uri);
// //设置WIFI下进行更新
// req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
// //下载中和下载完后都显示通知栏
// req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// //使用系统默认的下载路径 此处为应用内 /android/data/packages ,所以兼容7.0
// req.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, title);
// //通知栏标题
// req.setTitle(title);
// //通知栏描述信息
// req.setDescription(desc);
// //设置类型为.apk
// req.setMimeType("application/vnd.android.package-archive");
// //获取下载任务ID
// DownloadManager dm = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
// return dm.enqueue(req);
// }
/**
* 比较实用的升级版下载功能
*
* @param url 下载地址
* @param title 文件名字
* @param desc 文件路径
*/
public long download(String url, String title, String desc) {
DownloadManager downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
long ID;
//以下两行代码可以让下载的apk文件被直接安装而不用使用Fileprovider,系统7.0或者以上才启动。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder localBuilder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(localBuilder.build());
}
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
// 仅允许在WIFI连接情况下下载
// request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
// 通知栏中将出现的内容
request.setTitle(title);
request.setDescription(desc);
//7.0以上的系统适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
request.setRequiresDeviceIdle(false);
request.setRequiresCharging(false);
}
//制定下载的文件类型为APK
request.setMimeType("application/vnd.android.package-archive");
// 下载过程和下载完成后通知栏有通知消息。
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE | DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// 指定下载文件地址,使用这个指定地址可不需要WRITE_EXTERNAL_STORAGE权限。
request.setDestinationUri(Uri.fromFile(new File(PublicUtile.getApkDownPath(mContext) + PublicUtile.TestApkName)));
//大于11版本手机允许扫描
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
//表示允许MediaScanner扫描到这个文件,默认不允许。
request.allowScanningByMediaScanner();
}
Activity activity = PublicUtile.getInstance().getmActivity();
if (activity != null) {
activity.startActivity(new android.content.Intent(DownloadManager.ACTION_VIEW_DOWNLOADS));//启动系统下载界面
}
ID = downloadManager.enqueue(request);
return ID;
}
/**
* 下载前先移除前一个任务,防止重复下载
*
* @param downloadId
*/
public void clearCurrentTask(long downloadId) {
DownloadManager dm = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
try {
dm.remove(downloadId);
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
}
}
以上为重要代码。
最后如果有更好的实现方式或者有其他问题,欢迎在评论区留言交流。