Merging Henrik's and Peter's changes for AppRTCDemo
from https://github.com/hkjellander/AppRTCDemo.

Description of changes:
- Add connect screen with an option to enter room number or select loopback mode.
- Add 'hangup' and 'WebRTC statistics' buttons to AppRTCDemo activity.

BUG=3938
R=kjellander@webrtc.org, pbos@webrtc.org, pthatcher@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/28749004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7500 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/examples/android/AndroidManifest.xml b/talk/examples/android/AndroidManifest.xml
index f898641..cdf674d 100644
--- a/talk/examples/android/AndroidManifest.xml
+++ b/talk/examples/android/AndroidManifest.xml
@@ -4,38 +4,40 @@
           android:versionCode="1"
           android:versionName="1.0">
 
-  <uses-feature android:name="android.hardware.camera" />
-  <uses-feature android:name="android.hardware.camera.autofocus" />
-  <uses-feature android:glEsVersion="0x00020000" android:required="true"></uses-feature>
-  <uses-sdk android:minSdkVersion="13" android:targetSdkVersion="17" />
+    <uses-feature android:name="android.hardware.camera" />
+    <uses-feature android:name="android.hardware.camera.autofocus" />
+    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+    <uses-sdk android:minSdkVersion="13" android:targetSdkVersion="17" />
 
-  <uses-permission android:name="android.permission.CAMERA"></uses-permission>
-  <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
-  <uses-permission android:name="android.permission.RECORD_AUDIO" />
-  <uses-permission android:name="android.permission.INTERNET" />
-  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 
-  <application android:label="@string/app_name"
-               android:icon="@drawable/ic_launcher"
-               android:debuggable="true"
-               android:allowBackup="false">
-    <activity android:name="AppRTCDemoActivity"
-              android:label="@string/app_name"
-              android:screenOrientation="fullUser"
-              android:configChanges="orientation|screenSize"
-              android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
-      <intent-filter>
-        <action android:name="android.intent.action.MAIN" />
-        <category android:name="android.intent.category.LAUNCHER" />
-      </intent-filter>
+    <application android:label="@string/app_name"
+                 android:icon="@drawable/ic_launcher"
+                 android:allowBackup="false">
+        <activity android:name="ConnectActivity"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
 
-      <intent-filter>
-        <action android:name="android.intent.action.VIEW" />
-        <category android:name="android.intent.category.DEFAULT" />
-        <category android:name="android.intent.category.BROWSABLE" />
-        <data android:scheme="https" android:host="apprtc.appspot.com" />
-        <data android:scheme="http" android:host="apprtc.appspot.com" />
-      </intent-filter>
-    </activity>
-  </application>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+                <data android:scheme="https" android:host="apprtc.appspot.com"/>
+                <data android:scheme="http" android:host="apprtc.appspot.com"/>
+            </intent-filter>
+        </activity>
+        <activity android:name="AppRTCDemoActivity"
+                  android:label="@string/app_name"
+                  android:screenOrientation="fullUser"
+                  android:configChanges="orientation|screenSize"
+                  android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
+        </activity>
+    </application>
 </manifest>
diff --git a/talk/examples/android/res/drawable-hdpi/disconnect.png b/talk/examples/android/res/drawable-hdpi/disconnect.png
new file mode 100644
index 0000000..be36174
--- /dev/null
+++ b/talk/examples/android/res/drawable-hdpi/disconnect.png
Binary files differ
diff --git a/talk/examples/android/res/drawable-hdpi/ic_launcher.png b/talk/examples/android/res/drawable-hdpi/ic_launcher.png
index f3e9d12..f01a31a 100644
--- a/talk/examples/android/res/drawable-hdpi/ic_launcher.png
+++ b/talk/examples/android/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/talk/examples/android/res/drawable-ldpi/disconnect.png b/talk/examples/android/res/drawable-ldpi/disconnect.png
new file mode 100644
index 0000000..be36174
--- /dev/null
+++ b/talk/examples/android/res/drawable-ldpi/disconnect.png
Binary files differ
diff --git a/talk/examples/android/res/drawable-mdpi/disconnect.png b/talk/examples/android/res/drawable-mdpi/disconnect.png
new file mode 100644
index 0000000..be36174
--- /dev/null
+++ b/talk/examples/android/res/drawable-mdpi/disconnect.png
Binary files differ
diff --git a/talk/examples/android/res/drawable-mdpi/ic_launcher.png b/talk/examples/android/res/drawable-mdpi/ic_launcher.png
index 9709a1e..b8b4b0e 100644
--- a/talk/examples/android/res/drawable-mdpi/ic_launcher.png
+++ b/talk/examples/android/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/talk/examples/android/res/drawable-xhdpi/disconnect.png b/talk/examples/android/res/drawable-xhdpi/disconnect.png
new file mode 100644
index 0000000..be36174
--- /dev/null
+++ b/talk/examples/android/res/drawable-xhdpi/disconnect.png
Binary files differ
diff --git a/talk/examples/android/res/drawable-xhdpi/ic_launcher.png b/talk/examples/android/res/drawable-xhdpi/ic_launcher.png
index db2c4f6..a3cd458 100644
--- a/talk/examples/android/res/drawable-xhdpi/ic_launcher.png
+++ b/talk/examples/android/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/talk/examples/android/res/layout/activity_connect.xml b/talk/examples/android/res/layout/activity_connect.xml
new file mode 100644
index 0000000..e9e7faf
--- /dev/null
+++ b/talk/examples/android/res/layout/activity_connect.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:weightSum="1"
+        android:layout_margin="8dp"
+        android:layout_centerHorizontal="true">
+    <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:text="@string/apprtc_url"/>
+    <EditText
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:id="@+id/url_edittext"
+            android:inputType="textWebEmailAddress"
+            android:text="https://apprtc.appspot.com"
+            android:imeOptions="actionNext"/>
+    <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="5dp"
+            android:lines="1"
+            android:maxLines="1"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:text="@string/room_name"/>
+    <EditText
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:id="@+id/room_edittext"
+            android:imeOptions="actionGo"/>
+    <TextView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:layout_margin="5dp"
+            android:text="@string/room_description"/>
+    <CheckBox
+            android:id="@+id/check_loopback"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:text="@string/loopback_text" />
+    <Button
+            android:id="@+id/connect_button"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/connect_text"
+            android:textAppearance="?android:attr/textAppearanceLarge" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/talk/examples/android/res/layout/activity_fullscreen.xml b/talk/examples/android/res/layout/activity_fullscreen.xml
new file mode 100644
index 0000000..fc9ee9e
--- /dev/null
+++ b/talk/examples/android/res/layout/activity_fullscreen.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:tools="http://schemas.android.com/tools"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+    <android.opengl.GLSurfaceView
+            android:id="@+id/glview"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+    <TextView
+        android:id="@+id/room_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_above="@+id/menubar_fragment"
+        android:textSize="24sp"
+        android:layout_margin="8dp"/>
+    <fragment
+        android:name="org.appspot.apprtc.AppRTCDemoActivity$MenuBarFragment"
+        android:id="@+id/menubar_fragment"
+        android:layout_centerHorizontal="true"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_marginBottom="32dp"
+        tools:layout="@layout/fragment_menubar"/>
+
+</RelativeLayout>
diff --git a/talk/examples/android/res/layout/fragment_menubar.xml b/talk/examples/android/res/layout/fragment_menubar.xml
new file mode 100644
index 0000000..6d40138
--- /dev/null
+++ b/talk/examples/android/res/layout/fragment_menubar.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:tools="http://schemas.android.com/tools"
+              tools:context="org.appspot.apprtc.AppRTCDemoActivity$MenuBarFragment"
+              android:id="@+id/menubar"
+              android:orientation="horizontal"
+              android:layout_width="wrap_content"
+              android:layout_height="match_parent"
+              android:layout_gravity="center_vertical|center_horizontal">
+
+    <ImageButton
+        android:id="@+id/button_disconnect"
+        android:background="@drawable/disconnect"
+        android:contentDescription="@string/disconnect_call"
+        android:layout_width="48dp"
+        android:layout_height="48dp"/>
+
+    <!-- TODO(kjellander): Add audio and video mute buttons. -->
+
+    <ImageButton
+        android:id="@+id/button_toggle_debug"
+        android:background="@android:drawable/ic_menu_info_details"
+        android:contentDescription="@string/disconnect_call"
+        android:layout_width="48dp"
+        android:layout_height="48dp"/>
+
+</LinearLayout>
diff --git a/talk/examples/android/res/values/strings.xml b/talk/examples/android/res/values/strings.xml
index bac765a..756a7a2f 100644
--- a/talk/examples/android/res/values/strings.xml
+++ b/talk/examples/android/res/values/strings.xml
@@ -1,4 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="app_name">AppRTC</string>
+    <string name="app_name" translatable="no">AppRTC</string>
+    <string name="disconnect_call">Disconnect Call</string>
+    <string name="apprtc_url">URL:</string>
+    <string name="room_name">Room name:</string>
+    <string name="room_description">
+        Please enter a room name. Room names are shared with everyone, so think
+        of something unique and send it to a friend.
+    </string>
+    <string name="connect_text">Connect</string>
+    <string name="loopback_text">Loopback connection</string>
+    <string name="invalid_url_title">Invalid URL</string>
+    <string name="invalid_url_text">The URL or room name you entered resulted in an invalid URL: %1$s
+    </string>
+    <string name="connecting_to">Connecting to: %1$s</string>
+    <string name="missing_url">FATAL ERROR: Missing URL to connect to.</string>
+    <string name="ok">OK</string>
 </resources>
diff --git a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
index 4718a01..32728aa 100644
--- a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
+++ b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
@@ -29,19 +29,24 @@
 
 import android.app.Activity;
 import android.app.AlertDialog;
+import android.app.Fragment;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.res.Configuration;
 import android.graphics.Color;
-import android.graphics.Point;
 import android.media.AudioManager;
+import android.net.Uri;
+import android.opengl.GLSurfaceView;
 import android.os.Bundle;
 import android.util.Log;
 import android.util.TypedValue;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.view.Window;
 import android.view.WindowManager;
 import android.widget.EditText;
+import android.widget.ImageButton;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -66,13 +71,16 @@
   private PeerConnectionClient pc;
   private AppRTCClient appRtcClient = new GAERTCClient(this, this);
   private AppRTCSignalingParameters appRtcParameters;
-  private AppRTCGLView vsv;
+  private View rootView;
+  private View menuBar;
+  private GLSurfaceView videoView;
   private VideoRenderer.Callbacks localRender;
   private VideoRenderer.Callbacks remoteRender;
   private Toast logToast;
   private final LayoutParams hudLayout =
       new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
   private TextView hudView;
+  private TextView roomName;
   // Synchronize on quit[0] to avoid teardown-related crashes.
   private final Boolean[] quit = new Boolean[] { false };
 
@@ -80,29 +88,66 @@
   public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
 
+    // Set window styles for fullscreen-window size. Needs to be done before
+    // adding content.
+    requestWindowFeature(Window.FEATURE_NO_TITLE);
+    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+    getWindow().getDecorView().setSystemUiVisibility(
+        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
+        View.SYSTEM_UI_FLAG_FULLSCREEN |
+        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+
+    setContentView(R.layout.activity_fullscreen);
+
     Thread.setDefaultUncaughtExceptionHandler(
         new UnhandledExceptionHandler(this));
 
-    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
-    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+    rootView = findViewById(android.R.id.content);
+    menuBar = findViewById(R.id.menubar_fragment);
+    roomName = (TextView) findViewById(R.id.room_name);
+    videoView = (GLSurfaceView) findViewById(R.id.glview);
 
-    Point displaySize = new Point();
-    getWindowManager().getDefaultDisplay().getRealSize(displaySize);
-
-    vsv = new AppRTCGLView(this, displaySize);
-    VideoRendererGui.setView(vsv);
+    VideoRendererGui.setView(videoView);
     remoteRender = VideoRendererGui.create(0, 0, 100, 100,
         VideoRendererGui.ScalingType.SCALE_ASPECT_FIT);
     localRender = VideoRendererGui.create(0, 0, 100, 100,
         VideoRendererGui.ScalingType.SCALE_ASPECT_FIT);
 
-    vsv.setOnClickListener(new View.OnClickListener() {
-        @Override public void onClick(View v) {
-          toggleHUD();
-        }
-      });
-    setContentView(vsv);
-    logAndToast("Tap the screen to toggle stats visibility");
+    videoView.setOnClickListener(
+        new View.OnClickListener() {
+          @Override
+          public void onClick(View view) {
+            int visibility = menuBar.getVisibility() == View.VISIBLE
+                    ? View.INVISIBLE : View.VISIBLE;
+            menuBar.setVisibility(visibility);
+            roomName.setVisibility(visibility);
+            if (visibility == View.VISIBLE) {
+              menuBar.bringToFront();
+              roomName.bringToFront();
+              rootView.invalidate();
+            }
+          }
+        });
+
+    ((ImageButton) findViewById(R.id.button_disconnect)).setOnClickListener(
+        new View.OnClickListener() {
+          @Override
+          public void onClick(View view) {
+            logAndToast("Disconnecting call.");
+            disconnect();
+          }
+        });
+
+    ((ImageButton) findViewById(R.id.button_toggle_debug)).setOnClickListener(
+        new View.OnClickListener() {
+          @Override
+          public void onClick(View view) {
+            int visibility = hudView.getVisibility() == View.VISIBLE
+                ? View.INVISIBLE : View.VISIBLE;
+            hudView.setVisibility(visibility);
+          }
+        });
 
     hudView = new TextView(this);
     hudView.setTextColor(Color.BLACK);
@@ -123,17 +168,40 @@
     audioManager.setSpeakerphoneOn(!isWiredHeadsetOn);
 
     final Intent intent = getIntent();
-    if ("android.intent.action.VIEW".equals(intent.getAction())) {
-      connectToRoom(intent.getData().toString());
-      return;
+    Uri url = intent.getData();
+    if (url != null) {
+      String room = url.getQueryParameter("r");
+      String loopback = url.getQueryParameter("debug");
+      if ((room != null && !room.equals("")) ||
+          (loopback != null && loopback.equals("loopback"))) {
+        logAndToast(getString(R.string.connecting_to, url));
+        appRtcClient.connectToRoom(url.toString());
+        roomName.setText(room);
+      } else {
+        logAndToast("Empty or missing room name!");
+        finish();
+      }
+    } else {
+      logAndToast(getString(R.string.missing_url));
+      Log.wtf(TAG, "Didn't get any URL in intent!");
+      finish();
     }
-    showGetRoomUI();
+  }
+
+  public static class MenuBarFragment extends Fragment {
+    @Override
+    public View onCreateView(
+        LayoutInflater inflater,
+        ViewGroup container,
+        Bundle savedInstanceState) {
+      return inflater.inflate(R.layout.fragment_menubar, container, false);
+    }
   }
 
   @Override
   public void onPause() {
     super.onPause();
-    vsv.onPause();
+    videoView.onPause();
     if (pc != null) {
       pc.stopVideoSource();
     }
@@ -142,59 +210,18 @@
   @Override
   public void onResume() {
     super.onResume();
-    vsv.onResume();
+    videoView.onResume();
     if (pc != null) {
       pc.startVideoSource();
     }
   }
 
   @Override
-  public void onConfigurationChanged (Configuration newConfig) {
-    Point displaySize = new Point();
-    getWindowManager().getDefaultDisplay().getSize(displaySize);
-    vsv.updateDisplaySize(displaySize);
-    super.onConfigurationChanged(newConfig);
-  }
-
-  @Override
   protected void onDestroy() {
-    disconnectAndExit();
+    disconnect();
     super.onDestroy();
   }
 
-  private void showGetRoomUI() {
-    final EditText roomInput = new EditText(this);
-    roomInput.setText("https://apprtc.appspot.com/?r=");
-    roomInput.setSelection(roomInput.getText().length());
-    DialogInterface.OnClickListener listener =
-        new DialogInterface.OnClickListener() {
-          @Override
-          public void onClick(DialogInterface dialog, int which) {
-            abortUnless(which == DialogInterface.BUTTON_POSITIVE, "lolwat?");
-            dialog.dismiss();
-            connectToRoom(roomInput.getText().toString());
-          }
-        };
-    AlertDialog.Builder builder = new AlertDialog.Builder(this);
-    builder
-        .setMessage("Enter room URL").setView(roomInput)
-        .setPositiveButton("Go!", listener).show();
-  }
-
-  private void connectToRoom(String roomUrl) {
-    logAndToast("Connecting to room...");
-    appRtcClient.connectToRoom(roomUrl);
-  }
-
-  // Toggle visibility of the heads-up display.
-  private void toggleHUD() {
-    if (hudView.getVisibility() == View.VISIBLE) {
-      hudView.setVisibility(View.INVISIBLE);
-    } else {
-      hudView.setVisibility(View.VISIBLE);
-    }
-  }
-
   // Update the heads-up display with information from |reports|.
   private void updateHUD(StatsReport[] reports) {
     StringBuilder builder = new StringBuilder();
@@ -243,7 +270,7 @@
   }
 
   // Disconnect from remote resources, dispose of local resources, and exit.
-  private void disconnectAndExit() {
+  private void disconnect() {
     synchronized (quit[0]) {
       if (quit[0]) {
         return;
@@ -300,7 +327,7 @@
               }
               final Runnable runnableThis = this;
               if (hudView.getVisibility() == View.INVISIBLE) {
-                vsv.postDelayed(runnableThis, 1000);
+                videoView.postDelayed(runnableThis, 1000);
                 return;
               }
               boolean success = finalPC.getStats(new StatsObserver() {
@@ -313,7 +340,7 @@
                     for (StatsReport report : reports) {
                       Log.d(TAG, "Stats: " + report.toString());
                     }
-                    vsv.postDelayed(runnableThis, 1000);
+                    videoView.postDelayed(runnableThis, 1000);
                   }
                 }, null);
               if (!success) {
@@ -322,7 +349,7 @@
             }
           }
         };
-      vsv.postDelayed(repeatedStatsLogger, 1000);
+      videoView.postDelayed(repeatedStatsLogger, 1000);
     }
 
     logAndToast("Waiting for remote connection...");
@@ -358,13 +385,13 @@
   @Override
   public void onChannelClose() {
     logAndToast("Remote end hung up; dropping PeerConnection");
-    disconnectAndExit();
+    disconnect();
   }
 
   @Override
   public void onChannelError(int code, String description) {
     logAndToast("Channel error: " + code + ". " + description);
-    disconnectAndExit();
+    disconnect();
   }
 
   // -----Implementation of PeerConnectionClient.PeerConnectionEvents.---------
diff --git a/talk/examples/android/src/org/appspot/apprtc/AppRTCGLView.java b/talk/examples/android/src/org/appspot/apprtc/AppRTCGLView.java
deleted file mode 100644
index e622ab9..0000000
--- a/talk/examples/android/src/org/appspot/apprtc/AppRTCGLView.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * libjingle
- * Copyright 2014, 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.content.Context;
-import android.graphics.Point;
-import android.opengl.GLSurfaceView;
-
-public class AppRTCGLView extends GLSurfaceView {
-  private Point screenDimensions;
-
-  public AppRTCGLView(Context c, Point screenDimensions) {
-    super(c);
-    this.screenDimensions = screenDimensions;
-  }
-
-  public void updateDisplaySize(Point screenDimensions) {
-    this.screenDimensions = screenDimensions;
-  }
-
-  @Override
-  protected void onMeasure(int unusedX, int unusedY) {
-    // Go big or go home!
-    setMeasuredDimension(screenDimensions.x, screenDimensions.y);
-  }
-
-  @Override
-  protected void onAttachedToWindow() {
-    super.onAttachedToWindow();
-    setSystemUiVisibility(SYSTEM_UI_FLAG_HIDE_NAVIGATION |
-        SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
-  }
-}
diff --git a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java
new file mode 100644
index 0000000..e02104e
--- /dev/null
+++ b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java
@@ -0,0 +1,131 @@
+/*
+ * libjingle
+ * Copyright 2014, 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.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.EditorInfo;
+import android.webkit.URLUtil;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.TextView;
+
+/**
+ * Handles the initial setup where the user selects which room to join.
+ */
+public class ConnectActivity extends Activity {
+
+  private static final String TAG = "ConnectActivity";
+  public static final String CONNECT_URL_EXTRA = "connect_url";
+  private Button connectButton;
+  private EditText urlEditText;
+  private EditText roomEditText;
+  private CheckBox loopbackCheckBox;
+
+  @Override
+  public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+
+    // If an implicit VIEW intent is launching the app, go directly to that URL.
+    final Intent intent = getIntent();
+    if ("android.intent.action.VIEW".equals(intent.getAction())) {
+      connectToRoom(intent.getData().toString());
+      return;
+    }
+
+    setContentView(R.layout.activity_connect);
+
+    urlEditText = (EditText) findViewById(R.id.url_edittext);
+
+    loopbackCheckBox = (CheckBox) findViewById(R.id.check_loopback);
+    loopbackCheckBox.setChecked(false);
+
+    roomEditText = (EditText) findViewById(R.id.room_edittext);
+    roomEditText.setOnEditorActionListener(
+        new TextView.OnEditorActionListener() {
+          @Override
+          public boolean onEditorAction(
+              TextView textView, int i, KeyEvent keyEvent) {
+            if (i == EditorInfo.IME_ACTION_GO) {
+              connectButton.performClick();
+              return true;
+            }
+            return false;
+          }
+    });
+    roomEditText.requestFocus();
+
+    connectButton = (Button) findViewById(R.id.connect_button);
+    connectButton.setOnClickListener(new OnClickListener() {
+      @Override
+      public void onClick(View view) {
+        String url = urlEditText.getText().toString();
+        if (loopbackCheckBox.isChecked()) {
+          url += "/?debug=loopback";
+        } else {
+          url += "/?r=" + roomEditText.getText();
+        }
+        // TODO(kjellander): Add support for custom parameters to the URL.
+        connectToRoom(url);
+      }
+    });
+  }
+
+  private void connectToRoom(String roomUrl) {
+    if (validateUrl(roomUrl)) {
+      Uri url = Uri.parse(roomUrl);
+      Intent intent = new Intent(this, AppRTCDemoActivity.class);
+      intent.setData(url);
+      startActivity(intent);
+    }
+  }
+
+  private boolean validateUrl(String url) {
+    if (URLUtil.isHttpsUrl(url) || URLUtil.isHttpUrl(url))
+      return true;
+
+    new AlertDialog.Builder(this)
+        .setTitle(getText(R.string.invalid_url_title))
+        .setMessage(getString(R.string.invalid_url_text, url))
+        .setCancelable(false)
+        .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int id) {
+              dialog.cancel();
+            }
+          }).create().show();
+    return false;
+  }
+}
diff --git a/talk/libjingle_examples.gyp b/talk/libjingle_examples.gyp
index 085da39..ff49a8e 100755
--- a/talk/libjingle_examples.gyp
+++ b/talk/libjingle_examples.gyp
@@ -318,13 +318,20 @@
                 'examples/android/jni/Android.mk',
                 'examples/android/project.properties',
                 'examples/android/res/drawable-hdpi/ic_launcher.png',
+                'examples/android/res/drawable-hdpi/disconnect.png',
                 'examples/android/res/drawable-ldpi/ic_launcher.png',
+                'examples/android/res/drawable-ldpi/disconnect.png',
                 'examples/android/res/drawable-mdpi/ic_launcher.png',
+                'examples/android/res/drawable-mdpi/disconnect.png',
                 'examples/android/res/drawable-xhdpi/ic_launcher.png',
+                'examples/android/res/drawable-xhdpi/disconnect.png',
+                'examples/android/res/layout/activity_connect.xml',
+                'examples/android/res/layout/activity_fullscreen.xml',
+                'examples/android/res/layout/fragment_menubar.xml',
                 'examples/android/res/values/strings.xml',
                 'examples/android/src/org/appspot/apprtc/AppRTCClient.java',
                 'examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java',
-                'examples/android/src/org/appspot/apprtc/AppRTCGLView.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',