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_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" /> <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.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/> <uses-permission android:name="android.permission.RECORD_VIDEO"/>

View File

@ -22,9 +22,11 @@ import android.content.Context;
import android.media.AudioManager; import android.media.AudioManager;
import com.phonegap.api.Plugin; import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult; import com.phonegap.api.PluginResult;
import java.util.ArrayList;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import com.phonegap.api.LOG;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -41,13 +43,16 @@ import java.util.Map.Entry;
*/ */
public class AudioHandler extends Plugin { public class AudioHandler extends Plugin {
public static String TAG = "AudioHandler";
HashMap<String,AudioPlayer> players; // Audio player object HashMap<String,AudioPlayer> players; // Audio player object
ArrayList<AudioPlayer> pausedForPhone; // Audio players that were paused when phone call came in
/** /**
* Constructor. * Constructor.
*/ */
public AudioHandler() { public AudioHandler() {
this.players = new HashMap<String,AudioPlayer>(); this.players = new HashMap<String,AudioPlayer>();
this.pausedForPhone = new ArrayList<AudioPlayer>();
} }
/** /**
@ -134,6 +139,44 @@ public class AudioHandler extends Plugin {
} }
this.players.clear(); 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 // LOCAL METHODS

View File

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

View File

@ -22,17 +22,27 @@ import java.util.TimeZone;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import com.phonegap.api.LOG;
import com.phonegap.api.PhonegapActivity; import com.phonegap.api.PhonegapActivity;
import com.phonegap.api.Plugin; import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult; 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.provider.Settings;
import android.telephony.TelephonyManager;
public class Device extends Plugin { public class Device extends Plugin {
public static final String TAG = "Device";
public static String phonegapVersion = "1.2.0"; // PhoneGap version public static String phonegapVersion = "1.2.0"; // PhoneGap version
public static String platform = "Android"; // Device OS public static String platform = "Android"; // Device OS
public static String uuid; // Device UUID public static String uuid; // Device UUID
BroadcastReceiver telephonyReceiver = null;
/** /**
* Constructor. * Constructor.
*/ */
@ -48,6 +58,7 @@ public class Device extends Plugin {
public void setContext(PhonegapActivity ctx) { public void setContext(PhonegapActivity ctx) {
super.setContext(ctx); super.setContext(ctx);
Device.uuid = getUuid(); Device.uuid = getUuid();
this.initTelephonyReceiver();
} }
/** /**
@ -93,11 +104,57 @@ public class Device extends Plugin {
} }
return false; return false;
} }
/**
* Unregister receiver.
*/
public void onDestroy() {
this.ctx.unregisterReceiver(this.telephonyReceiver);
}
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// LOCAL METHODS // 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. * 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. * 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); PluginResult result = new PluginResult(PluginResult.Status.OK, type);
result.setKeepCallback(true); result.setKeepCallback(true);
this.success(result, this.connectionCallbackId); 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(); 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, * 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. * 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. * @param url The URL to load.
*/ */
abstract public void loadUrl(String url); 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() { 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, * 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. * the resultCode it returned, and any additional data from it.

View File

@ -318,7 +318,23 @@ public final class PluginManager {
plugin.onDestroy(); 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. * Called when the activity receives a new intent.
*/ */