<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Meher</title>
    <description>The latest articles on DEV Community by Meher (@meherdeep).</description>
    <link>https://dev.to/meherdeep</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F657683%2F69b9a785-1f2b-4325-bc99-afab698dce31.jpeg</url>
      <title>DEV Community: Meher</title>
      <link>https://dev.to/meherdeep</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/meherdeep"/>
    <language>en</language>
    <item>
      <title>Building a Scalable UI for Your Flutter Application Using Agora</title>
      <dc:creator>Meher</dc:creator>
      <pubDate>Tue, 12 Oct 2021 15:48:13 +0000</pubDate>
      <link>https://dev.to/meherdeep/building-a-scalable-ui-for-your-flutter-application-using-agora-52pf</link>
      <guid>https://dev.to/meherdeep/building-a-scalable-ui-for-your-flutter-application-using-agora-52pf</guid>
      <description>&lt;p&gt;One of the biggest challenges facing any developer is building applications that can scale. With a video-conferencing application using Agora, the main scaling issue is the bandwidth of your local device, especially if there are many incoming video streams. And as the number of participants rises, it becomes increasingly difficult to make sure that your application can keep up.&lt;br&gt;
In this tutorial, you will see how to use Agora to build an application that can scale to up to 17 users by optimizing the bandwidth usage of the incoming video streams.&lt;/p&gt;
&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;An Agora developer account (see &lt;a href="https://www.agora.io/en/blog/how-to-get-started-with-agora/"&gt;How to Get Started with Agora&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Flutter SDK&lt;/li&gt;
&lt;li&gt;Editor of your choice &lt;/li&gt;
&lt;li&gt;Android or iOS device for testing &lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In your project directory, open a terminal window and create a Flutter project by running this command:&lt;br&gt;
&lt;code&gt;flutter create agora_scalable_ui&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the newly created project in the editor of your choice.&lt;br&gt;
Navigate to &lt;code&gt;pubspec.yaml&lt;/code&gt; and add the latest version of the Agora Flutter SDK as a dependency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add relevant permission in your &lt;code&gt;AndroidManifest.xml&lt;/code&gt; file (Android) or &lt;code&gt;Info.plist&lt;/code&gt; file (iOS):&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Android (in your &lt;code&gt;AndroidManifest.xml&lt;/code&gt;):
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;uses-permission android:name="android.permission.INTERNET"/&amp;gt; 
&amp;lt;uses-permission android:name="android.permission.RECORD_AUDIO"/&amp;gt; 
&amp;lt;uses-permission android:name="android.permission.CAMERA"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;iOS (in your &lt;code&gt;info.plist&lt;/code&gt;): Add both &lt;a href="https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/plist/info/NSCameraUsageDescription"&gt;&lt;code&gt;NSCameraUsageDescription&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW25"&gt;&lt;code&gt;NSMicrophoneUsageDescription&lt;/code&gt;&lt;/a&gt; to &lt;code&gt;Info.plist&lt;/code&gt; along with text descriptions. See &lt;a href="https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_ios"&gt;here&lt;/a&gt; for more information on these, along with code samples of how to request and get authorization states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All done! Let's start building the app.&lt;/p&gt;
&lt;h2&gt;
  
  
  Build
&lt;/h2&gt;

&lt;p&gt;We will stick with a very simple grid view. Our goal is to scale this application as the user joins. To do this, we will optimize our bandwidth usage to ensure all the streams work concurrently without any difficulty.&lt;/p&gt;
&lt;h3&gt;
  
  
  Building a Home Page
&lt;/h3&gt;

&lt;p&gt;Our home page is responsible for prompting the user for the name of the channel they want to join and requesting camera and microphone permission.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To request user permission, we are using a plug-in called &lt;code&gt;permission_handler&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the video call page
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Adding all the required variables:&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Initializing the Agora methods:&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the above code snippet, we set up the Agora engine with dual-stream mode enabled. Dual-stream is an Agora feature that allows a client to publish two streams at the same time. One stream is for a higher resolution and bitrate, and the other stream is for a lower resolution and bitrate. With this dual-stream setup, when a remote client subscribes to your stream, they can switch to a lower stream based on their bandwidth requirements.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initializing the Agora SDK:&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The _initAgoraRtcEngine function creates an object of the AgoraRtcEngine, which we use to refer to all the methods provided in the Agora SDK.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adding Agora event handlers:&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the &lt;code&gt;userJoined&lt;/code&gt; callback, we are doing the following:&lt;br&gt;
Adding the UID of the remote video to a list of UIDs (&lt;code&gt;_users&lt;/code&gt;) that we use as the dataset for all the users' UIDs present in the channel&lt;br&gt;
Checking if the number of remote users has grown to five to know whether to switch to using the lower stream in dual-stream mode&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;userOffline&lt;/code&gt; callback, we are doing the following:&lt;br&gt;
Removing the UID from the &lt;code&gt;_users&lt;/code&gt; list&lt;br&gt;
Switching back to the higher stream in the dual-stream mode if the number of remote users shrinks to three&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating the grid view for local and remote user video&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here, we simply pass the UID present in the &lt;code&gt;_users&lt;/code&gt; list to generate a list of views. These views are then used to generate a grid that scales automatically as the user joins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleaning Up
&lt;/h3&gt;

&lt;p&gt;Finally, it is time to write the dispose method. We clean up all the resources relevant to Agora here:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;To test the application, you will need five or more users such that when they join the channel the video quality optimizes automatically in order to provide the best video calling experience.&lt;/p&gt;

&lt;p&gt;To run the app, enter this command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You now have a video chat application that can scale to up to 17 users by optimizing settings for incoming streams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Sw3xDp3L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AhRKFFDc4tj1HPiCFUpymkw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Sw3xDp3L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AhRKFFDc4tj1HPiCFUpymkw.png" alt="Demo Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find a complete application using all of the above code on &lt;a href="https://github.com/Meherdeep/Agora-Flutter-Scalable-UI"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Resources
&lt;/h2&gt;

&lt;p&gt;To learn more about the Agora Flutter SDK and other use cases, see the developer guide &lt;a href="https://docs.agora.io/en"&gt;here&lt;/a&gt;.&lt;br&gt;
You can also have a look at the complete documentation for the functions discussed above and many more &lt;a href="https://docs.agora.io/en/Video/API%20Reference/flutter/index.html"&gt;here&lt;/a&gt;.&lt;br&gt;
And I invite you to join the &lt;a href="https://agoraio.slack.com/"&gt;Agora.io Developer Slack Community&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agora</category>
      <category>flutter</category>
      <category>dart</category>
      <category>programming</category>
    </item>
    <item>
      <title>1-to-1 Video Chat App on Android Using the Agora 4.x SDK Preview</title>
      <dc:creator>Meher</dc:creator>
      <pubDate>Fri, 17 Sep 2021 21:40:59 +0000</pubDate>
      <link>https://dev.to/meherdeep/1-to-1-video-chat-app-on-android-using-the-agora-4-x-sdk-preview-1gbi</link>
      <guid>https://dev.to/meherdeep/1-to-1-video-chat-app-on-android-using-the-agora-4-x-sdk-preview-1gbi</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;In this post, we’ll build a basic video chat app in 10 easy steps, using the Agora Video 4.0 SDK Preview for Android.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Android Studio &lt;br&gt;
(&lt;a href="https://developer.android.com/studio/"&gt;https://developer.android.com/studio&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Basic knowledge of Java and the Android SDK&lt;br&gt;
(&lt;a href="https://developer.android.com/training/basics/firstapp/"&gt;https://developer.android.com/training/basics/firstapp&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agora.io developer account&lt;br&gt;
(see: &lt;a href="https://www.agora.io/en/blog/how-to-get-started-with-agora?utm_source=medium&amp;amp;utm_medium=blog&amp;amp;utm_campaign=de_content"&gt;How To Get Started with Agora&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Getting your App ID
&lt;/h2&gt;

&lt;p&gt;Once you finish the sign-up process, you are redirected to the Agora Console. Open the Projects tab in the left-hand nav to see your default project’s App ID.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step2: JCenter Integration
&lt;/h2&gt;

&lt;p&gt;Add the following line in your project level &lt;strong&gt;/app/build.gradle&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;allprojects {
    repositories {    ...**
        ***// Jit pack
        *maven { url ‘[https://www.jitpack.io'](https://www.jitpack.io%27/) }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Add the following line in the &lt;strong&gt;/app/build.gradle&lt;/strong&gt; file of your project:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
    ...**
    ***//Agora RTC 4.0 SDK for video call
    *implementation "com.github.agorabuilder:agora-full-preview:4.0.0"**
**}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_P83XXCu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/7160/1%2APJam2lIiXtuKOsHLmHxyFA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_P83XXCu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/7160/1%2APJam2lIiXtuKOsHLmHxyFA.png" alt="build.gradle (module level)"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Setting up the Agora App ID
&lt;/h2&gt;

&lt;p&gt;Now it’s time to add your Agora App ID (&lt;em&gt;see Step 1&lt;/em&gt;) to the Android project’s &lt;em&gt;Strings.xml (app/src/main/res/values/Strings.xml)&lt;/em&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;resources&amp;gt;
    &amp;lt;string name="app_name"&amp;gt;Agora-Android-Video-Tutorial&amp;lt;/string&amp;gt;
    &amp;lt;string name="agora_app_id"&amp;gt;#ADD YOUR APP ID HERE#&amp;lt;/string&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pUF3Ihls--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/7156/1%2A-ejxNsfAXB8K9P8eY01YfA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pUF3Ihls--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/7156/1%2A-ejxNsfAXB8K9P8eY01YfA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: This guide does not implement token authentication which is recommended for all RTE apps running in production environments.&lt;/em&gt;&lt;br&gt;
 &lt;em&gt;For more information about token based authentication within the Agora platform please refer to this guide: &lt;a href="https://bit.ly/3sNiFRs"&gt;https://bit.ly/3sNiFRs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next step is to add the appropriate permissions within &lt;em&gt;Manifest.xml&lt;/em&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The final step is to prevent obfuscation of the Agora classes. This might sound complex, but it’s really very simple. In the proguard-rules.pro file, add a&lt;br&gt;
-keep class configuration for the Agora SDK.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-keep class io.agora.**{*;}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VtdsmBGT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4000/0%2AzwYDfTMOj0DZAnxY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VtdsmBGT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4000/0%2AzwYDfTMOj0DZAnxY.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This prevents obfuscation of the Agora SDK public class names.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: **Ensure that the Android NDK plug-in is installed and set up for this project.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Step 4: Setting Up Views
&lt;/h2&gt;

&lt;p&gt;Now that we have the Agora SDK integrated, let’s set up our UI. I will breeze through this portion since we are using standard UI elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--weKrAKSt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4000/0%2AtpaT4r7AkkHTfohI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--weKrAKSt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4000/0%2AtpaT4r7AkkHTfohI.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the example, I chose to use ImageView instead of Button for the various UI elements. Either works. The important part is to note that there are functions that we link to using the onClick property.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Checking Permissions
&lt;/h2&gt;

&lt;p&gt;I know what you must be thinking: “Didn’t we already set up the permissions?” Earlier, we let the application’s Manifest know which permissions our app plans to use, but we still have to explicitly request the user to grant these permissions. Don’t worry — this is the final step in getting the boilerplate project running, and it’s painless.&lt;/p&gt;

&lt;p&gt;First, let’s declare which permissions we want to request:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Permissions
private static final int *PERMISSION_REQ_ID *= 22;
private static final String[] *REQUESTED_PERMISSIONS *= {Manifest.permission.*RECORD_AUDIO*, Manifest.permission.*CAMERA*};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Next, we set up a couple of functions to help us. First, we have a method that requests permissions for a given permission string and code.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Next, we have a callback method that gets called after the user has responded to the permissions request prompt.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Last, in our class’s onCreate we check if our permissions were granted. If they were not, the above methods handle the requests&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Step 6: Initializing the Agora SDK
&lt;/h2&gt;

&lt;p&gt;Now that we have our view, we are ready to initialize the Agora SDK, set up the user profile, and set the video quality settings.&lt;/p&gt;

&lt;p&gt;In the previous step, you may have noticed a couple of places that I call initAgoraEngine(). Before we can dive into the initialization, we need to make sure that our activity has access to an instance of the Agora &lt;em&gt;RtcEngine&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wiHrME1L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4000/0%2Az6OxbliF9_VlgKml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wiHrME1L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4000/0%2Az6OxbliF9_VlgKml.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our MainActivity class, we need to declare a class property to store our instance of &lt;em&gt;RtcEngine:&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private RtcEngine mRtcEngine;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now it’s time to initialize. After all the boilerplate setup, we are finally at the step where we can start playing with the Agora engine!&lt;/p&gt;

&lt;p&gt;Go ahead and declare your initAgoraEngine() method in your class. In this function, we will create a new instance of the RtcEngine using the baseContext, the Agora App ID (declared above), and an instance of the RtcEngineEventHandler (we’ll get into this a little later).&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Once we have our new instance, it’s time to set up our user’s session. Here we can set the Channel Profile to Communication, since this is a video chat and not a broadcasting application. This is also where we configure our video encoder settings.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Note: At this phase of the build, we can use the emulator to test our work, but I am choosing to use a mobile device.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 7: Connecting the Video Streams
&lt;/h2&gt;

&lt;p&gt;Before we can join a call we need to be able to present the local video stream to the user via the UI elements we set up earlier (&lt;a href="https://medium.com/#366e"&gt;step 4&lt;/a&gt;). For reference, below is the UI element’s ID that our local video will render into:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;android:id="@+id/floating_video_container"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;In the first line, we declare a &lt;a href="https://developer.android.com/reference/android/view/SurfaceView"&gt;*SurfaceView&lt;/a&gt; that renders the stream from the camera. &lt;em&gt;The second step is to set up the layout and link it with our local or remote video container. We then add a view to our container where we add our SurfaceView. This lets us play the camera feed in that particular container. Last, we pass the localView or remoteView, which is the object of our SurfaceView, to the engine as part of a VideoCanvas object. We leave the *uid&lt;/em&gt; parameter blank so that the SDK can handle creating a dynamic ID for each user.&lt;/p&gt;

&lt;p&gt;Now, that we have our local video feed set up, we need to use a similar function to connect our remote video stream.&lt;/p&gt;

&lt;p&gt;The main difference between the remote video and the local video is the user ID parameter that gets passed to the engine as part of the VideoCanvas object. The last line sets the fallback option: If the video degrades, the engine reverts to a low-quality video stream.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Step 8: Setting Up the SDK Event Handler
&lt;/h2&gt;

&lt;p&gt;Earlier, I made a reference to the &lt;em&gt;RtcEngineEventHandler&lt;/em&gt;, and now it’s time to declare it as a property of our MainActivity class. The engine will call these methods from the &lt;em&gt;RtcEngineEventHandler&lt;/em&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Each event triggers some fairly straightforward functions, including one we wrote in the previous step. In the interest of brevity, I provide the code below, but I don’t give an in-depth breakdown.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Feel free to leave a comment if anything is unclear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9: Joining and Leaving Channels
&lt;/h2&gt;

&lt;p&gt;I know what you’re thinking, step &lt;em&gt;9&lt;/em&gt; ?! Don’t sweat it — the next two steps are very simple. Let’s start by joining a call.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: if you do not specify the uid when joining the channel, the engine will assign one&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see from the first line, the Agora SDK makes it simple. The engine calls joinChannel, passing in the channel name followed by the call to set up our local video stream (&lt;a href="https://medium.com/#aabb"&gt;Step 7&lt;/a&gt;).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: With the 4.0 SDK you need to add the StartPreview() method after setting up your local video in order to start your camera feed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note: The remove video method is the same used in step 8&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Leaving the channel is even simpler: The engine calls leaveChannel. Above, you’ll notice there are a few lines to remove the video stream subviews from each UI element.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: It is also important to use the stopPreview() method before leaving the channel in order to stop the camera feed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 10: Adding Other Functionality
&lt;/h2&gt;

&lt;p&gt;The last remaining parts are related to connecting the UI elements for toggling the microphone and video streams on the local device. Let’s start with the audio toggle.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;First, we get the reference to our button and then check if it has been toggled on or off using isSelected(). Once we have updated the UI element state, we pass the button’s updated state to the RtcEngine.&lt;/p&gt;

&lt;p&gt;Moving on to the video toggle:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As with the audio toggle, we check or update the button’s state using isSelected() and then pass that to the RtcEngine. To give a better visual representation of the video being muted, we hide or show the videoSurface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uVv8G4HF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AAG_uZxifv_enHINQ" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uVv8G4HF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AAG_uZxifv_enHINQ" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope you enjoyed reading along and working together on creating a 1-to-1 video chat Android app using the Agora 4.0 SDK.&lt;/p&gt;

&lt;p&gt;Full source code: *&lt;a href="https://github.com/digitallysavvy/android-video-chat-demo/tree/ngsdk-update"&gt;*https://github.com/digitallysavvy/android-video-chat-demo/tree/ngsdk-update&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any questions or comments, I invite you to &lt;a href="https://www.agora.io/en/join-slack/"&gt;join the Agora Developer Slack&lt;/a&gt; community.&lt;/p&gt;

</description>
      <category>agora</category>
      <category>android</category>
      <category>videocalling</category>
    </item>
    <item>
      <title>Add Live Streaming to your Android App using Agora 4.0 SDK Preview</title>
      <dc:creator>Meher</dc:creator>
      <pubDate>Fri, 17 Sep 2021 20:54:36 +0000</pubDate>
      <link>https://dev.to/meherdeep/add-live-streaming-to-your-android-app-using-agora-4-0-sdk-preview-bb7</link>
      <guid>https://dev.to/meherdeep/add-live-streaming-to-your-android-app-using-agora-4-0-sdk-preview-bb7</guid>
      <description>&lt;p&gt;“You’re live!” — that’s a phrase that used to be limited to celebrities and other famous people. But now we see everyone going live and sharing their life stories. We have seen the market evolve so much that live streaming has become one of the biggest sources of real-time engagement (RTE).&lt;/p&gt;

&lt;p&gt;Building your own live streaming application can be difficult especially if scalability is a concern. Agora makes our lives much easier by providing an easy-to-use SDK that also gives developers low-level control of exactly how we want the streaming service to work. While using the Agora platform, you don’t have to worry about scalability, call drops, or latency.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will walk through how to add live streaming to an Android application with multiple broadcasters and audiences who can subscribe to their stream.&lt;/p&gt;

&lt;p&gt;So let’s get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An Agora developer account (see &lt;a href="https://www.agora.io/en/blog/how-to-get-started-with-agora"&gt;How to get started with Agora&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Android Studio&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A basic understanding of Android development&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Setup&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Though I won’t be going over the UI building part of the app, I have created a simple UI for our application. You can head over to GitHub to get the design used in this tutorial: &lt;a href="https://github.com/Meherdeep/agora-android-live-streaming/tree/design"&gt;https://github.com/Meherdeep/agora-android-live-streaming/tree/design&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cj1vFm0L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2800/0%2A6_8JvfCrU1wpo-KG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cj1vFm0L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2800/0%2A6_8JvfCrU1wpo-KG" alt="Github Repo For Agora Android Live Streaming"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the strings.xml file, and add your App ID to the private_app_id resource. Make sure to then sync your Gradle files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C1NTF33p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2800/0%2AKVWyOzfPiIChsslV" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C1NTF33p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2800/0%2AKVWyOzfPiIChsslV" alt="strings.xml"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MainActivity.java
&lt;/h2&gt;

&lt;p&gt;Now, let’s create a file called MainActivity.java. This file contains the logic of what the users see when they first open the app. The main UI elements include a radio button and a text box. The radio button allows a user to decide whether they want to be a host or an audience for the live stream. The text box allows the user to input the channel name they wish to join.&lt;/p&gt;

&lt;p&gt;In our onCreate method, we add the user permission so that the application asks for camera and microphone permissions as soon as the page is built.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We’ll be adding two methods to our class:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first method will be called when the user chooses an option from the radio buttons. We will be setting a variable accordingly. We will be setting it to a value that will determine whether the user is a broadcaster or an audience.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;We then implement a function that is called when the user submits the details. Here we will be getting all the details we need and sending them over to the next activity.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  VideoActivity.java
&lt;/h2&gt;

&lt;p&gt;By default, audiences have their cameras disabled and microphones muted, but the broadcasters have complete access. So when users join as a broadcaster, their videos are automatically added to the interface.&lt;/p&gt;

&lt;p&gt;So first we are adding some variables that we will be using throughout the class. We then modify the onCreate method to get the data that we had passed in from the previous activity.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We declare a method called initAgoraEngineAndJoinChannel that will call all the other methods needed in the life cycle of the broadcast. We also define the event handler that will decide what methods to call when a remote user joins or leaves or when the remote feed is muted.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let’s take a deeper look into the initAgoraEngineAndJoinChannel() method and all the other methods referred in it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;initializeAgoraEngine() : This is a method used to initialize the RtcEngine.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;p&gt;setClientRole(): This method sets the role of a user to host or an audience (default). This method should be called before joining the channel. You can call it again after joining the channel to switch the client role.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;setupLocalVideo(): This function is used to refer to the setupLocalVideo method from our AgoraRtcEngine, through which we set a surface view for our local user that is used in the live stream.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;&lt;p&gt;startPreview: This method allows you to add your local stream before joining a channel. It is important that before calling this method we have enabled the video and set up our local user video.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;joinChannel(): A channel acts as a common room for people to be in the same video call. The joinChannel() method can be called like this:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This method takes four parameters to run successfully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Token: Token authentication is recommended for all RTE apps running in production environments. For more information about token-based authentication in the Agora platform, see &lt;a href="https://docs.agora.io/en/Video/token?platform=All%20Platforms"&gt;https://docs.agora.io/en/Video/token?platform=All%20Platforms&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Channel Name: It takes a string input to put users into a common video call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optional Info: This is an optional field through which you can pass additional information about the channel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;uid: It is the unique ID for every user who joins the channel. If you pass 0 or the null value, then Agora automatically assigns a uid for every user.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Note: This project is meant for reference purposes and development environments, it is not intended for production environments. Token authentication is recommended for all RTE apps running in production environments. For more information about token based authentication within the Agora platform please refer to this guide: &lt;a href="https://bit.ly/3sNiFRs"&gt;https://bit.ly/3sNiFRs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our initialize function, we passed mRtcEventHandler as one of the parameters to the create method. This sets up a series of callback events that are triggered whenever a user joins a channel or leaves a channel.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Using these callbacks we are calling functions as a user joins or leaves the channel. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;setupRemoteVideo : When a remote user joins the call the remote container is selected to display the video of the remote user. Here we will be using FrameLayout to display the user video.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;onRemoteUserLeft : When a remote user leaves a channel this function removes all the views from the container.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We then add the onDestroy method for releasing the resources that we have used.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The leaveChannel function here calls the stopPreview and leaveChannel methods. &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;You can also add features like switching the camera by calling the switchCamera() method using our RtcEngine’s object:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mRtcEngine.switchCamera()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Or muting the microphone by calling the muteLocalAudioStream() method using our RtcEngine’s object:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mRtcEngine.muteLocalAudioStream(true)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With this, you’re ready to go and build your own live streaming application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Before you build the app, make sure that you did the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You added your App ID while initializing RtcEngine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You added your channel name for both RtcEngine and RtcChannel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your project has App Certificate enabled, you used your token in the token variable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You followed all the instructions correctly, such as adding the correct dependencies to the build.gradle file, adding the permissions to your manifest, and so on.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After you build the app, you should see something like this :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AF0l0Ae8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AS7zo-fEqcvSj8HML.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AF0l0Ae8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AS7zo-fEqcvSj8HML.png" alt="Testing the Agora Android Live Streaming Application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I have added two broadcaster streams while multiple audiences have subscribed to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations! You have implemented your own live video streaming application built using the Agora Android SDK.&lt;/p&gt;

&lt;p&gt;You can get the complete code for this application &lt;a href="https://github.com/Meherdeep/agora-android-live-streaming/tree/ngsdk-update"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Resources
&lt;/h2&gt;

&lt;p&gt;For more information about Agora.io applications, take a look at the &lt;a href="https://docs.agora.io/en/Video/start_call_android?platform=Android"&gt;Agora Video Call Quickstart Guide&lt;/a&gt; and&lt;a href="https://docs.agora.io/en/Video/API%20Reference/java/index.html"&gt; Agora API Reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And take a look at the complete documentation for the functions discussed above and many more &lt;a href="https://docs.agora.io/en/Agora%20Platform/api-ref?platform=Android"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also invite you to join the &lt;a href="https://agoraio.slack.com/"&gt;Agora.io Developer Slack community&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agora</category>
      <category>android</category>
      <category>livestreaming</category>
      <category>application</category>
    </item>
  </channel>
</rss>
