We have a need to programatically determine the user's Google Voice phone number from our own app. Here's how it can be done...
First, include the Google Voice FETCH_CONFIGURATION permission in your app's AndroidManifest.xml file:
<uses-permission android:name="com.google.android.apps.googlevoice.permission.FETCH_CONFIGURATION"/>
Next, include the following three files in your src directory:
src/com/google/android/apps/googlevoice/IGoogleVoiceConfiguration.aidl
package com.google.android.apps.googlevoice; interface IGoogleVoiceConfiguration { Bundle getConfiguration(); }
src/com/google/android/apps/googlevoice/GoogleVoiceConfigurationAPI.java
package com.google.android.apps.googlevoice; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; /** * API for fetching the Google Voice configuration. It currently only * provides one value, "subscriberNumber". */ public class GoogleVoiceConfigurationAPI implements ServiceConnection { private String logTag = "GoogleVoiceConfigAPI"; public GoogleVoiceConfigurationAPI() {} public GoogleVoiceConfigurationAPI( String logTag) { this.logTag = logTag; } /** * Key to use for extracting the subscriber number from the configuration bundle. */ public static final String KEY_SUBSCRIBER_NUMBER = "subscriberNumber"; private static final String GOOGLE_VOICE_CONFIGURATION_SERVICE_ACTION = "com.google.android.apps.googlevoice.IGoogleVoiceConfiguration"; private Bundle configuration = null; Context context = null; GoogleVoiceConfigurationListener listener = null; /** * Fetch the configuration and invoke the listener callback with the configuration bundle, * if available. * @param context context required to make service calls to Google Voice * @param listener listener to receive the configuration bundle - the listener's * onFetchGoogleVoiceConfiguration() will be called with the configuration info if this * method returns true. * @return true if the GoogleVoiceConfiguration service can be bound, otherwise false. * If true, you can expect the listener to be called, otherwise it won't be invoked. */ public boolean fetchConfiguration(Context context, GoogleVoiceConfigurationListener listener) { if (context == null || listener == null) throw new IllegalArgumentException("null parameter values not allowed"); if (configuration != null) { try { listener.onFetchGoogleVoiceConfiguration(configuration); } catch (Exception x) { Log.e(logTag, x.getMessage(), x); } return true; } this.context = context; this.listener = listener; Intent i = new Intent(GOOGLE_VOICE_CONFIGURATION_SERVICE_ACTION); return context.bindService(i, this, Context.BIND_AUTO_CREATE); } public void onServiceConnected(ComponentName componentName, IBinder iBinder) { try { IGoogleVoiceConfiguration iGoogleVoiceConfiguration = IGoogleVoiceConfiguration.Stub.asInterface(iBinder); configuration = iGoogleVoiceConfiguration.getConfiguration(); if (listener != null) listener.onFetchGoogleVoiceConfiguration(configuration); } catch (Exception x) { Log.e(logTag, x.getMessage(), x); } finally { context.unbindService(this); } } public void onServiceDisconnected(ComponentName componentName) { } }
src/com/google/android/apps/googlevoic/GoogleVoiceConfigurationListener.java
package com.google.android.apps.googlevoice; import android.os.Bundle; /** * Listener interface for receiving the google voice configuration bundle. */ public interface GoogleVoiceConfigurationListener { public void onFetchGoogleVoiceConfiguration(Bundle configuration); }
Finally, you can call the API from your own app:
Full source can be downloaded from: this linkpackage com.example.googlevoice.config; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.google.android.apps.googlevoice.GoogleVoiceConfigurationAPI; import com.google.android.apps.googlevoice.GoogleVoiceConfigurationListener; public class GoogleVoiceConfigActivity extends Activity { static final String TAG = "GoogleVoiceConfig"; GoogleVoiceConfigurationAPI googleVoiceConfigurationAPI = new GoogleVoiceConfigurationAPI(TAG); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button fetchItButton = (Button)findViewById(R.id.fetchConfigButton); fetchItButton.setOnClickListener( new View.OnClickListener() { public void onClick(View view) { TextView numberTextView = (TextView)findViewById(R.id.numberTextView); try { if (!googleVoiceConfigurationAPI.fetchConfiguration(GoogleVoiceConfigActivity.this, listener)) { numberTextView.setText( "Configuration unavailable: Google Voice is not installed or not configured"); } } catch (SecurityException x) { // This app is missing the following permission in its AndroidManifest.xml file: // <uses-permission android:name="com.google.android.apps.googlevoice.permission.FETCH_CONFIGURATION"> Log.e(TAG, x.getMessage(), x); numberTextView.setText( "Permission denied: this app's AndroidManifest.xml is missing permission"+ " com.google.android.apps.googlevoice.permission.FETCH_CONFIGURATION"); } catch (Exception x) { Log.e(TAG, x.getMessage(), x); numberTextView.setText(x.getMessage()); } } }); } GoogleVoiceConfigurationListener listener = new GoogleVoiceConfigurationListener() { public void onFetchGoogleVoiceConfiguration(Bundle configuration) { String subscriberNumber = configuration.getString( GoogleVoiceConfigurationAPI.KEY_SUBSCRIBER_NUMBER); TextView numberTextView = (TextView)findViewById(R.id.numberTextView); numberTextView.setText("Subscriber number: " + subscriberNumber); } }; }