Android Streaming SDK

The Streaming SDK provides to ability to both broadcast and subscribe to a live stream containing audio and video.

This short tutorial will introduce you to the Red5 Pro Android Streaming SDK API and instruct you in setting up a basic project in Android Studio to publish and subscribe to a stream on the Red5 Pro Server.

You will need the latest Red5 Pro Android Streaming SDK before you begin.

Download the Red5 Pro Android Streaming SDKs Download the latest
Streaming SDK for Android

Additionally, you will need to use the Mobile SDK License associated with your Red5 Pro Account.


Project Setup

  1. Open Android Studio and Create a New Project
  2. Fill in the appropriate project options and select Tabbed Activity as the template
  3. In the Options dialog, set the Activity Name to StreamingActivity and select Action Bar Tabs for the Navigation Style field
  4. After the project has finished being generated, Unzip the Red5 Pro Android Streaming SDK
  5. Click on Android tab in upper left and select Project
    Select the Android Project
  6. Move the JAR files from the libs folder of the distribution into the libs directory for your Android project
    Select the Android Project
  7. Move the jniLibs folder included in the distribution to the src/main (or equivalent dependending on your Gradle setup) for your Android project
    Select the Android Project
  8. Open the AndroidManifest.xml and add the following 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.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  1.  A FragmentPagerAdapter was autogenerated upon project creation and added to the StreamingActivity as SectionsPagerAdapter. We will modify this implementation in order to support switching between Publisher and Subscriber activities for our streaming application example. Open StreamingActivity and modify SectionsPagerAdapter as such for now:
public class SectionsPagerAdapter extends FragmentPagerAdapter {

  public SectionsPagerAdapter(FragmentManager fm) {
    super(fm);
  }

  @Override
  public Fragment getItem(int position) {
    // getItem is called to instantiate the fragment for the given page.
    // Return a PlaceholderFragment (defined as a static inner class below).
    return PlaceholderFragment.newInstance(position + 1);
  }

  @Override
  public int getCount() {
    return 2;
  }

  @Override
  public CharSequence getPageTitle(int position) {
    Locale l = Locale.getDefault();
    switch (position) {
      case 0:
        return "Publish";
      case 1:
        return "Subscribe";
    }
    return null;
  }
}

Publisher

  1.  Right-click on the app/src/main folder in the Project Explorer and select New > Fragment > Fragment (Blank)
  2.  Name the fragment PublishFragment which will update the layout name to fragment_publish
  3.  Click Finish
  4.  With the PublishFragment file open, remove most of the automated cruft so we have the following
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Button;

import com.red5pro.streaming.R5Connection;
import com.red5pro.streaming.R5Stream;
import com.red5pro.streaming.R5StreamProtocol;
import com.red5pro.streaming.config.R5Configuration;
import com.red5pro.streaming.source.R5Camera;
import com.red5pro.streaming.source.R5Microphone;
import com.red5pro.streaming.R5Stream.RecordType;

public class PublishFragment extends Fragment {

  public static PublishFragment newInstance() {
    PublishFragment fragment = new PublishFragment();
    Bundle args = new Bundle();
    fragment.setArguments(args);
    return fragment;
  }

  public PublishFragment() {
    // Required empty public constructor
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_publish, container, false);
    return v;
  }

}
  1.  Update the getItem method of the SectionsPagerAdapter in StreamingActivity
 @Override
public Fragment getItem(int position) {
  switch(position) {
    case 0:
      return PublishFragment.newInstance();
  }
  // getItem is called to instantiate the fragment for the given page.
  // Return a PlaceholderFragment (defined as a static inner class below).
  return PlaceholderFragment.newInstance(position + 1);
}
  1.  Open the fragment_publish.xml file, change the Layout to RelativeLayout and add a SurfaceView and Button control
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context="com.infrared5.streaming.sample.red5prostreamexample.PublishFragment">

  <SurfaceView
    android:id="@+id/surfaceView"
    android:layout_width="320px"
    android:layout_height="240px"
    android:layout_centerInParent="true"
    android:scaleX="1"
    android:scaleY="1"
    />

  <Button
    android:id="@+id/publishButton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="start"
    android:layout_marginBottom="0dp"
    android:layout_alignParentBottom="true"
    />

</RelativeLayout>
  1.  Define the R5Configuration in the onCreate override that will hold the attributes associated with the stream to broadcast.
    • Change the host attribute to point to the location of your Red5 Pro server.
    • Change the SDK license key to the one provided from your Red5 Pro Account.

public R5Configuration configuration;

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  configuration = new R5Configuration(R5StreamProtocol.RTSP, "localhost",  8554, "live", 1.0f);
  configuration.setLicenseKey("YOUR-SDK-LICENSE-KEY");
  configuration.setBundleID(getActivity().getPackageName());
}
  1.  Declare some class-levek variables related to Camera and Stream and create a new method named preview that will be responsible for setting up a stream to be displayed and broadcast
protected Camera camera;
protected boolean isPublishing = false;
protected R5Stream stream;

private void preview() {
  camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
  SurfaceView surface = (SurfaceView) getActivity().findViewById(R.id.surfaceView);
  surface.getHolder().addCallback(this);
}
  1.  Because we have added the PublishFragment class as a callback for the SurfaceHolder, set the class as an implementation of SurfaceHolder.Callback and add the delegates surfaceCreated, surfaceChanged and surfaceDestroyed
@Override
  public void surfaceCreated(SurfaceHolder surfaceHolder) {
    try {
      camera.setPreviewDisplay(surfaceHolder);
      camera.startPreview();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

  @Override
  public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {

  }

  @Override
  public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

  }
  1.  When the SurfaceHolder is created, we start the preview on the Camera instance created in the preview method
  1.  Since we will show the preview on enter of this fragment on selection in our Tab Activity, add a onResume override and call preview
@Override
public void onResume() {
  super.onResume();
  preview();
}
  1.  Now we will create a delegate for the Button added to the fragment that will invoke start and stop methods. To start, create an onActivityCreated override in PublishFragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
  super.onActivityCreated(savedInstanceState);

  Button publishButton = (Button) getActivity().findViewById(R.id.publishButton);
  publishButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
      onPublishToggle();
    }
  });
}
  1.  Add the onPublishToggle method that is called in the onClick override for the Button
private void onPublishToggle() {
  Button publishButton = (Button) getActivity().findViewById(R.id.publishButton);
  if(isPublishing) {
    stop();
  }
  else {
    start();
  }
  isPublishing = !isPublishing;
  publishButton.setText(isPublishing ? "stop" : "start");
}
  1.  The start and stop methods are responsible for starting and stopping the broadcasting session, respectively. Creating a broadcast session is more involved than stopping one, so we will tackle that first.
public void start() {
  camera.stopPreview();

  stream = new R5Stream(new R5Connection(configuration));
  stream.setView((SurfaceView) getActivity().findViewById(R.id.surfaceView));

  R5Camera r5Camera = new R5Camera(camera, 320, 240);
  R5Microphone r5Microphone = new R5Microphone();

  stream.attachCamera(r5Camera);
  stream.attachMic(r5Microphone);

  stream.publish("red5prostream", RecordType.Live);
  camera.startPreview();
}
  1.  When it comes time to stop the broadcast
 public void stop() {
  if(stream != null) {
    stream.stop();
    camera.startPreview();
  }
}
  1.  To manage moving to and from Subscribe tab we'll add some state management with an onPause override
@Override
public void onPause() {
  super.onPause();
  if(isPublishing) {
    onPublishToggle();
  }
}

If you remember from a previous step, we defined an onResume override that will start the Camera preview on enter of the fragment.

With that, the Publisher tab section is complete to start broadcasting a video stream.

Launching & Viewing

Ensure that you have a Red5 Pro Server running at the location defined in the R5Configuration of PublishFragment and select to build and deploy to a connected Android device. When the application is launched on the device and the Publish tab is selected, you will see the stream from front-facing camera being drawn to the screen - this is currently a preview of what will be broadcst.

  1. Click the UI button and start publishing the stream
  2. Navigate to the live broadcast section of your Red5 Pro Server installation and select the stream by the name provided in the stream.publish() call.

Subscriber

  1.  Right-click on the app/src/main folder in the Project Explorer and select New > Fragment > Fragment (Blank)
  2.  Name the fragment SubscribeFragment which will update the layout name to fragment_subscribe
  3.  Click Finish
  4.  With the SubscribeFragment file open, remove most of the automated cruft so we have the following
public class SubscribeFragment extends Fragment {

  public static SubscribeFragment newInstance() {
    SubscribeFragment fragment = new PublishFragment();
    Bundle args = new Bundle();
    fragment.setArguments(args);
    return fragment;
  }

  public SubscribeFragment() {
    // Required empty public constructor
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                           Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_subscribe, container, false);
    return v;
  }

}
  1.  Update the getItem method of the SectionsPagerAdapter in StreamingActivity to include a return of SuscribeFragment on selection of the second tab
 @Override
public Fragment getItem(int position) {
  switch(position) {
    case 0:
      return PublishFragment.newInstance();
    case 1:
      return SubscribeFragment.newInstance();
  }
  // getItem is called to instantiate the fragment for the given page.
  // Return a PlaceholderFragment (defined as a static inner class below).
  return PlaceholderFragment.newInstance(position + 1);
}
  1.  Open the fragment_subscribe.xml file, change the Layout to RelativeLayout and add a SurfaceView and Button control
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.infrared5.streaming.sample.red5prostreamexample.SubscribeFragment">

    <com.red5pro.streaming.view.R5VideoView
        android:id="@+id/subscribeView"
        android:layout_centerHorizontal="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <Button
        android:id="@+id/subscribeButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="start"
        android:layout_marginBottom="0dp"
        android:layout_alignParentBottom="true"
        />

</RelativeLayout>

</RelativeLayout>
  1.  Define the R5Configuration in the onCreate override that will hold the attributes associated with the stream to consume.
    • Change the host attribute to point to the location of your Red5 Pro server.
    • Change the SDK license key to the one provided from your Red5 Pro Account.
public R5Configuration configuration;

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  configuration = new R5Configuration(R5StreamProtocol.RTSP, "localhost",  8554, "live", 1.0f);
  configuration.setLicenseKey("YOUR-SDK-LICENSE-KEY");
  configuration.setBundleID(getActivity().getPackageName());
}
  1.  Now we will create a delegate for the Button added to the fragment that will invoke start and stop methods. To start, create an onActivityCreated override in SubcribeFragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
  super.onActivityCreated(savedInstanceState);

  Button publishButton = (Button) getActivity().findViewById(R.id.subscribeButton);
  publishButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
      onSubscribeToggle();
    }
  });
}
  1.  Add the onSubscribeToggle method that is called in the onClick override for the Button
private void onSubscribeToggle() {
  Button subscribeButton = (Button) getActivity().findViewById(R.id.subscribeButton);
  if(isSubscribing) {
    stop();
  }
  else {
    start();
  }
  isSubscribing = !isSubscribing;
  subscribeButton.setText(isSubscribing ? "stop" : "start");
}
  1.  The start and stop methods are responsible for starting and stopping the subsciber session, respectively
public void start() {
  R5VideoView videoView = (R5VideoView) getActivity().findViewById(R.id.subscribeView);

  stream = new R5Stream(new R5Connection(configuration));
  videoView.attachStream(stream);
  stream.play("red5prostream");
}

public void stop() {
  if(stream != null) {
    stream.stop();
  }
}
  1.  To manage moving to and from Publish tab we'll add some state management with an onPause override
@Override
public void onPause() {
  super.onPause();
  if(isSubscribing) {
    onSubscribeToggle();
  }
}

With that, the Subscribe tab section is complete to start broadcasting a video stream.

Launching & Viewing

Ensure that you have a Red5 Pro Server running at the location defined in the R5Configuration of SubscribeFragment and select to build and deploy to a connected Android device. When the application is launched on the device and the Subscribe tab is selected, you will see the stream being broadcast (if one started, see step #2).

  1. Click the UI button and start subscribing to the stream
  2. Navigate to the live broadcast section of your Red5 Pro Server installation and select broadcast a new stream using the name provided in stream.play().

Upgrading the SDK in Your Project

To upgrade your project with the latest version of the Red5 Pro Android Streaming SDK:

red5streaming.jar
jniLibs (folder, with the following sub-directories and files:)
  arm64-v8a
    libred5android.so
    libred5streaming.so
  armeabi-v7a
    libred5android.so
    libred5streaming.so
  x86
    libred5android.so
    libred5streaming.so

For example, if you open the Red5 Pro Android App on GitHub you'll find the red5streaming.jar in Red5Pro/lib, and the jniLibs directory under the Red5Pro/src/main directory.

directory


API Documentation

For more in-depth documentation about the structure of the Android Streaming SDK, please visit: Red5 Pro Android Streaming Documentation