Back to project page addlive-android-sdk-tutorials.
The source code is released under:
Copyright (c) 2012 LiveFoundry Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the S...
If you think the Android project addlive-android-sdk-tutorials listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.addlive.tutorials; /*w ww .j a v a 2 s. c om*/ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.Random; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.graphics.Color; import android.util.Log; import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; import com.addlive.platform.*; import com.addlive.service.*; import com.addlive.service.listener.*; public class Tutorial3 extends Activity { /** *=========================================================================== * Constants *=========================================================================== */ private static final long ADL_APP_ID = 1; // TODO set your app ID here. private static final String ADL_API_KEY = "AddLiveSuperSecret"; // TODO set you API key here. private static final String ADL_SCOPE_ID = "ADL_iOS"; // TODO set you scope ID here. private static final String LOG_TAG = "AddLiveTutorial"; /** *=========================================================================== * Properties *=========================================================================== */ // Local userId. private long _userId; // Remote videoSinkId. private String _remoteSinkId; // Remote VideoView object. com.addlive.view.VideoView _view; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tutorial3); // Hiding keyboard. getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); // Setting the local video view. SurfaceView local = (SurfaceView) findViewById(R.id.local_video); local.setZOrderMediaOverlay(true); // Setting the local userId. Random rand = new Random(); _userId = (1 + rand.nextInt(9999)); // Setting the reference to VideoView object. _view = (com.addlive.view.VideoView) findViewById(R.id.remote_video); // Setting view's listeners. initializeActions(); // Framework initialization. initializeAddLive(); } /** *=========================================================================== * UI Actions initialization and handling *=========================================================================== */ private void initializeActions() { // Setting the click listener for the connect button. findViewById(R.id.connect).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { // Calling method to handle the connection. onConnect(); } } ); // Setting the click listener for the disconnect button. findViewById(R.id.disconnect).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { // Calling method to handle the disconnection. onDisconnect(); } } ); } //========================================================================== private void onConnect() { // Showing a message when connecting. TextView status = (TextView) findViewById(R.id.status); status.setText("Connecting..."); // Disabling the connect button. Button connect = (Button) findViewById(R.id.connect); connect.setEnabled(false); Log.d(LOG_TAG, "Connecting to scope: '" + ADL_SCOPE_ID + "'"); // Creating the descriptor to send with the connect call. ConnectionDescriptor desc = genConnDescriptor(); // Responder to handle the connect response. UIThreadResponder<MediaConnection> connectResponder = new UIThreadResponder<MediaConnection>(this) { @Override protected void handleResult(MediaConnection result) { Log.d(LOG_TAG, "Successfully connected to the scope"); // Removing the message when connecting. TextView status = (TextView) findViewById(R.id.status); status.setText(""); // Hiding the connect button. Button connect = (Button) findViewById(R.id.connect); connect.setVisibility(View.GONE); // Showing and enabling the disconnect button. Button disconnect = (Button) findViewById(R.id.disconnect); disconnect.setVisibility(View.VISIBLE); disconnect.setEnabled(true); } @Override protected void handleError(int errCode, String errMessage) { // Setting and showing the error label. Log.e(LOG_TAG, "ERROR: (" + errCode + ") " + errMessage); TextView status = (TextView) findViewById(R.id.status); status.setTextColor(Color.RED); status.setText("ERROR: (" + errCode + ") " + errMessage); // Enabling the connect button again. Button connect = (Button) findViewById(R.id.connect); connect.setEnabled(true); } }; /* getService - Returns a reference to the implementation of the * AddLiveService interface. * * connect - Establishes connection to the streaming server using given * description. This is the most important method of all provided by * the AddLive Service API. */ ADL.getService().connect(connectResponder, desc); } //========================================================================== private void onDisconnect() { // Disabling the disconnect button. Button disconnect = (Button) findViewById(R.id.disconnect); disconnect.setEnabled(false); // Showing a messagewhen disconnecting. TextView status = (TextView) findViewById(R.id.status); status.setText("Disconnecting ..."); // Responder to handle the disconnect response. UIThreadResponder<Void> disconnectResponder = new UIThreadResponder<Void>(this) { @Override protected void handleResult(Void result) { // Removing the message when disconnecting. TextView status = (TextView) findViewById(R.id.status); status.setText(""); // Showing the connect button. Button connect = (Button) findViewById(R.id.connect); connect.setVisibility(View.VISIBLE); connect.setEnabled(true); // Hiding the disconnect button. Button disconnect = (Button) findViewById(R.id.disconnect); disconnect.setVisibility(View.GONE); // Clearing the remote VideoView. _view.stop(); _view.setSinkId(""); } @Override protected void handleError(int errCode, String errMessage) { // Setting and showing the error label. Log.e(LOG_TAG, "ERROR: (" + errCode + ") " + errMessage); TextView status = (TextView) findViewById(R.id.status); status.setTextColor(Color.RED); status.setText("ERROR: (" + errCode + ") " + errMessage); // Enabling the disconnect button again. Button disconnect = (Button) findViewById(R.id.disconnect); disconnect.setEnabled(true); } }; /* getService - Returns a reference to the implementation of the * AddLiveService interface. * * disconnect - Disconnects previously established connection to the * streaming server. */ ADL.getService().disconnect(disconnectResponder, ADL_SCOPE_ID); } /** *=========================================================================== * AddLive Platform initialization *=========================================================================== */ private void initializeAddLive() { // ADL.init listener PlatformInitListener listener = new PlatformInitListener() { @Override public void onInitProgressChanged(InitProgressChangedEvent e) { // Actually not used by the platform for now. Just a placeholder. } @Override public void onInitStateChanged(InitStateChangedEvent e) { if (e.getState() == InitState.INITIALIZED) { // Successfully initialized. onAdlInitialized(); } else { // Unsuccessfully initialized. onAdlInitError(e); } } }; // Describes the options allowing platform initialization. PlatformInitOptions initOptions = new PlatformInitOptions(); String storageDir = Environment.getExternalStorageDirectory().getAbsolutePath(); // Sets the path where platform should look for the native components // of the AddLive SDK. initOptions.setStorageDir(storageDir); // Sets the value of the applicationId property. initOptions.setApplicationId(ADL_APP_ID); Log.d(LOG_TAG, "Initializing the AddLive SDK."); /* Initializes the AddLive ADL. The process is asynchronous and * initialization state changes and progress updates are reported via * the listener provided. */ ADL.init(listener, initOptions, this); } //========================================================================== private void onAdlInitialized() { Log.d(LOG_TAG, "AddLive SDK initialized"); /* getService - Returns a reference to the implementation of the * AddLiveService interface. * * addServiceListener - Registers a AddLive Service listener. * Listener provided here should subclass the provided * AddLiveServiceListener stub and implement required methods. */ ADL.getService().addServiceListener(new ResponderAdapter<Void>(), getListener()); /* * getVideoCaptureDeviceNames - Returns an id of currently selected * video capture device. */ ADL.getService().getVideoCaptureDeviceNames( new UIThreadResponder<List<Device>>(this) { @Override protected void handleResult(List<Device> devices) { // On successful process the devices. onGetVideoCaptureDeviceNames(devices); } @Override protected void handleError(int errCode, String errMessage) { Log.e(LOG_TAG, "Failed to get video capture devices."); } } ); } //========================================================================== private void onAdlInitError(InitStateChangedEvent e) { // Setting and showing the error label. TextView status = (TextView) findViewById(R.id.status); status.setTextColor(Color.RED); String errMessage = "ERROR: (" + e.getErrCode() + ") " + e.getErrMessage(); status.setText(errMessage); Log.e(LOG_TAG, errMessage); } //========================================================================== private void onGetVideoCaptureDeviceNames(List<Device> devicesAvailables) { // Setting the front camera as the local video feeding camera. SurfaceView view = (SurfaceView) findViewById(R.id.local_video); ADL.getService().setVideoCaptureDevice(new ResponderAdapter<Void>(), VideoCaptureDevice.FRONT_CAMERA.getId(), view); /* * startLocalVideo - Starts previewing the local video feed. */ ADL.getService().startLocalVideo(new UIThreadResponder<String>(this) { @Override protected void handleResult(String videoSinkId) { Log.d(LOG_TAG, "Succesfully started local video."); } @Override protected void handleError(int errCode, String errMessage) { Log.e(LOG_TAG, "Failed to start local video."); } }, view); } /** *=========================================================================== * AddLive Service Events handling * Interface allowing implementation of global AddLive Service event handlers. *=========================================================================== */ private AddLiveServiceListener getListener() { return new AddLiveServiceListenerAdapter() { /* * onVideoFrameSizeChanged - Called whenever the video resolution of * any video sink changes. */ @Override public void onVideoFrameSizeChanged(final VideoFrameSizeChangedEvent e) { runOnUiThread(new Runnable() { @Override public void run() { Log.v(LOG_TAG, "videoFrameSizeChanged: " + e.getSinkId() + " -> " + e.getWidth() + "x" + e.getHeight()); // Setting the new resolution to the remote VideoView. _view.resolutionChanged(e.getWidth(), e.getHeight()); } }); } /* * onConnectionLost - Called whenever local user lost a connection * to the AddLive Streaming Server. * (e.g. due to Internet connectivity issues) */ @Override public void onConnectionLost(final ConnectionLostEvent e) { runOnUiThread(new Runnable() { @Override public void run() { Log.d(LOG_TAG, "onConnectionLost Listener triggered"); } }); } /* * onSessionReconnected - Called whenever the AddLive SDK * reestablishes a connection to the AddLive streaming server. */ @Override public void onSessionReconnected(final SessionReconnectedEvent e) { runOnUiThread(new Runnable() { @Override public void run() { Log.d(LOG_TAG, "onSessionReconnected Listener triggered"); } }); } /* * onMediaStreamEvent - Called whenever remote user publishes or * stops publishing media of particular type, inside a scope to * which local user is also connected. */ @Override public void onMediaStreamEvent(final UserStateChangedEvent e) { super.onMediaStreamEvent(e); runOnUiThread(new Runnable() { @Override public void run() { if (e.isVideoPublished()) { // Setting the new remoteVideoSink value. _remoteSinkId = e.getVideoSinkId(); // Setting the remoteVideoSink to the VideoView _view.setSinkId(_remoteSinkId); _view.start(); } else { // Removing the remoteVideoSink to the VideoView _view.stop(); _view.setSinkId(""); } } }); } /* * onUserEvent - Called whenever new remote user joined or * existing participant left a scope to which local user is also * connected. */ @Override public void onUserEvent(final UserStateChangedEvent e) { super.onUserEvent(e); runOnUiThread(new Runnable() { @Override public void run() { Log.d(LOG_TAG, "onAdlUserEvent: " + e.toString()); // If it's a new user connecting. if (e.isConnected()) { Log.i(LOG_TAG, "New user connected: " + e.getUserId()); // Setting the new remoteVideoSink value. _remoteSinkId = e.getVideoSinkId(); // Stopping the previous VideoView if any. _view.stop(); // Setting the remoteVideoSink to the VideoView _view.setSinkId(_remoteSinkId); _view.start(); } else { // Removing the remoteVideoSink to the VideoView _view.stop(); _view.setSinkId(""); } } }); } }; } /** *=========================================================================== * Private helpers *=========================================================================== */ // Generates the ConnectionDescriptor (authentication + video description) private ConnectionDescriptor genConnDescriptor() { ConnectionDescriptor desc = new ConnectionDescriptor(); desc.setAutopublishAudio(true); desc.setAutopublishVideo(true); desc.setScopeId(ADL_SCOPE_ID); // Authentication String salt = "Some random string salt"; long timeNow = System.currentTimeMillis() / 1000; long expires = timeNow + (5 * 60); AuthDetails authDetails = new AuthDetails(); authDetails.setUserId(_userId); authDetails.setSalt(salt); authDetails.setExpires(expires); String signatureBody = String.valueOf(ADL_APP_ID) + ADL_SCOPE_ID + _userId + salt + expires + ADL_API_KEY; MessageDigest digest; String signature = ""; try { digest = MessageDigest.getInstance("SHA-256"); digest.update(signatureBody.getBytes()); signature = bytesToHexString(digest.digest()); } catch (NoSuchAlgorithmException e1) { Log.e(LOG_TAG, "Failed to calculate authentication signature due to " + "missing SHA-256 algorithm."); } authDetails.setSignature(signature); desc.setAuthDetails(authDetails); return desc; } private static String bytesToHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte aByte : bytes) { String hex = Integer.toHexString(0xFF & aByte); if (hex.length() == 1) { sb.append('0'); } sb.append(hex); } return sb.toString(); } }