Output:
1/ Create an account on Agora:
link to Agora login page: https://sso2.agora.io/en/login
You can login or sign up here. I recommend Google sign in. it is easy and one-click login
2/ After Login you will be redirected to the console dashboard page.
or you can proceed with this link: https://console.agora.io/v2/project-management
Click on the project and then click on the Create New button
after creating the project you will see your project here and notice here given your App ID
Now you need to create a token with the name of your channel.
3/ Go to overview and click on your created app configure link as shown in the picture below
4/ Now you will see your project info and a button Generate Temp Token Click on it
5/ Now Generate a token and copy it will be needed for our app.
Now let's start the coding journey together.
We need a total of 3 Activities:
1. MainActivity ( for choosing audio or video call )
2. AudioActivity ( Join for audio call )
3. VideoActivity ( Join for video call )
6/Add dependency to your build.gradle (app module ) and sync your project
implementation("io.agora.rtc:full-sdk:4.1.1")
7/ Check Your settings.gradle file is there mentioned the mavenCentral()
if not mentioned then add this
8/ Add the Below Permission to your AndroidManifest.xml file
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
9/ Modify your MainActivity
9.1/ Modify activity_main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_gravity="center"
android:gravity="center"
>
<Button
android:id="@+id/btn_audio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Join Audio Call" />
<Button
android:id="@+id/btn_video"
android:layout_marginStart="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Join Video Call"/>
</LinearLayout>
</LinearLayout>
9.2/ MainActivity.java
package com.example.audiovideocallingwithagora;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQ_ID = 22;
private static final String[] REQUESTED_PERMISSIONS = {
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
};
private Button joinAudioCall;
private Button joinVideoCall;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (!checkPermissions()) {
requestPermissions();
}
joinAudioCall = findViewById(R.id.btn_audio);
joinVideoCall = findViewById(R.id.btn_video);
joinAudioCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, AudioActivity.class));
}
});
joinVideoCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, VideoActivity.class));
}
});
}
private boolean checkPermissions() {
for (String permission : REQUESTED_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
private void requestPermissions() {
ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, PERMISSION_REQ_ID);
}
}
10/ Modify your AudioActivity
10.1/ Modify activity_audio.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="16dp"
android:gravity="center"
>
<Button
android:id="@+id/btn_join"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Join Channel" />
<Button
android:id="@+id/btn_leave"
android:layout_marginStart="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Leave Channel"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
10.2/ AudioActivity.java
package com.example.audiovideocallingwithagora;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import io.agora.rtc2.Constants;
import io.agora.rtc2.IRtcEngineEventHandler;
import io.agora.rtc2.RtcEngine;
import io.agora.rtc2.RtcEngineConfig;
import io.agora.rtc2.ChannelMediaOptions;
public class AudioActivity extends AppCompatActivity {
private String appId = "paste here your app id within the quotation";
private String channelName = "agora_audio_video";
private String token = "paste here your token you genareted within the quotation";
private RtcEngine mRtcEngine;
private Button btn_join;
private Button btn_leave;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_audio);
btn_join = findViewById(R.id.btn_join);
btn_leave = findViewById(R.id.btn_leave);
final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
@Override
public void onJoinChannelSuccess(String channel, int uid, int elapsed) {
super.onJoinChannelSuccess(channel, uid, elapsed);
runOnUiThread(() -> {
Toast.makeText(AudioActivity.this, "Join channel success", Toast.LENGTH_SHORT).show();
});
}
@Override
public void onUserJoined(int uid, int elapsed) {
super.onUserJoined(uid, elapsed);
runOnUiThread(() -> {
Toast.makeText(AudioActivity.this, "User joined.. ", Toast.LENGTH_SHORT).show();
});
}
@Override
public void onUserOffline(int uid, int reason) {
super.onUserOffline(uid, reason);
runOnUiThread(() -> {
Toast.makeText(AudioActivity.this, "User offline ", Toast.LENGTH_SHORT).show();
});
}
};
RtcEngineConfig config = new RtcEngineConfig();
config.mContext = getBaseContext();
config.mAppId = appId;
config.mEventHandler = mRtcEventHandler;
try {
mRtcEngine = RtcEngine.create(config);
} catch (Exception e) {
throw new RuntimeException(e);
}
ChannelMediaOptions options = new ChannelMediaOptions();
options.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER;
options.channelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING;
options.publishMicrophoneTrack = true;
options.autoSubscribeAudio = true;
btn_join.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRtcEngine.joinChannel(token, channelName, 0, options);
btn_leave.setVisibility(View.VISIBLE);
}
});
btn_leave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mRtcEngine != null) {
mRtcEngine.leaveChannel();
mRtcEngine = null;
RtcEngine.destroy();
finish();
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mRtcEngine != null) {
mRtcEngine.leaveChannel();
mRtcEngine = null;
RtcEngine.destroy();
finish();
}
}
}
11/ Modify your VideoActivity
11.1/ Modify activity_video.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/local_video_view_container"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_weight="1"/>
<View
android:layout_width="1dp"
android:layout_height="1dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
/>
<FrameLayout
android:id="@+id/remote_video_view_container"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_weight="1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="16dp"
>
<Button
android:id="@+id/btn_join"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Join Channel" />
<Button
android:id="@+id/btn_leave"
android:layout_marginStart="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Leave Channel"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
11.2/ VideoActivity.java
package com.example.audiovideocallingwithagora;
import android.os.Bundle;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import io.agora.rtc2.ChannelMediaOptions;
import io.agora.rtc2.Constants;
import io.agora.rtc2.IRtcEngineEventHandler;
import io.agora.rtc2.RtcEngine;
import io.agora.rtc2.RtcEngineConfig;
import io.agora.rtc2.video.VideoCanvas;
public class VideoActivity extends AppCompatActivity {
private String appId = "paste here your app id within the quotation";private String channelName = "agora_audio_video";
private String token = "paste here your token you genareted within the quotation";
private RtcEngine mRtcEngine;
private Button btn_join;
private Button btn_leave;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_video);
btn_join = findViewById(R.id.btn_join);
btn_leave = findViewById(R.id.btn_leave);
final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
@Override
public void onUserJoined(int uid, int elapsed) {
runOnUiThread(new Runnable() {
@Override
public void run() {
setupRemoteVideo(uid);
}
});
}
};
RtcEngineConfig config = new RtcEngineConfig();
config.mContext = getBaseContext();
config.mAppId = appId;
config.mEventHandler = mRtcEventHandler;
try {
mRtcEngine = RtcEngine.create(config);
} catch (Exception e) {
throw new RuntimeException(e);
}
mRtcEngine.enableVideo();
mRtcEngine.startPreview();
FrameLayout container = findViewById(R.id.local_video_view_container);
SurfaceView surfaceView = new SurfaceView (getBaseContext());
container.addView(surfaceView);
mRtcEngine.setupLocalVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, 0));
ChannelMediaOptions options = new ChannelMediaOptions();
options.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER;
options.channelProfile = Constants.CHANNEL_PROFILE_COMMUNICATION;
btn_join.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRtcEngine.joinChannel(token, channelName, 0, options);
btn_leave.setVisibility(View.VISIBLE);
}
});
btn_leave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRtcEngine.stopPreview();
mRtcEngine.leaveChannel();
finish();
}
});
}
private void setupRemoteVideo(int uid) {
FrameLayout container = findViewById(R.id.remote_video_view_container);
SurfaceView surfaceView = new SurfaceView (getBaseContext());
surfaceView.setZOrderMediaOverlay(true);
container.addView(surfaceView);
mRtcEngine.setupRemoteVideo(new VideoCanvas(surfaceView, VideoCanvas.RENDER_MODE_FIT, uid));
}
@Override
protected void onDestroy() {
super.onDestroy();
mRtcEngine.stopPreview();
mRtcEngine.leaveChannel();
finish();
}
}