title: Using IExtendedNetworkService to get USSD response in Android
body: <p>I'm trying to find the way to make USSD requests in Android. I found this - <a href="http://commandus.com/blog/?p=58" rel="noreferrer">http://commandus.com/blog/?p=58</a> .
  I added all needed files to my project.</p>
  
  <p>USSDDumbExtendedNetworkService.java:</p>
  
  <pre><code>package com.android.ussdcodes;
  
  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;
  import com.android.ussdcodes.R;
  
  /**
   * 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 = "CommandusUSSDExtNetSvc";
      public static final String LOG_STAMP = "*USSDTestExtendedNetworkService bind successfully*";
      public static final String URI_SCHEME = "ussdcodes";
      public static final String URI_AUTHORITY = "android.com";
      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 = "USSD running..."; 
  
      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 = mContext.getString(R.string.USSD_run);
                      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 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) {
          // Do not localize!
          Log.i(TAG, LOG_STAMP);
          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);
  
          return mBinder; 
      }
  
      public IBinder asBinder() {
          Log.d(TAG, "asBinder");
          return mBinder;
      }
  
  }
  </code></pre>
  
  <p>Manifest:</p>
  
  <pre><code>&lt;receiver android:name="com.android.ussdcodes.BootReceiver"&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.BOOT_COMPLETED" /&gt;
              &lt;/intent-filter&gt;
          &lt;/receiver&gt;
  
          &lt;service
              android:name=".USSDDumbExtendedNetworkService" &gt;
              &lt;intent-filter android:icon="@drawable/ic_launcher"&gt;
                  &lt;action android:name="com.android.ussd.IExtendedNetworkService" /&gt;
                  &lt;category android:name="android.intent.category.DEFAULT" /&gt;
              &lt;/intent-filter&gt;
          &lt;/service&gt;
  </code></pre>
  
  <p>BootReceiver.java:</p>
  
  <pre><code>package com.android.ussdcodes;
  
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;
  import android.util.Log;
  
  public class BootReceiver extends BroadcastReceiver {
  
      @Override
      public void onReceive(Context context, Intent intent) {
          // TODO Auto-generated method stub
          Log.d("USSDService", context.getString(R.string.service_started));
          context.startService(new Intent(context,USSDDumbExtendedNetworkService.class));
      }
  
  }
  </code></pre>
  
  <p>So now the service starts after boot complete.</p>
  
  <p>And my question is how I have to send USSD request and get responce with service?
  Thanks!)</p>