DownloadManager
简介
DownloadManager是系统(2.3以后)开放给第三方应用使用的类,包含两个静态内部类DownloadManager.Query和DownloadManager.Request。DownloadManager.Request用来请求一个下载,DownloadManager.Query用来查询下载信息。在大多数涉及到下载的情况中使用Download Manager都是不错的选择,特别是当用户切换不同的应用以后下载需要在后台继续进行,以及当下载任务顺利完。
简单展示
package com.lv.okgodemo;
import android.app.DownloadManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
/**
* Date: 2016-11-10
* Time: 16:24
* Description: 下載
*/
public class DownloadService extends Service {
private BroadcastReceiver receiver;
private DownloadManager dm;
public static final String DOWN_URL = "down_url";
private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//主要是检查url是否存在
if (intent == null || intent.getStringExtra(DOWN_URL) == null) {
stopSelf();
return Service.START_STICKY;
}
//初始化下载完成广播
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || dm == null)
return;
//判断是否是下载完成
if (TextUtils.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE, intent.getAction())) {
//获取下载完成的文件名称
Bundle extras = intent.getExtras();
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID));
Cursor c = dm.query(q);
if (c != null && c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
if (status == DownloadManager.STATUS_SUCCESSFUL) {
String title = c.getString(c.getColumnIndex(DownloadManager.COLUMN_TITLE));
//执行安装
intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_DOWNLOADS + File.separator + title)),
"application/vnd.android.package-archive");
startActivity(intent);
}
}
if (c != null)
c.close();
}
stopSelf();
}
};
//注册广播
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
//用项目名称作为apk的文件名称
PackageManager pm = this.getPackageManager();
String apkName = getApplicationInfo().loadLabel(pm).toString() + ".apk";
startDownload(intent.getStringExtra(DOWN_URL), apkName);
return Service.START_REDELIVER_INTENT;
}
/**
* 主要是处理小米手机的
* @param url 下载地址
* @return 真实的下载地址
*/
public String doRealUrl(String url) {
try {
//获取build Properties 判断是不是小米手机
Properties properties = new Properties();
properties.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
if (properties.getProperty(KEY_MIUI_VERSION_CODE, null) != null || properties.getProperty(KEY_MIUI_VERSION_NAME, null) != null
|| properties.getProperty(KEY_MIUI_INTERNAL_STORAGE, null) != null) {
url += " ";
}
return url;
} catch (final IOException e) {
return url;
}
}
@Override
public void onDestroy() {
try {
unregisterReceiver(receiver);
stopSelf();
super.onDestroy();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 启动下载
* @param url 地址
* @param apkName 文件名称
*/
private void startDownload(String url, String apkName) {
if (url == null)
return;
dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(doRealUrl(url)));
//下载网络需求 手机数据流量、wifi
request.setAllowedNetworkTypes( DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI ) ;
//设置是否允许漫游网络 建立请求 默认true
request.setAllowedOverRoaming( true ) ;
/*在默认的情况下,通过Download Manager下载的文件是不能被Media Scanner扫描到的 。
进而这些下载的文件(音乐、视频等)就不会在Gallery 和 Music Player这样的应用中看到。
为了让下载的音乐文件可以被其他应用扫描到,我们需要调用Request对象的
*/
request.allowScanningByMediaScanner() ;
//设置请求的Mime
request.setMimeType("application/vnd.android.package-archive");
/*如果我们希望下载的文件可以被系统的Downloads应用扫描到并管理,
我们需要调用Request对象的setVisibleInDownloadsUi方法,传递参数true。*/
request.setVisibleInDownloadsUi( true ) ;
//设置下载路径
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkName);
//执行下载
dm.enqueue(request);
}
}
而我们启动的时候也很是简单,在Activity中
startService(new Intent(this, DownloadService.class).putExtra(DownloadService.DOWN_URL, url));
这就是简单的下载了。本文只是做一个简单的事例,没有去考虑太多情况。
那接下来说说我遇见的坑
没错就是代码中针对小米手机的处理。我们公司的apk防在一个服务器上,我用DownloadManager进行下载的时候始终是完成不了,而换成其他手机或者浏览器都是没有问题的。最后我才发现原来是要在url最后面加一个空格,但是如果每次都加一个空格其他手机又没办法识别了,所以才有了doRealUrl这个方法的判断是不是小米,以及处理url。
最后感谢大家浏览,有什么不对的地方请大家指正。