Add onMessage(id, data) to plugin API.

A solution was needed to notify the audio player to pause when a phone call comes in. The option was to add a specific onPhone() method or generalize it. Since there are other "events" that are useful to plugins, a generalized solution was used. It is also extensible without changing the plugin API again.

Any plugin can call DroidGap.onMessage() to send a message/event to all other plugins. NetworkManager was updated to send changes in connection status to plugins, so they can intelligently handle lost connections.
This commit is contained in:
Bryce Curtis 2011-11-09 10:34:49 -06:00
parent fd93404c7c
commit 0bbcf5cfd2
10 changed files with 174 additions and 8 deletions

1
framework/AndroidManifest.xml Normal file → Executable file
View File

@ -15,6 +15,7 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>

View File

@ -22,9 +22,11 @@ import android.content.Context;
import android.media.AudioManager;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONException;
import com.phonegap.api.LOG;
import java.util.HashMap;
import java.util.Map.Entry;
@ -41,13 +43,16 @@ import java.util.Map.Entry;
*/
public class AudioHandler extends Plugin {
public static String TAG = "AudioHandler";
HashMap<String,AudioPlayer> players; // Audio player object
ArrayList<AudioPlayer> pausedForPhone; // Audio players that were paused when phone call came in
/**
* Constructor.
*/
public AudioHandler() {
this.players = new HashMap<String,AudioPlayer>();
this.pausedForPhone = new ArrayList<AudioPlayer>();
}
/**
@ -134,6 +139,44 @@ public class AudioHandler extends Plugin {
}
this.players.clear();
}
/**
* Called when a message is sent to plugin.
*
* @param id The message id
* @param data The message data
*/
public void onMessage(String id, Object data) {
// If phone message
if (id.equals("telephone")) {
// If phone ringing, then pause playing
if ("ringing".equals(data) || "offhook".equals(data)) {
// Get all audio players and pause then
java.util.Set<Entry<String,AudioPlayer>> s = this.players.entrySet();
java.util.Iterator<Entry<String,AudioPlayer>> it = s.iterator();
while (it.hasNext()) {
Entry<String,AudioPlayer> entry = it.next();
AudioPlayer audio = entry.getValue();
if (audio.getState() == AudioPlayer.MEDIA_RUNNING) {
this.pausedForPhone.add(audio);
audio.pausePlaying();
}
}
}
// If phone idle, then resume playing those players we paused
else if ("idle".equals(data)) {
for (int i=0; i<this.pausedForPhone.size(); i++) {
AudioPlayer audio = this.pausedForPhone.get(i);
audio.startPlaying(null);
}
this.pausedForPhone = new ArrayList<AudioPlayer>();
}
}
}
//--------------------------------------------------------------------------
// LOCAL METHODS

View File

@ -44,11 +44,11 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
private static final String LOG_TAG = "AudioPlayer";
// AudioPlayer states
private static int MEDIA_NONE = 0;
private static int MEDIA_STARTING = 1;
private static int MEDIA_RUNNING = 2;
private static int MEDIA_PAUSED = 3;
private static int MEDIA_STOPPED = 4;
public static int MEDIA_NONE = 0;
public static int MEDIA_STARTING = 1;
public static int MEDIA_RUNNING = 2;
public static int MEDIA_PAUSED = 3;
public static int MEDIA_STOPPED = 4;
// AudioPlayer message ids
private static int MEDIA_STATE = 1;
@ -429,6 +429,15 @@ public class AudioPlayer implements OnCompletionListener, OnPreparedListener, On
this.state = state;
}
/**
* Get the audio state.
*
* @return int
*/
public int getState() {
return this.state;
}
/**
* Set the volume for audio player

View File

@ -22,17 +22,27 @@ import java.util.TimeZone;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.phonegap.api.LOG;
import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.provider.Settings;
import android.telephony.TelephonyManager;
public class Device extends Plugin {
public static final String TAG = "Device";
public static String phonegapVersion = "1.2.0"; // PhoneGap version
public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID
BroadcastReceiver telephonyReceiver = null;
/**
* Constructor.
*/
@ -48,6 +58,7 @@ public class Device extends Plugin {
public void setContext(PhonegapActivity ctx) {
super.setContext(ctx);
Device.uuid = getUuid();
this.initTelephonyReceiver();
}
/**
@ -93,11 +104,57 @@ public class Device extends Plugin {
}
return false;
}
/**
* Unregister receiver.
*/
public void onDestroy() {
this.ctx.unregisterReceiver(this.telephonyReceiver);
}
//--------------------------------------------------------------------------
// LOCAL METHODS
//--------------------------------------------------------------------------
/**
* Listen for telephony events: RINGING, OFFHOOK and IDLE
* Send these events to all plugins using
* DroidGap.onMessage("telephone", "ringing" | "offhook" | "idle")
*/
private void initTelephonyReceiver() {
IntentFilter intentFilter = new IntentFilter() ;
intentFilter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
final PhonegapActivity myctx = this.ctx;
this.telephonyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// If state has changed
if ((intent != null) && intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
if (intent.hasExtra(TelephonyManager.EXTRA_STATE)) {
String extraData = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (extraData.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
LOG.i(TAG, "Telephone RINGING");
myctx.onMessage("telephone", "ringing");
}
else if (extraData.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
LOG.i(TAG, "Telephone OFFHOOK");
myctx.onMessage("telephone", "offhook");
}
else if (extraData.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
LOG.i(TAG, "Telephone IDLE");
myctx.onMessage("telephone", "idle");
}
}
}
}
};
// Register the receiver
this.ctx.registerReceiver(this.telephonyReceiver, intentFilter);
}
/**
* Get the OS name.
*

View File

@ -814,6 +814,18 @@ public class DroidGap extends PhonegapActivity {
}
}
/**
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
public void onMessage(String id, Object data) {
// Forward to plugins
this.pluginManager.onMessage(id, data);
}
/**
* Add a class that implements a service.
*

View File

@ -199,6 +199,9 @@ public class NetworkManager extends Plugin {
PluginResult result = new PluginResult(PluginResult.Status.OK, type);
result.setKeepCallback(true);
this.success(result, this.connectionCallbackId);
// Send to all plugins
this.ctx.onMessage("networkconnection", type);
}
/**

View File

@ -87,6 +87,14 @@ public interface IPlugin {
*/
void onDestroy();
/**
* Called when a message is sent to plugin.
*
* @param id The message id
* @param data The message data
*/
public void onMessage(String id, Object data);
/**
* Called when an activity you launched exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.

View File

@ -65,4 +65,12 @@ public abstract class PhonegapActivity extends Activity {
* @param url The URL to load.
*/
abstract public void loadUrl(String url);
/**
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
abstract public void onMessage(String id, Object data);
}

View File

@ -103,6 +103,15 @@ public abstract class Plugin implements IPlugin {
public void onDestroy() {
}
/**
* Called when a message is sent to plugin.
*
* @param id The message id
* @param data The message data
*/
public void onMessage(String id, Object data) {
}
/**
* Called when an activity you launched exits, giving you the requestCode you started it with,
* the resultCode it returned, and any additional data from it.

View File

@ -318,7 +318,23 @@ public final class PluginManager {
plugin.onDestroy();
}
}
/**
* Send a message to all plugins.
*
* @param id The message id
* @param data The message data
*/
public void onMessage(String id, Object data) {
java.util.Set<Entry<String,IPlugin>> s = this.plugins.entrySet();
java.util.Iterator<Entry<String,IPlugin>> it = s.iterator();
while(it.hasNext()) {
Entry<String,IPlugin> entry = it.next();
IPlugin plugin = entry.getValue();
plugin.onMessage(id, data);
}
}
/**
* Called when the activity receives a new intent.
*/