2012-04-25 69 views
4

Im建立一個基於PhoneGAP的應用程序,我需要撥打電話然後在5秒後返回到我的應用程序。通過電話撥打電話後重新集中主要活動

關於撥打電話的部分工作正常。爲了使Android與呼叫開放而不僅僅是撥號盤,這使得調用的代碼被放置在一個com.phonegap.api.Plugin,看起來像

private void callNumber(String phoneNumber){ 
    Uri calling = Uri.parse("tel:" + phoneNumber); 
    Intent callIntent = new Intent(Intent.ACTION_CALL, calling); 
    this.ctx.startActivity(callIntent); 
} 

要重新啓動應用程序,即時通訊發動的AsyncTask剛在進行名爲RestartTask的調用之前。由於此代碼位於插件中,因此我必須使用Activity.runOnUiThread來啓動RestartTask,但除此之外沒有什麼特別的。

在RestartTask,只有doInBackground方法的實現和所有它,在睡覺爲5秒鐘,然後運行以下意圖:

Intent restartIntent = new Intent(DialerPlugin.this.ctx.getBaseContext(), MainActivity.class); 
restartIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 
DialerPlugin.this.ctx.startActivity(restartIntent); 

這裏MainActivity是從PhoneGap的,它擴展了派生主類DroidGap

設置FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_SINGLE_TOP是人在說什麼herehere應設置,如果活動被「激活」,意思是其中活動正在實例化的任務使用,而不是創建新任務,並且該活動與其運行狀態重用,而不是創建新的活動實例。當意圖由操作系統交付時,「舊」活動被呼叫onNewIntent

但是,當電話變爲活動狀態時,沒有任何反應,並且看起來該意圖沒有傳送到MainActivity,直到我掛斷其中一個電話。奇怪的。

如果我將標誌更改爲包含FLAG_ACTIVITY_CLEAR_TOP,則重新啓動應用任務或主要活動。然而,因爲這是PhoneGAP,兩者都對應於重新啓動應用程序,這不是我想要的。我還可以讓Android啓動一個全新的應用程序在另一個任務,這是重點。

但是我不能讓Android返回焦點到我的主要活動。我究竟做錯了什麼?

謝謝!

回答

3

經過數小時的黑客攻擊後,我設法解決了這個問題。 看來,一旦一個新的android任務獲得控制權,當內置撥號程序用於撥打電話時會發生什麼情況,後臺任務是從任務開始的,該任務使呼叫也失去了啓動新活動的權限,除非它在新任務中開始活動。

這意味着,這是一個AsyncTask在進行調用之前從該活動啓動,然後休眠一下以確保撥號程序任務/活動已打開,它必須啓動一個新任務以獲得後續焦點。不能再次啓動Cordova活動,因爲這樣可以有效地重新啓動整個應用程序,因此解決方案是執行精簡重新啓動任務,該任務立即完成。

在科爾多瓦插件,以下內部類可以被放置:

protected class RestartTask extends AsyncTask<Void, Void, Void>{ 
    protected RestartTask() { } 

    @Override 
    protected Void doInBackground(Void... unused){ 
     try { 
      // pass time so the built-in dialer app can make the call 
      Thread.sleep(MyPlugin.restartDelay); 
     } 
     catch (InterruptedException localInterruptedException) 
     { 
      Log.d("MyPlugin", "RestartTask received an InterruptedException"); 
     } 

     return null; 
    } 

    @Override 
    protected void onPostExecute(Void justEyeCandy){ 
     super.onPostExecute(justEyeCandy); 

     // Start the RestartActivity in a new task. This will snap the phone out of the built-in dialer app, which 
     // has started in it's own task at this point in time. The RestartActivity gains control and finishes 
     // immediately, leading control back to the activity at the top of the stack in the 
     // app (where the user came from when making the call). 
     Intent restartIntent = new Intent(MyPlugin.this.ctx.getApplicationContext(), RestartActivity.class); 
     restartIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     MyPlugin.this.ctx.getApplicationContext().startActivity(restartIntent); 
    } 
} 

AsyncTask可以在插件中發射了通過調用:

this.ctx.runOnUiThread(new Runnable(){ 
    public void run(){ 
     try { 
      RestartTask restartTask = new RestartTask(); 
      restartTask.execute(); 
     } 
     catch (Exception e) { 
      Log.d("MyPlugin", "Exploded when trying to start background task: " + e.getMessage()); 
     } 
    } 
}); 

的類的AsyncTask開始在新的任務是:

public class RestartActivity extends Activity { 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // the prototype RestartActivity there is a possibility that this will be the root activity of the app. 
     // If that is the case, this activity will boot the main activity of the app in a new task, before signing off. 
     // However, this is not the case for this app, as restarts are only used once a call diversion has taken place, 
     // form within the app. 
     if (isTaskRoot()) 
     { 
      // Start the app before finishing 
      String packageName = this.getBaseContext().getPackageName(); 
      Intent startAppIntent = this.getBaseContext().getPackageManager().getLaunchIntentForPackage(packageName); 
      startAppIntent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); 
      startActivity(startAppIntent); 
     } 

     // Now finish, which will drop the user in to the activity that was at the top of the task stack 
     finish(); 
    } 
}