Question

I'm trying to develop an application which silently dismiss the USSD responses. I've used the code from http://commandus.com/blog/?p=58 with minor changes. I've created the IExtendedNetworkService.aidl in the package com.android.internal.telephony and USSDDumbExtendedNetworkService inside the package com.commandus.ussd. The problem is, nothing happens after running the application (even after restarting the phone). Can someone point out what am I doing wrong? Should I write any additional code for making it work?

IExtendedNetworkService.aidl

package com.android.internal.telephony;

/**
*  Interface used to interact with extended MMI/USSD network service.
*/
interface IExtendedNetworkService {
 /**
 * Set a MMI/USSD command to ExtendedNetworkService for further process.
 * This should be called when a MMI command is placed from panel.
 * @param number the dialed MMI/USSD number.
 */
void setMmiString(String number);

/**
 * return the specific string which is used to prompt MMI/USSD is running
 */
CharSequence getMmiRunningText();

/**
 * Get specific message which should be displayed on pop-up dialog.
 * @param text original MMI/USSD message response from framework
 * @return specific user message correspond to text. null stands for no pop-up dialog need to show.
 */
CharSequence getUserMessage(CharSequence text);

/**
 * Clear timeout message and pre-set MMI/USSD command
 * This should be called when user cancel a pre-dialed MMI command.
 */
void clearMmiString();
}

USSDDumbExtendedNetworkService

    package com.commandus.ussd;
    import android.app.Service;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.net.Uri;
    import android.os.IBinder;
    import android.os.PatternMatcher;
    import android.os.RemoteException;
    import android.util.Log;

    import com.android.internal.telephony.IExtendedNetworkService;

    /**
    * Service implements IExtendedNetworkService interface.
    * USSDDumbExtendedNetworkService Service must have name
    * "com.android.ussd.IExtendedNetworkService" of the intent declared in the
    * Android manifest file so com.android.phone.PhoneUtils class bind to this
    * service after system rebooted. Please note service is loaded after system
    * reboot! Your application must check is system rebooted.
    * 
    * @see Util#syslogHasLine(String, String, String, boolean)
    */
    public class USSDDumbExtendedNetworkService extends Service {
    public static final String TAG = "MobileServices";
    public static final String LOG_STAMP = "*USSDTestExtendedNetworkService bind successfully*";
    public static final String URI_SCHEME = "ussd";
    public static final String URI_AUTHORITY = "g_el.net";
    public static final String URI_PATH = "/";
    public static final String URI_PAR = "return";
    public static final String URI_PARON = "on";
    public static final String URI_PAROFF = "off";
    public static final String MAGIC_ON = ":ON;)";
    public static final String MAGIC_OFF = ":OFF;(";
    public static final String MAGIC_RETVAL = ":RETVAL;(";

    private static boolean mActive = false;
    private static CharSequence mRetVal = null;
    private Context mContext = null;
    private String msgUssdRunning = "G Testing...";

final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (Intent.ACTION_INSERT.equals(intent.getAction())) {
            mContext = context;
            if (mContext != null) {
                msgUssdRunning = "ussd blocker Running";
                mActive = true;
                Log.d(TAG, "activate");
            }
        } else if (Intent.ACTION_DELETE.equals(intent.getAction())) {
            mContext = null;
            mActive = false;
            Log.d(TAG, "deactivate");
        }
    }
};

private final IExtendedNetworkService.Stub mBinder = new IExtendedNetworkService.Stub() {

    @Override
    public void setMmiString(String number) throws RemoteException {
        Log.d(TAG, "setMmiString: " + number);
    }

    @Override
    public CharSequence getMmiRunningText() throws RemoteException {
        Log.d(TAG, "getMmiRunningText: " + msgUssdRunning);
        return msgUssdRunning;
    }

    @Override
    public CharSequence getUserMessage(CharSequence text)
            throws RemoteException {
        if (MAGIC_ON.contentEquals(text)) {
            mActive = true;
            Log.d(TAG, "control: ON");
            return text;
        } else {
            if (MAGIC_OFF.contentEquals(text)) {
                mActive = false;
                Log.d(TAG, "control: OFF");
                return text;
            } else {
                if (MAGIC_RETVAL.contentEquals(text)) {
                    mActive = false;
                    Log.d(TAG, "control: return");
                    return mRetVal;
                }
            }
        }

        if (!mActive) {
            Log.d(TAG, "getUserMessage deactivated: " + text);
            //return null;//Use this in order to cancel the output on the screen.
            return text;
        }
        String s = text.toString();
        // store s to the !
        Uri uri = new Uri.Builder().scheme(URI_SCHEME).authority(URI_AUTHORITY).path(URI_PATH).appendQueryParameter(URI_PAR,text.toString()).build();
        sendBroadcast(new Intent(Intent.ACTION_GET_CONTENT, uri));
        mActive = false;
        mRetVal = text;
        Log.d(TAG, "getUserMessage: " + text + "=" + s);
        return null;
    }

    @Override
    public void clearMmiString() throws RemoteException {
        Log.d(TAG, "clearMmiString");
    }
};

/**
 * Put stamp to the system log when PhoneUtils bind to the service after
 * Android has rebooted. Application must call
 * {@link Util#syslogHasLine(String, String, String, boolean)} to check is
 * phone rebooted or no. Without reboot phone application does not bind tom
 * this service!
 */
@Override
public IBinder onBind(Intent intent) {
    IntentFilter filter = new IntentFilter();
    filter.addAction(Intent.ACTION_INSERT);
    filter.addAction(Intent.ACTION_DELETE);
    filter.addDataScheme(URI_SCHEME);
    filter.addDataAuthority(URI_AUTHORITY, null);
    filter.addDataPath(URI_PATH, PatternMatcher.PATTERN_LITERAL);
    registerReceiver(mReceiver, filter);
    // Do not localize!
    Log.i(TAG, LOG_STAMP);

    return mBinder;
}

public IBinder asBinder() {
    Log.d(TAG, "asBinder");
    return mBinder;
}

@Override
public boolean onUnbind(Intent intent) {
    unregisterReceiver(mReceiver);
    return super.onUnbind(intent);
}

   }

Manifest file

<service android:name="com.commandus.ussd.USSDDumbExtendedNetworkService">
        <intent-filter >
            <action android:name="com.android.ussd.IExtendedNetworkService" />
                <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
 </service>
Was it helpful?

Solution

Have you declared your broadcast receiver in your manifest file?

add inside your manifest:

<receiver android:name="com.xxx.receivers.BootReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

<service android:name="your.package.ExtendedNetworkService" />

in BootReceiver.java :

    public void onReceive(Context context, Intent intent) {

        context.startService(new Intent(context,ExtendedNetworkService.class));
}

in ExtendedNetworkService.java :

public class ExtendedNetworkService extends Service {

    IExtendedNetworkService.Stub binder = new IExtendedNetworkService.Stub() {

        public void setMmiString(String number) throws RemoteException {}
        public CharSequence getMmiRunningText() throws RemoteException {

            return null;
        }
        public CharSequence getUserMessage(CharSequence text)
                throws RemoteException {

            Log.d(Constants.TAG, "Message : " + text);
            Log.d(Constants.TAG, "getMmiRunningTest() : " + getMmiRunningText());
                return null;
        }
        public void clearMmiString() throws RemoteException {
        }

    };

        return false;
    }

    public void onCreate() {

        Log.d(Constants.TAG, "ExtendedNetworkService Started..");

        super.onCreate();
    }

public IBinder onBind(Intent arg0) {

        Log.d(Constants.TAG, "ExtendedNetworkService got binded...");

        return binder;

    }

}

OTHER TIPS

Complete working code sample https://github.com/alaasalman/ussdinterceptor

Enjoy!

Please note that, this interface IExtendedNetworkService was removed starting from Android 4.2.2 No alternative provided by Google yet, and no plans to provide such alternative For reference you can see http://code.google.com/p/android/issues/detail?id=57120.

If your using android 3.1 (API 12), when an app installs it's in a stopped state by default until the user starts your app explicitly as stated in the commonsblog:

http://commonsware.com/blog/2011/07/13/boot-completed-regression-confirmed.html

and in the android documentation:

http://developer.android.com/about/versions/android-3.1.html#launchcontrols

I believe the bottom line is that an app containing only an IntentService or BroadcastReceiver cannot be started by it's own.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top