package com.ik.mboxlauncher; import android.app.Service; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.preference.PreferenceManager; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import com.android.device.NetStateChangeReceiver; import com.android.eventbaus.EventBusUtils; import com.android.eventbaus.MessageEvent; import com.android.nebulasdk.ADManager; import com.android.device.NetStateChangeObserver; import com.android.nebulasdk.bean.ADInfo; import com.android.nebulasdk.presenter.AppnetPresenter; import com.android.nebulasdk.presenter.callback.AppnetCallback; import com.android.util.DeviceUtil; import com.android.util.LogUtils; import com.android.util.NetUtil; import com.android.util.NetworkType; import java.lang.ref.WeakReference; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.TimeZone; import java.util.UUID; /** * 资源同步后台服务 * 功能: * 1. 首次执行无条件请求接口(不检查时间) * 2. 首次成功执行后,必须等待8小时才能再次请求 * 3. 仅在请求成功时记录时间,失败不记录 * 4. 设备重启后重置为首次请求状态 */ public class SystemService extends Service implements AppnetCallback, NetStateChangeObserver { private static final String TAG = SystemService.class.getName(); private AppnetPresenter appnetPresenter; String deviceId = ""; /**launcher 资源更新通知*/ public static final String NOTIFY_LAUNCHER_UPDATE="com.ik.launcher.res.notify"; /**Advert 资源更新通知*/ public static final String NOTIFY_ADVERT_UPDATE="com.ik.Advert.res.notify"; private static boolean isRunning = false; //请求launcher资源信息 private static final int WHAT_REQUEST_ADMSG=0; /**更新资源信息*/ private static final int WHAT_REQUEST_UPDATEADINFO=1; //开启诊断是否启动任务 private static final int WHAT_ASK_CIRCLETASK=2; /**网络变化通知*/ private static final int WHAT_NETWORK_CHANGE=3; // -1表示无有效网络 private int lastEffectiveNetworkType = -1; //标记当前是否有广告请求在进行(防止并行请求) private boolean isRequesting = false; // 上次网络触发请求的时间戳(毫秒) private long lastNetTriggerTime = 0L; // 网络请求最小间隔(60秒) private static final long NET_REQUEST_INTERVAL = 10*60 * 1000; private static final long FIVE_MINUS_DELAY=5*60 * 1000; private static final long ONE_HOUR_DELAY= 60 * 60 * 1000; private boolean isFirstRequestDone; private boolean hasRequestDone;//请求成功过 更新时间间隔 8h private SharedPreferences sharedPreferences; //持久化存储成功请求时间 private static final String KEY_LAST_SUCCESS_TIME = "last_success_time"; private static class MyHandler extends Handler{ WeakReference weakReference; private MyHandler(SystemService service,Looper looper){ super(looper); if(weakReference==null) weakReference= new WeakReference<>(service); } @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); SystemService systemService = weakReference.get(); if(systemService!=null){ switch (msg.what){ case WHAT_REQUEST_ADMSG: systemService.isRequesting=true; try { if (systemService.appnetPresenter == null) { systemService.appnetPresenter = new AppnetPresenter(systemService); } systemService.appnetPresenter.postLauncherAds(systemService); } catch (Exception e) { LogUtils.loge("request exception"); systemService.isRequesting=false; if(!systemService.isFirstRequestDone){ systemService.isFirstRequestDone=true; }else { if(systemService.hasRequestDone){ systemService.lastNetTriggerTime=System.currentTimeMillis(); systemService.sharedPreferences.edit().putLong(KEY_LAST_SUCCESS_TIME, systemService.lastNetTriggerTime).apply(); }else { if(systemService.lastNetTriggerTime!=0L){ systemService.handler.removeMessages(WHAT_ASK_CIRCLETASK); systemService.handler.sendEmptyMessageDelayed(WHAT_ASK_CIRCLETASK, NET_REQUEST_INTERVAL); return; } } } systemService.scheduleNextCircleAsk(); } break; case WHAT_REQUEST_UPDATEADINFO: //发送更新广告信息的广播 break; case WHAT_ASK_CIRCLETASK: if(!systemService.isRequesting&&systemService.shouldRequestImmediately()&& systemService.isNetworkAvailable()){ systemService.handler.removeMessages(WHAT_REQUEST_ADMSG); systemService.handler.sendEmptyMessage(WHAT_REQUEST_ADMSG); }else{ systemService.scheduleNextCircleAsk();//刷新定时或启动定时 } break; case WHAT_NETWORK_CHANGE: LogUtils.loge("发送网络变化的通知"); EventBusUtils.postMsg(new MessageEvent(MessageEvent.ACTION_UPADATE_MEDIA_STATUS)); //网络变化刷新图标 break; } } } } private MyHandler handler; private boolean shouldRequestImmediately() { if (!isFirstRequestDone) { return true; } long lastSuccessTime = sharedPreferences.getLong(KEY_LAST_SUCCESS_TIME, 0); long currentTime = System.currentTimeMillis(); if (lastSuccessTime == 0) { LogUtils.loge("从未成功请求过,应立即请求 unsuccess task turn on"); return true; } if (currentTime < lastSuccessTime) { LogUtils.loge("满足(时间回退),应立即请求 time forecase task turn on"); return true; } long timeDiff = currentTime - lastSuccessTime; if (timeDiff >= NET_REQUEST_INTERVAL) { LogUtils.loge("满足8小时间隔条件,应立即请求 delay 8 hour task turn on"); return true; } LogUtils.loge("不满足8小时间隔条件,不应请求 undelay 8 hour task turn off"); return false; } @Override public void onCreate() { super.onCreate(); if(!isRunning){ isRunning =true; handler=new MyHandler(SystemService.this,Looper.getMainLooper()); sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); deviceId= DeviceUtil.getEthernetMac(); LogUtils.loge( "onCreate: systemservice is start :"+deviceId); NetStateChangeReceiver.registerReceiver(this); NetStateChangeReceiver.registerObserver(this); lastNetTriggerTime = sharedPreferences.getLong(KEY_LAST_SUCCESS_TIME, 0); handler.removeMessages(WHAT_ASK_CIRCLETASK); handler.sendEmptyMessage(WHAT_ASK_CIRCLETASK); } } @RequiresApi(api = Build.VERSION_CODES.O) @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { NetStateChangeReceiver.unRegisterObserver(this); NetStateChangeReceiver.unRegisterReceiver(this); isRunning = false; super.onDestroy(); } @Override public void onResult(Object data) { isRequesting=false; List adInfoList; if(data==null){ adInfoList = new ArrayList<>(); }else { adInfoList = (List) data; } ADManager.getInstance().updateADInfo(adInfoList); if(!isFirstRequestDone){ isFirstRequestDone=true; } hasRequestDone=true; lastNetTriggerTime=System.currentTimeMillis(); sharedPreferences.edit().putLong(KEY_LAST_SUCCESS_TIME,lastNetTriggerTime).apply(); scheduleNextCircleAsk(); } @Override public void onViewFailureString(int code, String message) { LogUtils.loge("onViewFailureString()"+message); isRequesting=false; if(!isFirstRequestDone){ isFirstRequestDone=true; }else { if(hasRequestDone){ lastNetTriggerTime=System.currentTimeMillis(); sharedPreferences.edit().putLong(KEY_LAST_SUCCESS_TIME,lastNetTriggerTime).apply(); }else { if(lastNetTriggerTime!=0L){ handler.removeMessages(WHAT_ASK_CIRCLETASK); handler.sendEmptyMessageDelayed(WHAT_ASK_CIRCLETASK, NET_REQUEST_INTERVAL); return; } } } scheduleNextCircleAsk(); } @Override public void onExceptionFailure(String message) { LogUtils.loge("onExceptionFailure()"+message); isRequesting=false; if(!isFirstRequestDone){ isFirstRequestDone=true; }else { if(hasRequestDone){ lastNetTriggerTime=System.currentTimeMillis(); sharedPreferences.edit().putLong(KEY_LAST_SUCCESS_TIME,lastNetTriggerTime).apply(); }else { if(lastNetTriggerTime!=0L){ handler.removeMessages(WHAT_ASK_CIRCLETASK); handler.sendEmptyMessageDelayed(WHAT_ASK_CIRCLETASK, NET_REQUEST_INTERVAL); return; } } } scheduleNextCircleAsk(); } @Override public void onServerFailure(int code, String message) { LogUtils.loge("onServerFailure()"+message); isRequesting=false; if(!isFirstRequestDone){ isFirstRequestDone=true; }else { if(hasRequestDone){ lastNetTriggerTime=System.currentTimeMillis(); sharedPreferences.edit().putLong(KEY_LAST_SUCCESS_TIME,lastNetTriggerTime).apply(); }else { if(lastNetTriggerTime!=0L){ handler.removeMessages(WHAT_ASK_CIRCLETASK); handler.sendEmptyMessageDelayed(WHAT_ASK_CIRCLETASK, NET_REQUEST_INTERVAL); return; } } } scheduleNextCircleAsk(); } @Override public void onNetDisconnected() { handler.sendEmptyMessage(WHAT_NETWORK_CHANGE); } @RequiresApi(api = Build.VERSION_CODES.O) @Override public void onNetConnected(NetworkType networkType) { int netWorkState = NetUtil.getNetWorkState(this); if (netWorkState == NetUtil.NETWORK_MOBILE || netWorkState == NetUtil.NETWORK_WIFI||netWorkState==NetUtil.NETWORK_ETHERNET) { LogUtils.loge("network is ok"); // if(!isRequesting){ // handler.removeMessages(WHAT_REQUEST_ADMSG); // handler.sendEmptyMessage(WHAT_REQUEST_ADMSG); // } handler.removeMessages(WHAT_ASK_CIRCLETASK); handler.sendEmptyMessage(WHAT_ASK_CIRCLETASK); } else { LogUtils.loge("network is not ok"); } handler.sendEmptyMessage(WHAT_NETWORK_CHANGE); } private String createUUID(){ String timems =System.currentTimeMillis()+""; return timems+"-"+ UUID.randomUUID().toString(); } private void scheduleNextRequest() { handler.removeMessages(WHAT_REQUEST_ADMSG); if (!isFirstRequestDone) { LogUtils.loge("first uncompletely,5mins later"); handler.sendEmptyMessageDelayed(WHAT_REQUEST_ADMSG, FIVE_MINUS_DELAY); return; } long currentTime = System.currentTimeMillis(); // 从未成功过,使用检查间隔 if (lastNetTriggerTime == 0) { LogUtils.loge("no success,1hour later try"); handler.sendEmptyMessageDelayed(WHAT_REQUEST_ADMSG, ONE_HOUR_DELAY); return; } long nextRequestTime = lastNetTriggerTime + NET_REQUEST_INTERVAL; long delay = Math.max(0, nextRequestTime - currentTime); LogUtils.loge("delay="+delay); handler.sendEmptyMessageDelayed(WHAT_REQUEST_ADMSG, delay); } private void scheduleNextCircleAsk() { handler.removeMessages(WHAT_ASK_CIRCLETASK); if (!isFirstRequestDone) { LogUtils.loge("first uncompletely,5mins later try"); handler.sendEmptyMessageDelayed(WHAT_ASK_CIRCLETASK, FIVE_MINUS_DELAY); return; } long currentTime = System.currentTimeMillis(); // 从未成功过,使用检查间隔 if (lastNetTriggerTime == 0) { LogUtils.loge("no success,1hour later try"); handler.sendEmptyMessageDelayed(WHAT_ASK_CIRCLETASK, ONE_HOUR_DELAY); return; } long nextRequestTime = lastNetTriggerTime + NET_REQUEST_INTERVAL; long delay = Math.max(0, nextRequestTime - currentTime); LogUtils.loge("delay="+delay); handler.sendEmptyMessageDelayed(WHAT_ASK_CIRCLETASK, delay); } private boolean isNetworkAvailable() { int netState = NetUtil.getNetWorkState(this); return netState == NetUtil.NETWORK_MOBILE || netState == NetUtil.NETWORK_WIFI || netState == NetUtil.NETWORK_ETHERNET; } }