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;
       }
    
     }
    
  5. 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);
     }
    
  6. 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>
    

Add your SDK license key (required)

  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());
      }
      
  2. Declare some class-level 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);
     }
    
  3. 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) {
    
       }
    
  4. When the SurfaceHolder is created, we start the preview on the Camera instance created in the preview method
  5. 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();
     }
    
  6. 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();
         }
       });
     }
    
  7. 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");
     }
    
  8. 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();
     }
    
  9. When it comes time to stop the broadcast
      public void stop() {
       if(stream != null) {
         stream.stop();
         camera.startPreview();
       }
     }
    
  10. 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 Project

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;
       }
    
     }
    
  5. 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);
     }
    
  6. 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>
    
  7. 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());
      }
      
  8. 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();
         }
       });
     }
    
  9. 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");
     }
    
  10. 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();
      }
    }
    
  11. 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 Subscriber

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:

  • Log into Red5 Pro, and navigate to the Downloads Section.
  • Under the Red5 Pro Streaming SDKs, download the latest streaming SDK for Android.
  • Unzip the streaming-android-sdk-latest.zip file, which contains:
      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
      
  • Replace all of the files and directories listed above with the new ones that you just downloaded.
  • Rebuild your project and launch. When you publish, if you have your device connected to your computer and Android Studio, you should see the new SDK version listed in logcat info output (e.g., Starting R5Pro Client Version 1.0.0.9).

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