1. DownloadManager简介
网上看到说DownloadManager存在适配问题,如三星部分手机需要生动开启权限,国内还有部分手机直接阉割了DownloadManager,因此,这里只做个介绍,了解即可。
功能:
DownloadManager是系统自带的下载管理器,可在通知栏查看下载进度。
要使用DownloadManager,需要了解DownloadManger的两个内部类,Request
和Query
。
- Request类可设置下载的一些属性。
- Query类可查询当前下载的进度,下载地址,文件存放目录等数据。
权限
//适配android 8.0 系统手机权限
使用
DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
long id = downloadManager.enqueue(request);
//每下载的一个文件对应一个id,通过此id可以查询数据。
取消下载
2. Request类
指定下载位置,及文件名称
/**
* 方法1:
* 目录: Android -> data -> com.app -> files -> Download -> dxtj.apk
* 这个文件是你的应用所专用的,软件卸载后,下载的文件将随着卸载全部被删除
*/
request.setDestinationInExternalFilesDir( this , Environment.DIRECTORY_DOWNLOADS , "dxtj.apk" );
/**
* 方法2:
* 下载的文件存放地址 SD卡 download文件夹,dxtj.apk
* 软件卸载后,下载的文件会保留
*/
request.setDestinationInExternalPublicDir( "/epmyg/" , "dxtj.apk" ) ;
/**
* 方法3:
* 如果下载的文件希望被其他的应用共享
* 特别是那些你下载下来希望被Media Scanner扫描到的文件(比如音乐文件)
*/
request.setDestinationInExternalPublicDir( Environment.DIRECTORY_MUSIC, "告白气球.mp3" );
/**
* 方法4
* 文件将存放在外部存储的确实download文件内,如果无此文件夹,创建之,如果有,下面将返回false。
* 系统有个下载文件夹,比如小米手机系统下载文件夹 SD卡--> Download文件夹
*/
//创建目录 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ;
//设置文件存放路径
request.setDestinationInExternalPublicDir( Environment.DIRECTORY_DOWNLOADS , "dxtj.apk" ) ;
指定下载的网络类型
//指定在WIFI状态下,执行下载操作。
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
//指定在MOBILE状态下,执行下载操作
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE);
//是否允许漫游状态下,执行下载操作
request.setAllowedOverRoaming(boolean);
//是否允许“计量式的网络连接”执行下载操作
request.setAllowedOverMetered(boolean); //默认是允许的。
定制Notification样式
//设置Notification的标题和描述
request.setTitle("标题");
request.setDescription("描述");
//设置Notification的显示,和隐藏。
request.setNotificationVisibility(visibility);
设置下载文件类型:
request.setMimeType("application/vnd.android.package-archive");
这是安卓.apk文件的类型。有些机型必须设置此方法,才能在下载完成后,点击通知栏的Notification时,才能正确的打开安装界面。不然会弹出一个Toast(can not open file)。
添加请求下载的网络链接的http头,比如User-Agent,gzip压缩等:
request.addRequestHeader(String header, String value);
3. Query 类
DownloadManager下载过程中,把相关数据保存到数据库中,如果你需要获取相关数据信息,需要通过Query实现。
DownloadManager.Query query = new DownloadManager.Query();
//获取Cursor
Cursor cursor = downloadManager.query(query.setFilterById(id));
if (cursor != null && cursor.moveToFirst()) {
//下载的文件到本地的目录
String address = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
//已经下载的字节数
int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
//总需下载的字节数
int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
//Notification 标题
String title =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
//描述
String description =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION));
//下载对应id
long id =cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
//下载文件名称
String filename =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
//下载文件的URL链接
String url =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
}
4. 监听广播
public class DownLoadBroadcastReceiver extends BroadcastReceiver {
@SuppressLint("NewApi")
public void onReceive(Context context, Intent intent) {
long myDwonloadID = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, -1);
LogUtils.i("下载完成 ID = " + myDwonloadID);
SharedPreferences sPreferences = context.getSharedPreferences(
"downloadplato", 0);
long refernece = sPreferences.getLong("plato", 0);
if (refernece == myDwonloadID) {
String serviceString = Context.DOWNLOAD_SERVICE;
DownloadManager dManager = (DownloadManager) context
.getSystemService(serviceString);
Intent install = new Intent(Intent.ACTION_VIEW);
Uri downloadFileUri = dManager
.getUriForDownloadedFile(myDwonloadID);
...
}
}
}
注册监听
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
5. Demo
创建DownloadManager.Request
,设置相关request配置,DownloadManager
发起下载请求,相关代码如下:
private void downloadApk(String url) {
DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setMimeType("application/vnd.android.package-archive")
//设置允许下载的网络情况
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI)
//移动网络情况下是否允许漫游
.setAllowedOverRoaming(false)
//表示下载进行中和下载完成的通知栏是否显示。
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
//设置下载的路径
.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS,"appname.apk");
long downloadId = downloadManager.enqueue(request);
SharedPreferences sp = getSharedPreferences("apkinfo", Context.MODE_PRIVATE);
sp.edit().putLong("downloadId", downloadId).commit();
}
其中url是下载最新apk的url地址。
request.setTitle(“MeiLiShuo”);设置下载中通知栏提示的标题
request.setDescription(“MeiLiShuo desc”);设置下载中通知栏提示的介绍
发起下载请求后,需要自定义广播(接收下载完成的通知),并注册监听。
public class ApkDownloadBroadcast extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID,-1);
Log.e("WelcomeActivity","下载完成,下载id="+id);
SharedPreferences sp = context.getSharedPreferences("apkinfo",0);
long downloadId = sp.getLong("downloadId",0);
if (id == downloadId){
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = downloadManager.getUriForDownloadedFile(downloadId);
Log.e("WelcomeActivity","apk保存的地址="+downloadUri.toString());
//TODO apk安装
}
}
}
注册广播 / 取消注册
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
broadcast = new ApkDownloadBroadcast();
registerReceiver(broadcast,intentFilter);
...
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(broadcast);
}