Adding setting screen to AppRTCDemo.

- Move server URL from connection screen
to the setting screen.
- Add setting for local video resolution.
- Auto save last entered room number.
- Use full screen mode in video renderer and fix
texture offsets recalculation when rendering type is
dynamically changed.

BUG=3935,3953
R=kjellander@webrtc.org, pbos@webrtc.org, pthatcher@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7534 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java
index a393774..acaa31e 100644
--- a/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java
+++ b/talk/app/webrtc/java/android/org/webrtc/VideoRendererGui.java
@@ -324,6 +324,8 @@
       float texLeft = this.texLeft;
       float texTop = this.texTop;
       float texBottom = this.texBottom;
+      float texOffsetU = 0;
+      float texOffsetV = 0;
       float displayWidth = (texRight - texLeft) * screenWidth / 2;
       float displayHeight = (texTop - texBottom) * screenHeight / 2;
       Log.d(TAG, "ID: "  + id + ". Display: " + displayWidth +
@@ -346,36 +348,33 @@
             texTop -= deltaY;
             texBottom += deltaY;
           }
-          Log.d(TAG, "  Texture vertices: (" + texLeft + "," + texBottom +
-              ") - (" + texRight + "," + texTop + ")");
-          // Re-allocate vertices buffer to adjust to video aspect ratio.
-          float textureVeticesFloat[] = new float[] {
-              texLeft, texTop,
-              texLeft, texBottom,
-              texRight, texTop,
-              texRight, texBottom
-          };
-          textureVertices = directNativeFloatBuffer(textureVeticesFloat);
         }
         if (scalingType == ScalingType.SCALE_ASPECT_FILL) {
-          float texOffsetU = 0;
-          float texOffsetV = 0;
           // Need to re-adjust UV coordinates to match display AR.
           if (displayAspectRatio > videoAspectRatio) {
             texOffsetV = (1.0f - videoAspectRatio / displayAspectRatio) / 2.0f;
           } else {
             texOffsetU = (1.0f - displayAspectRatio / videoAspectRatio) / 2.0f;
           }
-          Log.d(TAG, "  Texture UV offsets: " + texOffsetU + ", " + texOffsetV);
-          // Re-allocate coordinates buffer to adjust to display aspect ratio.
-          float textureCoordinatesFloat[] = new float[] {
-              texOffsetU, texOffsetV,               // left top
-              texOffsetU, 1.0f - texOffsetV,        // left bottom
-              1.0f - texOffsetU, texOffsetV,        // right top
-              1.0f - texOffsetU, 1.0f - texOffsetV  // right bottom
-          };
-          textureCoords = directNativeFloatBuffer(textureCoordinatesFloat);
         }
+        Log.d(TAG, "  Texture vertices: (" + texLeft + "," + texBottom +
+            ") - (" + texRight + "," + texTop + ")");
+        float textureVeticesFloat[] = new float[] {
+            texLeft, texTop,
+            texLeft, texBottom,
+            texRight, texTop,
+            texRight, texBottom
+        };
+        textureVertices = directNativeFloatBuffer(textureVeticesFloat);
+
+        Log.d(TAG, "  Texture UV offsets: " + texOffsetU + ", " + texOffsetV);
+        float textureCoordinatesFloat[] = new float[] {
+            texOffsetU, texOffsetV,               // left top
+            texOffsetU, 1.0f - texOffsetV,        // left bottom
+            1.0f - texOffsetU, texOffsetV,        // right top
+            1.0f - texOffsetU, 1.0f - texOffsetV  // right bottom
+        };
+        textureCoords = directNativeFloatBuffer(textureCoordinatesFloat);
       }
       updateTextureProperties = false;
     }
@@ -501,6 +500,7 @@
       texTop = (50 - y) / 50.0f;
       texRight = Math.min(1.0f, (x + width - 50) / 50.0f);
       texBottom = Math.max(-1.0f, (50 - y - height) / 50.0f);
+      this.scalingType = scalingType;
       updateTextureProperties = true;
     }
 
@@ -690,7 +690,7 @@
       onSurfaceCreatedCalled = true;
     }
     checkNoGLES2Error();
-    GLES20.glClearColor(0.0f, 0.0f, 0.1f, 1.0f);
+    GLES20.glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
   }
 
   @Override
diff --git a/talk/examples/android/AndroidManifest.xml b/talk/examples/android/AndroidManifest.xml
index cdf674d..30fd46c 100644
--- a/talk/examples/android/AndroidManifest.xml
+++ b/talk/examples/android/AndroidManifest.xml
@@ -7,7 +7,7 @@
     <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-sdk android:minSdkVersion="13" android:targetSdkVersion="19" />
 
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
@@ -18,6 +18,7 @@
     <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>
@@ -33,6 +34,11 @@
                 <data android:scheme="http" android:host="apprtc.appspot.com"/>
             </intent-filter>
         </activity>
+
+        <activity android:name="SettingsActivity"
+                  android:label="@string/settings_name">
+        </activity>
+
         <activity android:name="AppRTCDemoActivity"
                   android:label="@string/app_name"
                   android:screenOrientation="fullUser"
diff --git a/talk/examples/android/res/layout/activity_connect.xml b/talk/examples/android/res/layout/activity_connect.xml
index e9e7faf..2d6f6f8 100644
--- a/talk/examples/android/res/layout/activity_connect.xml
+++ b/talk/examples/android/res/layout/activity_connect.xml
@@ -10,19 +10,7 @@
     <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:layout_marginTop="15dp"
             android:lines="1"
             android:maxLines="1"
             android:textAppearance="?android:attr/textAppearanceMedium"
@@ -37,7 +25,7 @@
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:textAppearance="?android:attr/textAppearanceMedium"
-            android:layout_margin="5dp"
+            android:layout_margin="15dp"
             android:text="@string/room_description"/>
     <CheckBox
             android:id="@+id/check_loopback"
diff --git a/talk/examples/android/res/menu/connect_menu.xml b/talk/examples/android/res/menu/connect_menu.xml
new file mode 100644
index 0000000..d9f9486
--- /dev/null
+++ b/talk/examples/android/res/menu/connect_menu.xml
@@ -0,0 +1,8 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:icon="@android:drawable/ic_menu_preferences"
+        android:showAsAction="ifRoom"
+        android:title="@string/action_settings"/>
+</menu>
diff --git a/talk/examples/android/res/values/arrays.xml b/talk/examples/android/res/values/arrays.xml
new file mode 100644
index 0000000..af56eb9
--- /dev/null
+++ b/talk/examples/android/res/values/arrays.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string-array name="videoResolutions">
+        <item>Default</item>
+        <item>HD (1280 x 720)</item>
+        <item>VGA (640 x 480)</item>
+        <item>QVGA (320 x 240)</item>
+    </string-array>
+    <string-array name="videoResolutionsValues">
+        <item>Default</item>
+        <item>1280 x 720</item>
+        <item>640 x 480</item>
+        <item>320 x 240</item>
+    </string-array>
+</resources>
diff --git a/talk/examples/android/res/values/strings.xml b/talk/examples/android/res/values/strings.xml
index 756a7a2..8015489 100644
--- a/talk/examples/android/res/values/strings.xml
+++ b/talk/examples/android/res/values/strings.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <string name="app_name" translatable="no">AppRTC</string>
+    <string name="settings_name" translatable="no">AppRTC Settings</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
@@ -16,4 +16,20 @@
     <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>
+    <string name="action_settings">Settings</string>
+
+    <!-- Settings strings. -->
+    <string name="pref_room_key">room_preference</string>
+
+    <string name="pref_url_key">url_preference</string>
+    <string name="pref_url_title">Connection URL:</string>
+    <string name="pref_url_summary">AppRTC connection server URL.</string>
+    <string name="pref_url_dlg">Enter AppRTC connection server URL.</string>
+    <string name="pref_url_default">https://apprtc.appspot.com</string>
+
+    <string name="pref_resolution_key">resolution_preference</string>
+    <string name="pref_resolution_title">Video resolution.</string>
+    <string name="pref_resolution_summary">Video resolution.</string>
+    <string name="pref_resolution_dlg">Enter AppRTC local video resolution.</string>
+    <string name="pref_resolution_default">Default</string>
 </resources>
diff --git a/talk/examples/android/res/xml/preferences.xml b/talk/examples/android/res/xml/preferences.xml
new file mode 100644
index 0000000..efabd3e
--- /dev/null
+++ b/talk/examples/android/res/xml/preferences.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+    <EditTextPreference
+        android:key="@string/pref_url_key"
+        android:title="@string/pref_url_title"
+        android:summary="@string/pref_url_summary"
+        android:defaultValue="@string/pref_url_default"
+        android:inputType="textWebEmailAddress"
+        android:dialogTitle="@string/pref_url_dlg" />
+    <ListPreference
+        android:key="@string/pref_resolution_key"
+        android:title="@string/pref_resolution_title"
+        android:summary="@string/pref_resolution_summary"
+        android:defaultValue="@string/pref_resolution_default"
+        android:dialogTitle="@string/pref_resolution_dlg"
+        android:entries="@array/videoResolutions"
+        android:entryValues="@array/videoResolutionsValues" />
+</PreferenceScreen>
\ No newline at end of file
diff --git a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
index 32728aa..01ae734 100644
--- a/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
+++ b/talk/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
@@ -110,9 +110,9 @@
 
     VideoRendererGui.setView(videoView);
     remoteRender = VideoRendererGui.create(0, 0, 100, 100,
-        VideoRendererGui.ScalingType.SCALE_ASPECT_FIT);
+        VideoRendererGui.ScalingType.SCALE_ASPECT_FILL);
     localRender = VideoRendererGui.create(0, 0, 100, 100,
-        VideoRendererGui.ScalingType.SCALE_ASPECT_FIT);
+        VideoRendererGui.ScalingType.SCALE_ASPECT_FILL);
 
     videoView.setOnClickListener(
         new View.OnClickListener() {
diff --git a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java
index 2df6fcf..6a2ca5b 100644
--- a/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java
+++ b/talk/examples/android/src/org/appspot/apprtc/ConnectActivity.java
@@ -31,9 +31,15 @@
 import android.app.AlertDialog;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
 import android.net.Uri;
 import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
 import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.inputmethod.EditorInfo;
@@ -51,16 +57,25 @@
 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;
+  private SharedPreferences sharedPref;
+  private String keyprefUrl;
+  private String keyprefResolution;
+  private String keyprefRoom;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
 
+    // Get setting keys.
+    PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
+    sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
+    keyprefUrl = getString(R.string.pref_url_key);
+    keyprefResolution = getString(R.string.pref_resolution_key);
+    keyprefRoom = getString(R.string.pref_room_key);
+
     // 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())) {
@@ -70,8 +85,6 @@
 
     setContentView(R.layout.activity_connect);
 
-    urlEditText = (EditText) findViewById(R.id.url_edittext);
-
     loopbackCheckBox = (CheckBox) findViewById(R.id.check_loopback);
     loopbackCheckBox.setChecked(false);
 
@@ -94,15 +107,33 @@
     connectButton.setOnClickListener(new OnClickListener() {
       @Override
       public void onClick(View view) {
-        String url = urlEditText.getText().toString();
+        String url = sharedPref.getString(keyprefUrl,
+            getString(R.string.pref_url_default));
         if (loopbackCheckBox.isChecked()) {
           url += "/?debug=loopback";
         } else {
           url += "/?r=" + roomEditText.getText();
         }
 
-        if (MediaCodecVideoEncoder.isPlatformSupported()) {
-          url += "&hd=true";
+        // Add video resolution constraints.
+        String resolution = sharedPref.getString(keyprefResolution,
+            getString(R.string.pref_resolution_default));
+        String[] dimensions = resolution.split("[ x]+");
+        if (dimensions.length == 2) {
+          try {
+            int maxWidth = Integer.parseInt(dimensions[0]);
+            int maxHeight = Integer.parseInt(dimensions[1]);
+            if (maxWidth > 0 && maxHeight > 0) {
+              url += "&video=minHeight=" + maxHeight + ",maxHeight=" +
+                  maxHeight + ",minWidth=" + maxWidth + ",maxWidth=" + maxWidth;
+            }
+          } catch (NumberFormatException e) {
+            Log.e(TAG, "Wrong video resolution setting: " + resolution);
+          }
+        } else {
+          if (MediaCodecVideoEncoder.isPlatformSupported()) {
+            url += "&hd=true";
+          }
         }
         // TODO(kjellander): Add support for custom parameters to the URL.
         connectToRoom(url);
@@ -110,6 +141,40 @@
     });
   }
 
+  @Override
+  public boolean onCreateOptionsMenu(Menu menu) {
+    getMenuInflater().inflate(R.menu.connect_menu, menu);
+    return true;
+  }
+
+  @Override
+  public boolean onOptionsItemSelected(MenuItem item) {
+    // Handle presses on the action bar items.
+    if (item.getItemId() == R.id.action_settings) {
+      Intent intent = new Intent(this, SettingsActivity.class);
+      startActivity(intent);
+      return true;
+    } else {
+      return super.onOptionsItemSelected(item);
+    }
+  }
+
+  @Override
+  public void onPause() {
+    super.onPause();
+    String room = roomEditText.getText().toString();
+    SharedPreferences.Editor editor = sharedPref.edit();
+    editor.putString(keyprefRoom, room);
+    editor.commit();
+  }
+
+  @Override
+  public void onResume() {
+    super.onResume();
+    String room = sharedPref.getString(keyprefRoom, "");
+    roomEditText.setText(room);
+  }
+
   private void connectToRoom(String roomUrl) {
     if (validateUrl(roomUrl)) {
       Uri url = Uri.parse(roomUrl);
diff --git a/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java b/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java
new file mode 100644
index 0000000..e974aaf
--- /dev/null
+++ b/talk/examples/android/src/org/appspot/apprtc/SettingsActivity.java
@@ -0,0 +1,88 @@
+/*
+ * 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.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.os.Bundle;
+import android.preference.Preference;
+
+public class SettingsActivity extends Activity
+    implements OnSharedPreferenceChangeListener{
+  private SettingsFragment settingsFragment;
+  private String keyprefUrl;
+  private String keyprefResolution;
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    keyprefUrl = getString(R.string.pref_url_key);
+    keyprefResolution = getString(R.string.pref_resolution_key);
+
+    // Display the fragment as the main content.
+    settingsFragment = new SettingsFragment();
+    getFragmentManager().beginTransaction()
+        .replace(android.R.id.content, settingsFragment)
+        .commit();
+  }
+
+  @Override
+  protected void onResume() {
+    super.onResume();
+    // Set summary to be the user-description for the selected value
+    SharedPreferences sharedPreferences =
+        settingsFragment.getPreferenceScreen().getSharedPreferences();
+    sharedPreferences.registerOnSharedPreferenceChangeListener(this);
+    updateSummary(sharedPreferences, keyprefUrl);
+    updateSummary(sharedPreferences, keyprefResolution);
+  }
+
+  @Override
+  protected void onPause() {
+    super.onPause();
+    SharedPreferences sharedPreferences =
+        settingsFragment.getPreferenceScreen().getSharedPreferences();
+    sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
+  }
+
+  @Override
+  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+      String key) {
+    if (key.equals(keyprefUrl) || key.equals(keyprefResolution)) {
+      updateSummary(sharedPreferences, key);
+    }
+  }
+
+  private void updateSummary(SharedPreferences sharedPreferences, String key) {
+    Preference updatedPref = settingsFragment.findPreference(key);
+    // Set summary to be the user-description for the selected value
+    updatedPref.setSummary(sharedPreferences.getString(key, ""));
+  }
+
+}
diff --git a/talk/examples/android/src/org/appspot/apprtc/SettingsFragment.java b/talk/examples/android/src/org/appspot/apprtc/SettingsFragment.java
new file mode 100644
index 0000000..ec4b704
--- /dev/null
+++ b/talk/examples/android/src/org/appspot/apprtc/SettingsFragment.java
@@ -0,0 +1,41 @@
+/*
+ * 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.os.Bundle;
+import android.preference.PreferenceFragment;
+
+public class SettingsFragment extends PreferenceFragment {
+
+  @Override
+  public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    // Load the preferences from an XML resource
+    addPreferencesFromResource(R.xml.preferences);
+  }
+}
diff --git a/talk/libjingle_examples.gyp b/talk/libjingle_examples.gyp
index ff49a8e..ae15975 100755
--- a/talk/libjingle_examples.gyp
+++ b/talk/libjingle_examples.gyp
@@ -328,13 +328,18 @@
                 'examples/android/res/layout/activity_connect.xml',
                 'examples/android/res/layout/activity_fullscreen.xml',
                 'examples/android/res/layout/fragment_menubar.xml',
+                'examples/android/res/menu/connect_menu.xml',
+                'examples/android/res/values/arrays.xml',
                 'examples/android/res/values/strings.xml',
+                'examples/android/res/xml/preferences.xml',
                 '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/SettingsActivity.java',
+                'examples/android/src/org/appspot/apprtc/SettingsFragment.java',
                 'examples/android/src/org/appspot/apprtc/UnhandledExceptionHandler.java',
               ],
               'outputs': [