2010-07-14 105 views
8

目前我正在開發一個應用程序,該應用程序在BroadcastReceiver的幫助下捕獲了行動NEW_OUTGOING_CALL。我通過撥打setResultData(null)中止呼叫。之後,我向用戶顯示一個對話框,讓他決定是否要用我的應用程序重寫它的編號。當用戶決定發生時,我將根據決定發出新的呼叫。現在我的廣播接收器再次被調用。循環時處理動作NEW_OUTGOING_CALL的正確方法是什麼?

瞭解我已經處理了該號碼的正確方法是什麼?我得到了一個工作解決方案,它使用時間戳來猜測它是否可以被處理。另一種解決方案是在處理後的號碼末尾添加一個"+"。 這些方法工作正常,我的應用程序是唯一一個捕獲NEW_OUTGOING_CALL事件。但是,當其他應用程序(如Sipdroid或Google Voice)也在那裏捕捉NEW_OUTGOING_CALL廣播時,我應該做些什麼,然後再次重新啓動它?我看不出有可能知道我們是否仍然處於相同的「呼叫流程」,並且我是否已經處理了該號碼。

我很想聽聽你對這個問題的想法!

+0

重複:http://stackoverflow.com/q/808645/165674 – 2012-04-22 18:01:03

回答

2

你在使用什麼API級別?如果> = 11,請查看新的BroadcastReceiver.goAsync函數,該函數允許您擴展接收器的onReceive函數之外的廣播處理。這可以繞過完全循環的需要。

如果像我一樣,在第11級之前試圖做到這一點,那麼優雅地完成這件事就會非常棘手。你也可以這樣做,但我嘗試在我的代碼生成的ACTION_CALL目標中包含一個額外的「已處理」標誌,希望它能以某種方式包含在所產生的ACTION_NEW_OUTGOING_CALL廣播中,但可惜這是行不通的。

我已經能夠找到的最佳解決方案是在您生成的ACTION_CALL意圖的URI中包含一個片段。該片段將包含在所產生的ACTION_NEW_OUTGOING_CALL廣播中,因此您的廣播接收器可以區分原始調用和您生成的調用,但不會干擾不查找它的處理程序。

這是基本的代碼。

在你的BroadcastReceiver的ACTION_NEW_OUTGOING_CALL

public class YourBroadcastReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     // extract the fragment from the URI 
     String uriFragment = Uri.parse(
      intent.getStringExtra("android.phone.extra.ORIGINAL_URI")).getFragment(); 

     // if the fragment is missing or does not have your flag, it is new 
     if (uriFragment == null || !uriFragment.contains("your_flag")) { 

      // launch your activity, pass the phone number, etc. 
      // use getResultData to get the number in order to respect 
      // earlier broadcast receivers 
      ... 

      // abort the broadcast 
      this.setResultData(null); 
      this.abortBroadcast(); 
     } 
     // otherwise, your code is there, this call was triggered by you 
     else { 
      // unless you have a special need, you'll probably just let the broadcast 
      // go through here 

      // note that resultData ignores the fragment, so other receivers should 
      // be blissfully unaware of it 
     } 
    } 
} 

當用戶第一次撥打該號碼,片段要麼是完全缺失或您的標誌將不存在,所以你會中止廣播和啓動你的活動。在您的活動,如果你決定再次撥打電話,這樣做如下:

startActivity(new Intent(Intent.ACTION_CALL, 
         Uri.parse("tel:" + modified_number + "#your_flag"))); 

的「your_flag」片段屆時將出現在隨後的NEW_OUTGOING_CALL廣播,從而讓您在不同的方式處理這種情況下,您的廣播接收器。

關於這一點的好處是該片段被完全忽略,除非您在ORIGINAL_URI中查找它,以便其他廣播接收器可以繼續運行。如果你想變得非常好,你可能想要尋找一個現有的片段並添加你的標誌(也許用一個逗號分隔符)。

我希望有幫助。祝你好運!

+1

散列#有意義嗎?當您解析新調用意圖的URI「#your_flag」 – scottyab 2011-07-05 13:29:10

1

我沒有看到一個可能性去 知道,如果我們仍然處於相同的「致電 流」,如果我已經處理了 數。

從技術上講,您不在同一個「呼叫流程」中,因爲放置新呼叫是異步的。您必須使用提示(例如時間戳),因爲您似乎已經在執行這些提示。

如果您確信除了更改前綴或添加後綴外其他應用程序不會重寫數字,您可能需要添加另一個「接近檢查」提示以避免誤報/否定,但我擔心這就是你所能做的一切。

+0

謝謝您的意見。 – 2010-09-20 09:27:55

0

Broadcast receiver中的onReceive()方法接收一個Intent作爲參數。 使用Intent.getExtras()從Intent中提取Bundle。 此包包括如下3鍵 - 值對:

  1. android.phone.extra.ALREADY_CALLED = NULL
  2. android.intent.extra.PHONE_NUMBER = 98xxxxxx98
  3. android.phone.extra。 ORIGINAL_URI =電話:98xxxxxx98

98xxxxxx98是由用戶所撥的號碼。

當的onReceive()被再次調用,這個數量變爲98xxxxxx98 *0 * 通過檢查在所撥打的號碼的端部的星號(*),它可以當的onReceive推斷()方法在第一次或下一次後續時間被調用。

0

其中一個答案是跟蹤意圖中的布爾額外值。 Google Phone應用以類似的方式完成。您可以查看本廣播接收器here(查找已調用的使用)

另一種方式是將您的廣播中的「重寫」語音或自定義VoIP應用程序),而無需調用ACTION_CALL意圖(這就是爲什麼您會獲得循環並再次調用接收器)以下代碼是我如何在自定義VoIP應用程序中處理呼叫的示例。當我在廣播接收器中截取NEW_OUTGOING_CALL時,我首先檢查是否有互聯網連接。如果手機已連接到互聯網,則使用我的活動的自定義定義意圖操作通過我的VoIP應用程序撥打電話。如果沒有互聯網連接,我只需將原始電話號碼設置爲廣播接收機結果數據即可。這被下一個廣播接收機(可能是默認的電話應用程序,但不一定是)在流程中用於發出呼叫。

public class BHTTalkerCallReceiver extends BroadcastReceiver { 

    private static final String TAG = "BHTTalkerCallReceiver"; 

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

     Log.d(TAG, "Broadcast successfull ... "); 

     // Extract phone number reformatted by previous receivers 
     String phoneNumber = getResultData(); 
     if (phoneNumber == null) { 
      // No reformatted number, use the original 
      phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); 
     } 

     if (isNetworkAvailable(context)) { // Make sure this app handles call only if there is internet connection 
      // My app will bring up the call, so cancel the broadcast 
      setResultData(null); 
      // Start my app to bring up the call 
      Intent voipCallIntent = new Intent(context, TalkerActivity.class); 
      voipCallIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
      voipCallIntent.putExtra(TalkerActivity.OUT_CALL_NUMBER, phoneNumber); 
      voipCallIntent.setAction(TalkerActivity.BHT_TALKER_OUT_CALL); 
      context.startActivity(voipCallIntent); 
     } else { //otherwise make a regular call... 
      // Forward phone data to standard phone call 
      setResultData(phoneNumber); 
     } 
    } 

    private boolean isNetworkAvailable(final Context context) { 
     final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)); 
     return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected(); 
    } 
} 
相關問題