我正在使用Android AlarmManager
每隔5分钟启动一次事件。这在我的api 24手机上正常工作,但在我的api 28手机上无法正常工作。在api 28上运行时,电话dumpsys alarm
显示警报正在响起,但从未调用过按其意图传递的JobIntentService
。
到目前为止,我已经尝试了各种设置警报的方法,例如setAndAllowWhileIdle
没有任何效果。在api 28手机上运行dumpsys alarm
表示单拍setAlarmWhileIdle
熄灭,但没有再次熄灭。同样,setInexactRepeating
也以经过的重复间隔发出声音。两者都不调用传递的JobIntentService
。
public class DataUploadService extends JobIntentService
implements DataClientManager.OnDataChangedListener {
private static final String TAG = "DataUploadService";
private static void LOG(String msg) { Log.d(TAG,msg); }
private static void LOGE(String msg) { Log.e(TAG,msg); }
public static final int DELAY_PERIOD = 5;
public static void initialize(Context context) {
//parse minutes to get exact time
final Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MINUTE,DELAY_PERIOD);
DataUploadService.setAlarm(context,calendar.getTimeInMillis());
}
public static void setAlarm(Context context, long millis) {
clearAlarm(context);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, DataUploadService.class);
PendingIntent alarmIntent = PendingIntent.getService(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, millis,
DELAY_PERIOD * 60 * 1000, alarmIntent);
}
public static void clearAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, DataUploadService.class);
PendingIntent alarmIntent = PendingIntent.getService(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(alarmIntent);
}
@Override
protected void onHandleWork(Intent intent) {
LOGE("Data Acquisition Service has been called");
final Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
LOG(calendar.getTime().toString());
}
}
在我的MainActivity
中,我呼叫DataUploadService.initalize(this)
,此后我希望每隔5分钟在系统日志"Data Acquisition Service has been called"
中看到一次。这在我的api 24手机上按需要发生,但在我的api 28手机上却没有发生。我发现文档中AlarmManager
的api没有明显的区别。
更新:
我发现set(int type, long triggerAtMillis, String tag, AlarmManager.OnAlarmListener listener, Handler targetHandler)
可在我的api级别28设备上使用。空Handler
和非空JobIntentService
似乎都可以工作。这不能回答我关于DECLARE
TYPE my_id_tab IS
TABLE OF my_table.my_id%TYPE;
my_ids my_id_tab;
BEGIN
UPDATE my_table
SET
another_id = NULL
WHERE
another_id IS NULL
AND create_datetime BETWEEN '03-JUN-19' AND '05-JUN-19'
RETURNING my_id BULK COLLECT INTO my_ids;
COMMIT;
END;
为何不再起作用但确实可以解决临时问题的问题。
答案 0 :(得分:0)
我想问题是因为您正在计划警报并在服务到期时启动服务。
由于服务是后台任务,因此(从API26 +开始)它们现在受到了更多限制
所以,我看到了两种解决方案:
第一个解决方案
创建一个广播接收器(将意图添加到AndroidManifest.xml
中)。因此,在5分钟后,该广播将收到该意图,该广播将通过以下方式启动服务:
AndroidManifest
<receiver
android:name=".DataUploadBroadcast"
android:exported="true"
tools:ignore="ExportedReceiver">
<intent-filter>
<action android:name="MY_CUSTOM_ACTION" />
</intent-filter>
</receiver>
BroadcastReceiver
public class DataUploadBroadcast extends BroadcastReceiver {
public static final int DELAY_PERIOD = 5;
public void onReceive(Context receivedContext, Intent intent) {
if("MY_CUSTOM_ACTION".equals(intent.getAction() {
DataUploadService.enqueueWork(context, new Intent(context, DataUploadService.class);
}
}
private static void setAlarm(Context context, long millis) {
clearAlarm(context);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
// Note the class is different now
Intent intent = new Intent(context, DataUploadBroadcast.class);
// Set action
intent.setAction("MY_CUSTOM_ACTION");
// Note the getBroadcast
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, millis, DELAY_PERIOD * 60 * 1000, alarmIntent);
}
public static void initialize(Context context) {
// call setAlarm
}
private static void clearAlarm(Context context) {
// Clear the alarm
}
}
DataUploadService
private static final int JOB_ID = 100;
public static void enqueueWork(Context context, Intent work) {
// This is how you should start the job.. and not PendingIntent.getService(...)
enqueueWork(context, DataUploadService.class, JOB_ID, work);
}
@Override
protected void onHandleWork(Intent intent) {
LOGE("Data Acquisition Service has been called");
}
第二个解决方案
让服务在“活动”请求发送后立即启动。然后,在onHandleWork
期间,您将服务休眠5分钟:
public class DataUploadService extends JobIntentService
implements DataClientManager.OnDataChangedListener {
public static final int DELAY_PERIOD = 5;
private static final int JOB_ID = 100;
public static void initialize(Context context) {
enqueueWork(context, DataUploadService.class, JOB_ID, new Intent(context, DataUploadService.class));
}
@Override
protected void onHandleWork(Intent intent) {
try {
Thread.sleep(DELAY_PERIOD * 60 * 1000);
efectivellyExecuteWork()
} catch (InterruptedException e) {
LOGE("ERROR");
}
}
private void efectivellyExecuteWork() {
LOGE("Data Acquisition Service has been called");
final Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
LOG(calendar.getTime().toString());
}
在第二种解决方案中,我只是将线程休眠了5分钟。如果您需要更新该计时器,以防用户在活动到期之前打开活动,则可以添加一些逻辑。 例如,您可以存储带有日期的日历实例。这样,线程将休眠直到到达该日期为止。这样一来,您就可以在必要时更新日历日期(就像清除/重新创建活动一样);
类似的东西:
try {
while(futureDate.getTimeInMillis() > Calendar.getInstance.getTimeInMillis()) {
Thread.sleep(futureDate.getTimeInMillis() - Calendar.getInstance.getTimeInMillis());
}
efectivellyExecuteWork()
} catch (InterruptedException e) {
LOGE("ERROR");
}