好久沒寫Blog了,一是最近項目比較忙,二也是最近家裏的事也比較多
好了,寒暄到此爲止,貌似有些短暫 😁
最近項目有一些位置信息需要實時去上傳,也有好長一段時間沒用過心跳服務了,一直都在用激光推動啊,阿里的MQTT啊
也是藉此機會複習一下這個簡單的Service
那麼這裏用的定時器就是Google推薦的Alarm
下面簡單介紹一下這個AlarmManager
一. AlarmManager的常用方法有三個:
1.set(int type,long startTime,PendingIntent pi);
該方法用於設置一次性鬧鐘,第一個參數表示鬧鐘類型,第二個參數表示鬧鐘執行時間,第三個參數表示鬧鐘響應動作。
2.setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
該方法用於設置重複鬧鐘,第一個參數表示鬧鐘類型,第二個參數表示鬧鐘首次執行時間,第三個參數表示鬧鐘兩次執行的間隔時間,第三個參數表示鬧鐘響應動作。
3.setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
該方法也用於設置重複鬧鐘,與第二個方法相似,不過其兩個鬧鐘執行的間隔時間不是固定的而已。
二. 參數詳解:
**1.**int type: 鬧鐘的類型,常用的有5個值:AlarmManager.ELAPSED_REALTIME、 AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、 AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP。
AlarmManager.ELAPSED_REALTIME表示鬧鐘在手機睡眠狀態下不可用,該狀態下鬧鐘使用相對時間(相對於系統啓動開始),狀態值爲3;
AlarmManager.ELAPSED_REALTIME_WAKEUP表示鬧鐘在睡眠狀態下會喚醒系統並執行提示功能,該狀態下鬧鐘也使用相對時間,狀態值爲2;
AlarmManager.RTC表示鬧鐘在睡眠狀態下不可用,該狀態下鬧鐘使用絕對時間,即當前系統時間,狀態值爲1;
AlarmManager.RTC_WAKEUP表示鬧鐘在睡眠狀態下會喚醒系統並執行提示功能,該狀態下鬧鐘使用絕對時間,狀態值爲0;
AlarmManager.POWER_OFF_WAKEUP表示鬧鐘在手機關機狀態下也能正常進行提示功能,所以是5個狀態中用的最多的狀態之一,該狀態下鬧鐘也是用絕對時間,狀態值爲4;不過本狀態好像受SDK版本影響,某些版本並不支持;
2. long startTime: 鬧鐘的第一次執行時間,以毫秒爲單位,可以自定義時間,不過一般使用當前時間。需要注意的是,本屬性與第一個屬性(type)密切相關,
3. long intervalTime:對於後兩個方法來說,存在本屬性,表示兩次鬧鐘執行的間隔時間,也是以毫秒爲單位。
4. PendingIntent pi: 綁定了鬧鐘的執行動作,比如發送一個廣播、給出提示等等。PendingIntent是Intent的封裝類。需要注意的是,如果是通過啓動服務來實現鬧鐘提 示的話,PendingIntent對象的獲取就應該採用Pending.getService(Context c,int i,Intent intent,int j)方法;如果是通過廣播來實現鬧鐘提示的話,PendingIntent對象的獲取就應該採用 PendingIntent.getBroadcast(Context c,int i,Intent intent,int j)方法;如果是採用Activity的方式來實現鬧鐘提示的話,PendingIntent對象的獲取就應該採用 PendingIntent.getActivity(Context c,int i,Intent intent,int j)方法。如果這三種方法錯用了的話,雖然不會報錯,但是看不到鬧鐘提示效果。
接下來 也是直接上代碼吧
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.support.annotation.Nullable;
import com.bohan.ems.mdm.MdmManage;
import com.bohan.ems.mdm.utils.Constant;
import com.bohan.icexpressapp.business.base.ViewCallback;
import com.bohan.icexpressapp.core.MainApplication;
import com.bohan.icexpressapp.core.log.SLog;
import com.bohan.icexpressapp.network.base.BaseReq;
import com.bohan.icexpressapp.network.networkserver.handoverserver.entity.BeanRespEmpty;
import org.apache.commons.lang3.StringUtils;
/**
* @author The sky seems to be raining
* @class 主線程心跳服務
*/
public class HeartBeatService extends Service {
// 心跳間隔
// 以前爲final static的,但是服務器要求修改間隔時間,則去掉
//心跳間隔時間 默認毫秒
public static final int DEFAULT_INTERVAL = 3 * 60 * 1000;
//心跳間隔時間 默認毫秒
public static int HEART_SPE = DEFAULT_INTERVAL;
public static final String ACTION_ALARM_HEARTBEAT = "ACTION_ALARM_HEARTBEAT";
private PendingIntent heartbeatPi = null;
private AlarmManager heartbeatAlarm;
private MainService mMainService;
private int shark = 0;
private ScreenControlAlarmReceiver screenControlAlarmReceiver;
/**
* 初始化窗口
*/
@Override
public void onCreate() {
super.onCreate();
System.out.println("### N1GHeartService onCreate");
initData();
initReceiver();
}
private void initData() {
mMainService = new MainService(MainApplication.getInstance());
heartbeatAlarm = (AlarmManager) getSystemService(ALARM_SERVICE);
}
/**
* 初始化接收對象
*/
private void initReceiver() {
screenControlAlarmReceiver = new ScreenControlAlarmReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_ALARM_HEARTBEAT);
registerReceiver(screenControlAlarmReceiver, intentFilter);
}
/**
* 釋放資源
*/
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(screenControlAlarmReceiver);
endTimer();
}
// 每次啓動Servcie時都會調用該方法
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("--onStartCommand()--");
shark = intent.getIntExtra("SHARK", DEFAULT_INTERVAL);
startTimer(shark * 1000 + "");
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* 更新心跳間隔,並啓動心跳
*
* @param timeString 心跳間隔 單位:毫秒
*/
private void startTimer(String timeString) {
HEART_SPE = DEFAULT_INTERVAL;
int tempTime = 0;
if (StringUtils.isEmpty(timeString) || "null".equals(timeString)) {
//如果登錄認證就失敗了,也需要啓動timer
tempTime = HEART_SPE;
} else {
try {
tempTime = Integer.parseInt(timeString);
} catch (NumberFormatException e) {
tempTime = HEART_SPE;
e.printStackTrace();
}
}
if (tempTime == HEART_SPE && heartbeatPi != null) {
//間隔時間和原來一致,並且啓動過timer,不重啓timer
return;
} else {
//間隔時間和原來不一致,重啓timer
HEART_SPE = tempTime;
endTimer();
Intent alarmIntent = new Intent(ACTION_ALARM_HEARTBEAT);
heartbeatPi = PendingIntent.getBroadcast(HeartBeatService.this, 0, alarmIntent, 0);//通過廣播接收
heartbeatAlarm.setRepeating(AlarmManager.RTC, 0, HEART_SPE, heartbeatPi);//INTERVAL毫秒後觸發
SLog.Console("心跳間隔:" + HEART_SPE + "");
heartBeat();
}
}
public class ScreenControlAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//你的邏輯處理
//如果需要實現間隔定時器功能,在重新執行1的發送步驟,實現間隔定時,間隔時間爲INTERVAL
heartBeat();
}
}
/**
* 停止心跳
*/
private void endTimer() {
if (heartbeatAlarm != null && heartbeatPi != null) {
heartbeatAlarm.cancel(heartbeatPi);
heartbeatPi = null;
}
}
/**
* 心跳上傳數據
*/
private void heartBeat() {
BeanRespEmpty req = new BeanRespEmpty();
mMainService.heartbeat(new BaseReq<>(req), new ViewCallback() {
@Override
public void returnResult(boolean result, Object... objects) {
if (result) {
SLog.Console("心跳上傳位置信息成功" +
Constant.LOCATION + ":" + MdmManage.getInstance().getLongiTude() + "," +
MdmManage.getInstance().getLatiTude() + "," + MdmManage.getInstance().getLastAlt());
} else {
SLog.Console("心跳上傳位置信息失敗" +
Constant.LOCATION + ":" + MdmManage.getInstance().getLongiTude() + "," +
MdmManage.getInstance().getLatiTude() + "," + MdmManage.getInstance().getLastAlt());
}
}
});
}
}
看完代碼,總結一下使用步驟吧
AlarmManager的使用步驟
1)初始化ALarmManager實例 ALarmManager am=(ALarmManager)getSystemService(ALARM_SERVICE);
2)定義一個PendingIntent發出廣播
3)調用ALarmManager方法,設置定時或重複提醒
4)取消提醒:
我這直接用的cancle方法,並且記得註銷掉廣播監聽器
是不是特別簡單實用啊,如文中有不對的地方,請及時糾正,謝謝大家
另外,文中很多代碼可能與實際業務相關,我實在是懶得刪除了,大家一看便知,最後提前祝大家臘八節快樂