Step by Step Tutorial

 1. Create the application project

a. Open Xcode and select the option to create a new project from the File menu.

b. On the template selection dialog, select Single View Application.

c. On the project options dialog, enter values for the Product Name and Organization Identifier such that the Bundle Identifier matches the id that was used to generate your SDK license key.

d. Follow the instructions on the SDK installation page to add the SDK library to the project and configure the project setting accordingly.

a. Open Android Studio and select Start a New Android Studio Project from the Welcome to Android Studio dialog or select New Project from the File / New menu if you already have a project open.

b. On the New Project dialog, select Edit next to the Package Name field and enter the same application package name that was used to generate your SDK license key and press Next.

c. On the Target Android Devices dialog, select Phone and Tablet and select a minimum SDK version of API 19 or higher and press Next.

d. On the Add an Activity dialog, select Empty Activity and press Next.

c. On the Customize the Activity dialog, accept the default values and press Finish.

f. Follow the instructions on the SDK installation page to update the project's build.gradle file and add the SDK library to the project's app\libs folder.


 2. Setup the U/I layout

a. Open Main.storyboard and add a button to the View element.

b. Change the title of the button to Broadcast.

c. Add a referencing outlet property named broadcastButton to the ViewController interface definition in ViewController.m:

@interface ViewController ()

// Referencing outlet for the broadcast button
@property (weak, nonatomic) IBOutlet UIButton *broadcastButton;

@end

c. Connect the newly defined broadcastButton outlet to the View Controller in the storyboard editor.

Update the U/I layout defined in the file activity_main.xml located in the project's app/src/main/res/layout folder to match the definition below to add a view for the camera preview and a button to start and stop the live streaming broadcast.

Change the value of the tools:context property displayed below and replace com.mycompany.myapp with the specific package name for your app's MainActivity class.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:wowza="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.mycompany.myapp.MainActivity">

    <!-- The camera preview display -->
    <com.wowza.gocoder.sdk.api.devices.WZCameraView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/camera_preview"
        wowza:scaleMode="fill"
        wowza:defaultCamera="back"
        wowza:frameSizePreset="frameSize1280x720"/>

    <!-- The broadcast button -->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Broadcast"
        android:id="@+id/broadcast_button"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

Update the definition of the activity element in the AndroidManifest.xml file located in the project's app\src\main folder. to include the android:configChanges property as defined below:

    <activity android:name=".MainActivity"
              android:configChanges="orientation|keyboardHidden|screenSize">

Add a onWindowFocusChanged() method to the MainActivity class to enable Android's immersive full-screen mode.

//
// Enable Android's sticky immersive full-screen mode
//
@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
    if (rootView != null)
        rootView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}

 3. Define app properties

If you didn't do so as part of the installation instructions, add an #import statement for the GoCoder SDK's API header and then add a goCoder property to the ViewController class defined in ViewController.m:

#import <WowzaGoCoderSDK/WowzaGoCoderSDK.h>

@interface ViewController ()

// The top level GoCoder API interface
@property (nonatomic, strong) WowzaGoCoder *goCoder;

// Referencing outlet for the broadcast button
@property (weak, nonatomic) IBOutlet UIButton *broadcastButton;

@end

Add the following member variables to the MainActivity class in MainAcivity.java:

public class MainActivity extends AppCompatActivity {

    // The top level GoCoder API interface
    private WowzaGoCoder goCoder;

    // The GoCoder SDK camera view
    private WZCameraView goCoderCameraView;

    // The GoCoder SDK audio device
    private WZAudioDevice goCoderAudioDevice;

    // The broadcast configuration settings
    private WZBroadcastConfig goCoderBroadcastConfig;

    // Properties needed for Android 6+ permissions handling
    private static final int PERMISSIONS_REQUEST_CODE = 0x1;
    private boolean mPermissionsGranted = true;
    private String[] mRequiredPermissions = new String[] {
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
    };

 4. Initialize the GoCoder SDK

The first step is to register the SDK license key with [WowzaGoCoder registerLicenseKey] and then initialize the SDK itself by calling WowzaGoCoder.init. Add the following to the viewDidLoad method of the ViewController class, replacing the string "GOSK-XXXX-XXXX-XXXX-XXXX-XXXX" with your SDK license key:

// Register the GoCoder SDK license key
NSError *goCoderLicensingError = [WowzaGoCoder registerLicenseKey:@"GOSK-XXXX-XXXX-XXXX-XXXX-XXXX"];
if (goCoderLicensingError != nil) {
    // Log license key registration failure
    NSLog(@"%@", [goCoderLicensingError localizedDescription]);
} else {
    // Initialize the GoCoder SDK
    self.goCoder = [WowzaGoCoder sharedInstance];
}

The first step is to initialize the SDK by calling WowzaGoCoder.init() and supplying the Android application context and license key. Add the code below to the bottom of the onCreate() method in the MainActivity class, replacing the string "GOSK-XXXX-XXXX-XXXX-XXXX-XXXX" with your SDK license key:

// Initialize the GoCoder SDK
goCoder = WowzaGoCoder.init(getApplicationContext(), "GOSK-XXXX-XXXX-XXXX-XXXX-XXXX");

if (goCoder == null) {
    // If initialization failed, retrieve the last error and display it
    WZError goCoderInitError = WowzaGoCoder.getLastError();
    Toast.makeText(this,
            "GoCoder SDK error: " + goCoderInitError.getErrorDescription(),
            Toast.LENGTH_LONG).show();
    return;
}

 5. Check for app permissions

For iOS 10 and above, if you haven't done so as part of the SDK installation instructions, follow the steps below to define the messages displayed to the user when the app requests permission to access the camera and microphone.

a. Select your build target in the project inspector, and select the Info tab.

b. Add a string-valued key with the name "Privacy - Camera Usage Description" to Custom iOS Target Properties and set it's value to "The camera will be used to capture video for live streaming".

c. Add a string-valued key with the name "Privacy - Microphone Usage Description" to Custom iOS Target Properties and set it's value to "The microphone will be used to capture live audio for streaming".

If you haven't done so as part of the SDK installation instructions, add the following permissions to the AndroidManifest.xml file located in the project's app\src\main folder. Place the permission declarations just below the top level <manifest> element:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.cintimedia.foobar">

    <!-- Define the required application permissions -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

Add the onResume() and onRequestPermissionsResult() methods to the MainActivity class with logic for Android 6.0 and above to check that the user has granted the app the necessary permissions it needs to access the camera and microphone.

//
// Called when an activity is brought to the foreground
//
@Override
protected void onResume() {
    super.onResume();

    // If running on Android 6 (Marshmallow) or above, check to see if the necessary permissions
    // have been granted
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        mPermissionsGranted = hasPermissions(this, mRequiredPermissions);
        if (!mPermissionsGranted)
            ActivityCompat.requestPermissions(this, mRequiredPermissions, PERMISSIONS_REQUEST_CODE);
    } else
        mPermissionsGranted = true;

}

//
// Callback invoked in response to a call to ActivityCompat.requestPermissions() to interpret
// the results of the permissions request
//
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    mPermissionsGranted = true;
    switch (requestCode) {
        case PERMISSIONS_REQUEST_CODE: {
            // Check the result of each permission granted
            for(int grantResult : grantResults) {
                if (grantResult != PackageManager.PERMISSION_GRANTED) {
                    mPermissionsGranted = false;
                }
            }
        }
    }
}

//
// Utility method to check the status of a permissions request for an array of permission identifiers
//
private static boolean hasPermissions(Context context, String[] permissions) {
    for(String permission : permissions)
        if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
            return false;

    return true;
}

 6. Setup the camera preview

Add the following code to the bottom of the viewDidLoad method to associate the view defined in the U/I storyboard for the camera preview with the corresponding class property and start the preview display:

if (self.goCoder != nil) {
     // Associate the U/I view with the SDK camera preview
     self.goCoder.cameraView = self.view;

     // Start the camera preview
     [self.goCoder.cameraPreview startPreview];
}

Associate the view defined in the activity's layout with the corresponding goCoderCameraView class member and create an audio input device instance just below the section that initializes the SDK in the onCreate() method. :


// Associate the WZCameraView defined in the U/I layout with the corresponding class member
goCoderCameraView = (WZCameraView) findViewById(R.id.camera_preview);

// Create an audio device instance for capturing and broadcasting audio
goCoderAudioDevice = new WZAudioDevice();

Add the following code to the bottom of the onResume() method, after the permission checking logic, to turn on the camera preview when the application is brought to the foreground:


// Start the camera preview display
if (mPermissionsGranted && goCoderCameraView != null) {
    if (goCoderCameraView.isPreviewPaused())
        goCoderCameraView.onResume();
    else
        goCoderCameraView.startPreview();    
}


 7. Configure the broadcast stream

Add the following to the viewDidLoad method, replacing "live.someserver.net", "1935", "live", and "myStream" with appropriate values for your Wowza Streaming Engine server or Wowza Cloud account (if you are unsure of the settings for your Wowza Cloud account, see this note):

// Get a copy of the active config
WowzaConfig *goCoderBroadcastConfig = self.goCoder.config;

// Set the defaults for 720p video
[goCoderBroadcastConfig loadPreset:WZFrameSizePreset1280x720];

// Set the connection properties for the target Wowza Streaming Engine server or Wowza Cloud account
goCoderBroadcastConfig.hostAddress = @"live.someserver.net";
goCoderBroadcastConfig.portNumber = 1935;
goCoderBroadcastConfig.applicationName = @"live";
goCoderBroadcastConfig.streamName = @"myStream";

// Update the active config
self.goCoder.config = goCoderBroadcastConfig;

Add the code below to the bottom of the onCreate() method, replacing "live.someserver.net", "1935", "live", and "myStream" with the values appropriate for your Wowza Streaming Engine server or Wowza Cloud account (if you are unsure of the settings for your Wowza Cloud account, see this note):


// Create a broadcaster instance
goCoderBroadcaster = new WZBroadcast();

// Create a configuration instance for the broadcaster
goCoderBroadcastConfig = new WZBroadcastConfig(WZMediaConfig.FRAME_SIZE_1920x1080);

// Set the connection properties for the target Wowza Streaming Engine server or Wowza Cloud account
goCoderBroadcastConfig.setHostAddress("live.someserver.net");
goCoderBroadcastConfig.setPortNumber(1935);
goCoderBroadcastConfig.setApplicationName("live");
goCoderBroadcastConfig.setStreamName("myStream");

// Designate the camera preview as the video source
goCoderBroadcastConfig.setVideoBroadcaster(goCoderCameraView);

// Designate the audio device as the audio broadcaster
goCoderBroadcastConfig.setAudioBroadcaster(goCoderAudioDevice);


 9. Add broadcast monitoring callbacks

a. Update the interface definition for the ViewController class to include the WZStatusCallback protocol:

// Implements the WZStatusCallback protocol
@interface ViewController () <WZStatusCallback>

b. Add the methods defined by the WZStatusCallback protocol for monitoring status updates and errors during a live streaming broadcast.


- (void) onWZStatus:(WZStatus *) goCoderStatus {
    // A successful status transition has been reported by the GoCoder SDK
    NSString *statusMessage = nil;

    switch (goCoderStatus.state) {
        case WZStateIdle:
            statusMessage = @"The broadcast is stopped";
            break;

        case WZStateStarting:
            statusMessage = @"Broadcast initialization";
            break;

        case WZStateRunning:
            statusMessage = @"Streaming is active";
            break;

        case WZStateStopping:
            statusMessage = @"Broadcast shutting down";
            break;
    }

    if (statusMessage != nil)
        NSLog(@"Broadcast status: %@", statusMessage);
}

- (void) onWZError:(WZStatus *) goCoderStatus {
    // If an error is reported by the GoCoder SDK, display an alert dialog
    // containing the error details using the U/I thread
    dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertView *alertDialog =
            [[UIAlertView alloc] initWithTitle:@"Streaming Error"
                                  message:goCoderStatus.description
                                 delegate:nil
                        cancelButtonTitle:@"OK"
                        otherButtonTitles:nil];
        [alertDialog show];
    });
}

a. Update the class definition for the primary activity class to include the WZStatusCallback interface:


// Main app activity class
public class MainActivity extends AppCompatActivity
        implements WZStatusCallback {

b. Add the methods defined by the WZStatusCallback interface for monitoring status updates and errors during a live streaming broadcast.

//
// The callback invoked upon changes to the state of the steaming broadcast
//
@Override
public void onWZStatus(final WZStatus goCoderStatus) {
    // A successful status transition has been reported by the GoCoder SDK
    final StringBuffer statusMessage = new StringBuffer("Broadcast status: ");

    switch (goCoderStatus.getState()) {
        case WZState.STARTING:
            statusMessage.append("Broadcast initialization");
            break;

        case WZState.READY:
            statusMessage.append("Ready to begin streaming");
            break;

        case WZState.RUNNING:
            statusMessage.append("Streaming is active");
            break;

        case WZState.STOPPING:
            statusMessage.append("Broadcast shutting down");
            break;

        case WZState.IDLE:
            statusMessage.append("The broadcast is stopped");
            break;

        default:
            return;
    }

    // Display the status message using the U/I thread
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(MainActivity.this, statusMessage, Toast.LENGTH_LONG).show();
        }
    });
}

//
// The callback invoked when an error occurs during a broadcast
//
@Override
public void onWZError(final WZStatus goCoderStatus) {
    // If an error is reported by the GoCoder SDK, display a message
    // containing the error details using the U/I thread
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(MainActivity.this,
                    "Streaming error: " + goCoderStatus.getLastError().getErrorDescription(),
                    Toast.LENGTH_LONG).show();
        }
    });
}


 9. Start and stop streaming

Add an event handler method to the ViewController class to be invoked when the broadcast button is pressed:

- (IBAction)broadcastButtonTapped:(UIButton *)button
{
    // Ensure the minimum set of configuration settings have been specified necessary to
    // initiate a broadcast streaming session
    NSError *configValidationError = [self.goCoder.config validateForBroadcast];

    if (configValidationError != nil) {
        UIAlertView *alertDialog =
            [[UIAlertView alloc] initWithTitle:@"Incomplete Streaming Settings"
                        message: self.goCoder.status.description
                        delegate:nil
                        cancelButtonTitle:@"OK"
                        otherButtonTitles:nil];
        [alertDialog show];
    } else if (self.goCoder.status.state != WZStateRunning) {
        // Start streaming
        [self.goCoder startStreaming:self];
    }
    else {
        // Stop the broadcast that is currently running
        [self.goCoder endStreaming:self];
    }    
}

Add the code below to the bottom of the viewDidLoad method to associate the broadcastButtonTapped event handler with the broadcast button:

[self.broadcastButton addTarget:self action:@selector(broadcastButtonTapped:)
    forControlEvents:UIControlEventTouchUpInside];

Update the definition for the MainActivity class to include the View.OnClickListener interface:


// Main app activity class
public class MainActivity extends AppCompatActivity
        implements  WZStatusCallback, View.OnClickListener {

Add an onClick() event handler to the MainActivity class to be invoked when the broadcast button is pressed:

//
// The callback invoked when the broadcast button is pressed
//
@Override
public void onClick(View view) {
    // return if the user hasn't granted the app the necessary permissions
    if (!mPermissionsGranted) return;

    // Ensure the minimum set of configuration settings have been specified necessary to
    // initiate a broadcast streaming session
    WZStreamingError configValidationError = goCoderBroadcastConfig.validateForBroadcast();

    if (configValidationError != null) {
        Toast.makeText(this, configValidationError.getErrorDescription(), Toast.LENGTH_LONG).show();
    } else if (goCoderBroadcaster.getStatus().isRunning()) {
        // Stop the broadcast that is currently running
        goCoderBroadcaster.endBroadcast(this);
    } else {
        // Start streaming
        goCoderBroadcaster.startBroadcast(goCoderBroadcastConfig, this);
    }
}

Add the code below to the bottom of the onCreate() method to associate the onClick() event handler with the broadcast button defined in the U/I layout:


// Associate the onClick() method as the callback for the broadcast button's click event
Button broadcastButton = (Button) findViewById(R.id.broadcast_button);
broadcastButton.setOnClickListener(this);


 10. Build and deploy

At this stage you are ready to build and deploy your application. Choose Run from the Xcode Product menu.

The completed code for the ViewController class is displayed below:


#import "ViewController.h"
#import <WowzaGoCoderSDK/WowzaGoCoderSDK.h>

@interface ViewController () <WZStatusCallback>

// The top level GoCoder API interface
@property (nonatomic, strong) WowzaGoCoder *goCoder;

// Referencing outlet for the broadcast button
@property (weak, nonatomic) IBOutlet UIButton *broadcastButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // Register the GoCoder SDK license key
    NSError *goCoderLicensingError = [WowzaGoCoder registerLicenseKey:@"GOSK-8743-0103-A68E-7B1B-BD18"];
    if (goCoderLicensingError != nil) {
        // Log license key registration failure
        NSLog(@"%@", [goCoderLicensingError localizedDescription]);
    } else {
        // Initialize the GoCoder SDK
        self.goCoder = [WowzaGoCoder sharedInstance];
    }

    if (self.goCoder != nil) {
        // Associate the U/I view with the SDK camera preview
        self.goCoder.cameraView = self.view;

        // Start the camera preview
        [self.goCoder.cameraPreview startPreview];
    }

    // Get a copy of the active config
    WowzaConfig *goCoderBroadcastConfig = self.goCoder.config;

    // Set the defaults for 720p video
    [goCoderBroadcastConfig loadPreset:WZFrameSizePreset1280x720];

    // Set the connection properties for the target Wowza Streaming Engine server or Wowza Cloud account
    goCoderBroadcastConfig.hostAddress = @"live.someserver.net";
    goCoderBroadcastConfig.portNumber = 1935;
    goCoderBroadcastConfig.applicationName = @"live";
    goCoderBroadcastConfig.streamName = @"myStream";

    // Update the active config
    self.goCoder.config = goCoderBroadcastConfig;

    [self.broadcastButton addTarget:self action:@selector(broadcastButtonTapped:)
                   forControlEvents:UIControlEventTouchUpInside];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) onWZStatus:(WZStatus *) goCoderStatus {
    // A successful status transition has been reported by the GoCoder SDK
    NSString *statusMessage = nil;

    switch (goCoderStatus.state) {
        case WZStateIdle:
            statusMessage = @"The broadcast is stopped";
            break;

        case WZStateStarting:
            statusMessage = @"Broadcast initialization";
            break;

        case WZStateRunning:
            statusMessage = @"Streaming is active";
            break;

        case WZStateStopping:
            statusMessage = @"Broadcast shutting down";
            break;
    }

    if (statusMessage != nil)
        NSLog(@"Broadcast status: %@", statusMessage);
}

- (void) onWZError:(WZStatus *) goCoderStatus {
    // If an error is reported by the GoCoder SDK, display an alert dialog
    // containing the error details using the U/I thread
    dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertView *alertDialog =
        [[UIAlertView alloc] initWithTitle:@"Streaming Error"
                                   message:goCoderStatus.description
                                  delegate:nil
                         cancelButtonTitle:@"OK"
                         otherButtonTitles:nil];
        [alertDialog show];
    });
}

- (IBAction)broadcastButtonTapped:(UIButton *)button
{
    // Ensure the minimum set of configuration settings have been specified necessary to
    // initiate a broadcast streaming session
    NSError *configValidationError = [self.goCoder.config validateForBroadcast];

    if (configValidationError != nil) {
        UIAlertView *alertDialog =
        [[UIAlertView alloc] initWithTitle:@"Incomplete Streaming Settings"
                                   message: self.goCoder.status.description
                                  delegate:nil
                         cancelButtonTitle:@"OK"
                         otherButtonTitles:nil];
        [alertDialog show];
    } else if (self.goCoder.status.state != WZStateRunning) {
        // Start streaming
        [self.goCoder startStreaming:self];
    }
    else {
        // Stop the broadcast that is currently running
        [self.goCoder endStreaming:self];
    }    
}

@end

At this stage you are ready to build and deploy your application. Choose Run or Debug from the Android Studio Run menu and select a device for deployment.

The completed code for the MainActivity class is displayed below:

public class MainActivity extends AppCompatActivity
        implements WZStatusCallback, View.OnClickListener {

    // The top level GoCoder API interface
    private WowzaGoCoder goCoder;

    // The GoCoder SDK camera view
    private WZCameraView goCoderCameraView;

    // The GoCoder SDK audio device
    private WZAudioDevice goCoderAudioDevice;

    // The GoCoder SDK broadcaster
    private WZBroadcast goCoderBroadcaster;

    // The broadcast configuration settings
    private WZBroadcastConfig goCoderBroadcastConfig;

    // Properties needed for Android 6+ permissions handling
    private static final int PERMISSIONS_REQUEST_CODE = 0x1;
    private boolean mPermissionsGranted = true;
    private String[] mRequiredPermissions = new String[] {
            Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize the GoCoder SDK
        goCoder = WowzaGoCoder.init(getApplicationContext(), "GOSK-8743-0103-A68E-7B1B-BD18");

        if (goCoder == null) {
            // If initialization failed, retrieve the last error and display it
            WZError goCoderInitError = WowzaGoCoder.getLastError();
            Toast.makeText(this,
                    "GoCoder SDK error: " + goCoderInitError.getErrorDescription(),
                    Toast.LENGTH_LONG).show();
            return;
        }

        // Associate the WZCameraView defined in the U/I layout with the corresponding class member
        goCoderCameraView = (WZCameraView) findViewById(R.id.camera_preview);

        // Create an audio device instance for capturing and broadcasting audio
        goCoderAudioDevice = new WZAudioDevice();

        // Create a broadcaster instance
        goCoderBroadcaster = new WZBroadcast();

        // Create a configuration instance for the broadcaster
        goCoderBroadcastConfig = new WZBroadcastConfig(WZMediaConfig.FRAME_SIZE_1920x1080);

        // Set the connection properties for the target Wowza Streaming Engine server or Wowza Cloud account
        goCoderBroadcastConfig.setHostAddress("live.someserver.net");
        goCoderBroadcastConfig.setPortNumber(1935);
        goCoderBroadcastConfig.setApplicationName("live");
        goCoderBroadcastConfig.setStreamName("myStream");

        // Designate the camera preview as the video broadcaster
        goCoderBroadcastConfig.setVideoBroadcaster(goCoderCameraView);

        // Designate the audio device as the audio broadcaster
        goCoderBroadcastConfig.setAudioBroadcaster(goCoderAudioDevice);

        // Associate the onClick() method as the callback for the broadcast button's click event
        Button broadcastButton = (Button) findViewById(R.id.broadcast_button);
        broadcastButton.setOnClickListener(this);
    }

    //
    // Called when an activity is brought to the foreground
    //
    @Override
    protected void onResume() {
        super.onResume();

        // If running on Android 6 (Marshmallow) or above, check to see if the necessary permissions
        // have been granted
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mPermissionsGranted = hasPermissions(this, mRequiredPermissions);
            if (!mPermissionsGranted)
                ActivityCompat.requestPermissions(this, mRequiredPermissions, PERMISSIONS_REQUEST_CODE);
        } else
            mPermissionsGranted = true;

        // Start the camera preview display
        if (mPermissionsGranted && goCoderCameraView != null) {
            if (goCoderCameraView.isPreviewPaused())
                goCoderCameraView.onResume();
            else
                goCoderCameraView.startPreview();
        }

    }

    //
    // Callback invoked in response to a call to ActivityCompat.requestPermissions() to interpret
    // the results of the permissions request
    //
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        mPermissionsGranted = true;
        switch (requestCode) {
            case PERMISSIONS_REQUEST_CODE: {
                // Check the result of each permission granted
                for(int grantResult : grantResults) {
                    if (grantResult != PackageManager.PERMISSION_GRANTED) {
                        mPermissionsGranted = false;
                    }
                }
            }
        }
    }

    //
    // Utility method to check the status of a permissions request for an array of permission identifiers
    //
    private static boolean hasPermissions(Context context, String[] permissions) {
        for(String permission : permissions)
            if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
                return false;

        return true;
    }

    //
    // The callback invoked when the broadcast button is pressed
    //
    @Override
    public void onClick(View view) {
        // return if the user hasn't granted the app the necessary permissions
        if (!mPermissionsGranted) return;

        // Ensure the minimum set of configuration settings have been specified necessary to
        // initiate a broadcast streaming session
        WZStreamingError configValidationError = goCoderBroadcastConfig.validateForBroadcast();

        if (configValidationError != null) {
            Toast.makeText(this, configValidationError.getErrorDescription(), Toast.LENGTH_LONG).show();
        } else if (goCoderBroadcaster.getStatus().isRunning()) {
            // Stop the broadcast that is currently running
            goCoderBroadcaster.endBroadcast(this);
        } else {
            // Start streaming
            goCoderBroadcaster.startBroadcast(goCoderBroadcastConfig, this);
        }
    }

    //
    // The callback invoked upon changes to the state of the steaming broadcast
    //
    @Override
    public void onWZStatus(final WZStatus goCoderStatus) {
        // A successful status transition has been reported by the GoCoder SDK
        final StringBuffer statusMessage = new StringBuffer("Broadcast status: ");

        switch (goCoderStatus.getState()) {
            case WZState.STARTING:
                statusMessage.append("Broadcast initialization");
                break;

            case WZState.READY:
                statusMessage.append("Ready to begin streaming");
                break;

            case WZState.RUNNING:
                statusMessage.append("Streaming is active");
                break;

            case WZState.STOPPING:
                statusMessage.append("Broadcast shutting down");
                break;

            case WZState.IDLE:
                statusMessage.append("The broadcast is stopped");
                break;

            default:
                return;
        }

        // Display the status message using the U/I thread
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, statusMessage, Toast.LENGTH_LONG).show();
            }
        });
    }

    //
    // The callback invoked when an error occurs during a broadcast
    //
    @Override
    public void onWZError(final WZStatus goCoderStatus) {
        // If an error is reported by the GoCoder SDK, display a message
        // containing the error details using the U/I thread
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,
                        "Streaming error: " + goCoderStatus.getLastError().getErrorDescription(),
                        Toast.LENGTH_LONG).show();
            }
        });
    }

     //
     // Enable Android's sticky immersive full-screen mode
     //
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

        View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
        if (rootView != null)
            rootView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    }

}

Where To Go Next

Installation Information Information about installing the GoCoder SDK and using it within your mobile app projects
Developer Guides In depth information for common GoCoder SDK-related tasks and topics
API Reference Detailed GoCoder SDK API reference docs for each platform
FAQ Common GoCoder SDK-related questions
Release Notes Information related to each of the GoCoder SDK releases