告警管理器在服务中异常重复
Alarm Manager repeat abnormally with in Service
我创建了必须每隔一秒记录一次的简单服务。我使用了警报管理器(因为来自 official document 说 Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running.
)但它随机重复。
这是我的代码
MainActiviry.class
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
if (fab != null) {
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,LogService.class);
startService(intent);
}
});
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
我通过点击 FAB 按钮启动服务。
LogService.class
public class LogService extends Service {
private static final String TAG = LogService.class.getSimpleName();
public LogService() {
super();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand: Service calling" );
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onCreate() {
Timer(this);
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void Timer(Context context){
Intent intent = new Intent(context,LogService.class);
PendingIntent pendingIntent = PendingIntent.getService(context,0,intent,0);
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(getApplicationContext().ALARM_SERVICE);
alarmManager.setRepeating(alarmManager.RTC_WAKEUP,System.currentTimeMillis(),1*1000,pendingIntent);
}
}
这是我的LOG
它每分钟都在重复,但我每秒都在写。我做错了吗?
因为 API 19 次重复警报 不准确 。看到这个:
Note: as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whose targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.
您必须将 targetSdkVersion
设置为低于 19 的值,或者使用一次性精确警报并每次都重新设置它们。
使用 java.util.Timer
的简单解决方案
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
//Put your code here
Log.d("Log", "Hello World");
}
}, 0, 1000);
我创建了必须每隔一秒记录一次的简单服务。我使用了警报管理器(因为来自 official document 说 Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running.
)但它随机重复。
这是我的代码
MainActiviry.class
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
if (fab != null) {
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this,LogService.class);
startService(intent);
}
});
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
我通过点击 FAB 按钮启动服务。
LogService.class
public class LogService extends Service {
private static final String TAG = LogService.class.getSimpleName();
public LogService() {
super();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand: Service calling" );
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onCreate() {
Timer(this);
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void Timer(Context context){
Intent intent = new Intent(context,LogService.class);
PendingIntent pendingIntent = PendingIntent.getService(context,0,intent,0);
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(getApplicationContext().ALARM_SERVICE);
alarmManager.setRepeating(alarmManager.RTC_WAKEUP,System.currentTimeMillis(),1*1000,pendingIntent);
}
}
这是我的LOG
它每分钟都在重复,但我每秒都在写。我做错了吗?
因为 API 19 次重复警报 不准确 。看到这个:
Note: as of API 19, all repeating alarms are inexact. If your application needs precise delivery times then it must use one-time exact alarms, rescheduling each time as described above. Legacy applications whose targetSdkVersion is earlier than API 19 will continue to have all of their alarms, including repeating alarms, treated as exact.
您必须将 targetSdkVersion
设置为低于 19 的值,或者使用一次性精确警报并每次都重新设置它们。
使用 java.util.Timer
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
//Put your code here
Log.d("Log", "Hello World");
}
}, 0, 1000);