1 /* 2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 package org.appspot.apprtc; 12 13 import android.annotation.TargetApi; 14 import android.app.Activity; 15 import android.app.AlertDialog; 16 import android.content.DialogInterface; 17 import android.content.Intent; 18 import android.content.SharedPreferences; 19 import android.content.pm.PackageInfo; 20 import android.content.pm.PackageManager; 21 import android.net.Uri; 22 import android.os.Build; 23 import android.os.Bundle; 24 import android.preference.PreferenceManager; 25 import android.support.annotation.Nullable; 26 import android.util.Log; 27 import android.view.ContextMenu; 28 import android.view.KeyEvent; 29 import android.view.Menu; 30 import android.view.MenuItem; 31 import android.view.View; 32 import android.view.View.OnClickListener; 33 import android.view.inputmethod.EditorInfo; 34 import android.webkit.URLUtil; 35 import android.widget.AdapterView; 36 import android.widget.ArrayAdapter; 37 import android.widget.EditText; 38 import android.widget.ImageButton; 39 import android.widget.ListView; 40 import android.widget.TextView; 41 import java.util.ArrayList; 42 import java.util.Random; 43 import org.json.JSONArray; 44 import org.json.JSONException; 45 46 /** 47 * Handles the initial setup where the user selects which room to join. 48 */ 49 public class ConnectActivity extends Activity { 50 private static final String TAG = "ConnectActivity"; 51 private static final int CONNECTION_REQUEST = 1; 52 private static final int PERMISSION_REQUEST = 2; 53 private static final int REMOVE_FAVORITE_INDEX = 0; 54 private static boolean commandLineRun; 55 56 private ImageButton addFavoriteButton; 57 private EditText roomEditText; 58 private ListView roomListView; 59 private SharedPreferences sharedPref; 60 private String keyprefResolution; 61 private String keyprefFps; 62 private String keyprefVideoBitrateType; 63 private String keyprefVideoBitrateValue; 64 private String keyprefAudioBitrateType; 65 private String keyprefAudioBitrateValue; 66 private String keyprefRoomServerUrl; 67 private String keyprefRoom; 68 private String keyprefRoomList; 69 private ArrayList<String> roomList; 70 private ArrayAdapter<String> adapter; 71 72 @Override onCreate(Bundle savedInstanceState)73 public void onCreate(Bundle savedInstanceState) { 74 super.onCreate(savedInstanceState); 75 76 // Get setting keys. 77 PreferenceManager.setDefaultValues(this, R.xml.preferences, false); 78 sharedPref = PreferenceManager.getDefaultSharedPreferences(this); 79 keyprefResolution = getString(R.string.pref_resolution_key); 80 keyprefFps = getString(R.string.pref_fps_key); 81 keyprefVideoBitrateType = getString(R.string.pref_maxvideobitrate_key); 82 keyprefVideoBitrateValue = getString(R.string.pref_maxvideobitratevalue_key); 83 keyprefAudioBitrateType = getString(R.string.pref_startaudiobitrate_key); 84 keyprefAudioBitrateValue = getString(R.string.pref_startaudiobitratevalue_key); 85 keyprefRoomServerUrl = getString(R.string.pref_room_server_url_key); 86 keyprefRoom = getString(R.string.pref_room_key); 87 keyprefRoomList = getString(R.string.pref_room_list_key); 88 89 setContentView(R.layout.activity_connect); 90 91 roomEditText = findViewById(R.id.room_edittext); 92 roomEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { 93 @Override 94 public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { 95 if (i == EditorInfo.IME_ACTION_DONE) { 96 addFavoriteButton.performClick(); 97 return true; 98 } 99 return false; 100 } 101 }); 102 roomEditText.requestFocus(); 103 104 roomListView = findViewById(R.id.room_listview); 105 roomListView.setEmptyView(findViewById(android.R.id.empty)); 106 roomListView.setOnItemClickListener(roomListClickListener); 107 registerForContextMenu(roomListView); 108 ImageButton connectButton = findViewById(R.id.connect_button); 109 connectButton.setOnClickListener(connectListener); 110 addFavoriteButton = findViewById(R.id.add_favorite_button); 111 addFavoriteButton.setOnClickListener(addFavoriteListener); 112 113 requestPermissions(); 114 } 115 116 @Override onCreateOptionsMenu(Menu menu)117 public boolean onCreateOptionsMenu(Menu menu) { 118 getMenuInflater().inflate(R.menu.connect_menu, menu); 119 return true; 120 } 121 122 @Override onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)123 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { 124 if (v.getId() == R.id.room_listview) { 125 AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo; 126 menu.setHeaderTitle(roomList.get(info.position)); 127 String[] menuItems = getResources().getStringArray(R.array.roomListContextMenu); 128 for (int i = 0; i < menuItems.length; i++) { 129 menu.add(Menu.NONE, i, i, menuItems[i]); 130 } 131 } else { 132 super.onCreateContextMenu(menu, v, menuInfo); 133 } 134 } 135 136 @Override onContextItemSelected(MenuItem item)137 public boolean onContextItemSelected(MenuItem item) { 138 if (item.getItemId() == REMOVE_FAVORITE_INDEX) { 139 AdapterView.AdapterContextMenuInfo info = 140 (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); 141 roomList.remove(info.position); 142 adapter.notifyDataSetChanged(); 143 return true; 144 } 145 146 return super.onContextItemSelected(item); 147 } 148 149 @Override onOptionsItemSelected(MenuItem item)150 public boolean onOptionsItemSelected(MenuItem item) { 151 // Handle presses on the action bar items. 152 if (item.getItemId() == R.id.action_settings) { 153 Intent intent = new Intent(this, SettingsActivity.class); 154 startActivity(intent); 155 return true; 156 } else if (item.getItemId() == R.id.action_loopback) { 157 connectToRoom(null, false, true, false, 0); 158 return true; 159 } else { 160 return super.onOptionsItemSelected(item); 161 } 162 } 163 164 @Override onPause()165 public void onPause() { 166 super.onPause(); 167 String room = roomEditText.getText().toString(); 168 String roomListJson = new JSONArray(roomList).toString(); 169 SharedPreferences.Editor editor = sharedPref.edit(); 170 editor.putString(keyprefRoom, room); 171 editor.putString(keyprefRoomList, roomListJson); 172 editor.commit(); 173 } 174 175 @Override onResume()176 public void onResume() { 177 super.onResume(); 178 String room = sharedPref.getString(keyprefRoom, ""); 179 roomEditText.setText(room); 180 roomList = new ArrayList<>(); 181 String roomListJson = sharedPref.getString(keyprefRoomList, null); 182 if (roomListJson != null) { 183 try { 184 JSONArray jsonArray = new JSONArray(roomListJson); 185 for (int i = 0; i < jsonArray.length(); i++) { 186 roomList.add(jsonArray.get(i).toString()); 187 } 188 } catch (JSONException e) { 189 Log.e(TAG, "Failed to load room list: " + e.toString()); 190 } 191 } 192 adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, roomList); 193 roomListView.setAdapter(adapter); 194 if (adapter.getCount() > 0) { 195 roomListView.requestFocus(); 196 roomListView.setItemChecked(0, true); 197 } 198 } 199 200 @Override onActivityResult(int requestCode, int resultCode, Intent data)201 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 202 if (requestCode == CONNECTION_REQUEST && commandLineRun) { 203 Log.d(TAG, "Return: " + resultCode); 204 setResult(resultCode); 205 commandLineRun = false; 206 finish(); 207 } 208 } 209 210 @Override onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults)211 public void onRequestPermissionsResult( 212 int requestCode, String[] permissions, int[] grantResults) { 213 if (requestCode == PERMISSION_REQUEST) { 214 String[] missingPermissions = getMissingPermissions(); 215 if (missingPermissions.length != 0) { 216 // User didn't grant all the permissions. Warn that the application might not work 217 // correctly. 218 new AlertDialog.Builder(this) 219 .setMessage(R.string.missing_permissions_try_again) 220 .setPositiveButton(R.string.yes, 221 (dialog, id) -> { 222 // User wants to try giving the permissions again. 223 dialog.cancel(); 224 requestPermissions(); 225 }) 226 .setNegativeButton(R.string.no, 227 (dialog, id) -> { 228 // User doesn't want to give the permissions. 229 dialog.cancel(); 230 onPermissionsGranted(); 231 }) 232 .show(); 233 } else { 234 // All permissions granted. 235 onPermissionsGranted(); 236 } 237 } 238 } 239 onPermissionsGranted()240 private void onPermissionsGranted() { 241 // If an implicit VIEW intent is launching the app, go directly to that URL. 242 final Intent intent = getIntent(); 243 if ("android.intent.action.VIEW".equals(intent.getAction()) && !commandLineRun) { 244 boolean loopback = intent.getBooleanExtra(CallActivity.EXTRA_LOOPBACK, false); 245 int runTimeMs = intent.getIntExtra(CallActivity.EXTRA_RUNTIME, 0); 246 boolean useValuesFromIntent = 247 intent.getBooleanExtra(CallActivity.EXTRA_USE_VALUES_FROM_INTENT, false); 248 String room = sharedPref.getString(keyprefRoom, ""); 249 connectToRoom(room, true, loopback, useValuesFromIntent, runTimeMs); 250 } 251 } 252 253 @TargetApi(Build.VERSION_CODES.M) requestPermissions()254 private void requestPermissions() { 255 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 256 // Dynamic permissions are not required before Android M. 257 onPermissionsGranted(); 258 return; 259 } 260 261 String[] missingPermissions = getMissingPermissions(); 262 if (missingPermissions.length != 0) { 263 requestPermissions(missingPermissions, PERMISSION_REQUEST); 264 } else { 265 onPermissionsGranted(); 266 } 267 } 268 269 @TargetApi(Build.VERSION_CODES.M) getMissingPermissions()270 private String[] getMissingPermissions() { 271 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { 272 return new String[0]; 273 } 274 275 PackageInfo info; 276 try { 277 info = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_PERMISSIONS); 278 } catch (PackageManager.NameNotFoundException e) { 279 Log.w(TAG, "Failed to retrieve permissions."); 280 return new String[0]; 281 } 282 283 if (info.requestedPermissions == null) { 284 Log.w(TAG, "No requested permissions."); 285 return new String[0]; 286 } 287 288 ArrayList<String> missingPermissions = new ArrayList<>(); 289 for (int i = 0; i < info.requestedPermissions.length; i++) { 290 if ((info.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0) { 291 missingPermissions.add(info.requestedPermissions[i]); 292 } 293 } 294 Log.d(TAG, "Missing permissions: " + missingPermissions); 295 296 return missingPermissions.toArray(new String[missingPermissions.size()]); 297 } 298 299 /** 300 * Get a value from the shared preference or from the intent, if it does not 301 * exist the default is used. 302 */ 303 @Nullable sharedPrefGetString( int attributeId, String intentName, int defaultId, boolean useFromIntent)304 private String sharedPrefGetString( 305 int attributeId, String intentName, int defaultId, boolean useFromIntent) { 306 String defaultValue = getString(defaultId); 307 if (useFromIntent) { 308 String value = getIntent().getStringExtra(intentName); 309 if (value != null) { 310 return value; 311 } 312 return defaultValue; 313 } else { 314 String attributeName = getString(attributeId); 315 return sharedPref.getString(attributeName, defaultValue); 316 } 317 } 318 319 /** 320 * Get a value from the shared preference or from the intent, if it does not 321 * exist the default is used. 322 */ sharedPrefGetBoolean( int attributeId, String intentName, int defaultId, boolean useFromIntent)323 private boolean sharedPrefGetBoolean( 324 int attributeId, String intentName, int defaultId, boolean useFromIntent) { 325 boolean defaultValue = Boolean.parseBoolean(getString(defaultId)); 326 if (useFromIntent) { 327 return getIntent().getBooleanExtra(intentName, defaultValue); 328 } else { 329 String attributeName = getString(attributeId); 330 return sharedPref.getBoolean(attributeName, defaultValue); 331 } 332 } 333 334 /** 335 * Get a value from the shared preference or from the intent, if it does not 336 * exist the default is used. 337 */ sharedPrefGetInteger( int attributeId, String intentName, int defaultId, boolean useFromIntent)338 private int sharedPrefGetInteger( 339 int attributeId, String intentName, int defaultId, boolean useFromIntent) { 340 String defaultString = getString(defaultId); 341 int defaultValue = Integer.parseInt(defaultString); 342 if (useFromIntent) { 343 return getIntent().getIntExtra(intentName, defaultValue); 344 } else { 345 String attributeName = getString(attributeId); 346 String value = sharedPref.getString(attributeName, defaultString); 347 try { 348 return Integer.parseInt(value); 349 } catch (NumberFormatException e) { 350 Log.e(TAG, "Wrong setting for: " + attributeName + ":" + value); 351 return defaultValue; 352 } 353 } 354 } 355 356 @SuppressWarnings("StringSplitter") connectToRoom(String roomId, boolean commandLineRun, boolean loopback, boolean useValuesFromIntent, int runTimeMs)357 private void connectToRoom(String roomId, boolean commandLineRun, boolean loopback, 358 boolean useValuesFromIntent, int runTimeMs) { 359 ConnectActivity.commandLineRun = commandLineRun; 360 361 // roomId is random for loopback. 362 if (loopback) { 363 roomId = Integer.toString((new Random()).nextInt(100000000)); 364 } 365 366 String roomUrl = sharedPref.getString( 367 keyprefRoomServerUrl, getString(R.string.pref_room_server_url_default)); 368 369 // Video call enabled flag. 370 boolean videoCallEnabled = sharedPrefGetBoolean(R.string.pref_videocall_key, 371 CallActivity.EXTRA_VIDEO_CALL, R.string.pref_videocall_default, useValuesFromIntent); 372 373 // Use screencapture option. 374 boolean useScreencapture = sharedPrefGetBoolean(R.string.pref_screencapture_key, 375 CallActivity.EXTRA_SCREENCAPTURE, R.string.pref_screencapture_default, useValuesFromIntent); 376 377 // Use Camera2 option. 378 boolean useCamera2 = sharedPrefGetBoolean(R.string.pref_camera2_key, CallActivity.EXTRA_CAMERA2, 379 R.string.pref_camera2_default, useValuesFromIntent); 380 381 // Get default codecs. 382 String videoCodec = sharedPrefGetString(R.string.pref_videocodec_key, 383 CallActivity.EXTRA_VIDEOCODEC, R.string.pref_videocodec_default, useValuesFromIntent); 384 String audioCodec = sharedPrefGetString(R.string.pref_audiocodec_key, 385 CallActivity.EXTRA_AUDIOCODEC, R.string.pref_audiocodec_default, useValuesFromIntent); 386 387 // Check HW codec flag. 388 boolean hwCodec = sharedPrefGetBoolean(R.string.pref_hwcodec_key, 389 CallActivity.EXTRA_HWCODEC_ENABLED, R.string.pref_hwcodec_default, useValuesFromIntent); 390 391 // Check Capture to texture. 392 boolean captureToTexture = sharedPrefGetBoolean(R.string.pref_capturetotexture_key, 393 CallActivity.EXTRA_CAPTURETOTEXTURE_ENABLED, R.string.pref_capturetotexture_default, 394 useValuesFromIntent); 395 396 // Check FlexFEC. 397 boolean flexfecEnabled = sharedPrefGetBoolean(R.string.pref_flexfec_key, 398 CallActivity.EXTRA_FLEXFEC_ENABLED, R.string.pref_flexfec_default, useValuesFromIntent); 399 400 // Check Disable Audio Processing flag. 401 boolean noAudioProcessing = sharedPrefGetBoolean(R.string.pref_noaudioprocessing_key, 402 CallActivity.EXTRA_NOAUDIOPROCESSING_ENABLED, R.string.pref_noaudioprocessing_default, 403 useValuesFromIntent); 404 405 boolean aecDump = sharedPrefGetBoolean(R.string.pref_aecdump_key, 406 CallActivity.EXTRA_AECDUMP_ENABLED, R.string.pref_aecdump_default, useValuesFromIntent); 407 408 boolean saveInputAudioToFile = 409 sharedPrefGetBoolean(R.string.pref_enable_save_input_audio_to_file_key, 410 CallActivity.EXTRA_SAVE_INPUT_AUDIO_TO_FILE_ENABLED, 411 R.string.pref_enable_save_input_audio_to_file_default, useValuesFromIntent); 412 413 // Check OpenSL ES enabled flag. 414 boolean useOpenSLES = sharedPrefGetBoolean(R.string.pref_opensles_key, 415 CallActivity.EXTRA_OPENSLES_ENABLED, R.string.pref_opensles_default, useValuesFromIntent); 416 417 // Check Disable built-in AEC flag. 418 boolean disableBuiltInAEC = sharedPrefGetBoolean(R.string.pref_disable_built_in_aec_key, 419 CallActivity.EXTRA_DISABLE_BUILT_IN_AEC, R.string.pref_disable_built_in_aec_default, 420 useValuesFromIntent); 421 422 // Check Disable built-in AGC flag. 423 boolean disableBuiltInAGC = sharedPrefGetBoolean(R.string.pref_disable_built_in_agc_key, 424 CallActivity.EXTRA_DISABLE_BUILT_IN_AGC, R.string.pref_disable_built_in_agc_default, 425 useValuesFromIntent); 426 427 // Check Disable built-in NS flag. 428 boolean disableBuiltInNS = sharedPrefGetBoolean(R.string.pref_disable_built_in_ns_key, 429 CallActivity.EXTRA_DISABLE_BUILT_IN_NS, R.string.pref_disable_built_in_ns_default, 430 useValuesFromIntent); 431 432 // Check Disable gain control 433 boolean disableWebRtcAGCAndHPF = sharedPrefGetBoolean( 434 R.string.pref_disable_webrtc_agc_and_hpf_key, CallActivity.EXTRA_DISABLE_WEBRTC_AGC_AND_HPF, 435 R.string.pref_disable_webrtc_agc_and_hpf_key, useValuesFromIntent); 436 437 // Get video resolution from settings. 438 int videoWidth = 0; 439 int videoHeight = 0; 440 if (useValuesFromIntent) { 441 videoWidth = getIntent().getIntExtra(CallActivity.EXTRA_VIDEO_WIDTH, 0); 442 videoHeight = getIntent().getIntExtra(CallActivity.EXTRA_VIDEO_HEIGHT, 0); 443 } 444 if (videoWidth == 0 && videoHeight == 0) { 445 String resolution = 446 sharedPref.getString(keyprefResolution, getString(R.string.pref_resolution_default)); 447 String[] dimensions = resolution.split("[ x]+"); 448 if (dimensions.length == 2) { 449 try { 450 videoWidth = Integer.parseInt(dimensions[0]); 451 videoHeight = Integer.parseInt(dimensions[1]); 452 } catch (NumberFormatException e) { 453 videoWidth = 0; 454 videoHeight = 0; 455 Log.e(TAG, "Wrong video resolution setting: " + resolution); 456 } 457 } 458 } 459 460 // Get camera fps from settings. 461 int cameraFps = 0; 462 if (useValuesFromIntent) { 463 cameraFps = getIntent().getIntExtra(CallActivity.EXTRA_VIDEO_FPS, 0); 464 } 465 if (cameraFps == 0) { 466 String fps = sharedPref.getString(keyprefFps, getString(R.string.pref_fps_default)); 467 String[] fpsValues = fps.split("[ x]+"); 468 if (fpsValues.length == 2) { 469 try { 470 cameraFps = Integer.parseInt(fpsValues[0]); 471 } catch (NumberFormatException e) { 472 cameraFps = 0; 473 Log.e(TAG, "Wrong camera fps setting: " + fps); 474 } 475 } 476 } 477 478 // Check capture quality slider flag. 479 boolean captureQualitySlider = sharedPrefGetBoolean(R.string.pref_capturequalityslider_key, 480 CallActivity.EXTRA_VIDEO_CAPTUREQUALITYSLIDER_ENABLED, 481 R.string.pref_capturequalityslider_default, useValuesFromIntent); 482 483 // Get video and audio start bitrate. 484 int videoStartBitrate = 0; 485 if (useValuesFromIntent) { 486 videoStartBitrate = getIntent().getIntExtra(CallActivity.EXTRA_VIDEO_BITRATE, 0); 487 } 488 if (videoStartBitrate == 0) { 489 String bitrateTypeDefault = getString(R.string.pref_maxvideobitrate_default); 490 String bitrateType = sharedPref.getString(keyprefVideoBitrateType, bitrateTypeDefault); 491 if (!bitrateType.equals(bitrateTypeDefault)) { 492 String bitrateValue = sharedPref.getString( 493 keyprefVideoBitrateValue, getString(R.string.pref_maxvideobitratevalue_default)); 494 videoStartBitrate = Integer.parseInt(bitrateValue); 495 } 496 } 497 498 int audioStartBitrate = 0; 499 if (useValuesFromIntent) { 500 audioStartBitrate = getIntent().getIntExtra(CallActivity.EXTRA_AUDIO_BITRATE, 0); 501 } 502 if (audioStartBitrate == 0) { 503 String bitrateTypeDefault = getString(R.string.pref_startaudiobitrate_default); 504 String bitrateType = sharedPref.getString(keyprefAudioBitrateType, bitrateTypeDefault); 505 if (!bitrateType.equals(bitrateTypeDefault)) { 506 String bitrateValue = sharedPref.getString( 507 keyprefAudioBitrateValue, getString(R.string.pref_startaudiobitratevalue_default)); 508 audioStartBitrate = Integer.parseInt(bitrateValue); 509 } 510 } 511 512 // Check statistics display option. 513 boolean displayHud = sharedPrefGetBoolean(R.string.pref_displayhud_key, 514 CallActivity.EXTRA_DISPLAY_HUD, R.string.pref_displayhud_default, useValuesFromIntent); 515 516 boolean tracing = sharedPrefGetBoolean(R.string.pref_tracing_key, CallActivity.EXTRA_TRACING, 517 R.string.pref_tracing_default, useValuesFromIntent); 518 519 // Check Enable RtcEventLog. 520 boolean rtcEventLogEnabled = sharedPrefGetBoolean(R.string.pref_enable_rtceventlog_key, 521 CallActivity.EXTRA_ENABLE_RTCEVENTLOG, R.string.pref_enable_rtceventlog_default, 522 useValuesFromIntent); 523 524 // Get datachannel options 525 boolean dataChannelEnabled = sharedPrefGetBoolean(R.string.pref_enable_datachannel_key, 526 CallActivity.EXTRA_DATA_CHANNEL_ENABLED, R.string.pref_enable_datachannel_default, 527 useValuesFromIntent); 528 boolean ordered = sharedPrefGetBoolean(R.string.pref_ordered_key, CallActivity.EXTRA_ORDERED, 529 R.string.pref_ordered_default, useValuesFromIntent); 530 boolean negotiated = sharedPrefGetBoolean(R.string.pref_negotiated_key, 531 CallActivity.EXTRA_NEGOTIATED, R.string.pref_negotiated_default, useValuesFromIntent); 532 int maxRetrMs = sharedPrefGetInteger(R.string.pref_max_retransmit_time_ms_key, 533 CallActivity.EXTRA_MAX_RETRANSMITS_MS, R.string.pref_max_retransmit_time_ms_default, 534 useValuesFromIntent); 535 int maxRetr = 536 sharedPrefGetInteger(R.string.pref_max_retransmits_key, CallActivity.EXTRA_MAX_RETRANSMITS, 537 R.string.pref_max_retransmits_default, useValuesFromIntent); 538 int id = sharedPrefGetInteger(R.string.pref_data_id_key, CallActivity.EXTRA_ID, 539 R.string.pref_data_id_default, useValuesFromIntent); 540 String protocol = sharedPrefGetString(R.string.pref_data_protocol_key, 541 CallActivity.EXTRA_PROTOCOL, R.string.pref_data_protocol_default, useValuesFromIntent); 542 543 // Start AppRTCMobile activity. 544 Log.d(TAG, "Connecting to room " + roomId + " at URL " + roomUrl); 545 if (validateUrl(roomUrl)) { 546 Uri uri = Uri.parse(roomUrl); 547 Intent intent = new Intent(this, CallActivity.class); 548 intent.setData(uri); 549 intent.putExtra(CallActivity.EXTRA_ROOMID, roomId); 550 intent.putExtra(CallActivity.EXTRA_LOOPBACK, loopback); 551 intent.putExtra(CallActivity.EXTRA_VIDEO_CALL, videoCallEnabled); 552 intent.putExtra(CallActivity.EXTRA_SCREENCAPTURE, useScreencapture); 553 intent.putExtra(CallActivity.EXTRA_CAMERA2, useCamera2); 554 intent.putExtra(CallActivity.EXTRA_VIDEO_WIDTH, videoWidth); 555 intent.putExtra(CallActivity.EXTRA_VIDEO_HEIGHT, videoHeight); 556 intent.putExtra(CallActivity.EXTRA_VIDEO_FPS, cameraFps); 557 intent.putExtra(CallActivity.EXTRA_VIDEO_CAPTUREQUALITYSLIDER_ENABLED, captureQualitySlider); 558 intent.putExtra(CallActivity.EXTRA_VIDEO_BITRATE, videoStartBitrate); 559 intent.putExtra(CallActivity.EXTRA_VIDEOCODEC, videoCodec); 560 intent.putExtra(CallActivity.EXTRA_HWCODEC_ENABLED, hwCodec); 561 intent.putExtra(CallActivity.EXTRA_CAPTURETOTEXTURE_ENABLED, captureToTexture); 562 intent.putExtra(CallActivity.EXTRA_FLEXFEC_ENABLED, flexfecEnabled); 563 intent.putExtra(CallActivity.EXTRA_NOAUDIOPROCESSING_ENABLED, noAudioProcessing); 564 intent.putExtra(CallActivity.EXTRA_AECDUMP_ENABLED, aecDump); 565 intent.putExtra(CallActivity.EXTRA_SAVE_INPUT_AUDIO_TO_FILE_ENABLED, saveInputAudioToFile); 566 intent.putExtra(CallActivity.EXTRA_OPENSLES_ENABLED, useOpenSLES); 567 intent.putExtra(CallActivity.EXTRA_DISABLE_BUILT_IN_AEC, disableBuiltInAEC); 568 intent.putExtra(CallActivity.EXTRA_DISABLE_BUILT_IN_AGC, disableBuiltInAGC); 569 intent.putExtra(CallActivity.EXTRA_DISABLE_BUILT_IN_NS, disableBuiltInNS); 570 intent.putExtra(CallActivity.EXTRA_DISABLE_WEBRTC_AGC_AND_HPF, disableWebRtcAGCAndHPF); 571 intent.putExtra(CallActivity.EXTRA_AUDIO_BITRATE, audioStartBitrate); 572 intent.putExtra(CallActivity.EXTRA_AUDIOCODEC, audioCodec); 573 intent.putExtra(CallActivity.EXTRA_DISPLAY_HUD, displayHud); 574 intent.putExtra(CallActivity.EXTRA_TRACING, tracing); 575 intent.putExtra(CallActivity.EXTRA_ENABLE_RTCEVENTLOG, rtcEventLogEnabled); 576 intent.putExtra(CallActivity.EXTRA_CMDLINE, commandLineRun); 577 intent.putExtra(CallActivity.EXTRA_RUNTIME, runTimeMs); 578 intent.putExtra(CallActivity.EXTRA_DATA_CHANNEL_ENABLED, dataChannelEnabled); 579 580 if (dataChannelEnabled) { 581 intent.putExtra(CallActivity.EXTRA_ORDERED, ordered); 582 intent.putExtra(CallActivity.EXTRA_MAX_RETRANSMITS_MS, maxRetrMs); 583 intent.putExtra(CallActivity.EXTRA_MAX_RETRANSMITS, maxRetr); 584 intent.putExtra(CallActivity.EXTRA_PROTOCOL, protocol); 585 intent.putExtra(CallActivity.EXTRA_NEGOTIATED, negotiated); 586 intent.putExtra(CallActivity.EXTRA_ID, id); 587 } 588 589 if (useValuesFromIntent) { 590 if (getIntent().hasExtra(CallActivity.EXTRA_VIDEO_FILE_AS_CAMERA)) { 591 String videoFileAsCamera = 592 getIntent().getStringExtra(CallActivity.EXTRA_VIDEO_FILE_AS_CAMERA); 593 intent.putExtra(CallActivity.EXTRA_VIDEO_FILE_AS_CAMERA, videoFileAsCamera); 594 } 595 596 if (getIntent().hasExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE)) { 597 String saveRemoteVideoToFile = 598 getIntent().getStringExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE); 599 intent.putExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE, saveRemoteVideoToFile); 600 } 601 602 if (getIntent().hasExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_WIDTH)) { 603 int videoOutWidth = 604 getIntent().getIntExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_WIDTH, 0); 605 intent.putExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_WIDTH, videoOutWidth); 606 } 607 608 if (getIntent().hasExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_HEIGHT)) { 609 int videoOutHeight = 610 getIntent().getIntExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_HEIGHT, 0); 611 intent.putExtra(CallActivity.EXTRA_SAVE_REMOTE_VIDEO_TO_FILE_HEIGHT, videoOutHeight); 612 } 613 } 614 615 startActivityForResult(intent, CONNECTION_REQUEST); 616 } 617 } 618 validateUrl(String url)619 private boolean validateUrl(String url) { 620 if (URLUtil.isHttpsUrl(url) || URLUtil.isHttpUrl(url)) { 621 return true; 622 } 623 624 new AlertDialog.Builder(this) 625 .setTitle(getText(R.string.invalid_url_title)) 626 .setMessage(getString(R.string.invalid_url_text, url)) 627 .setCancelable(false) 628 .setNeutralButton(R.string.ok, 629 new DialogInterface.OnClickListener() { 630 @Override 631 public void onClick(DialogInterface dialog, int id) { 632 dialog.cancel(); 633 } 634 }) 635 .create() 636 .show(); 637 return false; 638 } 639 640 private final AdapterView.OnItemClickListener roomListClickListener = 641 new AdapterView.OnItemClickListener() { 642 @Override 643 public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { 644 String roomId = ((TextView) view).getText().toString(); 645 connectToRoom(roomId, false, false, false, 0); 646 } 647 }; 648 649 private final OnClickListener addFavoriteListener = new OnClickListener() { 650 @Override 651 public void onClick(View view) { 652 String newRoom = roomEditText.getText().toString(); 653 if (newRoom.length() > 0 && !roomList.contains(newRoom)) { 654 adapter.add(newRoom); 655 adapter.notifyDataSetChanged(); 656 } 657 } 658 }; 659 660 private final OnClickListener connectListener = new OnClickListener() { 661 @Override 662 public void onClick(View view) { 663 connectToRoom(roomEditText.getText().toString(), false, false, false, 0); 664 } 665 }; 666 } 667