Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 计划将来要执行的事件(Android方式的Cron作业)_Java_Android_Cron_Android Alarms - Fatal编程技术网

Java 计划将来要执行的事件(Android方式的Cron作业)

Java 计划将来要执行的事件(Android方式的Cron作业),java,android,cron,android-alarms,Java,Android,Cron,Android Alarms,我有一些日期一旦达到,就会失去相关性,应该计算数据库中这些字段的新日期,我知道我可以利用AlarmManager类实现这一点,但是我对此有一些顾虑: 1) 注意:从API 19(KITKAT)开始,警报传递是不精确的:操作系统将切换警报,以尽量减少唤醒和电池使用。有新的API支持需要严格交付保证的应用程序;请参见设置窗口(int,long,long,pendingent)和设置精确窗口(int,long,pendingent)。targetSdkVersion早于API 19的应用程序将继续看到

我有一些日期一旦达到,就会失去相关性,应该计算数据库中这些字段的新日期,我知道我可以利用AlarmManager类实现这一点,但是我对此有一些顾虑:

1) 注意:从API 19(KITKAT)开始,警报传递是不精确的:操作系统将切换警报,以尽量减少唤醒和电池使用。有新的API支持需要严格交付保证的应用程序;请参见设置窗口(int,long,long,pendingent)和设置精确窗口(int,long,pendingent)。targetSdkVersion早于API 19的应用程序将继续看到之前的行为,其中所有警报都会在请求时准确传递

那么,我是否需要分别为这两种情况编写代码,或者如果我以kitkat为目标,那么这是否也适用于较旧的版本?另外,由于我的代码执行是时间关键型的,比如某个日期午夜12点之后,我的数据失去了相关性,因此如何克服警报的转移

2) 当设备处于睡眠状态时,注册的报警会被保留(如果在此期间报警关闭,可以选择唤醒设备),但如果关闭并重新启动,则会被清除

2.1)在应用程序清单中设置RECEIVE_BOOT_COMPLETED权限。这允许您的应用程序接收在系统完成引导后广播的“启动完成”操作(仅当用户已启动应用程序至少一次时此操作才有效)

2.1.1)如果我将警报设置为12,那么与此警报相关的服务将在12触发,现在当我重新启动设备时,“12”的时间已经过去,警报将立即再次触发,服务将再次调用

重新启动时,为了在特定时间坚持代码执行策略,我需要实现什么机制?如果用户未启动我的应用程序,如何设置警报

第三件事是,如果我的应用程序被卸载,我想清除由我的代码设置的所有警报,那么当应用程序被卸载时,我该如何监听

另外,我想知道,我的应用程序对时间非常关键,我数据库中的值在每晚12点之前就会过时,当我更新应用程序时,如果用户选择在12点使用我的应用程序,而我在后台使用服务更新应用程序及其运行,结果会是什么

编辑:到目前为止我尝试的内容:

我有一个数据库,其中的记录会在午夜过后过期,比如说在12:00的夏普。我调用了报警管理器(在测试项目中,因为我喜欢隔离问题代码)来启动服务。我还获得了设备上的部分唤醒锁,这样我的大型数据库操作就可以正常进行了。我还实现了一个线程来完成耗时的任务。以下是我的MainActivity类,我在12点调用该类以启动报警(出于测试目的的随机时间):

这是我的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中释放wakelock

最后,这是我的清单:

<?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>
更多问题:我应该在哪里设置警报,如果我在启动屏幕的onCreate中设置警报,每次应用启动时都会调用警报,可能会覆盖旧值

第二,当我的服务运行时,我想获得DB上的锁,如果此时用户试图打开我的应用程序,我该怎么办?(由于数据正在更新,我没有任何东西要显示)

第三,在上面的代码中,我仍然发现在重新启动后注册警报时存在问题

1)要在准确的时间处理报警,您有两个选项: a) 将最低SDK级别设置为18而不是19。这将使你的应用程序在kitkat上准确运行 b) 使用setExact()方法告诉Kitkat在指定的准确时间保持警报 资料来源:

2) 启动完成通知是最好的方式。您可以设置广播接收器以在重新启动时获取通知。您可以将报警存储在数据库中,并在重新启动时检索

2.1)执行用户不希望您执行的操作是一种可怕的编程实践,即即使用户尚未打开应用程序,也会设置警报

3) 只要您不在SD卡上创建文件,卸载应用程序时,所有应用程序数据都将被删除


4) 您应该在写入或读取数据时锁定/解锁数据,以解决凌晨12点的问题。如果数据被锁定,则在用户提交事务之前不会受到影响。如果您正在使用SQLite,您可以从以下位置获得更多信息:

我认为,您可以编写一个类似于以下内容的
服务
(这将每5分钟完成一次任务),并从侦听
启动完成状态的
广播接收器
启动
服务

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
    }
}

打开应用程序的上下文是什么
这意味着在设备上至少打开一次应用程序,还是意味着在重新启动后至少打开一次应用程序?@AstralProjection:从蜂巢开始,MR1应用程序在安装时最初处于停止状态,在用户强制停止时返回。此时,所有
广播接收器都被禁用。因此,您还应该在
应用程序
onCreate()
方法以及引导完成
广播接收器
中注册警报。明白了,我在脑海中的某个地方记着这个。但是如果我把代码放在onCreate中,它会在每次调用onCreate时安排一个新的警报,还是会覆盖上一个警报
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
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
    }
}