最近在弄android整包下载,使用到Downloadmanager
下载和安装,新手尝试,欢迎大家指正。
关于 FileProvider 百度一下很简单。
public class ApkDownloadMgr {
//下载器
private DownloadManager m_dMgr;
private Context m_context;
private long m_downloadID = 0;
private String apkName ="";
private String apkPath = "";
private String file_name = "download_id";
private boolean hasRegister = false;
private final String GW_LINK = "http://xxx.com"; //下载失败直接打开移动官网
private int returnType_1 = 1; //浏览器下载
private int returnType_2 = 2; //app内下载 或者 删除文件成功重新下载
private int returnType_3 = 3; //已下载成功,直接安装
private int returnType_4 = 4; //删除文件失败
public static final Uri CONTENT_URI = Uri.parse("content://downloads/my_downloads");
private DownLoadChangeObserver downloadObserver;
private Activity m_activity;
private String saveName = ""; //保存到文件到下载文件名字
private enum CheckType{
CHECK_BEFOR_DOWN,
CHECK_AFTER_DOWN
};
public ApkDownloadMgr(Context context,Activity activity)
{
this.m_context = context;
m_activity = activity;
}
private boolean canDownloadState(Context ctx) {
try {
int state = ctx.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads");
if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|| state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
|| state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
//下载apk
public int downloadApk(String url,String name)
{
//创建下载任务
//创建下载任务
if( !canDownloadState(m_context)) { // 不可用
//浏览器下载
return returnType_1;
}
apkName = name;
//获取DownloadManager
m_dMgr = (DownloadManager) m_context.getSystemService(Context.DOWNLOAD_SERVICE);
//File file = new File(m_context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),name);
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), apkName);
if(file.exists()) { //判断文件是否存在
System.out.println("文件存在 "+file.getName());
if(readSaveFile()){//判断下载任务记录是否存在
//判断任务id的状态
checkStatus(CheckType.CHECK_BEFOR_DOWN);
//installAPK();
return returnType_3;
}else{
//删除下载的文件
if(!file.delete())
{
return returnType_4;
}
}
}
Request request = new Request(Uri.parse(url));
//移动网络情况下是否允许漫游
request.setAllowedOverRoaming(false);
//在通知栏中显示,默认就是显示的 隐藏通知栏
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.setTitle(name);
request.setVisibleInDownloadsUi(true);
request.allowScanningByMediaScanner();
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
//设置下载的路径
//request.setDestinationInExternalPublicDir(path , name);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, name);
apkPath = Environment.DIRECTORY_DOWNLOADS+"/"+name;
System.out.println(" 文件路径 "+apkPath);
System.out.println(" Environment.DIRECTORY_DOWNLOADS "+ Environment.DIRECTORY_DOWNLOADS);
//将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等
m_downloadID= m_dMgr.enqueue(request);
writeDownloadId(m_downloadID,name); //下载开始后保存下载id;
//在通知栏显示下载进度
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
request.allowScanningByMediaScanner();
//request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
//注册广播接收者,监听下载状态
m_context.registerReceiver(receiver,
new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
downloadObserver = new DownLoadChangeObserver(null);
m_context.getContentResolver().registerContentObserver(CONTENT_URI, true, downloadObserver);
hasRegister = true;
return returnType_2;
}
/*
* 应该保存任务id 和 对应但文件名
* 目前只保存了任务id
*/
private void writeDownloadId(long did,String name){
try{
FileOutputStream fout = m_context.openFileOutput(file_name, Context.MODE_PRIVATE); //保存到data/data/包名/files/ (可写目录)
Log.i(" msg ", String.valueOf(did));
System.out.println(did);
String strTemp = String.valueOf(did)+","+name;
byte [] bytes = strTemp.getBytes();
fout.write(bytes);
fout.flush();
fout.close();
Log.d("msg", " -- write download_id succe ");
}catch(Exception e){
e.printStackTrace();
Log.d("msg", " -- write download_id falied ");
}
}
private boolean readSaveFile() {
FileInputStream inputStream;
try {
File file = new File(m_context.getFilesDir().getAbsolutePath(),file_name);
if(!file.exists())
{
System.out.println(file_name +" no file read failed ");
return false;
}
inputStream = m_context.openFileInput(file_name);
byte temp[] = new byte[1024];
StringBuilder sb = new StringBuilder("");
int len = 0;
while ((len = inputStream.read(temp)) > 0){
sb.append(new String(temp, 0, len));
}
Log.d("msg", "readSaveFile: " + sb.toString());
String fileStr = sb.toString();
if(fileStr != ""){
String[] strs = fileStr.split(",");
m_downloadID = Long.parseLong(strs[0]);
saveName = strs[1];
}
inputStream.close();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context arg0, Intent arg1) {
checkStatus(CheckType.CHECK_AFTER_DOWN);
}
};
//检查下载状态
private void checkStatus(CheckType checkStatus) {
Query query = new Query();
//通过下载的id查找
query.setFilterById(m_downloadID);
System.out.println(" create c ");
Cursor c = m_dMgr.query(query);
System.out.println(" create c 2");
if (c == null )
System.out.println("下载任务不存在 ");
if (c!=null && c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
System.out.println(" --- status "+status);
switch (status) {
//下载暂停
case DownloadManager.STATUS_PAUSED:
if (checkStatus == CheckType.CHECK_BEFOR_DOWN) {
//如果是创建新任务之前检测任务状态 任务暂停状态直接跳转浏览器
AppActivity.openWebURL(GW_LINK); //跳转浏览器
}
break;
//下载延迟
case DownloadManager.STATUS_PENDING:
break;
//正在下载
case DownloadManager.STATUS_RUNNING:
System.out.println("---- start running --");
if (checkStatus == CheckType.CHECK_BEFOR_DOWN) {
Log.d("-- check status", " 新任务 前检测");
//如果是创建新任务之前检测任务状态 添加广播监听
m_context.registerReceiver(receiver,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
downloadObserver = new DownLoadChangeObserver(null);
m_context.getContentResolver().registerContentObserver(CONTENT_URI, true, downloadObserver);
hasRegister = true;
}
break;
//下载完成
case DownloadManager.STATUS_SUCCESSFUL:
System.out.println("---- start download --");
//下载完成安装APK
//isGoging=false;
installAPK(c);
break;
//下载失败
case DownloadManager.STATUS_FAILED:
//isGoging=false;
Toast.makeText(m_context, "下载失败", Toast.LENGTH_SHORT).show();
if(hasRegister){
m_context.unregisterReceiver(receiver);
m_context.getContentResolver().unregisterContentObserver(downloadObserver);
}
AppActivity.openWebURL(GW_LINK); //跳转浏览器
break;
}
}
c.close();
}
//下载到本地后执行安装
private void installAPK(Cursor c) {
//if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
if(Build.VERSION.SDK_INT >= 24)
{
System.out.println("--- install apk on 7.0 --");
System.out.println(" apkpath "+apkPath);
// File file= new File(apkPath);
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), apkName);
System.out.println("--- install apk 1 --");
Uri apkUri = FileProvider.getUriForFile(m_context, "com.xxx.fileprovider", file);//在AndroidManifest中的android:authorities值
System.out.println("--- install apk 2 --");
Intent install = new Intent(Intent.ACTION_VIEW);
// install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//添加这一句表示对目标应用临时授权该Uri所代表的文件
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
System.out.println("--- install apk 3 --");
m_context.startActivity(install);
if(hasRegister){
m_context.unregisterReceiver(receiver);
m_context.getContentResolver().unregisterContentObserver(downloadObserver);
}
System.out.println("--- install apk on 7.0 end --");
}else {
//获取下载文件的Uri
if(m_dMgr == null) m_dMgr = (DownloadManager) m_context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadFileUri = m_dMgr.getUriForDownloadedFile(m_downloadID);
if (downloadFileUri != null) {
Intent intent= new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
//以下trycatch 是为处理 Error receiving broadcast Intent { act=android.intent.action.DOWNLOAD_COMPLETE flg=0x10 pkg=com.kamron.pogoiv (has extras) } 这个错误
//三星 5c pro会发生此异常
try {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
m_context.startActivity(intent);
System.out.println(" --正常逻辑 安装完成");
} catch (ActivityNotFoundException e) {
e.printStackTrace();
String filePath= c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive");
installIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
m_context.startActivity(installIntent);
System.out.println(" --try catch 安装完成");
}
if(hasRegister){
m_context.unregisterReceiver(receiver);
m_context.getContentResolver().unregisterContentObserver(downloadObserver);
}
}
}
}
private class DownLoadChangeObserver extends ContentObserver{
public DownLoadChangeObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
queryDownloadStatus();
}
}
//只查询进度
private void queryDownloadStatus() {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(m_downloadID);
Cursor c = m_dMgr.query(query);
if(c!=null&&c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch(status) {
case DownloadManager.STATUS_PAUSED:
Log.v("tag", "STATUS_PAUSED");
case DownloadManager.STATUS_PENDING:
Log.v("tag", "STATUS_PENDING");
case DownloadManager.STATUS_RUNNING:
Log.v("tag", "STATUS_RUNNING");
/**
* 计算下载下载率;
*/
int totalSize = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
int currentSize = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
final int progress = (int) (((float) currentSize) / ((float) totalSize) * 100);
System.out.println(" -----percent "+progress);
((AppActivity)m_activity).runOnGLThread(new Runnable() {
@Override
public void run() {
int ret = Cocos2dxLuaJavaBridge.callLuaGlobalFunctionWithString("receiveUpdateProgress", progress+"");
Log.d(" --- runable ", " ret "+ret);
}
});
break;
case DownloadManager.STATUS_SUCCESSFUL:
//完成
Log.v("tag", "383 下载完成");
// dowanloadmanager.remove(lastDownloadId);
((AppActivity)m_activity).runOnGLThread(new Runnable() {
@Override
public void run() {
int ret = Cocos2dxLuaJavaBridge.callLuaGlobalFunctionWithString("receiveUpdateProgress", "100");
Log.d(" --- runable ", " ret "+ret);
}
});
break;
case DownloadManager.STATUS_FAILED:
//清除已下载的内容,重新下载
Log.v("tag", "STATUS_FAILED");
break;
}
}
}
}