2013-10-29 40 views
0

我正在开发一个Android应用程序,它启动后台任务以每x秒从用户访问一次URL(用户定义的时间间隔,默认为60)。我的结构是这样:AlarmManager.setRepeating - 服务似乎没有重复

MainActivity

这个时间表通过AlarmManager报警:

public static void scheduleAlarm(Context voContext, int viCheckInterval) 
{ 
    try { 
     moAlarmManager = (AlarmManager) voContext.getSystemService(Context.ALARM_SERVICE); 
     Intent intent = new Intent(voContext, AlarmReceiver.class); 
     moAlarmIntent = PendingIntent.getBroadcast(voContext, 0, intent, 
                PendingIntent.FLAG_CANCEL_CURRENT); 
     Calendar time = Calendar.getInstance(); 
     time.setTimeInMillis(System.currentTimeMillis()); 
     time.add(Calendar.SECOND, viCheckInterval); 
     moAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), 
             time.getTimeInMillis(), moAlarmIntent); 
    } catch (Exception e) { 
     Log.e("MessageCheckAlarmHandler", e.toString()); 
    } 
} 

AlarmReceiver

这是启动服务的BroadcastReceiver:

@Override 
public void onReceive(Context context, Intent intent) 
{ 
    Context oAppContext = context.getApplicationContext(); 

    if (oAppContext == null) { 
     oAppContext = context; 
    } 

    Intent serviceIntent = new Intent(oAppContext, MessagingService.class); 
    oAppContext.startService(serviceIntent); 
} 

的MessagingService

这就造成我们内部的记录(记录在TCP)并启动的AsyncTask称为FetchPageTask:

public class MessagingService extends Service 
{ 
    @Override 
    public void onCreate() 
    { 
     super.onCreate(); 

     ... 

     this.acquireLocks(); 

     try { 
      String sCheckerUrl = oPreferences.getString("pref_server", ""); 
      int sCheckerPort = Integer.parseInt(oPreferences.getString("pref_server_port", 
                      "8050")); 
      sCheckerUrl = String.format(URL, sCheckerUrl, sCheckerPort); 

      this.moFetchInboxTask = new FetchPageTask(this.logger, this); 
      this.moFetchInboxTask.execute(sCheckerUrl); 
     } finally { 
      this.releaseLocks(); 
      this.stopSelf(); 
     } 
    } 

    @Override 
    public void onDestroy() 
    { 
     super.onDestroy(); 

     this.logger.close(); 
    } 

    @Override 
    public IBinder onBind(Intent intent) 
    { 
     return null; 
    } 

    /** 
    * Acquire a WakeLock and a WifiLock. 
    */ 
    private void acquireLocks() 
    { 
     try { 
      // Acquire a wake lock to prevent the device from entering "deep sleep" 
      PowerManager oPowerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE); 
      this.moWakeLock = oPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 
      this.moWakeLock.acquire(); 
      // Acquire a WiFi lock to ensure WiFi is enabled 
      WifiManager wm = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); 
      this.moWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG); 
      this.moWifiLock.acquire(); 
     } catch (Exception e) { 
      this.logger.error(TAG + "->onCreate()", "Error acquiring locks: " + e.toString()); 
     } 
    } 

    /** 
    * Release our WakeLock and WifiLock. 
    */ 
    private void releaseLocks() 
    { 
     try { 
      this.moWakeLock.release(); 
      this.moWifiLock.release(); 
     } catch (Exception e) { 
      this.logger.error(TAG + "->releaseLocks()", e.toString()); 
     } 
    } 
} 

FetchPageTask

这延长的AsyncTask,并做了所有获取页面和解析XML的工作。它还会添加通知,并根据需要对数据进行操作。


这一切工作正常,但不会随后运行。我知道AsyncTask的工作方式与以前使用纯Java通过ScheduledExecutorService和ScheduledFuture一样工作,并且工作正常。我决定改用AlarmManager的唯一原因是出于可维护性的目的。

回答

2

首先,您正在设置您的闹钟以便立即发生,然后每隔约43年发生一次。这不太可能是你想要的。修改您的通话的第三个参数setRepeating()要以毫秒为单位,现在正好是午夜以来的1月1日1970年

第二盘的毫秒数所需周期,您采集的WakeLock为时已晚。不能保证您的acquireLocks()将有机会在设备入睡之前运行。 My WakefulIntentServicethe new WakefulBroadcastReceiver提供更好的模式将控制权传递给IntentService

+0

啊,现在这可能是一个肯定的问题。谢谢你指出这一点。关于唤醒者,我也会研究它们。非常感谢链接! – euantorano

0

我认为你不需要这里的日历。你只是想每隔x秒运行一次,所以它会是这样的:

moAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 
            viCheckInterval, moAlarmIntent); 

// viCheckInterval should be long miliseconds