1

我目前正在開發Android應用程序。其中一個要求是大量記錄有關應用程序的使用方式。更具體地說,應該記錄關於何時用戶關閉該應用。此日誌記錄由服務器交互組成。對於特定要求我偶然發現:Android服務在應用關閉後執行AsyncTask

Detect Application Exit(1)Detect application Exit (2)

這兩個問題有一個公認的答案依靠Service#onTaskRemoved(Intent)

然而,在我的情況下,這種解決方案似乎並不奏效,即以這種方法啓動的AsyncTask只有偶爾會執行。更具體地說,onPreExecute執行總是doInBackground不是。我在安裝了Android 6(Marshmallow)的Nexus 5上測試了它。

public class SomeService extends Service { 

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

    @Override 
    public void onTaskRemoved(Intent aRootIntent) { 
    new DoSomethingTask().executeOnExecutor(Asyntask.THREAD_POOL_EXECUTOR); 
    } 

    private static final class DoSomethingTask extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected void onPreExecute() { 
     Log.e(DoSomethingTask.class.getName(), "This is executed always"); 
    } 

    @Override 
    protected Void doInBackground(Void... aParams) { 
     Log.e(DoSomethingTask.class.getName(), "This appears to be executed only sometimes... "); 
     // here an actual call to a Rest API should be made to inform the server that the user has closed the application. 
    } 

    @Override 
    protected void onCancelled(Void result) { 
     super.onCancelled(result); 
     Log.e(DoSomethingTask.class.getName(), "Never invoked"); 
    } 

    @Override 
    protected void onCancelled() { 
     super.onCancelled(); 
     Log.e(DoSomethingTask.class.getName(), "Never invoked"); 
    } 
    } 
} 

這裏是一切我試圖在除了上述代碼示例的概述:

  • 我已經onStartCommand選項(START_STICKY,START_NOT_STICKY等)沒有成功嘗試過各種。
  • 我也嘗試在onTaskRemoved方法中重新啓動服務,然後在onStartCommand中執行AsyncTask
  • onTaskRemoved方法(它在onHandleIntent方法中啓動AsyncTask)中啓動IntentService也解決了這個問題。
  • 使用BroadcastReceiver結合本地廣播(LocalBroadcastManager#sendBroadcast)也不起作用(我仔細檢查過廣播接收器是否被有效註冊爲發送廣播的接收器)。

編輯

我也採取了看看在Application類的回調: - onTerminate:此方法只調用在仿真環境中,因此沒用 - onTrimMemory(int):這種方法可以用於檢測應用程序何時進入後臺,但應用程序退出時沒有明確的情況。

我可以保留一個活動堆棧(將在Activity#onPause()等更新)。但是這需要在每個單獨的Activity中進行相當多的工作,而不是上述Service方法,其只涉及在單個地方的干擾。

+0

您可以通過擴展Application類並重寫onTerminate()onDestroy()onLowMemory()和類似的東西來做到這一點。 – napkinsterror

+0

我也試過,但我忘了在帖子中提到它。我現在已經在底部完成了,請參閱**編輯**部分。 –

回答

0

首先:在Android中,您無法保證執行您的要求。期。系統隨時可以免費上課或終止您的程序。此外,Android概念並沒有像網站沒有的那樣真正擁有「關閉應用程序」操作的概念。所以在你繼續閱讀之前,我敦促你重新考慮你的要求。

這就是說。以下是一些提示: 我對Service#onTaskRemoved(Intent)的理解是,只有在通過任務切換器殺死應用程序時纔會執行該操作,所以我不知道這對您是否有用。在你的實例中,我會在應用程序對象中保留一個活動參考計數器(每個onResume()爲+1,任何活動的每個onPause()爲-1)。有了這個,你可以檢查你的用戶是否有活動的用戶界面。通常情況下,如果您按下最後一個與「關閉」應用程序範例接近的活動。然後,只需從應用程序對象(這可能是獲得gc的最後一個)開始執行任務,或者如果這不起作用,請嘗試使用未綁定的服務您可以生成的最獨立的組件。

另外,非常非常糟糕的解決方案正在覆蓋對象(例如您的活動)中的finalize()方法。只有非常少的理由使用它,因爲它會觸發額外的gc循環,並且您的代碼將在主線程上運行,但是如果該對象即將被gc化,則它是執行代碼的一種方式。因此,Android團隊使用它是不鼓勵的,只有在你的頭上有槍的時候才使用它。

相關問題