请选择 进入手机版 | 继续访问电脑版

Android 版本更新------后台服务和前台通知栏实现

[复制链接]
谭先生 发表于 2021-1-2 11:52:06 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
前言:最近公司项目版本需要把以前的版本更新代码更新一下,换成Service和前台通知栏形式的,所以在此记录一下。
目次
1.检测版本更新(省略)
2.创建Service开启前台通知栏,而且执行下载任务,将下载进度通知到通知栏,下载完成后举行安装
  完整的Service代码
Service所用到的变量增补
2.开启一个透明InstallApkActivity执行安装Apk操纵
  Activity代码
工具类代码
3.注意事项:因为24版本之后读取文件需要设置FileProvider,否则无法读取到apk文件
在res目次下建一个xml文件夹,然后创建file_path.xml文件
AndroidManifest.xml设置
OnlineFileProvider类代码
1.检测版本更新(省略)

这一步一般是通过背景接口对比当前APP版本是否低于服务器版本,从而获取最新版本的下载链接。这一步比力简单所以省略了。
2.创建Service开启前台通知栏,而且执行下载任务,将下载进度通知到通知栏,下载完成后举行安装

  完整的Service代码

  1. package com.qtz.online.service;import android.app.Notification;import android.app.NotificationChannel;import android.app.NotificationManager;import android.app.Service;import android.content.Context;import android.content.Intent;import android.os.Build;import android.os.IBinder;import androidx.annotation.Nullable;import androidx.core.app.NotificationCompat;import com.qtz.online.R;import com.qtz.online.common.AppService;import com.qtz.online.event_bus.DownloadApkMessage;import com.qtz.online.mvp.activitys.InstallApkActivity;import com.qtz.online.network.callback.ServiceDownloadObserver;import com.qtz.online.network.client.DownLoadClient;import com.qtz.online.utils.LogUtil;import org.greenrobot.eventbus.EventBus;import io.reactivex.Observable;import io.reactivex.android.schedulers.AndroidSchedulers;import io.reactivex.schedulers.Schedulers;import okhttp3.ResponseBody;/** * @author Created by PengGuiChu on 2020/12/19 19:32. * @explain  版本更新服务 */public class DownloadApkService extends Service {    private static final String TAG=DownloadApkService.class.getSimpleName();    private String url;//下载    private String fileDir;    private String fileName;    private NotificationManager notificationManager;    private NotificationCompat.Builder notificationBuilder;    private static final String name="download_apk";    private static final String id="Download_APK";    private static final int startForegroundId=777;    private int downLoadProgress;    @Override    public void onCreate() {        super.onCreate();        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);        notificationBuilder = getNotificationBuilder(notificationManager,getString(R.string.version_upgrade),getString(R.string.downloading,"0%"));        notificationBuilder.setProgress(100,0,false);        startForeground(startForegroundId,notificationBuilder.build());//        notificationManager.notify(2,notificationBuilder.build());    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        if (intent!=null){            url=intent.getStringExtra("url");            fileDir=intent.getStringExtra("fileDir");            fileName=intent.getStringExtra("fileName");            //该下载请求是我项目的下载请求,需要替换成你项目的下载文件的请求            downloadFile(DownLoadClient.getService(AppService.class).download(url), new ServiceDownloadObserver(fileDir,fileName) {                @Override                public void onDownloadStart() {                }                @Override                public void onDownloading(long progress, long total) {                    int down= (int) (progress*100/total);                    if (down!=downLoadProgress){                        downLoadProgress=down;                        if (notificationBuilder!=null){                            notificationBuilder.setContentText(getString(R.string.downloading,downLoadProgress+"%"));                            notificationBuilder.setProgress(100, downLoadProgress,false);                        }                        if (notificationManager!=null){                            notificationManager.notify(startForegroundId,notificationBuilder.build());                        }                    }                }                @Override                public void onDownloadSuccess(ResponseBody responseBody, String filePath) {                    LogUtil.d(TAG,"下载完成,开启一个空缺Activity执行安装窗口,包管用户在任何地方都能开启安装步调");//                    EventBus.getDefault().post(new DownloadApkMessage(0,filePath));                    Intent intent=new Intent(getApplicationContext(), InstallApkActivity.class);                    intent.putExtra("filePath",filePath);                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                    startActivity(intent);                    stopForeground(true);                    stopSelf();                }                @Override                public void onDownloadError(String msg) {                    LogUtil.d(TAG,"下载堕落");                    EventBus.getDefault().post(new DownloadApkMessage(1,msg));                    stopForeground(true);                    stopSelf();                }            });        }        return super.onStartCommand(intent, flags, startId);    }    private NotificationCompat.Builder getNotificationBuilder(NotificationManager notificationManager, String title, String message) {        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {            NotificationChannel channel = new NotificationChannel(DownloadApkService.id, DownloadApkService.name,                    NotificationManager.IMPORTANCE_LOW);            //闪光灯            channel.enableLights(false);            //是否允许震动            channel.enableVibration(false);            //设置可绕过  请勿打搅模式            channel.setBypassDnd(false);            channel.setSound(null,null);            notificationManager.createNotificationChannel(channel);        }        NotificationCompat.Builder notification = new NotificationCompat.Builder(this, DownloadApkService.id);        notification.build().flags= Notification.FLAG_ONGOING_EVENT;        notification.setContentTitle(title);        notification.setDefaults(NotificationCompat.DEFAULT_VIBRATE);        notification.setContentText(message);        notification.setSmallIcon(R.mipmap.ic_launcher);        notification.setAutoCancel(false);        notification.setCategory(Notification.CATEGORY_PROGRESS);        return notification;    }    protected void downloadFile(Observable downloadObservable, final ServiceDownloadObserver downloadObserver) {        downloadObservable.subscribeOn(Schedulers.io())//请求网络 在调理者的io线程                .observeOn(Schedulers.io()) //指定线程生存文件                .doOnNext(downloadObserver::saveFile)                .observeOn(AndroidSchedulers.mainThread()) //在主线程中更新ui                .subscribe(downloadObserver);    }}
复制代码
Service所用到的变量增补

  1. 发现新版本下载中…%1$s
复制代码
2.开启一个透明InstallApkActivity执行安装Apk操纵

  Activity代码

  1. package com.qtz.online.mvp.activitys;import android.content.Intent;import android.content.pm.PackageManager;import android.os.Bundle;import androidx.annotation.NonNull;import androidx.annotation.Nullable;import androidx.appcompat.app.AppCompatActivity;import com.qtz.online.R;import com.qtz.online.utils.InstallApkUtil;import java.io.File;public class InstallApkActivity extends AppCompatActivity {    private InstallApkUtil installApkUtil;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_install_apk);        String filePath = getIntent().getStringExtra("filePath");        initInstallApkUtil(new File(filePath));    }    private void initInstallApkUtil(File file) {        if (installApkUtil == null) {            installApkUtil = new InstallApkUtil(InstallApkActivity.this, file.getAbsolutePath());        }        installApkUtil.installApk();    }    //更具用户授权回调执行安装操纵    @Override    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if (requestCode == 101) {            if (installApkUtil != null) {                installApkUtil.installApk();            }        }else if (requestCode==102){            finish();        }    }}
复制代码
工具类代码

  1. package com.qtz.online.utils;import android.app.AlertDialog;import android.content.Context;import android.content.Intent;import android.net.Uri;import android.os.Build;import android.provider.Settings;import androidx.appcompat.app.AppCompatActivity;import androidx.core.content.FileProvider;import com.qtz.online.BuildConfig;import com.qtz.online.base.BaseActivity;import com.qtz.online.view.ChoiceDialog;import org.greenrobot.eventbus.EventBus;import java.io.File;/** * @author Created by PengGuiChu on 2020/12/19 15:53. * @explain */public class InstallApkUtil {    private AppCompatActivity baseActivity;    private String apkPath;    private ChoiceDialog choiceDialog;    public InstallApkUtil(AppCompatActivity baseActivity, String apkPath) {        this.baseActivity = baseActivity;        this.apkPath=apkPath;    }    public void installApk() {        if (Build.VERSION.SDK_INT >= 26) {            //来判定应用是否有权限安装apk            boolean installAllowed = baseActivity.getPackageManager().canRequestPackageInstalls();            //有权限            if (installAllowed) {                //安装apk                install();            } else {//这里弹出一个选择对话框,提示用户需要授权第三方安装应用,需要自己实现                if (choiceDialog==null){                    choiceDialog = new ChoiceDialog(baseActivity, new ChoiceDialog.ClauseDialogCallBack() {                        @Override                        public void onExit() {                            baseActivity.finish();                        }                        @Override                        public void onAgree() {                            Uri packageURI = Uri.parse("package:" + baseActivity.getPackageName());                            Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);                            baseActivity.startActivityForResult(intent, 101);                        }                    }, "安装应用需要打开未知泉源权限,请去设置中开启权限", "权限申请", "取消", "前往");                }                choiceDialog.show();            }        } else {            install();        }    }    public void install() {        if (Build.VERSION.SDK_INT >= 24) {            Uri apkUri = FileProvider.getUriForFile(baseActivity,                    BuildConfig.APPLICATION_ID + ".myprovider", new File(apkPath));            Intent installIntent = new Intent(Intent.ACTION_VIEW);            installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);            installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);            installIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");            baseActivity.startActivityForResult(installIntent,102);        } else {            Intent intent = new Intent(Intent.ACTION_VIEW);            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);            intent.setDataAndType(Uri.parse("file://" + apkPath), "application/vnd.android.package-archive");            baseActivity.startActivityForResult(intent,102);        }    }}
复制代码
3.注意事项:因为24版本之后读取文件需要设置FileProvider,否则无法读取到apk文件

在res目次下建一个xml文件夹,然后创建file_path.xml文件


  1.    
复制代码
因为我是把apk下载在了Android/Data/包名/cache/apk目次下所以这样设置,这里需要根据你的详细情况举行设置
 


  • 代表设备的根目次new File("/");
  • 代表context.getFilesDir()
  • 代表context.getCacheDir()
  • 代表Environment.getExternalStorageDirectory()
  • 代表context.getExternalFilesDirs()
  • 代表getExternalCacheDirs()
 
AndroidManifest.xml设置

  1.                                 
复制代码
OnlineFileProvider类代码

  1. package com.qtz.online.utils;import androidx.core.content.FileProvider;/** * @author Created by PengGuiChu on 2020/12/19 16:39. * @explain */public class OnlineFileProvider extends FileProvider {}
复制代码
 

来源:https://blog.csdn.net/pengguichu/article/details/112022040
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

发布主题

专注素材教程免费分享
全国免费热线电话

18768367769

周一至周日9:00-23:00

反馈建议

27428564@qq.com 在线QQ咨询

扫描二维码关注我们

Powered by Discuz! X3.4© 2001-2013 Comsenz Inc.( 蜀ICP备2021001884号-1 )