him*_*eam 11 service android alarmmanager
我Service以30分钟的间隔调用背景来读取当前位置的纬度/经度并通过POST API将其发送到服务器.
我每隔30分钟使用课程setRepeating()方法AlarmManager来安排闹钟.但有时警报会被遗漏而且服务没有被调用.为了监控是否每隔30分钟调用一次警报,我在SD卡中生成了Log.txt文件.对于每次报警当前时间的报警都将写入Log.txt文件中.但是在比较4到5个设备的Log.txt文件后,我注意到对于某些设备,报警不是调用onCreate()方法UserTrackingReceiver.java(后台服务).下面提到的完整代码块.
当app start registerUserTrackingReceiver()方法被调用时,如下所示:
public static void registerUserTrackingReceiver(Context context) {
try {
Intent intent = new Intent(context, UserTrackingReceiver.class);
boolean alarmUp = (PendingIntent.getService(context, 1001, intent, PendingIntent.FLAG_NO_CREATE) == null);
if (alarmUp) {
Calendar calendar = Calendar.getInstance();
if (calendar.get(Calendar.MINUTE) > 0 && calendar.get(Calendar.MINUTE) <= 30) {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
} else if (calendar.get(Calendar.MINUTE) > 30) {
if (calendar.get(Calendar.HOUR_OF_DAY) == 23) {
calendar.set(Calendar.HOUR_OF_DAY, 0);
} else {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1);
}
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
} else {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
}
PendingIntent sender = PendingIntent.getService(context, 1001, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_HALF_HOUR, sender);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
UserTrackingReceiver.java如下:
public class UserTrackingReceiver extends Service
implements LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
@Override
public void onCreate() {
super.onCreate();
Calendar calendar = Calendar.getInstance();
Util.appendLog("Tracking Alarm Called on: " + calendar.get(Calendar.HOUR_OF_DAY) + " : " + calendar.get(Calendar.MINUTE) + " : " + calendar.get(Calendar.SECOND));
stopSelf();
}
}
Run Code Online (Sandbox Code Playgroud)
在Util.java中有appendLog()以下方法:
public static void appendLog(String text) {
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
File logFile = new File(baseDir + "/" + Constant.AppNameSuper + "/log.txt");
if (!logFile.exists()) {
try {
logFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
//BufferedWriter for performance, true to set append to file flag
BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true));
buf.append(text);
buf.newLine();
buf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
如果按照上述代码每隔30分钟调用一次警报,则应将其写入SDCARD中的Log.txt文件中.但问题是它不能每30分钟写一次日志文件,这意味着警报丢失.根据阅读两天的时间,我注意到,由于用户不断使用手机,白天不会丢失警报,但是当手机不使用时,它会在晚上错过.
带有不同设备的输出日志文件如下:
设备A Log.txt
- 跟踪警报呼叫:0:0:31(从12:00开始)
- 跟踪警报呼叫:1:10:27
- 跟踪警报呼叫:3:5:25
- 跟踪警报呼叫:6:55:31
- 跟踪警报调用:7:0:6
- 跟踪警报调用:7:30:0
- 跟踪警报调用:8:0:6
- 跟踪警报呼叫:8:30:0
- 跟踪警报调用:9:0:6
- 跟踪警报调用:9:30:0
- 跟踪警报调用:10:0:0
Device B Log.txt
- 跟踪警报呼叫:0:0:27(从12:00开始)
- 跟踪警报调用:0:30:1
- 跟踪警报调用:1:0:1
- 跟踪警报调用:1:30:2
- 跟踪警报调用:2:0:1
- 跟踪警报呼叫:2:30:1
- 跟踪警报调用:3:0:1
- 跟踪警报呼叫:3:30:1
- 跟踪警报调用:4:0:1
- 跟踪警报呼叫:4:30:29
- 跟踪警报调用:5:0:1
- 跟踪警报呼叫:5:30:2
- 跟踪警报呼叫:6:0:30
- 跟踪警报呼叫:6:30:1
- 跟踪警报调用:7:0:1
- 跟踪警报调用:7:30:1
- 跟踪警报调用:8:0:1
- 跟踪警报呼叫:8:30:1
- 跟踪警报调用:9:0:32
- 跟踪警报呼叫:9:30:1
Device C Log.txt
- 跟踪警报呼叫:0:0:7(从12:00开始)
- 跟踪警报呼叫:0:30:3
- 跟踪警报调用:1:0:6
- 跟踪警报调用:1:30:1
- 跟踪警报调用:2:0:32
- 跟踪警报呼叫:2:30:3
- 跟踪警报调用:3:1:50
- 跟踪警报呼叫:3:30:5
- 跟踪警报调用:4:1:58
- 跟踪警报呼叫:4:31:14
- 跟踪警报调用:5:0:1
- 跟踪警报呼叫:5:30:1
- 跟踪警报调用:6:2:1
- 跟踪警报呼叫:6:30:1
- 跟踪警报调用:7:0:1
- 跟踪警报调用:7:30:1
- 跟踪警报调用:8:0:1
- 跟踪警报呼叫:8:30:4
- 跟踪警报调用:9:1:44
- 跟踪警报呼叫:9:30:1
Device D Log.txt
- 跟踪警报呼叫:0:1:25(从12:00开始)
- 跟踪警报调用:0:30:0
- 跟踪警报调用:1:31:41
- 跟踪警报呼叫:2:39:52
- 跟踪警报调用:3:0:25
- 跟踪警报呼叫:3:30:58
- 跟踪警报调用:4:0:25
- 跟踪警报呼叫:4:30:56
- 跟踪警报呼叫:5:30:51
- 跟踪警报呼叫:7:18:55
- 跟踪警报调用:7:30:0
- 跟踪警报调用:8:0:25
- 跟踪警报呼叫:8:30:43
- 跟踪警报调用:9:0:3
- 跟踪警报呼叫:9:30:25
- 跟踪警报呼叫:10:0:25
- 跟踪警报呼叫:10:30:4
- 跟踪警报呼叫:11:1:52
- 跟踪警报呼叫:11:30:27
- 跟踪警报调用时:12:1:6按下
问题可能是你的PendingIntent呼唤Service.在Service完成(甚至开始)执行之前,设备可以返回睡眠状态.
我建议你BroadcastReceiver改用(因为a WakeLock期间保证onReceive()).
获取WakeLockin onReceive(),Service从那里开始并在适当的时候WakeLock从中释放Service.
要简化此过程,您可以使用WakefulBroadcastReceiver帮助程序类:
PendingIntent.getBroadcast()而不是PendingIntent.getService().IntentService从onReceive()调用WakefulBroadcastReceiver.startWakefulService().onHandleIntent()然后打电话WakefulBroadcastReceiver.completeWakefulIntent().例如,BroadcastReceivera唤醒Service:
public class ExampleReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent wakefulServiceIntent = new Intent(context,
ExampleWakefulService.class);
WakefulBroadcastReceiver.startWakefulService(context,
wakefulServiceIntent);
}
}
Run Code Online (Sandbox Code Playgroud)
而且Service:
public class ExampleWakefulService extends IntentService {
private static final String NAME = "com.example.ExampleWakefulService";
public ExampleWakefulService() {
super(NAME);
}
@Override
protected void onHandleIntent(Intent intent) {
// doing stuff
WakefulBroadcastReceiver.completeWakefulIntent(intent);
}
}
Run Code Online (Sandbox Code Playgroud)
另外,请查看开发人员指南中关于保持设备唤醒的这篇文章.
在API级别23+,您必须处理Doze.
从文档:
为了帮助安排警报,Android 6.0(API级别23)引入了两种新
AlarmManager方法:setAndAllowWhileIdle()和setExactAndAllowWhileIdle().使用这些方法,您可以设置即使设备处于打盹状态也会触发的警报.
不幸的是没有其他选择setRepeating(),所以你有两个选择:
| 归档时间: |
|
| 查看次数: |
1245 次 |
| 最近记录: |