Java tutorial
/* * Copyright (C) Justson(https://github.com/Justson/DingDingHelper) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ucmap.dingdinghelper.services; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.text.TextUtils; import android.util.Log; import com.ucmap.dingdinghelper.ITimerListener; import com.ucmap.dingdinghelper.ITimingAidlInterface; import com.ucmap.dingdinghelper.R; import com.ucmap.dingdinghelper.entity.AccountEntity; import com.ucmap.dingdinghelper.sphelper.SPUtils; import com.ucmap.dingdinghelper.ui.MainActivity; import com.ucmap.dingdinghelper.utils.Constants; import com.ucmap.dingdinghelper.utils.DateUtils; import com.ucmap.dingdinghelper.utils.JsonUtils; import com.ucmap.dingdinghelper.utils.ShellUtils; import java.util.List; import static com.ucmap.dingdinghelper.utils.DateUtils.getHourAndMin; public class TimingService extends Service { /** * ID */ private static final int NOTIFICATION_ID = 0x0033888; @Override public void onCreate() { super.onCreate(); init(); increasePriority(); } private List<AccountEntity> mAccountEntities = null; private AccountEntity mAccountEntity = null; private int hour = 8; private int min = 45; private NotifyThread mNotifyThread; /*0?1?*/ private static int STATE = 0; private void init() { String jsonAccountList = (String) SPUtils.getString(Constants.ACCOUNT_LIST, "-1"); mAccountEntities = JsonUtils.listJson(jsonAccountList, AccountEntity.class); if (mAccountEntities == null || mAccountEntities.isEmpty()) { return; } this.mAccountEntity = mAccountEntities.get(0); /*try { *//* ? kill ? *//* Daemon.run(this, TimingService.class, Daemon.INTERVAL_ONE_MINUTE); } catch (Exception e) { e.printStackTrace(); }*/ initCheckInTime(null); if (mNotifyThread == null || !mNotifyThread.isAlive()) { mNotifyThread = new NotifyThread(); runing_monitor = true; mNotifyThread.setPriority(Thread.MAX_PRIORITY); /*?*/ mNotifyThread.start(); } } private void initCheckInTime(String remoteTime) { String current = DateUtils.getHourAndMin(System.currentTimeMillis()); int hour = Integer.parseInt(current.split(":")[0]); int min = Integer.parseInt(current.split(":")[1]); if (TextUtils.isEmpty(remoteTime)) { String time = ""; if (hour < 12) { STATE = 0; time = (String) SPUtils.getString(Constants.MORNING_CHECK_IN_TIME, "8:45"); } else { STATE = 1; time = (String) SPUtils.getString(Constants.AFTERNOON_CHECK_IN_TIME, "20:45"); } if (time.length() >= 4) { String[] hourAndMin = time.split(":"); this.hour = Integer.parseInt(hourAndMin[0]); this.min = Integer.parseInt(hourAndMin[1]); } } else { String hm[] = remoteTime.split(":"); int tempH = Integer.parseInt(hm[0]); int tempM = Integer.parseInt(hm[1]); if (hour < 12 && ((tempH > hour) || (tempH == hour && tempM > min))) { STATE = 0; this.hour = tempH; this.min = tempM; } else if (hour >= 12 && ((tempH > hour) || (tempH == hour && tempM > min))) { STATE = 1; this.hour = tempH; this.min = tempM; } else { initCheckInTime(null); } String t = (String) SPUtils.getString(Constants.AFTERNOON_CHECK_IN_TIME, "8:45"); } } private RemoteCallbackList<ITimerListener> mITimerListenerRemoteCallbackList = new RemoteCallbackList<>(); @Nullable @Override public IBinder onBind(Intent intent) { return new ITimingAidlInterface.Stub() { @Override public void registerTimerListener(ITimerListener timerListener) throws RemoteException { mITimerListenerRemoteCallbackList.register(timerListener); } @Override public void unRegisterTimerListener(ITimerListener timerListener) throws RemoteException { mITimerListenerRemoteCallbackList.unregister(timerListener); } @Override public void reInitCheckInTime(String time) throws RemoteException { initCheckInTime(time); } }; } /*???service */ private void increasePriority() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { Notification.Builder mBuilder = new Notification.Builder(this); mBuilder.setSmallIcon(R.mipmap.app_logo); startForeground(NOTIFICATION_ID, mBuilder.build()); InnerService.startInnerService(this); } else { startForeground(NOTIFICATION_ID, new Notification()); } } @Override public void onDestroy() { super.onDestroy(); runing_monitor = false; if (mNotifyThread != null && mNotifyThread.isAlive()) { /*Thread ? ???*/ if (!mNotifyThread.isInterrupted()) { mNotifyThread.interrupt(); } } NotificationManager mNotificationManager = (NotificationManager) this .getSystemService(NOTIFICATION_SERVICE); mNotificationManager.cancel(NOTIFICATION_ID_PROGRESS_ID); mNotificationManager.cancel(NOTIFICATION_ID); } public static class InnerService extends Service { private static final void startInnerService(Context context) { context.startService(new Intent(context, InnerService.class)); } @Override public void onCreate() { super.onCreate(); Notification.Builder mBuilder = new Notification.Builder(this); mBuilder.setSmallIcon(R.mipmap.app_logo); startForeground(NOTIFICATION_ID, mBuilder.build()); new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { stopForeground(true); NotificationManager mNotificationManager = (NotificationManager) InnerService.this .getSystemService(NOTIFICATION_SERVICE); mNotificationManager.cancel(NOTIFICATION_ID); stopSelf(); } }, 250); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { super.onDestroy(); stopForeground(true); } } private static final int NOTIFICATION_ID_PROGRESS_ID = 0x100100; private int[] parseTime(String time) { if (TextUtils.isEmpty(time)) return null; String[] hm = time.split(":"); int[] times = new int[hm.length]; for (int i = 0; i < hm.length; i++) { times[i] = Integer.parseInt(hm[i]); } return times; } private void setTargetTimeForLockIn() { String time = ""; time = (String) SPUtils.getString(Constants.MORNING_CHECK_IN_TIME, "6:45"); int[] hm = parseTime(time); this.hour = hm[0]; this.min = hm[1]; } private void toCheckIn() { if (Constants.IS_NOTITY_TYPE_CHECK_IN_TAG) { ShellUtils.execCmd("am broadcast -a com.ucmap.dingdinghelper.clock", true); } else { Log.i("Info", " AlarmManager "); } } private void sendNotification(int hour, int min) { if ((STATE == 0) && (this.hour < hour || (this.hour == hour && this.min <= min))) { if ((this.hour == hour && this.min <= min)) toCheckIn(); String time = ""; time = (String) SPUtils.getString(Constants.AFTERNOON_CHECK_IN_TIME, "20:45"); STATE = 1; String[] hm = time.split(":"); this.hour = Integer.parseInt(hm[0]); this.min = Integer.parseInt(hm[1]); /*?*/ sendNotification(hour, min); return; } else if (STATE == 1 && (this.hour < hour || (this.hour == hour && this.min <= min))) { if ((this.hour == hour && this.min <= min)) toCheckIn(); setTargetTimeForLockIn(); STATE = 2; sendNotification(hour, min); return; } else if (STATE == 2) { if (hour < 23 && hour >= 12) { setTargetTimeForLockIn(); } else STATE = 0; } int lHour = 0; if (hour <= this.hour) { lHour = this.hour - hour; } else { lHour = 24 - hour + this.hour; } int lMin = 0; if (min <= this.min) { lMin = this.min - min; } else { if (this.hour != hour) lHour--; if (hour == this.hour) { lMin = this.min - min; } else lMin = 60 - min + this.min; } NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this); mBuilder.setSmallIcon(R.mipmap.app_logo); notifyUpdateUi("?:" + this.hour + ":" + this.min + ", " + lHour + "? " + lMin + " "); mBuilder.setContentText("??: " + lHour + " ?" + lMin + " ") .setContentTitle("?"); PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); mBuilder.setContentIntent(mPendingIntent); NotificationManager mNotificationManager = (NotificationManager) this .getSystemService(NOTIFICATION_SERVICE); mNotificationManager.notify(NOTIFICATION_ID_PROGRESS_ID, mBuilder.build()); } /**/ private volatile boolean runing_monitor = true; private void notifyUpdateUi(String time) { if (mITimerListenerRemoteCallbackList == null) return; int number = mITimerListenerRemoteCallbackList.beginBroadcast(); for (int i = 0; i < number; i++) { ITimerListener mITimerListener = mITimerListenerRemoteCallbackList.getBroadcastItem(i); if (mITimerListener == null) continue; try { mITimerListener.toCallback(time); } catch (RemoteException e) { e.printStackTrace(); } } mITimerListenerRemoteCallbackList.finishBroadcast(); } /* */ class NotifyThread extends Thread { @Override public void run() { /*??,???*/ Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO); while (runing_monitor) { String time = getHourAndMin(System.currentTimeMillis()); if (TextUtils.isEmpty(time)) continue; String[] hourAndMin = time.split(":"); if (hourAndMin == null || hourAndMin.length < 2) continue; String hour = hourAndMin[0]; int hourInt = Integer.parseInt(hour); int min = Integer.parseInt(hourAndMin[1]); sendNotification(hourInt, min); try { /*----?15s*/ sleep(1000 * 10); } catch (InterruptedException e) { // e.printStackTrace(); return; } } } } }