我正在创建视频通话活动,直到昨天一切正常。今天,我继续开发该应用程序,发现视频通话中没有声音,视频通话正常,但声音丢失了。
strings.xml
中从Agora Dashboard获得的新ID更新项目ID。清单中声明的权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
package sixstrings.guitar.boc;
import android.Manifest;
import android.content.pm.PackageManager;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;
import io.agora.rtc.Constants;
import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoEncoderConfiguration;
import io.agora.rtc.video.VideoCanvas;
public class VideoCall extends AppCompatActivity {
private RtcEngine mRtcEngine;
// Permissions
private static final int PERMISSION_REQ_ID = 22;
private static final String[] REQUESTED_PERMISSIONS = {Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA};
private static final String LOG_TAG = VideoCall.class.getSimpleName();
// Handle SDK Events
private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
@Override
public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// set first remote user to the main bg video container
setupRemoteVideoStream(uid);
}
});
}
// remote user has left channel
@Override
public void onUserOffline(int uid, int reason) { // Tutorial Step 7
runOnUiThread(new Runnable() {
@Override
public void run() {
onRemoteUserLeft();
}
});
}
// remote user has toggled their video
@Override
public void onUserMuteVideo(final int uid, final boolean toggle) { // Tutorial Step 10
runOnUiThread(new Runnable() {
@Override
public void run() {
onRemoteUserVideoToggle(uid, toggle);
}
});
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.video_call_test);
if (checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID) &&
checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID)) {
initAgoraEngine();
}
findViewById(R.id.audioBtn).setVisibility(View.GONE); // set the audio button hidden
findViewById(R.id.leaveBtn).setVisibility(View.GONE); // set the leave button hidden
findViewById(R.id.videoBtn).setVisibility(View.GONE); // set the video button hidden
}
private void initAgoraEngine() {
try {
mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
} catch (Exception e) {
Log.e(LOG_TAG, Log.getStackTraceString(e));
throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
}
setupSession();
}
private void setupSession() {
mRtcEngine.setChannelProfile(Constants.CHANNEL_PROFILE_COMMUNICATION);
mRtcEngine.enableVideo();
mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(VideoEncoderConfiguration.VD_640x480, VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_30,
VideoEncoderConfiguration.STANDARD_BITRATE,
VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT));
}
private void setupLocalVideoFeed() {
// setup the container for the local user
FrameLayout videoContainer = findViewById(R.id.floating_video_container);
SurfaceView videoSurface = RtcEngine.CreateRendererView(getBaseContext());
videoSurface.setZOrderMediaOverlay(true);
videoContainer.addView(videoSurface);
mRtcEngine.setupLocalVideo(new VideoCanvas(videoSurface, VideoCanvas.RENDER_MODE_FIT,0));
}
private void setupRemoteVideoStream(int uid) {
// setup ui element for the remote stream
FrameLayout videoContainer = findViewById(R.id.bg_video_container);
FrameLayout videoContainer2 = findViewById(R.id.floating_video_container2);
FrameLayout videoContainer3 = findViewById(R.id.floating_video_container3);
FrameLayout videoContainer4 = findViewById(R.id.floating_video_container4);
// ignore any new streams that join the session
if (videoContainer.getChildCount() >= 4) {
return;
}
SurfaceView videoSurface = RtcEngine.CreateRendererView(getBaseContext());
SurfaceView videoSurface2 = RtcEngine.CreateRendererView(getBaseContext());
SurfaceView videoSurface3 = RtcEngine.CreateRendererView(getBaseContext());
SurfaceView videoSurface4 = RtcEngine.CreateRendererView(getBaseContext());
videoContainer.addView(videoSurface);
videoContainer2.addView(videoSurface2);
videoContainer3.addView(videoSurface3);
videoContainer4.addView(videoSurface4);
mRtcEngine.setupRemoteVideo(new VideoCanvas(videoSurface, VideoCanvas.RENDER_MODE_FIT, uid));
mRtcEngine.setupRemoteVideo(new VideoCanvas(videoSurface2, VideoCanvas.RENDER_MODE_FIT, uid));
mRtcEngine.setupRemoteVideo(new VideoCanvas(videoSurface3, VideoCanvas.RENDER_MODE_FIT, uid));
mRtcEngine.setupRemoteVideo(new VideoCanvas(videoSurface4, VideoCanvas.RENDER_MODE_FIT, uid));
mRtcEngine.setRemoteSubscribeFallbackOption(io.agora.rtc.Constants.STREAM_FALLBACK_OPTION_AUDIO_ONLY);
}
public void onAudioMuteClicked(View view) {
ImageView btn = (ImageView) view;
if (btn.isSelected()) {
btn.setSelected(false);
btn.setImageResource(R.drawable.ic_mic_black_24dp);
} else {
btn.setSelected(true);
btn.setImageResource(R.drawable.ic_mic_off_black_24dp);
}
mRtcEngine.muteLocalAudioStream(btn.isSelected());
}
public void onVideoMuteClicked(View view) {
ImageView btn = (ImageView) view;
if (btn.isSelected()) {
btn.setSelected(false);
btn.setImageResource(R.drawable.ic_videocam_red_24dp);
} else {
btn.setSelected(true);
btn.setImageResource(R.drawable.ic_videocam_off_black_24dp);
}
mRtcEngine.muteLocalVideoStream(btn.isSelected());
FrameLayout container = findViewById(R.id.floating_video_container);
FrameLayout container2 = findViewById(R.id.floating_video_container2);
FrameLayout container3 = findViewById(R.id.floating_video_container3);
FrameLayout container4 = findViewById(R.id.floating_video_container4);
container.setVisibility(btn.isSelected() ? View.GONE : View.VISIBLE);
container2.setVisibility(btn.isSelected() ? View.GONE : View.VISIBLE);
container3.setVisibility(btn.isSelected() ? View.GONE : View.VISIBLE);
container4.setVisibility(btn.isSelected() ? View.GONE : View.VISIBLE);
SurfaceView videoSurface = (SurfaceView) container.getChildAt(0);
videoSurface.setZOrderMediaOverlay(!btn.isSelected());
videoSurface.setVisibility(btn.isSelected() ? View.GONE : View.VISIBLE);
}
// join the channel when user clicks UI button
public void onjoinChannelClicked(View view) {
mRtcEngine.joinChannel(null, "test-channel", "Extra Optional Data", 0); // if you do not specify the uid, Agora will assign one.
setupLocalVideoFeed();
findViewById(R.id.joinBtn).setVisibility(View.GONE); // set the join button hidden
findViewById(R.id.audioBtn).setVisibility(View.VISIBLE); // set the audio button hidden
findViewById(R.id.leaveBtn).setVisibility(View.VISIBLE); // set the leave button hidden
findViewById(R.id.videoBtn).setVisibility(View.VISIBLE); // set the video button hidden
}
public void onLeaveChannelClicked(View view) {
leaveChannel();
removeVideo(R.id.floating_video_container);
removeVideo(R.id.floating_video_container2);
removeVideo(R.id.floating_video_container4);
removeVideo(R.id.floating_video_container3);
removeVideo(R.id.bg_video_container);
findViewById(R.id.joinBtn).setVisibility(View.VISIBLE); // set the join button visible
findViewById(R.id.audioBtn).setVisibility(View.GONE); // set the audio button hidden
findViewById(R.id.leaveBtn).setVisibility(View.GONE); // set the leave button hidden
findViewById(R.id.videoBtn).setVisibility(View.GONE); // set the video button hidden
}
private void leaveChannel() {
mRtcEngine.leaveChannel();
}
private void removeVideo(int containerID) {
FrameLayout videoContainer = findViewById(containerID);
videoContainer.removeAllViews();
}
private void onRemoteUserVideoToggle(int uid, boolean toggle) {
FrameLayout videoContainer = findViewById(R.id.bg_video_container);
SurfaceView videoSurface = (SurfaceView) videoContainer.getChildAt(0);
videoSurface.setVisibility(toggle ? View.GONE : View.VISIBLE);
// add an icon to let the other user know remote video has been disabled
if(toggle){
ImageView noCamera = new ImageView(this);
noCamera.setImageResource(R.drawable.video_disabled);
videoContainer.addView(noCamera);
} else {
ImageView noCamera = (ImageView) videoContainer.getChildAt(1);
if(noCamera != null) {
videoContainer.removeView(noCamera);
}
}
}
private void onRemoteUserLeft() {
removeVideo(R.id.bg_video_container);
}
public boolean checkSelfPermission(String permission, int requestCode) {
Log.i(LOG_TAG, "checkSelfPermission " + permission + " " + requestCode);
if (ContextCompat.checkSelfPermission(this,
permission)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
REQUESTED_PERMISSIONS,
requestCode);
return false;
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[], @NonNull int[] grantResults) {
Log.i(LOG_TAG, "onRequestPermissionsResult " + grantResults[0] + " " + requestCode);
switch (requestCode) {
case PERMISSION_REQ_ID: {
if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
Log.i(LOG_TAG, "Need permissions " + Manifest.permission.RECORD_AUDIO + "/" + Manifest.permission.CAMERA);
break;
}
initAgoraEngine();
break;
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
leaveChannel();
RtcEngine.destroy();
mRtcEngine = null;
}
public final void showLongToast(final String msg) {
this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
});
}
}
<resources>
<string name="agora_app_id">xxasldfsidfshjdfskdsfsl</string>
<string name="app_name">6 STRINGS </string>
</resources>