警报管理器无法在 android 的确切时间启动
alarm manager can't start at exact time in android
我有一个示例应用程序,我想在后台执行一些操作。
当我立即为闹钟管理器设置时间时,我的服务工作正常,但下次我设置时间时它不起作用(更改代码并在接下来的 2 分钟内再次 运行 应用程序)。
这是我的场景: 我设置了启动服务的时间和 运行 应用程序,然后单击 fab 并关闭应用程序并等待吐司。
这是我的一些 类 :
MainActivity.class
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener( view -> { startBackup();});
}
private void startBackup() {
Intent serviceIntent = new Intent(getApplicationContext(), ExampleService.class);
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 123, serviceIntent, 0);
Calendar cal = initCalendar(14, 36, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= 23) {
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
} else if (Build.VERSION.SDK_INT >= 19) {
alarm.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
} else {
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
}pintent);
}
private Calendar initCalendar(int hour, int minute, int second) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
return calendar;
}
}
ExampleService.class
public class ExampleService extends Service {
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "service create service", Toast.LENGTH_LONG).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Service you ", Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="sample.app.serviceserviceyou">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:name=".MainActivity"
android:label="service test"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ExampleService"
android:enabled="true"
android:exported="true"
/>
</application>
</manifest>
使用 setExact
和 setExactAndAllowWhileIdle
是正确的方法,但他们仍然需要唤醒一个 BroadcastReceiver
,它需要一个唤醒锁,而 Service
发布。甚至为此定义了一个有用的 class:WakefulBroadcastReceiver
.
本文将有助于提供有关警报的更多信息:http://hiqes.com/android-alarm-ins-outs/
经过大量研究,我终于发现 API 26 添加了一个名为 getForeGroundService()
的待处理意图的新方法
所以代码应该是这样的:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener( view -> startBackup());
}
private void startBackup() {
Intent serviceIntent = new Intent(getApplicationContext(), ExampleService.class);
Calendar cal = initCalendar(10, 0, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= 26) {
PendingIntent pintent = PendingIntent.getForegroundService(getApplicationContext(), 6546548, serviceIntent, 0);
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
}else if (Build.VERSION.SDK_INT >= 23) {
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 6546548, serviceIntent, 0);
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
} else if (Build.VERSION.SDK_INT >= 19) {
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 6546548, serviceIntent, 0);
alarm.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis() , pintent);
} else {
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 6546548, serviceIntent, 0);
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis() , pintent);
}
}
private Calendar initCalendar(int hour, int minute, int second) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
return calendar;
}
}
我有一个示例应用程序,我想在后台执行一些操作。 当我立即为闹钟管理器设置时间时,我的服务工作正常,但下次我设置时间时它不起作用(更改代码并在接下来的 2 分钟内再次 运行 应用程序)。
这是我的场景: 我设置了启动服务的时间和 运行 应用程序,然后单击 fab 并关闭应用程序并等待吐司。
这是我的一些 类 :
MainActivity.class
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener( view -> { startBackup();});
}
private void startBackup() {
Intent serviceIntent = new Intent(getApplicationContext(), ExampleService.class);
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 123, serviceIntent, 0);
Calendar cal = initCalendar(14, 36, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= 23) {
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
} else if (Build.VERSION.SDK_INT >= 19) {
alarm.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
} else {
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
}pintent);
}
private Calendar initCalendar(int hour, int minute, int second) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
return calendar;
}
}
ExampleService.class
public class ExampleService extends Service {
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "service create service", Toast.LENGTH_LONG).show();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Service you ", Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="sample.app.serviceserviceyou">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:name=".MainActivity"
android:label="service test"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ExampleService"
android:enabled="true"
android:exported="true"
/>
</application>
</manifest>
使用 setExact
和 setExactAndAllowWhileIdle
是正确的方法,但他们仍然需要唤醒一个 BroadcastReceiver
,它需要一个唤醒锁,而 Service
发布。甚至为此定义了一个有用的 class:WakefulBroadcastReceiver
.
本文将有助于提供有关警报的更多信息:http://hiqes.com/android-alarm-ins-outs/
经过大量研究,我终于发现 API 26 添加了一个名为 getForeGroundService()
所以代码应该是这样的:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener( view -> startBackup());
}
private void startBackup() {
Intent serviceIntent = new Intent(getApplicationContext(), ExampleService.class);
Calendar cal = initCalendar(10, 0, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
if (Build.VERSION.SDK_INT >= 26) {
PendingIntent pintent = PendingIntent.getForegroundService(getApplicationContext(), 6546548, serviceIntent, 0);
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
}else if (Build.VERSION.SDK_INT >= 23) {
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 6546548, serviceIntent, 0);
alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
} else if (Build.VERSION.SDK_INT >= 19) {
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 6546548, serviceIntent, 0);
alarm.setExact(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis() , pintent);
} else {
PendingIntent pintent = PendingIntent.getService(getApplicationContext(), 6546548, serviceIntent, 0);
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis() , pintent);
}
}
private Calendar initCalendar(int hour, int minute, int second) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, second);
return calendar;
}
}