您的位置:首页 > 移动开发

Android 在线下载更新App 下载完成安装APK(兼容Android7.0)

2017-12-06 11:52 971 查看
先上图:



首先对android7.0的打开文件方式进行适配


使用FileProvider

第一步:
在AndroidManifest.xml清单文件中注册provider,因为provider也是Android四大组件之一,可以简单把它理解为向外提供数据的组件,这种组件在实际开发中用的频率并不高,四大组件都可以在清单文件中进行配置。

<application
...>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.dl.install"
android:grantUriPermissions="true"
android:exported="false">
<!--元数据-->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>


注意:
exported
:要求必须为false,为true则会报安全异常。
grantUriPermissions:true
,表示授予
URI 临时访问权限。
authorities
 组件标识,按照江湖规矩,都以包名开头,避免和其它应用发生冲突。
第二步:指定共享的目录
上面配置文件中 
android:resource="@xml/file_paths"
 指的是当前组件引用 
res/xml/file_paths.xml
 这个文件。

我们需要在资源(res)目录下创建一个xml目录,然后创建一个名为“file_paths”(名字可以随便起,只要和在manifest注册的provider所引用的resource保持一致即可)的资源文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<paths>
<external-path path="" name="download"/>
</paths>
</resources>


<files-path/>代表的根目录: Context.getFilesDir()

<external-path/>代表的根目录: Environment.getExternalStorageDirectory()

<cache-path/>代表的根目录: getCacheDir()

上述代码中path="",是有特殊意义的,它代码根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了。

如果你将path设为path="pictures",那么它代表着根目录下的pictures目录(eg:/storage/emulated/0/pictures),如果你向其它应用
4000
分享pictures目录范围之外的文件是不行的。

第三步:使用FileProvider

上述准备工作做完之后,现在我们就可以使用FileProvider了。会在下个代码块中注释中具体解释

下面是下载安装的具体逻辑

首先在服务中创建DownloadManager

public class DownloadService extends Service {
private DownloadFinishReceiver mReceiver;
public DownloadService() {
}

@Override
public void onCreate() {
super.onCreate();

//注册下载完成的广播
mReceiver = new DownloadFinishReceiver();
registerReceiver(mReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}

@Override
public IBinder onBind(Intent intent) {
return new DownBinder();
}

class DownBinder extends Binder{
public void startDownload (String downUrl) {
//删除已经存在的apk包
File apkFile = new File(DownloadService.this.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "小熊.apk");
if (apkFile.exists()) {
apkFile.delete();
}
//初始化DownloadManager并开始下载
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downUrl));
File file = new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"小熊.apk");
request.setDestinationUri(Uri.fromFile(file));
DownloadManager mDownloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
mDownloadManager.enqueue(request);
}
}

//下载完成的广播
private class DownloadFinishReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
//Android获取一个用于打开APK文件的intent
Intent intent1 = new Intent(Intent.ACTION_VIEW);
// 由于没有在Activity环境下启动Activity,设置下面的标签
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if(Build.VERSION.SDK_INT>=24) { //判读版本是否在7.0以上
//参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
Uri apkUri =
FileProvider.getUriForFile(DownloadService.this, "com.example.dl.install",
new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"小熊.apk"));
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent1.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent1.setDataAndType(apkUri, "application/vnd.android.package-archive");
}else{
intent1.setDataAndType(Uri.fromFile(new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"小熊.apk")),
"application/vnd.android.package-archive");
}
DownloadService.this.startActivity(intent1);
}
}

@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
}
}

然后在anctivity中与服务bind绑定 布局文件只有一个按钮来模拟

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private Button btn;
private DownloadService.DownBinder binder;

private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (DownloadService.DownBinder) service;
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();

//与服务连接
Intent intent = new Intent(MainActivity.this,DownloadService.class);
startService(intent);
bindService(intent,connection,BIND_AUTO_CREATE);

}

private void initView() {
btn = (Button) findViewById(R.id.btn);

btn.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn:
binder.startDownload("http://cdn.xiaoxiongyouhao.com/apps/androilas.apk");
break;
}
}
}


最后添加权限 动态权限前文有使用介绍 这里我没有使用动态权限

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: