我是Agora.io的新手,我正在为1对1的视频通话创建一个Android应用。我的应用程序一切正常,我可以加入/退出频道,甚至可以通过相机查看自己的本地图像。但是,在通话中,仅音频被传输而视频未被传输。
当我调试应用程序时,可以看到未触发“ onFirstRemoteVideoFrame”事件。我尝试将其更改为“ onFirstRemoteVideoDecoded”(我在许多教程中都看到过,但android studio表示该方法已弃用),但仍无法正常工作。
另外,请注意,当我在proguard-rules.pro文件中添加“ -keep class io.agora。** {;}”行时,它表示找不到该类。所以我改为使用'-keep class io.agora。 {*;}'。
下面是我的活动的Java代码。我正在使用agora 3.1.3。
package com.guideu.helloagora;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoCanvas;
import io.agora.rtc.video.VideoEncoderConfiguration;
public class MainActivity extends AppCompatActivity {
private static final String TAG=MainActivity.class.getSimpleName();
private static final int PERMISSION_REQ_ID=22;
private static final String[] REQUESTED_PERMISSIONS={
Manifest.permission.RECORD_AUDIO,
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private RtcEngine mRtcEngine; // Agora engine reference
private FrameLayout mLocalContainer;
private RelativeLayout mRemoteContainer;
private SurfaceView mLocalView;
private SurfaceView mRemoteView;
private ImageView mCallBtn;
private ImageView mMuteBtn;
private ImageView mSwitchCameraBtn;
private boolean mCallEnd;
private boolean mMuted;
//Agora engine event handler
private final IRtcEngineEventHandler mRTCHandler=new IRtcEngineEventHandler() {
@Override
public void onJoinChannelSuccess(String channel, final int uid, int elapsed) {
super.onJoinChannelSuccess(channel, uid, elapsed);
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("agora","Join channel success, uid: " + (uid & 0xFFFFFFFFL));
}
});
}
@Override
public void onUserOffline(final int uid, int reason) {
super.onUserOffline(uid, reason);
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("agora","User offline, uid: " + (uid & 0xFFFFFFFFL));
removeRemoteView();
}
});
}
@Override
public void onFirstRemoteVideoFrame(final int uid, int width, int height, int elapsed) {
super.onFirstRemoteVideoFrame(uid, width, height, elapsed);
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("agora","First remote video decoded, uid: " + (uid & 0xFFFFFFFFL));
setupRemoteVideo(uid);
}
});
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUI();
if(checkSelfPermission(REQUESTED_PERMISSIONS[0],PERMISSION_REQ_ID) &&
checkSelfPermission(REQUESTED_PERMISSIONS[1],PERMISSION_REQ_ID) &&
checkSelfPermission(REQUESTED_PERMISSIONS[2],PERMISSION_REQ_ID)){
//init engine
initEngineAndJoinChannel();
}
}
@Override
protected void onDestroy(){
super.onDestroy();
if(!mCallEnd){
leaveChannel();
}
RtcEngine.destroy();
}
private void initUI(){
mLocalContainer=findViewById(R.id.local_video_view_container);
mRemoteContainer=findViewById(R.id.remote_video_view_container);
mCallBtn=findViewById(R.id.btn_call);
mMuteBtn=findViewById(R.id.btn_mute);
mSwitchCameraBtn=findViewById(R.id.btn_switch_camera);
}
private void initEngineAndJoinChannel(){
//initialize engine
initializeEngine();
//setup video config
setupVideoConfig();
//setup local video
setupLocalVideo();
//join channel
joinChannel();
}
private void initializeEngine(){
try {
mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRTCHandler);
}
catch (Exception e){
Log.e(TAG,Log.getStackTraceString(e));
throw new RuntimeException("Need to check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
}
private void setupVideoConfig(){
mRtcEngine.enableVideo();
mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(
VideoEncoderConfiguration.VD_640x360,
VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,
VideoEncoderConfiguration.STANDARD_BITRATE,
VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT
));
}
private void setupLocalVideo(){
mRtcEngine.enableVideo();
mLocalView=RtcEngine.CreateRendererView(getBaseContext());
mLocalView.setZOrderMediaOverlay(true);
mLocalContainer.addView(mLocalView);
VideoCanvas localVideoCanvas=new VideoCanvas(mLocalView,VideoCanvas.RENDER_MODE_HIDDEN,0);
mRtcEngine.setupLocalVideo(localVideoCanvas);
}
private void setupRemoteVideo(int uid){
/*int count=mRemoteContainer.getChildCount();
View view=null;
for(int i=0;i<count;i++){
View v=mRemoteContainer.getChildAt(i);
if(v.getTag() instanceof Integer && ((int) v.getTag())==uid){
view=v;
}
}
if(view!=null){
return;
}*/
mRemoteView=RtcEngine.CreateRendererView(getBaseContext());
mRemoteContainer.addView(mRemoteView);
mRtcEngine.setupRemoteVideo(new VideoCanvas(mRemoteView,VideoCanvas.RENDER_MODE_HIDDEN,uid));
mRemoteView.setTag(uid);
}
private void removeRemoteView(){
if(mRemoteView!=null){
mRemoteContainer.removeView(mRemoteView);
}
mRemoteView=null;
}
private void joinChannel(){
String token=getString(R.string.agora_access_token);
if(TextUtils.isEmpty(token)){
token=null;
}
mRtcEngine.joinChannel(token,"HelloAgora","",0);
}
private void leaveChannel(){
mRtcEngine.leaveChannel();
}
public void onLocalAudioMuteClicked(View view){
mMuted=!mMuted;
mRtcEngine.muteLocalAudioStream(mMuted);
int res=mMuted?R.drawable.btn_mutecall:R.drawable.btn_unmute;
mMuteBtn.setImageResource(res);
}
public void onSwitchCameraClicked(View view){
mRtcEngine.switchCamera();
}
public void onCallClicked(View view){
if(mCallEnd){
startCall();
mCallEnd=false;
mCallBtn.setImageResource(R.drawable.btn_endcall);
}
else{
endCall();
mCallEnd=true;
mCallBtn.setImageResource(R.drawable.btn_startcall);
}
showButtons(!mCallEnd);
}
private void startCall(){
setupLocalVideo();
joinChannel();
}
private void endCall(){
removeLocalVideo();
removeRemoteView();
leaveChannel();
}
private void removeLocalVideo(){
if(mLocalView!=null){
mLocalContainer.removeView(mLocalView);
}
mLocalView=null;
}
private void showButtons(boolean show){
int visibility=show?View.VISIBLE:View.GONE;
mMuteBtn.setVisibility(visibility);
mSwitchCameraBtn.setVisibility(visibility);
}
private boolean checkSelfPermission(String permission, int requestCode){
if(ContextCompat.checkSelfPermission(this,permission)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,REQUESTED_PERMISSIONS,requestCode);
Toast.makeText(this,"No Permission",Toast.LENGTH_LONG);
return false;
}
return true;
}
}
'''
答案 0 :(得分:0)
您可以尝试使用“ onRemoteVideoStateChanged”回调代替“ onFirstRemoteVideoFrame”。
这是代码段:
@Override
public void onRemoteVideoStateChanged(final int uid, int state, int reason, int elapsed) {
super.onRemoteVideoStateChanged(uid, state, reason, elapsed);
if (state == Constants.REMOTE_VIDEO_STATE_STARTING) {
runOnUiThread(new Runnable() {
@Override
public void run() {
setupRemoteVideo(uid);
}
});
}
}