Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way of handling the action NEW_OUTGOING_CALL while looping?

Tags:

android

At the moment I am developing an application which catches the action NEW_OUTGOING_CALL with the help of a BroadcastReceiver. I am aborting the call by calling setResultData(null). After that I am showing the user a dialog which allows him to decide if he wants to use my application to rewrite its number. When the users decision has happened I am placing the new call depending on the decision. Now my broadcast receiver gets called up once again.

What is the correct way of getting to know that I have already processed the number? I got a working solution that uses a timestamp to guess if it could be already processed. Another solution would be to add a "+" at the end of the processed number. These methods are working fine for my application being the only one catching the NEW_OUTGOING_CALL event. But what should I do when other applications (like Sipdroid or Google Voice) are also sitting there catching the NEW_OUTGOING_CALL broadcast aborting it and restarting it again? I don't see a possibility to get to know if we are still in the same "call flow" and if I already processed the number.

I would love to hear your ideas about this problem!

like image 249
denis Avatar asked Jul 14 '10 05:07

denis


2 Answers

What API level are you working with? If it's >= 11, check out the new BroadcastReceiver.goAsync function that lets you extend the processing of the broadcast outside of the onReceive function of your receiver. This could bypass the need to loop altogether.

If, like me, you're stuck trying to do this before level 11, it is surprisingly tricky to do this elegantly. You may have done this as well, but I tried to include a "processed" flag as an extra in the ACTION_CALL intent that my code generated, hoping that it would somehow get included in the resulting ACTION_NEW_OUTGOING_CALL broadcast, but that sadly does not work.

The best solution I have been able to find is including a fragment in the URI for the ACTION_CALL intent that you generate. This fragment will be included for the resulting ACTION_NEW_OUTGOING_CALL broadcast, so your broadcast receiver can differentiate between the original call and the one that you generate, but it won't interfere with handlers that aren't looking for it.

Here's the basic code.

In your BroadcastReceiver for the 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
        }
    }
}

When the user first dials the number, the fragment will either be missing altogether or your flag won't be present, so you'll abort the broadcast and start your activity. In your activity, if you decide to place the call again, do something like the following:

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

The "your_flag" fragment will then be present in the subsequent NEW_OUTGOING_CALL broadcast and thus allow you to handle this case differently in your broadcast receiver.

The nice thing about this is the the fragment is completely ignored unless you look for it in the ORIGINAL_URI, so other broadcast receivers can continue to function. If you want to be really nice, you may want to look for an existing fragment and add your flag to it (perhaps with a comma separator).

I hope that helps. Good luck!

like image 146
Scot Avatar answered Sep 22 '22 15:09

Scot


I don't see a possibility to get to know if we are still in the same "call flow" and if I already processed the number.

Technically, you are not in the same "call flow" as placing a new call is asynchronous. You have to use hints (such as a timestamp) as you seem to be doing already.

If you are confident that other applications will not rewrite the number except to change the prefix or to add a suffix, you may want to add another "proximity check" hint to avoid false positives/negatives, but I'm afraid that's about all you can do.

like image 36
Samuel Tardieu Avatar answered Sep 19 '22 15:09

Samuel Tardieu