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:
package 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);
}
};
}
Full source can be downloaded from: this link