2012-06-25 47 views
2

我正在編寫我的第一個使用服務的應用程序,按照這裏的教程/指南http://www.vogella.com/articles/AndroidServices/article.html 我有我的服務工作,它描述了爲BOOT_COMPLETED製作一個廣播接收器,它工作並允許我每隔幾分鐘運行一次服務。開始服務計劃,無需重新啓動?

我的問題是,它不工作,直到用戶重新啓動他們的手機。該服務從活動開始,但似乎隨着活動而消失,除非設備已重新啓動。

有沒有什麼辦法可以在第一次運行時從活動中啓動調度程序而無需重新啓動?

我對調度代碼如下:

public class ScheduleReceiver extends BroadcastReceiver { 

    // Restart service every 30 seconds 
    private static final long REPEAT_TIME = 1000 * 60; // check every minute. 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     Log.d("schedulereceiver", "starting schedule"); 
     AlarmManager service = (AlarmManager) context 
       .getSystemService(Context.ALARM_SERVICE); 
     Intent i = new Intent(context, StartServiceReceiver.class); 
     PendingIntent pending = PendingIntent.getBroadcast(context, 0, i, 
       PendingIntent.FLAG_CANCEL_CURRENT); 
     Calendar cal = Calendar.getInstance(); 
     // Start 30 seconds after boot completed 
     cal.add(Calendar.SECOND, 30); 
     // 
     // Fetch every 30 seconds 
     // InexactRepeating allows Android to optimize the energy consumption 
     service.setInexactRepeating(AlarmManager.RTC_WAKEUP, 
       cal.getTimeInMillis(), REPEAT_TIME, pending); 

     // service.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 
     // REPEAT_TIME, pending); 

    } 
} 

我的清單文件看起來是這樣的:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 

    <uses-sdk android:minSdkVersion="8" /> 

    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" > 

     <activity 
      android:name=".ProximityActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

     <service 
      android:name=".ProximityService" 
      android:enabled="true" 
      android:icon="@drawable/ic_launcher" 
      android:label="@string/service_name" > 
     </service> 

     <receiver android:name="ScheduleReceiver" > 
      <intent-filter> 
       <action android:name="android.intent.action.BOOT_COMPLETED" /> 
      </intent-filter> 
     </receiver> 
     <receiver android:name="StartServiceReceiver" > 
     </receiver> 
    </application> 

</manifest> 

回答

2

這裏的基本問題是,你想設置定時器在兩種不同的情況。

您希望在啓動時對其進行設置,並且您希望在用戶第一次啓動應用程序時對其進行設置。 (恐怕你不能在安裝時執行此操作)。

我發現要做到這一點的最好方法就是在文件系統中簡單地記錄下你設置定時器的時間,第一次設置它。

在ScheduleReceiver,打造兩個公共靜態方法:

public static void startupActions(Context ctx) { 
    setupTimer(); 
    try { 
     ctx.openFileOutput(".inited", Context.MODE_PRIVATE).close(); 
    } catch (IOException e) { 
     throw new Error(e); 
    } 
} 

呼叫從自己的onReceive()方法,方法同上。我們稍後會再次使用它。

public static boolean hasStartupRun(Context ctx) { 
    try { 
     ctx.openFileInput(".inited").close(); 
     return true; 
    } catch (IOException e) { 
     return false; 
    } 
} 

在主要活動的onCreate()方法,用這些來告訴你是否需要啓動定時器:

if (! ScheduleReceiver.hasStartupRun(this)) { 
     ScheduleReceiver.startupActions(this); 
    } 

看來,重新安裝不清除定時器,所以只能等干擾你如果需要修改計時器(或其他啓動操作),需要擔心的是。爲了處理這個問題,你可以修改意圖,以便不處理舊的意圖,並重新命名該文件,以便新的意向被安排。

您可以使用任何其他持久性標誌,例如數據庫創建,首選項文件等,但以這種方式創建文件是我可以從BroadcastReceiver中想到的最簡單的方式。

我發現在你的問題中有一點令你困惑的一件事是你的服務「開始」和「死亡」的活動。

我意識到這個問題已經過去幾個月了,但是爲了其他讀者可能會穿上類似的鞋子...這聽起來有點困惑。你的意思是,當活動開始時調用服務的onCreate()方法,並且當活動「死亡」時調用onDestroy()方法?或者你的活動開始或綁定到它,但它會消失,並且當進程被殺時永遠不會回來。

我提出這個問題的原因是,根據您的服務的不同,您可能需要刪除任何其他代碼開始您的服務,並只依靠計時器。

服務和活動生命週期是完全不同和不相關的,並且過程生命週期與任何一個都有很大的不同。如果你想從你的活動中與你的服務進行交互,你可能想綁定到它,並從定時器啓動它。兩者都完全可以! (儘管有兩種服務通常會更好 - 一種是基於背景或基於計時器的服務,另一種是後臺服務和活動綁定的控件/配置)。

只要確保將每個綁定與解除綁定匹配,並且每次都啓動Service.stopSelfResult(int)(如果服務在每次啓動時執行一個工作單元)或Context.stopService(Intent) (如果服務是按照調用者的需要而連續的),那麼系統知道你何時完成服務。

如果您使用startService,請務必仔細選擇從onStartCommand(...)返回的標誌。

+0

儘管如此多月後,我很欣賞答案。在那個階段,我仍然在學習很多東西,並沒有完全理解一些概念。你已經很好地解釋過了,謝謝!恐怕我無法回答你關於令人費解的「死於活動」的問題,因爲我不再使用該代碼。我正在搞一個沒有按照我想要的方式工作的想法(由於硬件限制),所以我放棄了它。 – hyarion

0

事情與Service的是,它會作爲一個單獨的實例。每次啓動相同的服務時,都只會調用onStartCommand()方法。因此在警報管理器中使用它並期望Service重新運行可能不會發生。

詳細信息請參考以下內容: http://developer.android.com/guide/components/services.html#StartingAService

+0

此答案與問題無關。 這裏的問題是BOOT_COMPLETED不會被解僱,除非用戶運行一次應用程序,然後重新啓動。 使用警報管理器的服務是完全正確的,並會導致它「運行」。 也許通過「重新運行」你想到它不調用onCreate()?但這不是您應該考慮的作爲服務運行。請參閱圖2中的「Active Lifetime」框:http://developer.android.com/guide/components/services.html –

相關問題