2013-11-24 47 views
2

我試圖每隔30秒開始一次服務(即使應用程序已關閉)。但它立即運行一個又一個。我開始首次由服務:android - 如何定期啓動服務?

Intent i= new Intent(this, MyService.class); 
this.startService(i); 

,我的服務是

public class MyService extends Service { 

    public static String READ_NEMAD_URL = "http://..."; 

    @Override 
    public void onStart(Intent intent, int startId) { 
     ReadNemad task = new ReadNemad("GCAZ92"); 
     task.execute(); 
    } 

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

    @Override 
    public void onDestroy() { 
     Calendar cal = Calendar.getInstance(); 

     Intent intent1 = new Intent(this, MyService.class); 
     PendingIntent pintent = PendingIntent.getService(this, 0, intent1, 0); 

     AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
     // Start every 30 seconds 
     alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 
       30 * 1000, pintent); 
    } 

    private class ReadNemad extends AsyncTask<String, Void, String> { 

      //Do Somethings 
      return response; 
     } 

     @Override 
     public void onPostExecute(String response) { 
      stopSelf(); 
     } 
    } 
} 

爲什麼服務本身運行?我怎樣才能解決它每30秒運行一次?

回答

2

我試圖每30秒定期啓動一次服務(即使應用程序關閉時也是如此)。但它立即運行一個又一個。

這是我覺得非常錯誤的做法。服務(其來源)用於非常長的任務和處理一些數據。它很適合你想擁有「永久」運行的情況。

你的描述是正常的行爲 - 在設置中打開運行的服務,然後在任務管理器關閉應用程序,並快速查找爲您服務 - - 你可以很簡單地測試了將被停止,並立即啓動後。

因此,我認爲你的想法是不好的設計。如果你想開始的代碼片段一些每30秒,最好是使用例如Handler(只處理程序或處理程序服務),良好的指定BroadcastReceivers - 與發送廣播權及其處理等

的主要用途操縱服務是在後臺運行,直到應用程序將被卸載並且您不應該嘗試更改它(這不是非常有效)。

一說來我的頭可能的方法(假設你想要做的每30秒的東西)是使用處理器和每30秒發送新的廣播,這將使一招。

+0

那麼爲什麼所有的教程都學習了AlarmManager如果運行時經常運行服務呢? AlarmManager是一個錯誤的方法? – user3021005

+0

@ user3021005你不明白我說了什麼,我沒有說alarmmanager是錯的我說,每30秒運行一次服務不會犯錯和錯誤。 – Sajmon

1

創建一個廣播接收器將從AlarmManager接收廣播後啓動服務:

public class SyncAlarm extends BroadcastReceiver { 

@Override 
public void onReceive(Context context, Intent data) { 

    // set alarm to start service 
    Calendar calendar = new GregorianCalendar(); 
    calendar.setTimeInMillis(System.currentTimeMillis()); 

    Calendar cal = new GregorianCalendar(); 
    cal.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR)); 
    cal.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)); 

    // start service after an hour 
    cal.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 60); 
    cal.set(Calendar.SECOND, calendar.get(Calendar.SECOND)); 
    cal.set(Calendar.MILLISECOND, calendar.get(Calendar.MILLISECOND)); 
    cal.set(Calendar.DATE, calendar.get(Calendar.DATE)); 
    cal.set(Calendar.MONTH, calendar.get(Calendar.MONTH)); 

    // set alarm to start service again after receiving broadcast 
    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
    Intent intent = new Intent(context, SyncAlarm.class); 
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); 
    am.cancel(pendingIntent); 
    am.set(AlarmManager.RTC, cal.getTimeInMillis(), pendingIntent); 

    intent = new Intent(context, Reminder.class); 
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
    context.startService(intent); 
    } 
} 

開始首次的廣播接收器,當你啓動應用程序:

AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 
    Intent intent = new Intent(context, SyncAlarm.class); 
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); 
    am.cancel(pendingIntent); 
    am.set(AlarmManager.RTC, System.currentTimeMillis(), pendingIntent); 

同時添加這到您的清單文件:

<receiver android:name=".SyncAlarm" > 
</receiver> 

如果您希望在資源可用時立即通過Android系統啓動服務,而不是通過AlarmManager接收廣播,則您還應該熟悉此START_STICKY

已回答相似問題here

0

在你的代碼中的錯誤是把cal.getTimeInMillis()setRepeating

AlarmManager's documentation說:

triggerAtMillis - >時間以毫秒爲單位的報警應先熄滅,使用相應的時鐘(取決於報警類型)。

所以你迫使它開始「現在」。