2

我的學生應用程序在後臺服務中下載標記,並檢查是否有比上次更多的標記。如果有新標記,它將推送通知並重寫sharedPreferences中的標記數。它可以工作,但有時它會同時爲相同標記創建多個通知。Android服務setInexact使用SharedPreferences重複asyncTask問題

IntentService這觸發一個廣播接收機

public int onStartCommand(Intent intent, int flags, int startId) { 
    AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
    Intent i = new Intent(getApplicationContext(), CheckNewMarksReceiver.class); 
    PendingIntent alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0); 

    alarmManager.setInexactRepeating(
      AlarmManager.ELAPSED_REALTIME_WAKEUP, 
      0, 
      2500, alarmIntent); 

    return START_STICKY; 
} 

的廣播接收機的onReceive方法初始化sharedPreferences屬性和numberOfMarksSaved並啓動的AsyncTask下載數據:

DownloadDataTask task = new DownloadDataTask(); 
task.execute(context.getString(R.string.LOGIN_PAGE_URL), username, password); 

dataPreferences = context.getApplicationContext().getSharedPreferences(context.getString(R.string.SHARED_PREFERENCES), Context.MODE_PRIVATE); 
numberOfMarksSaved = dataPreferences.getInt(context.getString(R.string.PREFERENCE_NUMBER_OF_MARKS_KEY), -1); 

AsyncTasks onPostExecute個方法檢查下載標記的數量比上一次更大:

if (numberOfDownloadedMarks > numberOfMarksSaved) { 
    ... 
    notifyUserAbout(newMarks, response); // method to fire a notification 
} 

dataPreferences 
    .edit() 
    .putInt(context.getString(R.string.PREFERENCE_NUMBER_OF_MARKS_KEY), 
      numberOfDownloadedMarks) 
    .apply(); 

正如我所說的,這主要是工作,但有時廣播接收器被連續觸發兩次立即 - 第一個重寫值在sharedPreferences中,但第二個不會「注意到」共享首選項中的值已更改。我怎樣才能防止呢?我試過甚至setRepeating,而不是setInexactRepeating - 沒有任何改變(我懷疑android alarmManager時間轉移)。這是我的日誌:

06-11 18:14:27.732 ... I /剛想:下載新的數據

06-11 18:14:27.761 ... I /剛想:下載新的數據

06-11 18:14:27.907 ... I /保存&新:89,90

06-11 18:14:27.933 ... I /通知出爐 - ID:1077819997

06-11 18:14:28.004 ... I /已保存&新:89,90

06-11 18:14:28.006 ... I /通知出爐 - ID:1077820069

+0

有一個答案表明從不正確的重複變爲重複。它沒有幫助。 – cuddlecheek

回答

1

,因爲如何不精確重複報警工作,並且長時間運行的後臺操作,最有可能有在運行多個實例AsyncTask發生問題的同時。

AlarmManager文檔:

你的報警器的第一個觸發器將不是要求的時間之前,但 它可能不適合在此時間之後幾乎整整間隔發生。此外,在重複報警的整個週期將爲 請求的情況下,報警 的任意兩次連續發射之間的時間可能會有所不同。

對於如此低的區間,我建議使用setRepeating()代替setInexactRepeating()

讓您AsyncTask的實例在Service

然後,你可以做這樣的事情:

if(task.getStatus == AsyncTask.Status.FINISHED) { 
    task = new DownloadDataTask(); 
    task.execute(context.getString(R.string.LOGIN_PAGE_URL), username, password); 
} 

爲了避免在同一時間運行您AsyncTask的多個實例。

+0

我在一個Handler中使用了postDelayed這個服務,它的功能就像一個魅力。非常感謝你。 – cuddlecheek