Android AppRTCDemo improvements:
- Add a room list to ConnectActivity with buttons to add/remove rooms. - Add loopback call button. - Add option to toggle full screen / letterbox video. - Add camera fps settings. - Fix device to landscape orientation for HD video until issue 3936 will be fixed. - Fix a few crashes by avoiding calling peer connection and GAE signaling function while connection is closing. - Better handling GAE channel error - catch channel exceptions and display dialog with error messages. BUG=3939, 3935 R=kjellander@webrtc.org, pthatcher@webrtc.org, tkchin@webrtc.org Review URL: https://webrtc-codereview.appspot.com/26979004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@7601 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
		| @@ -32,6 +32,7 @@ import android.app.AlertDialog; | ||||
| import android.app.Fragment; | ||||
| import android.content.DialogInterface; | ||||
| import android.content.Intent; | ||||
| import android.content.pm.ActivityInfo; | ||||
| import android.graphics.Color; | ||||
| import android.media.AudioManager; | ||||
| import android.net.Uri; | ||||
| @@ -45,7 +46,6 @@ 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; | ||||
| @@ -58,6 +58,7 @@ import org.webrtc.StatsObserver; | ||||
| import org.webrtc.StatsReport; | ||||
| import org.webrtc.VideoRenderer; | ||||
| import org.webrtc.VideoRendererGui; | ||||
| import org.webrtc.VideoRendererGui.ScalingType; | ||||
|  | ||||
| /** | ||||
|  * Main Activity of the AppRTCDemo Android app demonstrating interoperability | ||||
| @@ -76,13 +77,14 @@ public class AppRTCDemoActivity extends Activity | ||||
|   private GLSurfaceView videoView; | ||||
|   private VideoRenderer.Callbacks localRender; | ||||
|   private VideoRenderer.Callbacks remoteRender; | ||||
|   private ScalingType scalingType; | ||||
|   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 }; | ||||
|   private ImageButton videoScalingButton; | ||||
|   private boolean iceConnected; | ||||
|  | ||||
|   @Override | ||||
|   public void onCreate(Bundle savedInstanceState) { | ||||
| @@ -102,6 +104,7 @@ public class AppRTCDemoActivity extends Activity | ||||
|  | ||||
|     Thread.setDefaultUncaughtExceptionHandler( | ||||
|         new UnhandledExceptionHandler(this)); | ||||
|     iceConnected = false; | ||||
|  | ||||
|     rootView = findViewById(android.R.id.content); | ||||
|     menuBar = findViewById(R.id.menubar_fragment); | ||||
| @@ -109,10 +112,9 @@ public class AppRTCDemoActivity extends Activity | ||||
|     videoView = (GLSurfaceView) findViewById(R.id.glview); | ||||
|  | ||||
|     VideoRendererGui.setView(videoView); | ||||
|     remoteRender = VideoRendererGui.create(0, 0, 100, 100, | ||||
|         VideoRendererGui.ScalingType.SCALE_ASPECT_FILL); | ||||
|     localRender = VideoRendererGui.create(0, 0, 100, 100, | ||||
|         VideoRendererGui.ScalingType.SCALE_ASPECT_FILL); | ||||
|     scalingType = ScalingType.SCALE_ASPECT_FILL; | ||||
|     remoteRender = VideoRendererGui.create(0, 0, 100, 100, scalingType); | ||||
|     localRender = VideoRendererGui.create(0, 0, 100, 100, scalingType); | ||||
|  | ||||
|     videoView.setOnClickListener( | ||||
|         new View.OnClickListener() { | ||||
| @@ -143,7 +145,9 @@ public class AppRTCDemoActivity extends Activity | ||||
|         new View.OnClickListener() { | ||||
|           @Override | ||||
|           public void onClick(View view) { | ||||
|             pc.switchCamera(); | ||||
|             if (pc != null) { | ||||
|               pc.switchCamera(); | ||||
|             } | ||||
|           } | ||||
|         }); | ||||
|  | ||||
| @@ -157,6 +161,24 @@ public class AppRTCDemoActivity extends Activity | ||||
|           } | ||||
|         }); | ||||
|  | ||||
|     videoScalingButton = (ImageButton) findViewById(R.id.button_scaling_mode); | ||||
|     videoScalingButton.setOnClickListener( | ||||
|         new View.OnClickListener() { | ||||
|           @Override | ||||
|           public void onClick(View view) { | ||||
|             if (scalingType == ScalingType.SCALE_ASPECT_FILL) { | ||||
|               videoScalingButton.setBackgroundResource( | ||||
|                   R.drawable.ic_action_full_screen); | ||||
|               scalingType = ScalingType.SCALE_ASPECT_FIT; | ||||
|             } else { | ||||
|               videoScalingButton.setBackgroundResource( | ||||
|                   R.drawable.ic_action_return_from_full_screen); | ||||
|               scalingType = ScalingType.SCALE_ASPECT_FILL; | ||||
|             } | ||||
|             updateVideoView(); | ||||
|           } | ||||
|         }); | ||||
|  | ||||
|     hudView = new TextView(this); | ||||
|     hudView.setTextColor(Color.BLACK); | ||||
|     hudView.setBackgroundColor(Color.WHITE); | ||||
| @@ -184,7 +206,11 @@ public class AppRTCDemoActivity extends Activity | ||||
|           (loopback != null && loopback.equals("loopback"))) { | ||||
|         logAndToast(getString(R.string.connecting_to, url)); | ||||
|         appRtcClient.connectToRoom(url.toString()); | ||||
|         roomName.setText(room); | ||||
|         if (room != null && !room.equals("")) { | ||||
|           roomName.setText(room); | ||||
|         } else { | ||||
|           roomName.setText("loopback"); | ||||
|         } | ||||
|       } else { | ||||
|         logAndToast("Empty or missing room name!"); | ||||
|         finish(); | ||||
| @@ -230,6 +256,16 @@ public class AppRTCDemoActivity extends Activity | ||||
|     super.onDestroy(); | ||||
|   } | ||||
|  | ||||
|   private void updateVideoView() { | ||||
|     VideoRendererGui.update(remoteRender, 0, 0, 100, 100, scalingType); | ||||
|     if (iceConnected) { | ||||
|       VideoRendererGui.update(localRender, 70, 70, 28, 28, | ||||
|           ScalingType.SCALE_ASPECT_FIT); | ||||
|     } else { | ||||
|       VideoRendererGui.update(localRender, 0, 0, 100, 100, scalingType); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // Update the heads-up display with information from |reports|. | ||||
|   private void updateHUD(StatsReport[] reports) { | ||||
|     StringBuilder builder = new StringBuilder(); | ||||
| @@ -279,21 +315,28 @@ public class AppRTCDemoActivity extends Activity | ||||
|  | ||||
|   // Disconnect from remote resources, dispose of local resources, and exit. | ||||
|   private void disconnect() { | ||||
|     synchronized (quit[0]) { | ||||
|       if (quit[0]) { | ||||
|         return; | ||||
|       } | ||||
|       quit[0] = true; | ||||
|       if (pc != null) { | ||||
|         pc.close(); | ||||
|         pc = null; | ||||
|       } | ||||
|       if (appRtcClient != null) { | ||||
|         appRtcClient.disconnect(); | ||||
|         appRtcClient = null; | ||||
|       } | ||||
|       finish(); | ||||
|     if (appRtcClient != null) { | ||||
|       appRtcClient.disconnect(); | ||||
|       appRtcClient = null; | ||||
|     } | ||||
|     if (pc != null) { | ||||
|       pc.close(); | ||||
|       pc = null; | ||||
|     } | ||||
|     finish(); | ||||
|   } | ||||
|  | ||||
|   private void disconnectWithMessage(String errorMessage) { | ||||
|     new AlertDialog.Builder(this) | ||||
|     .setTitle(getText(R.string.channel_error_title)) | ||||
|     .setMessage(errorMessage) | ||||
|     .setCancelable(false) | ||||
|     .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() { | ||||
|         public void onClick(DialogInterface dialog, int id) { | ||||
|           dialog.cancel(); | ||||
|           disconnect(); | ||||
|         } | ||||
|       }).create().show(); | ||||
|   } | ||||
|  | ||||
|   // Poor-man's assert(): die with |msg| unless |condition| is true. | ||||
| @@ -324,39 +367,41 @@ public class AppRTCDemoActivity extends Activity | ||||
|     logAndToast("Creating peer connection..."); | ||||
|     pc = new PeerConnectionClient( | ||||
|         this, localRender, remoteRender, appRtcParameters, this); | ||||
|     if (pc.isHDVideo()) { | ||||
|       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); | ||||
|     } else { | ||||
|       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); | ||||
|     } | ||||
|  | ||||
|     { | ||||
|       final PeerConnectionClient finalPC = pc; | ||||
|       final Runnable repeatedStatsLogger = new Runnable() { | ||||
|           public void run() { | ||||
|             synchronized (quit[0]) { | ||||
|               if (quit[0]) { | ||||
|                 return; | ||||
|               } | ||||
|               final Runnable runnableThis = this; | ||||
|               if (hudView.getVisibility() == View.INVISIBLE) { | ||||
|                 videoView.postDelayed(runnableThis, 1000); | ||||
|                 return; | ||||
|               } | ||||
|               boolean success = finalPC.getStats(new StatsObserver() { | ||||
|                   public void onComplete(final StatsReport[] reports) { | ||||
|                     runOnUiThread(new Runnable() { | ||||
|                         public void run() { | ||||
|                           updateHUD(reports); | ||||
|                         } | ||||
|                       }); | ||||
|                     for (StatsReport report : reports) { | ||||
|                       Log.d(TAG, "Stats: " + report.toString()); | ||||
|                     } | ||||
|                     videoView.postDelayed(runnableThis, 1000); | ||||
|         public void run() { | ||||
|             if (pc == null) { | ||||
|               return; | ||||
|             } | ||||
|             final Runnable runnableThis = this; | ||||
|             if (hudView.getVisibility() == View.INVISIBLE) { | ||||
|               videoView.postDelayed(runnableThis, 1000); | ||||
|               return; | ||||
|             } | ||||
|             boolean success = pc.getStats(new StatsObserver() { | ||||
|                 public void onComplete(final StatsReport[] reports) { | ||||
|                   runOnUiThread(new Runnable() { | ||||
|                       public void run() { | ||||
|                         updateHUD(reports); | ||||
|                       } | ||||
|                     }); | ||||
|                   for (StatsReport report : reports) { | ||||
|                     Log.d(TAG, "Stats: " + report.toString()); | ||||
|                   } | ||||
|                 }, null); | ||||
|               if (!success) { | ||||
|                 throw new RuntimeException("getStats() return false!"); | ||||
|               } | ||||
|                   videoView.postDelayed(runnableThis, 1000); | ||||
|                 } | ||||
|               }, null); | ||||
|             if (!success) { | ||||
|               throw new RuntimeException("getStats() return false!"); | ||||
|             } | ||||
|           } | ||||
|         }; | ||||
|       }; | ||||
|       videoView.postDelayed(repeatedStatsLogger, 1000); | ||||
|     } | ||||
|  | ||||
| @@ -365,6 +410,9 @@ public class AppRTCDemoActivity extends Activity | ||||
|  | ||||
|   @Override | ||||
|   public void onChannelOpen() { | ||||
|     if (pc == null) { | ||||
|       return; | ||||
|     } | ||||
|     if (appRtcParameters.initiator) { | ||||
|       logAndToast("Creating OFFER..."); | ||||
|       // Create offer. Offer SDP will be sent to answering client in | ||||
| @@ -375,6 +423,9 @@ public class AppRTCDemoActivity extends Activity | ||||
|  | ||||
|   @Override | ||||
|   public void onRemoteDescription(final SessionDescription sdp) { | ||||
|     if (pc == null) { | ||||
|       return; | ||||
|     } | ||||
|     logAndToast("Received remote " + sdp.type + " ..."); | ||||
|     pc.setRemoteDescription(sdp); | ||||
|     if (!appRtcParameters.initiator) { | ||||
| @@ -387,7 +438,9 @@ public class AppRTCDemoActivity extends Activity | ||||
|  | ||||
|   @Override | ||||
|   public void onRemoteIceCandidate(final IceCandidate candidate) { | ||||
|     pc.addRemoteIceCandidate(candidate); | ||||
|     if (pc != null) { | ||||
|       pc.addRemoteIceCandidate(candidate); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
| @@ -398,8 +451,7 @@ public class AppRTCDemoActivity extends Activity | ||||
|  | ||||
|   @Override | ||||
|   public void onChannelError(int code, String description) { | ||||
|     logAndToast("Channel error: " + code + ". " + description); | ||||
|     disconnect(); | ||||
|     disconnectWithMessage(description); | ||||
|   } | ||||
|  | ||||
|   // -----Implementation of PeerConnectionClient.PeerConnectionEvents.--------- | ||||
| @@ -407,19 +459,35 @@ public class AppRTCDemoActivity extends Activity | ||||
|   // All callbacks are invoked from UI thread. | ||||
|   @Override | ||||
|   public void onLocalDescription(final SessionDescription sdp) { | ||||
|     logAndToast("Sending " + sdp.type + " ..."); | ||||
|     appRtcClient.sendLocalDescription(sdp); | ||||
|     if (appRtcClient != null) { | ||||
|       logAndToast("Sending " + sdp.type + " ..."); | ||||
|       appRtcClient.sendLocalDescription(sdp); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void onIceCandidate(final IceCandidate candidate) { | ||||
|     appRtcClient.sendLocalIceCandidate(candidate); | ||||
|     if (appRtcClient != null) { | ||||
|       appRtcClient.sendLocalIceCandidate(candidate); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void onIceConnected() { | ||||
|     logAndToast("ICE connected"); | ||||
|     VideoRendererGui.update(localRender, 70, 70, 28, 28, | ||||
|         VideoRendererGui.ScalingType.SCALE_ASPECT_FIT); | ||||
|     iceConnected = true; | ||||
|     updateVideoView(); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void onIceDisconnected() { | ||||
|     logAndToast("ICE disconnected"); | ||||
|     disconnect(); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void onPeerConnectionError(String description) { | ||||
|     disconnectWithMessage(description); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 glaznev@webrtc.org
					glaznev@webrtc.org