通过IntentService轮询并使用AlarmManager

时间:2014-05-21 12:31:17

标签: android broadcastreceiver android-service alarmmanager intentservice

我只是很难理解AlarmManager系统,与未来的通知等相关。我似乎无法让AlarmManager以正确的频率设置闹钟。

我也不确定我应该在哪里制作闹钟,以及哪种类型最适合我的需要。

更新基于偏好设置,详情如下。


启动服务

启动我的应用程序时,会在创建FragmentActivity时调用该服务。在onCreate()中,我有以下内容:

Intent mServiceIntent = new Intent(this, ServiceUpdater.class);
if(startService(mServiceIntent)==null)
startService(mServiceIntent);

发生了很多其他的事情并且显示了片段等,但这主要是为了确保服务正在运行。注意,我也将它设置为在系统启动时调用BroadcastReceiver。

ServiceUpdater.class

public class ServiceUpdater extends IntentService{

    private SharedPreferences defaultPrefs;
    private SharedPreferences userPrefs;
    private SharedPreferences.Editor editor;

    // Alarm Service
    private AlarmManager alarmManager;
    private PendingIntent alarmIntent;

    public ServiceUpdater() {
            super("MyService");
}

    @Override
    protected void onHandleIntent(Intent intent) {

            defaultPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            userPrefs = getSharedPreferences("user", Context.MODE_PRIVATE);


            long updateFrequency = (Long.parseLong(defaultPrefs.getString("updateFrequencyPref", "24")))*1000*60*60; 
            // in hours = 1000*60*60*'24'        

            long thirtySecondsAfterWake = SystemClock.elapsedRealtime() + 30*1000; // 30 seconds after the device boots

            Intent intent1 = new Intent(this, UpdateReceiver.class);
            alarmIntent = PendingIntent.getBroadcast(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
            alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, thirtySecondsAfterWake, updateFrequency, alarmIntent); 

            if(defaultPrefs.getBoolean("updatePref", true))
                    new Update().execute();
    }


    private class Update extends AsyncTask<Void, Void, Integer>{
        private int newNumber;

    @Override
    protected Integer doInBackground(Void... params) {
        newNumber= new HttpServices().getNewNumber(); 
        return newNumber;
    }

    @Override
    protected void onPostExecute(Integer noJobs){
        if(newNumber > 0){ //userPrefs.getInt("oldNumber", 0)){
            editor = userPrefs.edit();
            editor.putInt("oldNumber", newNumber);
            editor.commit();
            if(!FragActivity.active)
                new MyNotif(getApplicationContext(), "NewData");
        }
    }

} // end Async
} // end service class

UpdateReceiver.class

public class UpdateReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent updater = new Intent(context, ServiceUpdater.class);
        context.startService(updater);
    }

}

---------------------

我的猜测是当闹钟呼叫接收器时,它会创建一个新的闹钟,然后更新旧闹钟,将下一个更新时间设置为30秒;这解释了为什么HTTP请求正在发生(我每30秒左右收到一次通知。

即使应用程序未运行,我也希望确保警报运行。

我的目标是执行以下操作。

  1. 运行App /或/ On Phone Startup
  2. 启动轮询(例如每日)单个Http请求
  3. 的服务
  4. 无论响应如何,请确保在下一个迭代时间范围内再次进行轮询
  5. 将根据投票结果从onPostExecute触发通知
  6. 我在哪里正确设置闹钟,以便每次服务都不会重新创建 - 但即使应用程序没有运行也能正确运行?

    感谢您提前提供任何帮助。

1 个答案:

答案 0 :(得分:1)

  

但这主要是为了确保服务正在运行

我不知道你为什么要两次启动这项服务。

  

ServiceUpdater.class

我不知道你为什么在AsyncTask内使用IntentService。这在几个层面都很糟糕。 onHandleIntent()已在后台线程上调用,我希望您的应用在尝试在后台线程上创建AsyncTask时会崩溃。只需将所有后台逻辑移动到onHandleIntent()(或onHandleIntent()调用的方法)。

  

我的猜测是当闹钟呼叫接收器时,它会创建一个新的闹钟,然后更新旧闹钟,将下一个更新时间设置为30秒;这解释了为什么HTTP请求正在发生(我每30秒左右收到一次通知。

我不知道你为什么要在每次跑步中设置重复闹钟。

  

我在哪里正确设置警报,以便每次服务时都不会重新创建 - 但即使应用程序未运行也能正确运行?

您需要执行设置AlarmManager计划的代码:

  • 首次运行你的应用程序(因为你还没有机会设置闹钟)

  • 用户强制停止您的应用程序设置(因为您之前安排的警报已被清除)

  • 重新启动后(因为您之前安排的警报被清除)

处理前两个问题的典型模式是跟踪上次运行警报代码的时间,例如SharedPreference。然后,在自定义Application或应用的可能入口点(例如,启动器活动)中,检查上次警报运行时间的SharedPreference值:

  • 如果没有值,则表示这是您应用的首次运行,因此您可以安排闹钟

  • 如果有值,并且它显着长于您的轮询周期,则表示您的应用已强制停止,因此您安排了警报

  • 否则,有一个合理的值,所以你假设你的闹钟工作正常

处理重启方案是为了响应AlarmManager广播而运行ACTION_BOOT_COMPLETED调度逻辑。

请注意,您使用的是ELAPSED_REALTIME,这意味着如果设备处于睡眠模式,闹钟将会延迟。

另请注意,您正在使用setInexactRepeating(),这意味着闹钟将在轮询期间的某个时间关闭,但不会以精确的间隔关闭。