package xn.update.service; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.content.IntentFilter; import android.os.Build; import android.os.CountDownTimer; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.util.Pair; import androidx.work.ExistingPeriodicWorkPolicy; import androidx.work.PeriodicWorkRequest; import androidx.work.WorkManager; import com.blankj.utilcode.util.ActivityUtils; import com.blankj.utilcode.util.AppUtils; import com.blankj.utilcode.util.FileUtils; import com.blankj.utilcode.util.LogUtils; import com.blankj.utilcode.util.NetworkUtils; import com.blankj.utilcode.util.SPUtils; import com.blankj.utilcode.util.ThreadUtils; import com.hikvision.dmb.display.InfoDisplayApi; import com.hikvision.dmb.network.InfoNetworkApi; import com.hikvision.dmb.system.InfoSystemApi; import com.hikvision.dmb.util.InfoUtilApi; import com.hjq.permissions.OnPermissionCallback; import com.hjq.permissions.Permission; import com.hjq.permissions.XXPermissions; import com.lxj.xpopup.XPopup; import org.greenrobot.eventbus.EventBus; import org.json.JSONObject; import java.io.File; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import okhttp3.Response; import xn.update.R; import xn.update.Tool; import xn.update.constant.AppConstant; import xn.update.evnet.UpdateUiEvent; import xn.update.http.HttpTool; import xn.update.receiver.TimeTickReceiver; import xn.update.works.TaskWork; public class TaskService extends Service { private TimeTickReceiver timeTickReceiver; private CountDownTimer permissionCdt; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); // 卸载老旧app Tool.INSTANCE.cmd("pm uninstall com.dlc.xn.eboard"); // 启动保活worker PeriodicWorkRequest taskRequest = new PeriodicWorkRequest.Builder(TaskWork.class, 15, TimeUnit.MINUTES).build(); WorkManager.getInstance(getApplicationContext()).enqueueUniquePeriodicWork("Task", ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, taskRequest); // 自动更新应用 SPUtils.getInstance().put(AppConstant.AUTO_UPDATE, true); // 自动拉起主应用 SPUtils.getInstance().put(AppConstant.AUTO_MASTER, true); InfoSystemApi.openAdb(); InfoDisplayApi.setStatusBarEnable(false); InfoDisplayApi.setNavigationBarEnable(false); InfoUtilApi.setUsbSwitch(false); SPUtils.getInstance().put("isRoot", 0 == InfoUtilApi.getRoot()); SPUtils.getInstance().put("IP", InfoNetworkApi.getEthernetConfig().ipAddress); InfoUtilApi.enableProtection(AppUtils.getAppPackageName(), false); InfoSystemApi.setLauncherForced(AppUtils.getAppPackageName()); createNotificationChannel(); timeTickReceiver = new TimeTickReceiver(); // 监听分钟广播 registerReceiver(timeTickReceiver, new IntentFilter(Intent.ACTION_TIME_TICK)); Tool.INSTANCE.cmd("pm grant " + AppUtils.getAppPackageName() + " android.permission.READ_EXTERNAL_STORAGE"); Tool.INSTANCE.cmd("pm grant " + AppUtils.getAppPackageName() + " android.permission.WRITE_EXTERNAL_STORAGE"); Tool.INSTANCE.cmd("pm grant " + AppUtils.getAppPackageName() + " android.permission.NOTIFICATION_SERVICE"); permissionCdt = new CountDownTimer(1000, 1000) { @Override public void onTick(long millisUntilFinished) { } @Override public void onFinish() { if (!XXPermissions.isGranted(ActivityUtils.getTopActivity(), Permission.READ_EXTERNAL_STORAGE) || !XXPermissions.isGranted(ActivityUtils.getTopActivity(), Permission.WRITE_EXTERNAL_STORAGE) || !XXPermissions.isGranted(ActivityUtils.getTopActivity(), Permission.NOTIFICATION_SERVICE) ) { Tool.INSTANCE.cmd("pm grant " + AppUtils.getAppPackageName() + " android.permission.READ_EXTERNAL_STORAGE"); Tool.INSTANCE.cmd("pm grant " + AppUtils.getAppPackageName() + " android.permission.WRITE_EXTERNAL_STORAGE"); Tool.INSTANCE.cmd("pm grant " + AppUtils.getAppPackageName() + " android.permission.NOTIFICATION_SERVICE"); permissionCdt.start(); } else { requestPermission(); permissionCdt.cancel(); permissionCdt = null; } } }; permissionCdt.start(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { LogUtils.d(getClass().getName(), "onStartCommand"); Notification notification = createNotification(); startForeground(1, notification); return START_REDELIVER_INTENT; } @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); LogUtils.d(getClass().getName(), "onTaskRemoved"); stopSelf(); } @Override public void onDestroy() { super.onDestroy(); if (null != timeTickReceiver) { unregisterReceiver(timeTickReceiver); timeTickReceiver = null; } LogUtils.d(getClass().getName(), "onDestroy"); } private void createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { int importance = NotificationManager.IMPORTANCE_DEFAULT; NotificationChannel channel = new NotificationChannel("task", "task", importance); NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } } private Notification createNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "task") .setContentTitle("Task") .setContentText("Task is running") .setSmallIcon(R.mipmap.ic_launcher) .setContentIntent(null) .setSilent(true) .setPriority(NotificationCompat.PRIORITY_DEFAULT); return builder.build(); } private void requestPermission() { // 全量权限申请 XXPermissions.with(ActivityUtils.getTopActivity()) .permission(Permission.READ_EXTERNAL_STORAGE) .permission(Permission.WRITE_EXTERNAL_STORAGE) .permission(Permission.NOTIFICATION_SERVICE) .request(new OnPermissionCallback() { @Override public void onGranted(@NonNull List permissions, boolean allGranted) { if (allGranted) { terminalAuth(); } else { new XPopup.Builder(TaskService.this) .dismissOnBackPressed(false) .dismissOnTouchOutside(false) .asConfirm("Tips", "您必须同意所有权限才可以继续使用", () -> requestPermission()) .show(); } } @Override public void onDenied(@NonNull List permissions, boolean doNotAskAgain) { OnPermissionCallback.super.onDenied(permissions, doNotAskAgain); if (doNotAskAgain) { new XPopup.Builder(TaskService.this) .dismissOnBackPressed(false) .dismissOnTouchOutside(false) .asConfirm("Tips", "您必须同意所有权限才可以继续使用", () -> XXPermissions.startPermissionActivity(TaskService.this, permissions)) .show(); } else { new XPopup.Builder(TaskService.this) .dismissOnBackPressed(false) .dismissOnTouchOutside(false) .asConfirm("Tips", "您必须同意所有权限才可以继续使用", () -> requestPermission()) .show(); } } }); } ThreadUtils.SimpleTask simpleTask = new ThreadUtils.SimpleTask() { @Override public Boolean doInBackground() throws Throwable { return NetworkUtils.isAvailableByPing(Tool.INSTANCE.getBaseUrl().host()); } @Override public void onSuccess(Boolean result) { if (result) { EventBus.getDefault().post(new UpdateUiEvent("鉴权中...")); ThreadUtils.executeByCached(new ThreadUtils.SimpleTask>() { @Override public Pair doInBackground() throws Throwable { try { SPUtils.getInstance().put("TerminalAuth", ""); Response response = HttpTool.INSTANCE.terminalAuth(); if (response.isSuccessful()) { String json = response.body().string(); JSONObject jsonObject = new JSONObject(json); int code = jsonObject.getInt("code"); if (200 == code) { String data = jsonObject.getString("data"); SPUtils.getInstance().put("TerminalAuth", TextUtils.isEmpty(data) ? "" : data); return Pair.create(true, ""); } else { return Pair.create(false, jsonObject.getString("message")); } } } catch (Exception e) { LogUtils.e(Log.getStackTraceString(e)); } return Pair.create(false, "鉴权异常,请联系管理员!"); } @Override public void onSuccess(Pair result) { if (result.first) { EventBus.getDefault().post(new UpdateUiEvent(result.second)); ThreadUtils.cancel(simpleTask); } else { EventBus.getDefault().post(new UpdateUiEvent(result.second)); } } }); } else { EventBus.getDefault().post(new UpdateUiEvent("无法连接到服务器,请联系管理员!")); } } }; private void terminalAuth() { ThreadUtils.executeByCachedAtFixRate(simpleTask, ThreadLocalRandom.current().nextInt(10, 20), TimeUnit.SECONDS); // 清理一个月前的log ThreadUtils.executeByCached(new ThreadUtils.SimpleTask() { @Override public Object doInBackground() throws Throwable { List fileList = FileUtils.listFilesInDir("/sdcard/logs/"); for (int i = 0; i < fileList.size(); i++) { File file = fileList.get(i); long oneMonth = 30 * 86400 * 1000L; if ((System.currentTimeMillis() - file.lastModified()) > oneMonth) { LogUtils.d("删除日志文件", file); FileUtils.delete(file); } } return null; } @Override public void onSuccess(Object result) { } }); } }