QuickBlox onRemoteVideoTrackReceive 从未调用过

QuickBlox onRemoteVideoTrackReceive never called

我正在尝试从 this 资源创建一个简单的点对点视频通话。

我只是做了所有需要的事情,但我仍然没有从远程渲染 它只从本地相机渲染并且 onRemoteVideoTrackReceive 从未调用过。 我正在使用 qb 2.5 sdk 我还从 qb-sdk 编译了示例 sample-videochat-webrtc,它的工作正常。 这是我的项目代码:

mudol:app

apply plugin: 'com.android.application'

android {
compileSdkVersion 'Google Inc.:Google APIs:23'
buildToolsVersion "23.0.2"

defaultConfig {
    applicationId "com.hm.runanddelete"
    minSdkVersion 14
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-  android.txt'), 'proguard-rules.pro'
    }
}
  }

dependencies {
testCompile 'junit:junit:4.12'
compile fileTree(dir: 'libs', include: ['*.jar'])


}

项目:____

// Top-level build file where you can add configuration options common to    all sub-projects/modules.

buildscript {
repositories {
    jcenter()
}

dependencies {
    classpath 'com.android.tools.build:gradle:2.0.0-alpha5'

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}
}

allprojects {
repositories {
    jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hm.runanddelete">

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera.front" />
<uses-feature android:name="android.hardware.microphone"/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

<uses-feature
    android:glEsVersion="0x00020000"
    android:required="true" />




<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

MainActivity

public class MainActivity extends Activity implements QBRTCClientSessionCallbacks, QBRTCClientVideoTracksCallbacks, QBRTCSignalingCallback, QBRTCSessionConnectionCallbacks {
static final String APP_ID = "...";
static final String AUTH_KEY = "...";
static final String AUTH_SECRET = "...";
static final String ACCOUNT_KEY = "...";

RTCGLVideoView LocalVideoView;
RTCGLVideoView remoteVideoView;

String login = "";
String password = "";


QBChatService chatService;
QBRTCClient rtcClient;


EditText et_user, et_paw, et_id;
Button btn_call, btn_login;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    et_user = (EditText) findViewById(R.id.et_caller_user);
    et_paw = (EditText) findViewById(R.id.et_caller_pw);
    et_id = (EditText) findViewById(R.id.et_caller_tid);
    btn_call = (Button) findViewById(R.id.btn_caller_call);
    btn_login = (Button) findViewById(R.id.btn_caller_login);

    LocalVideoView = (RTCGLVideoView) findViewById(R.id.localView);
    remoteVideoView = (RTCGLVideoView) findViewById(R.id.opponentView);


    btn_login.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            login = et_user.getText().toString();
            password = et_paw.getText().toString();
            initializingQB();
        }
    });
    btn_call.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {


            starcall(Integer.parseInt(et_id.getText().toString()));

        }
    });


}

private void initializingQB() {
    QBSettings.getInstance().init(getApplicationContext(), APP_ID, AUTH_KEY, AUTH_SECRET);
    QBSettings.getInstance().setAccountKey(ACCOUNT_KEY);

    final QBUser user = new QBUser(login, password);

// CREATE SESSION WITH USER
// If you use create session with user data,
// then the user will be logged in automatically
    QBAuth.createSession(login, password, new QBEntityCallback<QBSession>() {
        @Override
        public void onSuccess(QBSession session, Bundle bundle) {

            user.setId(session.getUserId());
            Toast.makeText(MainActivity.this, "Loging in!!!", Toast.LENGTH_LONG).show();
            Log.w("qb", "logedin app");
            // INIT CHAT SERVICE
            chatService = QBChatService.getInstance();
            Log.w("qb", "loging chat");
            // LOG IN CHAT SERVICE
            chatService.login(user, new QBEntityCallback<QBUser>() {


                @Override
                public void onSuccess(QBUser qbUser, Bundle bundle) {
                    Log.w("qb", "loged chat");
                    initQBRTCClient();

                }

                @Override
                public void onError(QBResponseException errors) {
                    Log.w("qb", "not loged\n" + errors.getMessage());
                    //error

                }
            });
        }

        @Override
        public void onError(QBResponseException errors) {
            //error
            Toast.makeText(MainActivity.this, "ERROR!!!\n" + errors.getMessage(), Toast.LENGTH_LONG).show();
        }
    });
}

private void initQBRTCClient() {
    rtcClient = QBRTCClient.getInstance(this);

    // Add signalling manager
    QBChatService.getInstance().getVideoChatWebRTCSignalingManager().addSignalingManagerListener(new QBVideoChatSignalingManagerListener() {
        @Override
        public void signalingCreated(QBSignaling qbSignaling, boolean createdLocally) {
            if (!createdLocally) {
                rtcClient.addSignaling((QBWebRTCSignaling) qbSignaling);
            }
        }
    });

    rtcClient.setCameraErrorHendler(new VideoCapturerAndroid.CameraErrorHandler() {
        @Override
        public void onCameraError(final String s) {
            MainActivity.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, s, Toast.LENGTH_LONG).show();
                }
            });
        }
    });


    // Configure
    //


    QBRTCConfig.setMaxOpponentsCount(2);
    QBRTCConfig.setDisconnectTime(30);
    QBRTCConfig.setAnswerTimeInterval(301);
    QBRTCConfig.setDebugEnabled(true);


    //rtcClient.addVideoTrackCallbacksListener(this);

    // rtcSession.removeVideoTrackCallbacksListener(this);
    // Add activity as callback to RTCClient
    rtcClient.addSessionCallbacksListener(this);

    //rtcClient.addVideoTrackCallbacksListener(this);

    //QBRTCClient.getInstance(this).removeSessionCallbacksListener(this);
    // Start mange QBRTCSessions according to VideoCall parser's callbacks
    rtcClient.prepareToProcessCalls();


}

private void starcall(int tid) {


    //Set conference type
//There are two types of calls:
// - QB_CONFERENCE_TYPE_VIDEO - for video call;
// - QB_CONFERENCE_TYPE_AUDIO - for audio call;
    QBRTCTypes.QBConferenceType qbConferenceType = QBRTCTypes.QBConferenceType.QB_CONFERENCE_TYPE_VIDEO;


//Initiate opponents list
    List<Integer> opponents = new ArrayList<Integer>();
    opponents.add(tid); //12345 - QBUser ID

//Set user information
// User can set any string key and value in user info
// Then retrieve this data from sessions which is returned in callbacks
// and parse them as he wish
    Map<String, String> userInfo = new HashMap<>();
    userInfo.put("key", "value");

//Init session
    QBRTCSession session = rtcClient.createNewSessionWithOpponents(opponents, qbConferenceType);
    session.addVideoTrackCallbacksListener(this);
    session.addSessionCallbacksListener(this);
    session.addSessionCallbacksListener(this);


//Start call
    session.startCall(userInfo);
    Log.w("qb", "startcall: " + String.valueOf(tid));
}


@Override
public void onReceiveNewSession(QBRTCSession qbrtcSession) {
    // obtain received user info
    Map<String, String> userInfo = qbrtcSession.getUserInfo();

    // .....
    // ..... your code
    // .....


    // Set userInfo
    // User can set any string key and value in user info
    userInfo = new HashMap<String, String>();
    userInfo.put("Key", "Value");

    // Accept incoming call

    qbrtcSession.addVideoTrackCallbacksListener(this);
    qbrtcSession.addSessionCallbacksListener(this);
    qbrtcSession.acceptCall(userInfo);

    Log.w("call", "accepted:" + String.valueOf(qbrtcSession.getSessionID()));
}

@Override
public void onUserNotAnswer(QBRTCSession qbrtcSession, Integer integer) {

}

@Override
public void onCallRejectByUser(QBRTCSession qbrtcSession, Integer integer, Map<String, String> map) {

}

@Override
public void onCallAcceptByUser(QBRTCSession qbrtcSession, Integer integer, Map<String, String> map) {


}

@Override
public void onReceiveHangUpFromUser(QBRTCSession qbrtcSession, Integer integer) {

}

@Override
public void onUserNoActions(QBRTCSession qbrtcSession, Integer integer) {

}

@Override
public void onSessionClosed(QBRTCSession qbrtcSession) {

}

@Override
public void onSessionStartClose(QBRTCSession qbrtcSession) {

}


@Override
public void onLocalVideoTrackReceive(QBRTCSession qbrtcSession, QBRTCVideoTrack qbrtcVideoTrack) {
    Log.w("TAG", "onLocalVideoTrackReceive()");
    //  RTCGLVideoView videoView, QBRTCVideoTrack videoTrack, boolean remoteRenderer

    fillVideoView(LocalVideoView, qbrtcVideoTrack, false);

}

@Override
public void onRemoteVideoTrackReceive(QBRTCSession qbrtcSession, QBRTCVideoTrack qbrtcVideoTrack, Integer integer) {
    Log.w("TAG", "onRemoteVideoTrackReceive(),,,");

    fillVideoView(remoteVideoView, qbrtcVideoTrack, true);

}


private void fillVideoView(RTCGLVideoView videoView, QBRTCVideoTrack videoTrack, boolean remoteRenderer) {
    videoTrack.addRenderer(new VideoRenderer(remoteRenderer ?
            videoView.obtainVideoRenderer(RTCGLVideoView.RendererSurface.MAIN) :
            videoView.obtainVideoRenderer(RTCGLVideoView.RendererSurface.SECOND)));
}

@Override
public void onSuccessSendingPacket(QBSignalingSpec.QBSignalCMD qbSignalCMD, Integer integer) {

}

@Override
public void onErrorSendingPacket(QBSignalingSpec.QBSignalCMD qbSignalCMD, Integer integer, QBRTCSignalException e) {

}

@Override
public void onStartConnectToUser(QBRTCSession qbrtcSession, Integer integer) {
    Log.w("connection", "onStartConnectToUser");
}

@Override
public void onConnectedToUser(QBRTCSession qbrtcSession, Integer integer) {
    Log.w("connection", "onConnectedToUser");
}

@Override
public void onConnectionClosedForUser(QBRTCSession qbrtcSession, Integer integer) {
    Log.w("connection", "onConnectionClosedForUser");

}

@Override
public void onDisconnectedFromUser(QBRTCSession qbrtcSession, Integer integer) {
    Log.w("connection", "onDisconnectedFromUser");

}

@Override
public void onDisconnectedTimeoutFromUser(QBRTCSession qbrtcSession, Integer integer) {
    Log.w("connection", "onDisconnectedTimeoutFromUser");

}

@Override
public void onConnectionFailedWithUser(QBRTCSession qbrtcSession, Integer integer) {
    Log.w("connection", "onConnectionFailedWithUser");

}

@Override
public void onError(QBRTCSession qbrtcSession, QBRTCException e) {
    Log.w("connection", "onError");

}
}

布局

    <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"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.hm.runanddelete.MainActivity">




<com.quickblox.videochat.webrtc.view.RTCGLVideoView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/localView"
    android:layout_width="150dp"
    android:layout_height="150dp"
    />

<com.quickblox.videochat.webrtc.view.RTCGLVideoView
    android:id="@+id/opponentView"
    android:layout_width="150dp"
    android:layout_height="150dp"
    android:layout_alignParentBottom="true"
    android:layout_alignRight="@+id/btn_caller_login"
    android:layout_alignEnd="@+id/btn_caller_login" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="LOGIN"
    android:id="@+id/btn_caller_login"
    android:layout_below="@+id/et_caller_pw"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/et_caller_user"
    android:hint="QB USERNAME"
    android:layout_below="@+id/localView"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_marginTop="25dp"
    android:layout_alignRight="@+id/et_caller_pw"
    android:layout_alignEnd="@+id/et_caller_pw"
    android:text="" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/et_caller_pw"
    android:layout_below="@+id/et_caller_user"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/btn_caller_login"
    android:layout_alignEnd="@+id/btn_caller_login"
    android:hint="QB PASSWORD"
    android:text="" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/et_caller_tid"
    android:hint="QB TARGET ID"
    android:layout_below="@+id/et_caller_pw"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_toLeftOf="@+id/btn_caller_login"
    android:layout_toStartOf="@+id/btn_caller_login"
    android:text="" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="MAKE CALL"
    android:id="@+id/btn_caller_call"
    android:layout_below="@+id/et_caller_tid"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignRight="@+id/btn_caller_login"
    android:layout_alignEnd="@+id/btn_caller_login" />

 </RelativeLayout>

如果我错了请纠正我!

更新: 添加 addSessionCallbacksListener 接听电话后登录:

02-23 22:23:09.731 18666-18666/com.hm.runanddelete W/qb: logedin app
02-23 22:23:09.787 18666-18666/com.hm.runanddelete W/qb: loging chat
02-23 22:23:13.051 18666-18958/com.hm.runanddelete W/qb: loged chat
02-23 22:24:10.454 18666-19016/com.hm.runanddelete W/call: accepted:835226fc-d9a5-4bbc-82db-3ad6e0524168
02-23 22:24:11.230 18666-19016/com.hm.runanddelete W/TAG: onLocalVideoTrackReceive()

拨打电话:

02-23 22:25:54.104 20763-20763/com.hm.runanddelete W/qb: logedin app
02-23 22:25:54.163 20763-20763/com.hm.runanddelete W/qb: loging chat
02-23 22:25:59.801 20763-21845/com.hm.runanddelete W/qb: loged chat
02-23 22:26:02.550 20763-20763/com.hm.runanddelete W/qb: startcall: 5510686
02-23 22:26:03.412 20763-21968/com.hm.runanddelete W/TAG: onLocalVideoTrackReceive()

Callback 的onRemoteVideoTrackReceive 方法在与远程轨道建立连接后调用。要监听连接状态更改,您可以通过 rtcSession.addSessionCallbacksListener() 添加 QBRTCSessionConnectionCallbacks 监听器。 peer 建立连接时首先会调用 onStartConnectToUser 方法,然后 onConnectedToUser 然后 peer 将通过 onRemoteVideoTrackReceive 方法接收远程跟踪。 确保调用所有方法。

我相信您面临的问题是在接受呼叫后,呼叫发起者没有收到触发“onCallAcceptByUser”然后开始呈现的接受回调消息远程视频。

您的所有设置似乎都是正确的,使其工作所需的更改是您应该实施“QBRTCSessionConnectionCallbacksQBRTCClientVideoTracksCallbacks " 在不同的 Activity 或片段上。

因此 MainActivity 将实现 QBRTCClientSessionCallbacksQBRTCSessionConnectionCallbacks" 和另一个 Activity 或 Fragment 我们称它为 ConversationFragment 将实现“QBRTCSessionConnectionCallbacksQBRTCClientVideoTracksCallbacks”,在这种情况下,会话实例你在呼叫发起者逻辑中创建,或者您在呼叫接收者逻辑中收到的会话将在 MainActivity 中创建,并使其可供 ConversationFragment 访问以初始化“ QBRTCSessionConnectionCallbacks, QBRTCClientVideoTracksCallbacks".

我没有时间调查这个问题的原因 "Call accept message is not received if all CallBack Listeners are implemented in the same Activity" 以及如何按照上面的解释将它们分开来解决这个问题。但这就是我修复它的方式。

注意:我在 2.5 和 2.5.1 版本上都遇到过这个问题。此修复适用于两者。

如果您需要进一步的帮助,请告诉我。

小更新注: 我在 iOS 上遇到过类似的问题。在视图控制器中创建 QBSession 对象并将其传递给另一个视图控制器会阻止调用 "ConnectedToUser" 回调方法,从而阻止调用完全建立。 要修复它,只需创建 QBSession 或者让我们在处理调用的同一个 ViewController 中调用 "createNewSession"