我有一些日期曾经失去它们的相关性,并且应该计算DB中这些字段的新日期,我知道我可以利用AlarmManager类,但是我对此有一些担忧:
1)注意:从API 19(KITKAT)开始,警报传递不准确:操作系统将移动警报以最小化唤醒和电池使用。有新的API支持需要严格交付保证的应用程序;请参阅setWindow(int,long,long,PendingIntent)和setExact(int,long,PendingIntent)。 targetSdkVersion早于API 19的应用程序将继续查看之前在请求时准确传递所有警报的行为。
所以我需要单独编写这两种情况的代码,或者如果我的目标是kitkat,那么它是否适用于旧版本?此外,由于我的代码执行时间紧迫,比如在某个日期的午夜12点之后,我的数据失去了相关性,如何克服警报的转移。
2)在设备处于睡眠状态时保留已注册的警报(如果设备在此期间关闭,可以选择将设备唤醒),但如果设备关闭并重新启动,则会清除设备。
2.1)在应用程序的清单中设置RECEIVE_BOOT_COMPLETED权限。这允许您的应用接收系统完成启动后广播的ACTION_BOOT_COMPLETED (仅当用户已至少启动一次应用时才有效)
2.1.1)如果我在12处设置了警报,则与此警报相关的服务将在12时触发。现在,当我重启设备时,时间“在12”已经过去,警报将立即再次触发并将再次调用该服务?
重启时我需要实现哪些机制才能在特定时间坚持我的代码执行策略?如果用户未启动我的应用,如何设置闹钟?
第三件事是,如果我的应用程序已卸载,我想清除我的代码设置的所有警报,如何在卸载应用程序时收听?
另外我想知道,我的应用程序非常关键,我的数据库中的值每晚12点都会过时,而我正在更新应用程序,如果用户选择使用我的应用程序,结果会是什么? 12我使用服务来更新它并在后台运行?
编辑:到目前为止我尝试了什么:
我有一个数据库,其中记录在午夜过时,在12:00时说得很清楚。我调用了一个警报管理器(在我喜欢的测试项目中隔离问题代码)来启动一个服务。我还在设备上获得了PARTIAL_WAKE_LOCK,这样我的数据库操作就可以正常完成。我还实现了一个线程来完成我耗时的任务。以下是我的MainActivity类,我在12处调用它来启动警报(随机时间用于测试目的):
public class MainActivity extends Activity {
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
BroadcastReceiver br;
TextView t;
int sum;
public void setSum(int s){
sum = s;
// t = (TextView)findViewById(R.id.textView1);
// t.setText(sum);
System.out.println("In Set Sum"+s);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setup();
t = (TextView)findViewById(R.id.textView1);
ComponentName receiver = new ComponentName(getApplicationContext(), SampleBootReceiver.class);
PackageManager pm = getApplicationContext().getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 17);
calendar.set(Calendar.MINUTE, 05); // Particular minute
calendar.set(Calendar.SECOND, 0);
alarmMgr = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000*60*60*24, alarmIntent);
}
public void setup() {
br = new BroadcastReceiver() {
@Override
public void onReceive(Context c, Intent i) {
Toast.makeText(c, "Rise and Shine!", Toast.LENGTH_LONG).show();
//Invoke the service here Put the wake lock and initiate bind service
t.setText("Hello Alarm set");
startService(new Intent(MainActivity.this, MyService.class));
stopService(new Intent(MainActivity.this, MyService.class));
}
};
registerReceiver(br, new IntentFilter("com.testrtc") );
alarmIntent = PendingIntent.getBroadcast( this, 0, new Intent("com.testrtc"),0 );
alarmMgr = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
这是我的SampleBootReceiver类,以便在重新启动后检查重新启动并再次设置警报,我不确定它是否按预期工作。我找不到测试这是否正常工作的方法,但我收到关于完成启动的Toast消息。
public class SampleBootReceiver extends BroadcastReceiver {
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
BroadcastReceiver br;
TextView t;
MainActivity main;
@Override
public void onReceive(Context context, Intent intent) {
main= new MainActivity();
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
Toast.makeText(context, "Hello from Bootloader", 10000).show();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 15);
calendar.set(Calendar.MINUTE, 50); // Particular minute
calendar.set(Calendar.SECOND, 0);
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
1000*60*60*24, alarmIntent);
context.getApplicationContext().registerReceiver(br, new IntentFilter("com.testrtc") );
alarmIntent = PendingIntent.getBroadcast( context.getApplicationContext(), 0, new Intent("com.testrtc"),
0 );
alarmMgr = (AlarmManager)(context.getApplicationContext().getSystemService( Context.ALARM_SERVICE ));
}
}
}
以下是我的服务类,不确定我在onStartCommand方法中所做的返回:
public class MyService extends Service {
int a = 2;
int b = 2;
int c = a+b;
public MainActivity main = new MainActivity();
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
Toast.makeText(this, "The new Service was Created", Toast.LENGTH_LONG).show();
}
@Override
public int onStartCommand(Intent i, int flags , int startId){
WakeLock wakeLock = null;
try{
PowerManager mgr = (PowerManager)getApplicationContext().getSystemService(Context.POWER_SERVICE);
wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
Toast.makeText(this, " Service Started", Toast.LENGTH_LONG).show();
new Thread(new Runnable() {
public void run(){
//Will be substituted with a time consuming long task.
main.setSum(c);
}
}).start();
}catch(Exception e){
System.out.println(e);
}finally{
wakeLock.release();
}
return 1;
}
@Override
public void onDestroy() {
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
同样在上面,我想知道我开始的线程是否会与我如何获取唤醒锁。如果我可以使用异步任务并在onPostExecute中释放唤醒锁?
最后这是我的清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.testrtc"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.testrtc.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".SampleBootReceiver"
android:enabled="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" >
</action>
</intent-filter>
</receiver>
<service
android:name="com.testrtc.MyService"
android:enabled="true"
android:exported="true" >
</service>
</application>
</manifest>
这是我的日志Cat重新启动后,有很多日志消息,但是我发现这些与应用程序有关,它们包含th epackage名称:
01-22 15:18:35.652: V/ActivityManager(419): getTasks: max=1, flags=0, receiver=null
01-22 15:18:35.652: V/ActivityManager(419): com.xxx.xxx/.MainActivity: task=TaskRecord{425c58f0 #5 A com.xxx.xxx U 0}
01-22 15:18:35.653: V/ActivityManager(419): We have pending thumbnails: null
更多问题:我应该在哪里设置闹钟,如果我在启动画面的onCreate中执行此操作,则每次应用启动时都会调用它,可能会覆盖较旧的值。
其次我想在我的服务运行时获取数据库上的锁,如果在这个时候用户试图打开我的应用程序我该怎么办? (随着数据的更新,我没有任何东西可以展示)。
在上面的代码中,我仍然发现重启后注册警报的问题。
答案 0 :(得分:1)
1)要在确切的时间处理警报,您有两个选择: a)将最低SDK级别设置为18而不是19.这将使您的应用程序在确切的时间在kitkat上运行 b)使用setExact()方法告诉Kitkat在指定的确切时间保持警报 资料来源:http://developer.android.com/about/versions/android-4.4.html
2)启动完成通知是最好的方法。您可以设置广播接收器以在重新启动时获取通知。您可以将警报存储在数据库中并在重新启动时检索。
2.1)使用用户不希望你做的事情是一种可怕的编程习惯,即即使用户没有打开应用程序也会设置警报。3)只要您不在SD卡上创建文件,卸载应用程序后就会删除所有应用程序数据
4)您应该在写入或读取数据时锁定/解锁数据以解决您的12AM问题。如果数据被锁定,则在用户提交事务之前不会受到影响。如果您使用的是SQLite,可以从http://www.sqlite.org/lockingv3.html
获取更多相关信息答案 1 :(得分:-1)
我认为,你可以写一个Service
类似下面的内容(这将每隔5分钟执行一次)并从Service
开始BroadcastReceiver
听取BOOT_COMPLETED
州。
public class YourService extends IntentService {
public YourService() {
super("YourService");
}
public YourService(String name) {
super(name);
}
private static Timer timer = new Timer();
private class mainTask extends TimerTask {
public void run() {
// TASK WHATEVER YOU WANT TO DO
}
}
public void onDestroy() {
super.onDestroy();
}
@Override
protected void onHandleIntent(Intent intent) {
timer.scheduleAtFixedRate(new mainTask(), 0, 300000); // 5 minutes
}
}