diff --git a/talk/examples/android/README b/talk/examples/android/README index e68db6dcdc..5fefb945d8 100644 --- a/talk/examples/android/README +++ b/talk/examples/android/README @@ -14,12 +14,12 @@ Prerequisites: Example of building & using the app: -cd /trunk +cd /src ninja -C out/Debug AppRTCDemo adb install -r out/Debug/AppRTCDemo-debug.apk -In desktop chrome, navigate to https://3-dot-apprtc.appspot.com and note the r= room -this redirects to or navigate directly to https://3-dot-apprtc.appspot.com/room/ with +In desktop chrome, navigate to https://apprtc.appspot.com and note the r= room +this redirects to or navigate directly to https://apprtc.appspot.com/r/ with your own room number. Launch AppRTC on the device and add same into the room name list. You can also run application from a command line to connect to the first room in a list: diff --git a/talk/examples/android/res/values/strings.xml b/talk/examples/android/res/values/strings.xml index c290505217..08ff541909 100644 --- a/talk/examples/android/res/values/strings.xml +++ b/talk/examples/android/res/values/strings.xml @@ -57,11 +57,6 @@ Use VP8 VP8 hardware accelerated codec (if available). true - signaling_preference - Use WebSocket signaling. - Use WebSocket signaling. - true - Enabled Disabled diff --git a/talk/examples/android/res/xml/preferences.xml b/talk/examples/android/res/xml/preferences.xml index 57c0315d8b..cffcb6b8c6 100644 --- a/talk/examples/android/res/xml/preferences.xml +++ b/talk/examples/android/res/xml/preferences.xml @@ -43,10 +43,4 @@ android:dialogTitle="@string/pref_cpu_usage_detection_dlg" android:defaultValue="@string/pref_cpu_usage_detection_default" /> - - diff --git a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java index b4e11d6a6c..72adf89118 100644 --- a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java +++ b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java @@ -215,17 +215,11 @@ public class AppRTCDemoActivity extends Activity runTimeMs = intent.getIntExtra(ConnectActivity.EXTRA_RUNTIME, 0); startBitrate = intent.getIntExtra(ConnectActivity.EXTRA_BITRATE, 0); hwCodec = intent.getBooleanExtra(ConnectActivity.EXTRA_HWCODEC, true); - boolean useWebsocket = intent.getBooleanExtra( - ConnectActivity.EXTRA_WEBSOCKET, false); if (url != null) { if (loopback || (roomName != null && !roomName.equals(""))) { logAndToast(getString(R.string.connecting_to, url)); - if (useWebsocket) { - appRtcClient = new WebSocketRTCClient(this); - } else { - appRtcClient = new GAERTCClient(this, this); - } + appRtcClient = new WebSocketRTCClient(this); appRtcClient.connectToRoom(url.toString(), loopback); if (loopback) { roomNameView.setText("loopback"); diff --git a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java index b8e0e6a73d..7427bb4da1 100644 --- a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java +++ b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java @@ -72,7 +72,6 @@ public class ConnectActivity extends Activity { public static final String EXTRA_WEBSOCKET = "org.appspot.apprtc.WEBSOCKET"; private static final String TAG = "ConnectRTCClient"; private final String APPRTC_SERVER = "https://apprtc.appspot.com"; - private final String APPRTC_WS_SERVER = "https://3-dot-apprtc.appspot.com"; private final int CONNECTION_REQUEST = 1; private static boolean commandLineRun = false; @@ -89,7 +88,6 @@ public class ConnectActivity extends Activity { private String keyprefBitrateValue; private String keyprefHwCodec; private String keyprefCpuUsageDetection; - private String keyprefWebsocketSignaling; private String keyprefRoom; private String keyprefRoomList; private ArrayList roomList; @@ -108,7 +106,6 @@ public class ConnectActivity extends Activity { keyprefBitrateValue = getString(R.string.pref_startbitratevalue_key); keyprefHwCodec = getString(R.string.pref_hwcodec_key); keyprefCpuUsageDetection = getString(R.string.pref_cpu_usage_detection_key); - keyprefWebsocketSignaling = getString(R.string.pref_signaling_key); keyprefRoom = getString(R.string.pref_room_key); keyprefRoomList = getString(R.string.pref_room_list_key); @@ -244,10 +241,6 @@ public class ConnectActivity extends Activity { } private void connectToRoom(boolean loopback, int runTimeMs) { - // Check webSocket signaling flag. - boolean useWebsocket = sharedPref.getBoolean(keyprefWebsocketSignaling, - Boolean.valueOf(getString(R.string.pref_signaling_default))); - // Get room name (random for loopback). String roomName; if (loopback) { @@ -259,18 +252,8 @@ public class ConnectActivity extends Activity { } } - // Build room URL. String url; - if (useWebsocket) { - url = APPRTC_WS_SERVER; - url += "/register/" + roomName; - } else { - url = APPRTC_SERVER; - url = appendQueryParameter(url, "r=" + roomName); - if (loopback) { - url = appendQueryParameter(url, "debug=loopback"); - } - } + url = APPRTC_SERVER + "/register/" + roomName; // Check HW codec flag. boolean hwCodec = sharedPref.getBoolean(keyprefHwCodec, @@ -362,7 +345,6 @@ public class ConnectActivity extends Activity { intent.putExtra(EXTRA_RUNTIME, runTimeMs); intent.putExtra(EXTRA_BITRATE, startBitrate); intent.putExtra(EXTRA_HWCODEC, hwCodec); - intent.putExtra(EXTRA_WEBSOCKET, useWebsocket); startActivityForResult(intent, CONNECTION_REQUEST); } } diff --git a/talk/examples/android/src/org/appspot/apprtc/GAEChannelClient.java b/talk/examples/android/src/org/appspot/apprtc/GAEChannelClient.java deleted file mode 100644 index d44975b7b6..0000000000 --- a/talk/examples/android/src/org/appspot/apprtc/GAEChannelClient.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.appspot.apprtc; - -import android.annotation.SuppressLint; -import android.app.Activity; -import android.util.Log; -import android.webkit.ConsoleMessage; -import android.webkit.JavascriptInterface; -import android.webkit.WebChromeClient; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -/** - * Java-land version of Google AppEngine's JavaScript Channel API: - * https://developers.google.com/appengine/docs/python/channel/javascript - * - * Requires a hosted HTML page that opens the desired channel and dispatches JS - * on{Open,Message,Close,Error}() events to a global object named - * "androidMessageHandler". - */ -public class GAEChannelClient { - private static final String TAG = "GAERTCClient"; - private WebView webView; - private final ProxyingMessageHandler proxyingMessageHandler; - - /** - * Callback interface for messages delivered on the Google AppEngine channel. - */ - public interface GAEMessageHandler { - public void onOpen(); - public void onMessage(final String data); - public void onClose(); - public void onError(final int code, final String description); - } - - /** Asynchronously open an AppEngine channel. */ - @SuppressLint("SetJavaScriptEnabled") - public GAEChannelClient( - Activity activity, String token, GAEMessageHandler handler) { - webView = new WebView(activity); - webView.getSettings().setJavaScriptEnabled(true); - webView.setWebChromeClient(new WebChromeClient() { // Purely for debugging. - public boolean onConsoleMessage (ConsoleMessage msg) { - Log.d(TAG, "console: " + msg.message() + " at " + - msg.sourceId() + ":" + msg.lineNumber()); - return false; - } - }); - webView.setWebViewClient(new WebViewClient() { // Purely for debugging. - public void onReceivedError( - WebView view, int errorCode, String description, - String failingUrl) { - Log.e(TAG, "JS error: " + errorCode + " in " + failingUrl + - ", desc: " + description); - } - }); - proxyingMessageHandler = new ProxyingMessageHandler(handler, token); - webView.addJavascriptInterface( - proxyingMessageHandler, "androidMessageHandler"); - webView.loadUrl("file:///android_asset/channel.html"); - } - - /** Close the connection to the AppEngine channel. */ - public void close() { - if (webView == null) { - return; - } - proxyingMessageHandler.disconnect(); - webView.removeJavascriptInterface("androidMessageHandler"); - webView.loadUrl("about:blank"); - webView = null; - } - - // Helper class for proxying callbacks from the Java<->JS interaction - // (private, background) thread. - private static class ProxyingMessageHandler { - private final GAEMessageHandler handler; - private boolean disconnected = false; - private final String token; - - public ProxyingMessageHandler(GAEMessageHandler handler, String token) { - this.handler = handler; - this.token = token; - } - - public void disconnect() { - disconnected = true; - } - - @JavascriptInterface - public String getToken() { - return token; - } - - @JavascriptInterface - public void onOpen() { - if (!disconnected) { - handler.onOpen(); - } - } - - @JavascriptInterface - public void onMessage(final String data) { - if (!disconnected) { - handler.onMessage(data); - } - } - - @JavascriptInterface - public void onClose() { - if (!disconnected) { - handler.onClose(); - } - } - - @JavascriptInterface - public void onError(final int code, final String description) { - Log.e(TAG, "Channel error. Code: " + code + - ". Description: " + description); - if (!disconnected) { - handler.onError(code, description); - } - } - } -} diff --git a/talk/examples/android/src/org/appspot/apprtc/GAERTCClient.java b/talk/examples/android/src/org/appspot/apprtc/GAERTCClient.java deleted file mode 100644 index c1d7a51848..0000000000 --- a/talk/examples/android/src/org/appspot/apprtc/GAERTCClient.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * libjingle - * Copyright 2013, Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.appspot.apprtc; - -import android.app.Activity; -import android.os.AsyncTask; -import android.util.Log; - -import org.appspot.apprtc.RoomParametersFetcher.RoomParametersFetcherEvents; -import org.json.JSONException; -import org.json.JSONObject; -import org.webrtc.IceCandidate; -import org.webrtc.SessionDescription; - -import java.io.IOException; -import java.net.URL; -import java.net.URLConnection; -import java.util.LinkedList; - -/** - * Negotiates signaling for chatting with apprtc.appspot.com "rooms". - * Uses the client<->server specifics of the apprtc AppEngine webapp. - * - * To use: create an instance of this object (registering a message handler) and - * call connectToRoom(). Once room connection is established - * onConnectedToRoom() callback with room parameters is invoked. - * Messages to other party (with local Ice candidates and SDP) can - * be sent after GAE channel is opened and onChannelOpen() callback is invoked. - */ -public class GAERTCClient implements AppRTCClient, RoomParametersFetcherEvents { - private static final String TAG = "GAERTCClient"; - private GAEChannelClient channelClient; - private final Activity activity; - private SignalingEvents events; - private GAEChannelClient.GAEMessageHandler gaeHandler; - private SignalingParameters signalingParameters; - private RoomParametersFetcher fetcher; - private LinkedList sendQueue = new LinkedList(); - private String postMessageUrl; - - public GAERTCClient(Activity activity, SignalingEvents events) { - this.activity = activity; - this.events = events; - } - - // -------------------------------------------------------------------- - // AppRTCClient interface implementation. - /** - * Asynchronously connect to an AppRTC room URL, e.g. - * https://apprtc.appspot.com/?r=NNN and register message-handling callbacks - * on its GAE Channel. - */ - @Override - public void connectToRoom(String url, boolean loopback) { - fetcher = new RoomParametersFetcher(this, false, loopback); - fetcher.execute(url); - } - - /** - * Disconnect from the GAE Channel. - */ - @Override - public void disconnect() { - if (channelClient != null) { - Log.d(TAG, "Closing GAE Channel."); - sendMessage("{\"type\": \"bye\"}"); - channelClient.close(); - channelClient = null; - gaeHandler = null; - } - } - - /** - * Send local SDP (offer or answer, depending on role) to the - * other participant. Note that it is important to send the output of - * create{Offer,Answer} and not merely the current value of - * getLocalDescription() because the latter may include ICE candidates that - * we might want to filter elsewhere. - */ - @Override - public void sendOfferSdp(final SessionDescription sdp) { - JSONObject json = new JSONObject(); - jsonPut(json, "type", "offer"); - jsonPut(json, "sdp", sdp.description); - sendMessage(json.toString()); - } - - @Override - public void sendAnswerSdp(final SessionDescription sdp) { - JSONObject json = new JSONObject(); - jsonPut(json, "type", "answer"); - jsonPut(json, "sdp", sdp.description); - sendMessage(json.toString()); - } - - /** - * Send Ice candidate to the other participant. - */ - @Override - public void sendLocalIceCandidate(final IceCandidate candidate) { - JSONObject json = new JSONObject(); - jsonPut(json, "type", "candidate"); - jsonPut(json, "label", candidate.sdpMLineIndex); - jsonPut(json, "id", candidate.sdpMid); - jsonPut(json, "candidate", candidate.sdp); - sendMessage(json.toString()); - } - - // Queue a message for sending to the room's channel and send it if already - // connected (other wise queued messages are drained when the channel is - // eventually established). - private synchronized void sendMessage(String msg) { - synchronized (sendQueue) { - sendQueue.add(msg); - } - requestQueueDrainInBackground(); - } - - // Put a |key|->|value| mapping in |json|. - private static void jsonPut(JSONObject json, String key, Object value) { - try { - json.put(key, value); - } catch (JSONException e) { - throw new RuntimeException(e); - } - } - - // Request an attempt to drain the send queue, on a background thread. - private void requestQueueDrainInBackground() { - (new AsyncTask() { - public Void doInBackground(Void... unused) { - maybeDrainQueue(); - return null; - } - }).execute(); - } - - // Send all queued messages if connected to the room. - private void maybeDrainQueue() { - synchronized (sendQueue) { - if (signalingParameters == null) { - return; - } - try { - for (String msg : sendQueue) { - Log.d(TAG, "SEND: " + msg); - URLConnection connection = new URL(postMessageUrl).openConnection(); - connection.setDoOutput(true); - connection.getOutputStream().write(msg.getBytes("UTF-8")); - if (!connection.getHeaderField(null).startsWith("HTTP/1.1 200 ")) { - String errorMessage = "Non-200 response to POST: " + - connection.getHeaderField(null) + " for msg: " + msg; - reportChannelError(errorMessage); - } - } - } catch (IOException e) { - reportChannelError("GAE Post error: " + e.getMessage()); - } - sendQueue.clear(); - } - } - - private void reportChannelError(final String errorMessage) { - Log.e(TAG, errorMessage); - activity.runOnUiThread(new Runnable() { - public void run() { - events.onChannelError(errorMessage); - } - }); - } - - // -------------------------------------------------------------------- - // RoomConnectionEvents interface implementation. - // All events are called on UI thread. - @Override - public void onSignalingParametersReady(final SignalingParameters params) { - Log.d(TAG, "Room signaling parameters ready."); - if (params.websocketSignaling) { - reportChannelError("Room does not support GAE channel signaling."); - return; - } - postMessageUrl = params.roomUrl + "/message?r=" + - params.roomId + "&u=" + params.clientId; - gaeHandler = new GAEHandler(); - channelClient = - new GAEChannelClient(activity, params.channelToken, gaeHandler); - synchronized (sendQueue) { - signalingParameters = params; - } - requestQueueDrainInBackground(); - events.onConnectedToRoom(signalingParameters); - } - - @Override - public void onSignalingParametersError(final String description) { - reportChannelError("Room connection error: " + description); - } - - - // -------------------------------------------------------------------- - // GAEMessageHandler interface implementation. - // Implementation detail: handler for receiving GAE messages and dispatching - // them appropriately. All dispatched messages are called from UI thread. - private class GAEHandler implements GAEChannelClient.GAEMessageHandler { - private boolean channelOpen = false; - - public void onOpen() { - activity.runOnUiThread(new Runnable() { - public void run() { - events.onChannelOpen(); - channelOpen = true; - } - }); - } - - public void onMessage(final String msg) { - Log.d(TAG, "RECEIVE: " + msg); - activity.runOnUiThread(new Runnable() { - public void run() { - if (!channelOpen) { - return; - } - try { - JSONObject json = new JSONObject(msg); - String type = json.getString("type"); - if (type.equals("candidate")) { - IceCandidate candidate = new IceCandidate( - json.getString("id"), - json.getInt("label"), - json.getString("candidate")); - events.onRemoteIceCandidate(candidate); - } else if (type.equals("answer") || type.equals("offer")) { - SessionDescription sdp = new SessionDescription( - SessionDescription.Type.fromCanonicalForm(type), - (String)json.get("sdp")); - events.onRemoteDescription(sdp); - } else if (type.equals("bye")) { - events.onChannelClose(); - } else { - reportChannelError("Unexpected channel message: " + msg); - } - } catch (JSONException e) { - reportChannelError("Channel message JSON parsing error: " + - e.toString()); - } - } - }); - } - - public void onClose() { - activity.runOnUiThread(new Runnable() { - public void run() { - events.onChannelClose(); - channelOpen = false; - } - }); - } - - public void onError(final int code, final String description) { - channelOpen = false; - reportChannelError("GAE Handler error. Code: " + code + - ". " + description); - } - } - -} diff --git a/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java b/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java index 0bed403134..aef1d77b04 100644 --- a/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java +++ b/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java @@ -53,7 +53,6 @@ public class SettingsActivity extends Activity keyprefStartBitrateValue = getString(R.string.pref_startbitratevalue_key); keyprefHwCodec = getString(R.string.pref_hwcodec_key); keyprefCpuUsageDetection = getString(R.string.pref_cpu_usage_detection_key); - keyprefSignaling = getString(R.string.pref_signaling_key); // Display the fragment as the main content. settingsFragment = new SettingsFragment(); diff --git a/talk/libjingle_examples.gyp b/talk/libjingle_examples.gyp index ec9e4dcca3..1a573443e3 100755 --- a/talk/libjingle_examples.gyp +++ b/talk/libjingle_examples.gyp @@ -341,8 +341,6 @@ 'examples/android/src/org/appspot/apprtc/AppRTCClient.java', 'examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java', 'examples/android/src/org/appspot/apprtc/ConnectActivity.java', - 'examples/android/src/org/appspot/apprtc/GAEChannelClient.java', - 'examples/android/src/org/appspot/apprtc/GAERTCClient.java', 'examples/android/src/org/appspot/apprtc/PeerConnectionClient.java', 'examples/android/src/org/appspot/apprtc/RoomParametersFetcher.java', 'examples/android/src/org/appspot/apprtc/SettingsActivity.java',