You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AppUpdater/app-updater/src/main/java/com/king/app/updater/AppUpdater.java

372 lines
12 KiB

package com.king.app.updater;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import com.king.app.updater.callback.UpdateCallback;
import com.king.app.updater.constant.Constants;
import com.king.app.updater.http.HttpManager;
import com.king.app.updater.http.IHttpManager;
import com.king.app.updater.http.OkHttpManager;
import com.king.app.updater.service.DownloadService;
import com.king.app.updater.util.PermissionUtils;
import java.util.Map;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
/**
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
*/
public class AppUpdater {
/**
* {@link #mContext}不强制要求是{@link Activity},但能传{@link Activity}尽量传。AppUpdater本应该只专注于App更新,尽量不涉及动态权限相关的处理。如果mContext传的是{@link Activity},则默认会校验一次动态权限。
*/
private Context mContext;
/**
* 配置信息
*/
private UpdateConfig mConfig;
/**
* 更新回调
*/
private UpdateCallback mCallback;
/**
* http管理接口,可自定义实现。如:使用okHttp
*/
private IHttpManager mHttpManager;
private ServiceConnection mServiceConnection;
public AppUpdater(@NonNull Context context,@NonNull UpdateConfig config){
this.mContext = context;
this.mConfig = config;
}
public AppUpdater(@NonNull Context context,@NonNull String url){
this.mContext = context;
mConfig = new UpdateConfig();
mConfig.setUrl(url);
}
/**
* 设置下载更新进度回调
* @param callback
* @return
*/
public AppUpdater setUpdateCallback(UpdateCallback callback){
this.mCallback = callback;
return this;
}
/**
* 设置一个IHttpManager
* @param httpManager AppUpdater内置提供{@link HttpManager} 和 {@link OkHttpManager}两种实现。
* 如果不设置,将默认使用{@link HttpManager},你也可以使用{@link OkHttpManager}或自己去实现一个
* {@link IHttpManager}。
* 当使用{@link OkHttpManager}时,必需依赖okhttp库
* @return
*/
public AppUpdater setHttpManager(IHttpManager httpManager){
this.mHttpManager = httpManager;
return this;
}
/**
* 开始下载
*/
public void start(){
if(mConfig!=null && !TextUtils.isEmpty(mConfig.getUrl())){
//如果mContext是Activity,并且配置了下载路径,则默认会校验一次动态权限。
if(mContext instanceof Activity && !TextUtils.isEmpty(mConfig.getPath())){
PermissionUtils.verifyReadAndWritePermissions((Activity) mContext,Constants.RE_CODE_STORAGE_PERMISSION);
}
if(mConfig.isShowNotification() && !PermissionUtils.isNotificationEnabled(mContext)){
Log.w(Constants.TAG,"Notification permission not enabled.");
}
startDownloadService();
}else{
throw new NullPointerException("Url = null");
}
}
/**
* 启动下载服务
*/
private void startDownloadService(){
Intent intent = new Intent(mContext, DownloadService.class);
if(mCallback!=null || mHttpManager!=null){//bindService
mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
DownloadService.DownloadBinder binder = ((DownloadService.DownloadBinder)service);
binder.start(mConfig,mHttpManager,mCallback);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
mContext.getApplicationContext().bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
}else{//startService
intent.putExtra(Constants.KEY_UPDATE_CONFIG,mConfig);
mContext.startService(intent);
}
}
/**
* 取消下载
*/
public void stop(){
stopDownloadService();
}
/**
* 停止下载服务
*/
private void stopDownloadService(){
Intent intent = new Intent(mContext, DownloadService.class);
intent.putExtra(Constants.KEY_STOP_DOWNLOAD_SERVICE,true);
mContext.startService(intent);
}
/**
* AppUpdater建造者
*/
public static class Builder{
private UpdateConfig mConfig;
public Builder(){
mConfig = new UpdateConfig();
}
/**
* 设置APK下载地址
* @param url 下载地址
* @return
*/
public Builder setUrl(@NonNull String url){
mConfig.setUrl(url);
return this;
}
/**
* 设置保存的路径,(建议使用默认,不做设置)
* @param path 下载保存的文件路径
* @return
* @deprecated 因为适配Android Q的分区存储,所以此方法已弃用,不建议再使用
*/
@Deprecated
public Builder setPath(String path){
mConfig.setPath(path);
return this;
}
/**
* 设置保存的文件名
* @param filename 下载的保存的apk文件名 (默认优先取url文件名)
* @return
*/
public Builder setFilename(String filename){
mConfig.setFilename(filename);
return this;
}
/**
* 设置是否显示通知栏
* @param isShowNotification 是否显示通知栏 (默认true)
* @return
*/
public Builder setShowNotification(boolean isShowNotification) {
mConfig.setShowNotification(isShowNotification);
return this;
}
/**
* 设置通知ID
* @param notificationId 通知ID
* @return
*/
public Builder setNotificationId(int notificationId) {
mConfig.setNotificationId(notificationId);
return this;
}
/**
* 设置通知渠道ID
* @param channelId 通知渠道ID (默认兼容O)
* @return
*/
public Builder setChannelId(String channelId) {
mConfig.setChannelId(channelId);
return this;
}
/**
* 设置通知渠道名称
* @param channelName 通知渠道名称 (默认兼容O)
* @return
*/
public Builder setChannelName(String channelName) {
mConfig.setChannelName(channelName);
return this;
}
/**
* 设置通知图标
* @param icon 通知栏图标 (默认取App的icon)
* @return
*/
public Builder setNotificationIcon(@DrawableRes int icon) {
mConfig.setNotificationIcon(icon);
return this;
}
/**
* 设置通知是否震动提示
* @param vibrate 是否震动提示,为true时使用通知默认震动,Android O(8.0)以上设置,只有初次创建channel时有效,后续修改属性无效,想要重新有效需修改channelId或卸载App重装。
* @return
*/
public Builder setVibrate(boolean vibrate) {
mConfig.setVibrate(vibrate);
return this;
}
/**
* 设置通知是否铃声提示
* @param sound 是否铃声提示,为true时使用通知默认铃声,Android O(8.0)以上设置,只有初次创建channel时有效,后续修改属性无效,想要重新有效需修改channelId或卸载App重装。
* @return
*/
public Builder setSound(boolean sound) {
mConfig.setSound(sound);
return this;
}
/**
* 设置下载完成后知否自动触发安装APK
* @param isInstallApk 下载完成后是否自动调用安装APK(默认true)
* @return
*/
public Builder setInstallApk(boolean isInstallApk){
mConfig.setInstallApk(isInstallApk);
return this;
}
/**
* 设置FileProvider的authority
* @param authority FileProvider的authority(默认兼容N,默认值{@link Context#getPackageName() + ".fileProvider"})
* @return
*/
public Builder setAuthority(String authority){
mConfig.setAuthority(authority);
return this;
}
/**
* 设置下载时,通知栏是否显示下载百分比
* @param showPercentage 下载时通知栏是否显示百分比
* @return
*/
public Builder setShowPercentage(boolean showPercentage) {
mConfig.setShowPercentage(showPercentage);
return this;
}
/**
* 设置下载失败时,是否支持点击通知栏重新下载。与之相关联的方法{@link #setReDownloads(int)}
* @param reDownload 下载失败时是否支持点击通知栏重新下载,默认true
* @return
*/
public Builder setReDownload(boolean reDownload) {
mConfig.setReDownload(reDownload);
return this;
}
/**
* 设置下载失败时,最多重新下载次数。与之相关联的方法{@link #setReDownload(boolean)}
* @param reDownloads 下载失败时是否支持点击通知栏重新下载,默认最多重新下载3次
* @return
*/
public Builder setReDownloads(int reDownloads) {
mConfig.setReDownloads(reDownloads);
return this;
}
/**
* 设置要下载APK的versionCode,用于优先取缓存时通过versionCode校验APK文件是否一致。
* 缓存校验目前支持两种方式,一种是通过versionCode校验,即{@link #setVersionCode(Integer)};一种是文件MD5校验,即{@link #setApkMD5(String)}。推荐使用MD5校验方式
* 如果两种方式都设置了,则只校验MD5
* @param versionCode 为null表示不处理,默认不存在则下载,存在则重新下载。不为null时,表示会优先校验本地是否存在已下载版本号为versionCode的APK。
* 如果存在则不会重新下载(AppUpdater会自动校验packageName一致性),直接取本地APK,反之重新下载。
* @return
*/
public Builder setVersionCode(Integer versionCode) {
mConfig.setVersionCode(versionCode);
return this;
}
/**
* 设置APK文件的MD5,用于优先取缓存时通过MD5校验文件APK是否一致。
* 缓存校验目前支持两种方式,一种是通过versionCode校验,即{@link #setVersionCode(Integer)};一种是文件MD5校验,即{@link #setApkMD5(String)}。推荐使用MD5校验方式
* 如果两种方式都设置了,则只校验MD5
* @param md5 为null表示不处理,如果设置了MD5,则缓存APK的MD5相同时,只下载一次,优先取本地缓存
* @return
*/
public Builder setApkMD5(String md5) {
mConfig.setApkMD5(md5);
return this;
}
/**
* 请求头添加参数
* @param key
* @param value
* @return
*/
public Builder addHeader(String key, String value){
mConfig.addHeader(key,value);
return this;
}
/**
* 请求头添加参数
* @param headers
* @return
*/
public Builder addHeader(Map<String,String> headers){
mConfig.addHeader(headers);
return this;
}
/**
* 设置是否自动删除取消下载的文件
* @param deleteCancelFile 是否删除取消下载的文件(默认为true)
*/
public Builder setDeleteCancelFile(boolean deleteCancelFile){
mConfig.setDeleteCancelFile(deleteCancelFile);
return this;
}
public AppUpdater build(@NonNull Context context){
AppUpdater appUpdater = new AppUpdater(context,mConfig);
return appUpdater;
}
}
}