service使用案例(文件下载)

应用程序下载,并在通知栏提醒下载完成。过程大概分成三步:

  1. 创建一个service
  2. 在service启动的时候创建一个广播接收者
  3. 当BroadcastReceiver接收到下载完成的广播时,开始执行安装

此过程兼容了Android 7.0权限限制安装功能,Android 7.0 因为设置了“私有目录被限制访问”,“StricMode API”等安全机制,因此安装时会产生FileUriExposedException错误,此错误用FileProvider解决。

  1. 在AndroidMenifest.xml文件中注册provider,向外提供数据的组件。其中exported="false"必须设置成false,否则会报安全异常;grantUriPermissions="true"表示授予Uri临时访问权限;authorities组件标识,一般以包名开头。

    
       
       
    
    
  2. 指定共享的目录。在res文件下创建一个xml目录,再在xml目录下创建一个名为file_paths的资源文件。其中,file-path 表示Context.getFilesDir(),external-path表示Environment.getExternalStorageDirectory(),cache-path表示 getCacheDir()。

    
    
      
            //path="" 表示共享根目录以及根目录下所有文件
      
    
    
  3. 使用FileProvider ,主要代码片段如下

    Uri apkUri = FileProvider.getUriForFile(context,"com.nxyuntui.testproject.fileprovider",file);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    
  4. RxPermission 第三方动态库申请权限
    首先gradle中添加动态库,接着申请权限。

    implementation 'com.tbruyelle.rxpermissions:rxpermissions:0.7.0@aar'
    implementation 'io.reactivex:rxjava:1.1.6'
    
    //申请sd卡权限,targetSdkVersion>=23,需要动态申请
    RxPermissions.getInstance(this)
    //申请权限
    .request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
    .subscribe(new Action1() {
        @Override
        public void call(Boolean aBoolean) {
            if (aBoolean){
                //请求成功
                startDownload(downloadUrl);
            }else{
                //请求失败回收当前服务
                stopSelf();
            }
        }
    });
    

整体示例如下 :
AndroidMenifest.xml






  
  


DownLoadService.java

public class DownLoadService extends Service {
private BroadcastReceiver receiver;
private DownloadManager dm;
private long enqueue;
private String downloadUrl = "http://downapp.baidu.com";

@Override
public void onCreate() {
    super.onCreate();
    Log.i("DownLoadService","--onCreate");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.i("DownLoadService","--onStartCommand");
    receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            install(context);
            stopSelf();   //销毁当前service
        }
    };
    registerReceiver(receiver,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

    //申请sd卡权限,targetSdkVersion>=23,需要动态申请
    RxPermissions.getInstance(this)
            //申请权限
            .request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
            .subscribe(new Action1() {
                @Override
                public void call(Boolean aBoolean) {
                    if (aBoolean){
                        //请求成功
                        startDownload(downloadUrl);
                    }else{
                        //请求失败回收当前服务
                        stopSelf();
                    }
                }
            });
    return Service.START_STICKY;
}

@Override
public void onDestroy() {
    super.onDestroy();
    Log.i("DownLoadService","--onDestroy");
    unregisterReceiver(receiver);
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

public static void install(Context context){
    File file = new File(
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
            "myApp.apk");
    Intent intent = new Intent(Intent.ACTION_VIEW);
    //没有在Activity环境下启动activity,设置如下标签
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    if (Build.VERSION.SDK_INT >= 24){
        Uri apkUri = FileProvider.getUriForFile(context,
                "com.nxyuntui.testproject.fileprovider",file);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(apkUri,"application/vnd.android.package-archive");
    }else{
        intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");
    }
    context.startActivity(intent);
}

private void startDownload(String downloadUrl){
    //获得系统下载器
    dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    //设置下载地址
    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
    //设置下载文件的类型
    request.setMimeType("application/vnd.android.package-archive");
    //设置下载存放的文件夹和文件名称
    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,"myApp.apk");
    //设置下载时或下载完成时,通知栏是否显示
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    request.setTitle("下载新版本");
    //执行下载,并返回任务唯一id
    enqueue = dm.enqueue(request);
}
}

MainActivity.java
oncreat()里面调用此方法即可。

public void download(View view){
  Log.i("MainActivity","--下载服务");
  Intent intent = new Intent(this,DownLoadService.class);
  startService(intent);
}

activity_main.xml

你可能感兴趣的:(Android,Service,Broadcast,下载安装)