Skip to content

Instantly share code, notes, and snippets.

@poberwong
Last active December 12, 2017 02:36
Show Gist options
  • Save poberwong/35b698b72de88e382d8daff57d01649e to your computer and use it in GitHub Desktop.
Save poberwong/35b698b72de88e382d8daff57d01649e to your computer and use it in GitHub Desktop.
package com.drr;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Layout;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.RequestCallback;
import com.netease.nimlib.sdk.auth.AuthService;
import com.netease.nimlib.sdk.auth.LoginInfo;
import com.netease.nimlib.sdk.avchat.AVChatCallback;
import com.netease.nimlib.sdk.avchat.AVChatManager;
import com.netease.nimlib.sdk.avchat.AVChatManagerLite;
import com.netease.nimlib.sdk.avchat.model.AVChatExternalVideoRender;
import com.netease.nimlib.sdk.avchat.AVChatStateObserver;
import com.netease.nimlib.sdk.avchat.constant.AVChatEventType;
import com.netease.nimlib.sdk.avchat.constant.AVChatType;
import com.netease.nimlib.sdk.avchat.constant.AVChatVideoScalingType;
import com.netease.nimlib.sdk.avchat.model.AVChatAudioFrame;
import com.netease.nimlib.sdk.avchat.model.AVChatCalleeAckEvent;
import com.netease.nimlib.sdk.avchat.model.AVChatCameraCapturer;
import com.netease.nimlib.sdk.avchat.model.AVChatData;
import com.netease.nimlib.sdk.avchat.model.AVChatI420Frame;
import com.netease.nimlib.sdk.avchat.model.AVChatNetworkStats;
import com.netease.nimlib.sdk.avchat.model.AVChatNotifyOption;
import com.netease.nimlib.sdk.avchat.model.AVChatSessionStats;
import com.netease.nimlib.sdk.avchat.model.AVChatSurfaceViewRenderer;
import com.netease.nimlib.sdk.avchat.model.AVChatVideoCapturerFactory;
import com.netease.nimlib.sdk.avchat.model.AVChatVideoFrame;
import java.util.Map;
public class VideoChatActivity extends AppCompatActivity implements AVChatStateObserver{
/**
* account info
*/
private String account = null;
private String token = null;
private String aimAccount = null;
/**
* view info
*/
private LinearLayout waitingView;
private LinearLayout surfaceRoot;
private LinearLayout localRoot;
private ImageButton bt;
private AVChatSurfaceViewRenderer largeRender;
private AVChatSurfaceViewRenderer miniRender;
/**
* component info
*/
private CallStateEnum callingState = CallStateEnum.INVALID;
private AVChatCameraCapturer mVideoCapturer;
private AVChatData avChatData = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_chat);
bt = (ImageButton) findViewById(R.id.button);
waitingView = (LinearLayout) findViewById(R.id.waiting_screen);
surfaceRoot = (LinearLayout) findViewById(R.id.chatting_surface);
localRoot = (LinearLayout) findViewById(R.id.local_surface);
largeRender = new AVChatSurfaceViewRenderer(this);
miniRender = new AVChatSurfaceViewRenderer(this);
Bundle data = getIntent().getExtras();
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
hangup();
}
});
account = data.getString("account");
token = data.getString("token");
aimAccount = data.getString("aimAccount");
doLogin();
getPermission();
}
public void doLogin() {
LoginInfo info = new LoginInfo(account, token); // config...
RequestCallback<LoginInfo> callback =
new RequestCallback<LoginInfo>() {
@Override
public void onSuccess(LoginInfo param) {
Log.i("nim: ", param.getAccount());
outGoingCalling(aimAccount, AVChatType.VIDEO);
}
@Override
public void onFailed(int code) {
}
@Override
public void onException(Throwable exception) {
}
// 可以在此保存LoginInfo到本地,下次启动APP做自动登录用
};
NIMClient.getService(AuthService.class).login(info)
.setCallback(callback);
}
public void logout () {
NIMClient.getService(AuthService.class).logout();
}
public void hangup () {
if (avChatData == null) {
AVChatManager.getInstance().disableVideo();
AVChatManager.getInstance().disableRtc();
logout();
finish();
} else {
AVChatManager.getInstance().hangUp2(avChatData.getChatId(), new AVChatCallback<Void>() {
@Override
public void onSuccess(Void aVoid) {
AVChatManager.getInstance().disableRtc();
logout();
finish();
}
@Override
public void onFailed(int code) {
}
@Override
public void onException(Throwable exception) {
}
});
}
}
/**
* 拨打音视频
*/
public void outGoingCalling(String account, final AVChatType callTypeEnum) {
AVChatNotifyOption notifyOption = new AVChatNotifyOption();
//附加字段
notifyOption.extendMessage = "extra_data";
//是否兼容WebRTC模式
notifyOption.webRTCCompat = true;
//默认forceKeepCalling为true,开发者如果不需要离线持续呼叫功能可以将forceKeepCalling设为false
notifyOption.forceKeepCalling = false;
//打开Rtc模块
AVChatManager.getInstance().enableRtc();
this.callingState = (callTypeEnum == AVChatType.VIDEO ? CallStateEnum.VIDEO : CallStateEnum.AUDIO);
// //设置自己需要的可选参数
// AVChatManager.getInstance().setParameters(avChatParameters);
//视频通话
if (callTypeEnum == AVChatType.VIDEO) {
//打开视频模块
AVChatManager.getInstance().enableVideo();
AVChatManager.getInstance().startVideoPreview();
//创建视频采集模块并且设置到系统中
if (mVideoCapturer == null) {
mVideoCapturer = AVChatVideoCapturerFactory.createCameraCapturer();
AVChatManager.getInstance().setupVideoCapturer(mVideoCapturer);
}
//设置本地预览画布
// AVChatManager.getInstance().setupLocalVideoRender(textureViewRenderer, false, scalingType);
//开始视频预览
// AVChatManager.getInstance().startVideoPreview();
}
//呼叫
AVChatManager.getInstance().call2(account, callTypeEnum, notifyOption, new AVChatCallback<AVChatData>() {
@Override
public void onSuccess(AVChatData data) {
avChatData = data;
//发起会话成功
Log.i("call nim", "call success");
}
@Override
public void onFailed(int code) {
Log.i("call nim", "call fail" + code);
}
@Override
public void onException(Throwable exception) {
Log.i("call nim", "call ex");
}
});
// 监听对方接听
AVChatManager.getInstance().observeCalleeAckNotification(new Observer<AVChatCalleeAckEvent>() {
@Override
public void onEvent(AVChatCalleeAckEvent ackInfo) {
if (ackInfo.getEvent() == AVChatEventType.CALLEE_ACK_BUSY) {
// 对方正在忙
} else if (ackInfo.getEvent() == AVChatEventType.CALLEE_ACK_REJECT) {
// 对方拒绝接听
} else if (ackInfo.getEvent() == AVChatEventType.CALLEE_ACK_AGREE) {
// 对方同意接听
}
}
}, true);
AVChatManager.getInstance().observeAVChatState(this, true);
}
@Override
public void onTakeSnapshotResult(String account, boolean success, String file) {
}
@Override
public void onAVRecordingCompletion(String account, String filePath) {
}
@Override
public void onAudioRecordingCompletion(String filePath) {
}
@Override
public void onLowStorageSpaceWarning(long availableSize) {
}
@Override
public void onAudioMixingEvent(int event) {
}
@Override
public void onJoinedChannel(int code, String audioFile, String videoFile, int elapsed) {
}
@Override
public void onUserJoined(String account) {
initLargeSurfaceView();
}
@Override
public void onUserLeave(String account, int event) {
}
@Override
public void onLeaveChannel() {
}
@Override
public void onProtocolIncompatible(int status) {
}
@Override
public void onDisconnectServer() {
}
@Override
public void onNetworkQuality(String account, int quality, AVChatNetworkStats stats) {
}
@Override
public void onCallEstablished() {
Log.i("nim", "established");
}
@Override
public void onDeviceEvent(int code, String desc) {
}
@Override
public void onConnectionTypeChanged(int netType) {
}
@Override
public void onFirstVideoFrameAvailable(String account) {
}
@Override
public void onFirstVideoFrameRendered(String account) {
}
@Override
public void onVideoFrameResolutionChanged(String account, int width, int height, int rotate) {
}
@Override
public void onVideoFpsReported(String account, int fps) {
}
@Override
public boolean onVideoFrameFilter(AVChatVideoFrame frame, boolean maybeDualInput) {
return false;
}
@Override
public boolean onAudioFrameFilter(AVChatAudioFrame frame) {
return false;
}
@Override
public void onAudioDeviceChanged(int device) {
}
@Override
public void onReportSpeaker(Map<String, Integer> speakers, int mixedEnergy) {
}
@Override
public void onSessionStats(AVChatSessionStats sessionStats) {
}
@Override
public void onLiveEvent(int event) {
}
/** 获取权限*/
private void getPermission() {
if (Build.VERSION.SDK_INT>22){
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){
//先判断有没有权限 ,没有就在这里进行权限的申请
ActivityCompat.requestPermissions(this,new String[]{
android.Manifest.permission.CAMERA}, 1);
}else {
//说明已经获取到摄像头权限了
Log.i("MainActivity","已经获取了权限");
}
}else {
//这个说明系统版本在6.0之下,不需要动态获取权限。
Log.i("MainActivity","这个说明系统版本在6.0之下,不需要动态获取权限。");
}
}
/**
* 大图像surfaceview 初始化
*
*/
public void initLargeSurfaceView() {
/**
* 设置画布,加入到自己的布局中,用于呈现视频图像
* account 要显示视频的用户帐号x
*/
/**
* 应该是开启推流
*/
AVChatManager.getInstance().muteLocalVideo(false);
Log.i("muted", AVChatManager.getInstance().isLocalVideoMuted() + "");
if (AVChatManager.getInstance().isLocalVideoMuted()) {
AVChatManager.getInstance().muteLocalVideo(false);
}
Log.i("call nim", aimAccount);
AVChatManager.getInstance().setupRemoteVideoRender(aimAccount, largeRender, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);
AVChatManager.getInstance().setupLocalVideoRender(miniRender, false, AVChatVideoScalingType.SCALE_ASPECT_BALANCED);
addIntoRoot(largeRender);
}
private void addIntoRoot (SurfaceView surfaceView) {
if (surfaceView.getParent() != null) {
((ViewGroup) surfaceView.getParent()).removeView(surfaceView);
}
// surfaceView.setZOrderMediaOverlay(false);
waitingView.setVisibility(View.GONE);
localRoot.addView(miniRender);
surfaceRoot.addView(largeRender);
surfaceRoot.setVisibility(View.VISIBLE);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment