您的位置:首页 > 其它

根据环信3.0集成的视频通话

2016-09-29 09:54 204 查看
本项目中我用到的第三方框架:evenbus,和ButterKnife

ButterKnife:

@BindView(R.id.tv_call_state)
TextView callStateTextView;

这句就相当于findViewById

@OnClick(R.id.register)

相当于给这个id设置了点击监听

eventbus:

其实很简单,前面有介绍 ,这里就不多说了

第一步就是当环信官网下载jar包并放入自己的项目里面



整个项目需要那几包类和包如图



在Manifest的要声明的权限和service,activity

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yangzhelin.myvideo30">
<uses-permission android:name="android.permission.VIBRATE" />
<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.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" <
22b21
/span>/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

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

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 设置环信应用的AppKey -->
<meta-data android:name="EASEMOB_APPKEY"  android:value="9i#110" />
<!-- 声明SDK所需的service SDK核心功能-->
<service android:name="com.hyphenate.chat.EMChatService" android:exported="true"/>
<!-- 声明SDK所需的receiver -->
<receiver android:name="com.hyphenate.chat.EMMonitorReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
<!-- 可选filter -->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.USER_PRESENT" />
</intent-filter>
</receiver>
<!-- 视频通话 -->
<activity
android:name=".activities.VideoCallActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:theme="@style/horizontal_slide" >
</activity>
</application>

</manifest>


下面是整个项目的的代码:

package com.example.yangzhelin.myvideo30.app;

import android.app.Application;
import android.content.Context;
import android.content.IntentFilter;

import com.example.yangzhelin.myvideo30.receiver.CallReceiver;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMOptions;

/**
* User:yangzhelin
* Date:2015-09-18
* Time: 11:31
*/
public class App extends Application{
public static Context applicationContext;
private CallReceiver callReceiver;
@Override
public void onCreate() {
super.onCreate();
applicationContext = this;
EMOptions options = new EMOptions();
// 默认添加好友时,是不需要验证的,改成需要验证
options.setAcceptInvitationAlways(false);
EMClient.getInstance().init(applicationContext, options);
//在做打包混淆时,关闭debug模式,避免消耗不必要的资源
EMClient.getInstance().setDebugMode(true);

//注册通话广播接收者
registerReceiver(new CallReceiver(), new IntentFilter(EMClient.getInstance().callManager().getIncomingCallBroadcastAction()));
}

}

/**
* Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*     http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.yangzhelin.myvideo30.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.example.yangzhelin.myvideo30.activities.VideoCallActivity;
import com.example.yangzhelin.myvideo30.DemoHelper;
import com.hyphenate.util.EMLog;

/**
* Created by yangzhelin on 2016/7/28.
*/
public class CallReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
if(!DemoHelper.getInstance().isLoggedIn())
return;
//username
String from = intent.getStringExtra("from");
//call type
String type = intent.getStringExtra("type");
if("video".equals(type)){ //video call
context.startActivity(new Intent(context, VideoCallActivity.class).
putExtra("username", from).putExtra("isComingCall", true).
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}else{ //voice call
//       context.startActivity(new Intent(context, VoiceCallActivity.class).
//             putExtra("username", from).putExtra("isComingCall", true).
//             addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
EMLog.d("CallReceiver", "app received a incoming call");
}

}

package com.example.yangzhelin.myvideo30;

import com.hyphenate.chat.EMClient;

public class DemoHelper {

private static DemoHelper instance = null;
public boolean isVoiceCalling;
public boolean isVideoCalling;
private DemoHelper() {
}

public synchronized static DemoHelper getInstance() {
if (instance == null) {
instance = new DemoHelper();
}
return instance;
}
/**
* if ever logged in
*
* @return
*/
public boolean isLoggedIn() {
return EMClient.getInstance().isLoggedInBefore();
}
}

package com.example.yangzhelin.myvideo30;

import com.halove.android.framework.event.BaseEvent;

/**
* Copyright (2012-2016) by 杭州九爱科技有限公司. All rights reserved
* Comments:
*
* @author yining
*         Created on 2016/7/4
*/

public class ToastEvent extends BaseEvent {
public String text;

public ToastEvent(String text) {
this.text = text;
}

}

package com.example.yangzhelin.myvideo30.util;

import android.content.Context;

/**
* Created by yangzhelin on 2016/7/28.
*/
public interface IVideoManager {
/**注册
* 用户名字
* @param username*
* 用户密码
* @param password
* @return
*/
void register(String username, String password);

/**
* 登入服务器
* @param username
* @param password
*/
void login(String username, String password);

/**
* 登出服务器
*/
void logout();

/**
* 视频聊天
* @param username
*/
void video(String username);

/**
* 语音聊天
* @param username
*/
void voice(String username);

}

package com.example.yangzhelin.myvideo30.util;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.example.yangzhelin.myvideo30.ToastEvent;
import com.example.yangzhelin.myvideo30.activities.VideoCallActivity;
import com.hyphenate.EMCallBack;
import com.hyphenate.chat.EMClient;
import com.hyphenate.exceptions.HyphenateException;

/**
* Created by yangzhelin on 2016/7/28.
*/
public class VideoManager implements IVideoManager {
private static IVideoManager instance = null;
private Context context;

private VideoManager(Context context){
this.context=context;
}

public  synchronized static IVideoManager getInstance(Context context){
if (instance == null) {
instance = new VideoManager(context);
}
return instance;
}
@Override
public void register(final String username, final String password) {
new Thread(new Runnable() {
@Override
public void run() {
//注册失败会抛出HyphenateException
try {
EMClient.getInstance().createAccount(username, password);//同步方法
} catch (final HyphenateException e) {
toast("注册失败"+ e.getMessage());
}
}
}).start();
}

@Override
public void login(String username, String password) {
if(TextUtils.isEmpty(username)){
toast("请输入用户");
return;
}else if(TextUtils.isEmpty(password)){
toast("请输入密码");
return;
}

EMClient.getInstance().login(username,password,new EMCallBack() {//回调
@Override
public void onSuccess() {
EMClient.getInstance().groupManager().loadAllGroups();
EMClient.getInstance().chatManager().loadAllConversations();
Log.d("main", "登录聊天服务器成功!");
toast("登入成功");
}
@Override
public void onProgress(int progress, String status) {

}
@Override
public void onError(int code, String message) {
//                Log.d("main", "登录聊天服务器失败!");
toast("登入失败");
}
});
}

@Override
public void logout() {
new Thread(new Runnable() {
@Override
public void run() {
EMClient.getInstance().logout(true, new EMCallBack() {

@Override
public void onSuccess() {
toast("退出成功");
}
@Override
public void onProgress(int progress, String status) {
}
@Override
public void onError(int code, String message) {

toast("退出失败");
}
});
}
}).start();

}

@Override
public void video(String toUser) {
if (! EMClient.getInstance().isConnected()) {
toast("未连接到服务器");
return;
}else{
if (TextUtils.isEmpty(toUser)){
toast("请填写接受方账号");
return ;
}
Intent intent = new Intent(context, VideoCallActivity.class);
intent.putExtra("username", toUser);
intent.putExtra("isComingCall", false);
context.startActivity(intent);
}
}

@Override
public void voice(String username) {

}
public void toast(final String text){
new ToastEvent(text).fire();

}
}


/**
* Copyright (C) 2016 Hyphenate Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.yangzhelin.myvideo30.activities;

import java.util.UUID;

import com.example.yangzhelin.myvideo30.DemoHelper;
import com.example.yangzhelin.myvideo30.R;
import com.hyphenate.chat.EMCallManager.EMCameraDataProcessor;
import com.hyphenate.chat.EMCallManager.EMVideoCallHelper;
import com.hyphenate.chat.EMCallStateChangeListener;
import com.hyphenate.chat.EMClient;

import com.hyphenate.media.EMLocalSurfaceView;
import com.hyphenate.media.EMOppositeSurfaceView;

import com.hyphenate.util.PathUtil;

import android.hardware.Camera;
import android.media.AudioManager;
import android.media.RingtoneManager;
import android.media.SoundPool;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class VideoCallActivity extends CallActivity {

@BindView(R.id.tv_call_state) TextView callStateTextView;
@BindView(R.id.ll_coming_call)
LinearLayout comingBtnContainer;
@BindView(R.id.btn_refuse_call)
Button refuseBtn;
@BindView(R.id.btn_answer_call)
Button answerBtn;
@BindView(R.id.btn_hangup_call)
Button hangupBtn;
@BindView(R.id.iv_mute)
ImageView muteImage;
@BindView(R.id.iv_handsfree)
ImageView handsFreeImage;
@BindView(R.id.tv_nick)
TextView nickTextView;
@BindView(R.id.chronometer)
Chronometer chronometer;
@BindView(R.id.ll_voice_control)
LinearLayout voiceContronlLayout;
@BindView(R.id.root_layout)
RelativeLayout rootContainer;
@BindView(R.id.ll_btns)
RelativeLayout btnsContainer;
@BindView(R.id.rl_Video_function)
RelativeLayout videoFunction;
@BindView(R.id.ll_top_container)
LinearLayout topContainer;
@BindView(R.id.ll_bottom_container)
LinearLayout bottomContainer;
@BindView(R.id.tv_call_monitor)
TextView monitorTextView;
@BindView(R.id.tv_network_status)
TextView netwrokStatusVeiw;
@BindView(R.id.btn_record_video)
Button recordBtn;
@BindView(R.id.btn_switch_camera)
Button switchCameraBtn;
@BindView(R.id.seekbar_y_detal)
SeekBar YDeltaSeekBar;

private boolean isMuteState;
private boolean isHandsfreeState;
private boolean isAnswered;
private boolean endCallTriggerByMe = false;
private boolean monitor = true;
private boolean isInCalling;
private boolean isRecording = false;
private Handler uiHandler;
private EMVideoCallHelper callHelper;
private BrightnessDataProcess dataProcessor = new BrightnessDataProcess();
// dynamic adjust brightness
class BrightnessDataProcess implements EMCameraDataProcessor {
byte yDelta = 0;
synchronized void setYDelta(byte yDelta) {
Log.d("VideoCallActivity", "brigntness uDelta:" + yDelta);
this.yDelta = yDelta;
}
// data size is width*height*2
// the first width*height is Y, second part is UV
// the storage layout detailed please refer 2.x demo CameraHelper.onPreviewFrame
@Override
public synchronized void onProcessData(byte[] data, Camera camera, int width, int height) {
int wh = width * height;
for (int i = 0; i < wh; i++) {
int d = (data[i] & 0xFF) + yDelta;
d = d < 16 ? 16 : d;
d = d > 235 ? 235 : d;
data[i] = (byte)d;
}
}
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null){
finish();
return;
}
setContentView(R.layout.em_activity_video_call);
ButterKnife.bind(this);
DemoHelper.getInstance().isVideoCalling = true;
callType = 1;

getWindow().addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

uiHandler = new Handler();

YDeltaSeekBar.setOnSeekBarChangeListener(new YDeltaSeekBarListener());

msgid = UUID.randomUUID().toString();
isInComingCall = getIntent().getBooleanExtra("isComingCall", false);
username = getIntent().getStringExtra("username");

nickTextView.setText(username);

localSurface.setZOrderMediaOverlay(true);
localSurface.setZOrderOnTop(true);

// remote surfaceview

// set call state listener
addCallStateListener();
if (!isInComingCall) {// outgoing call
soundPool = new SoundPool(1, AudioManager.STREAM_RING, 0);
outgoing = soundPool.load(this, R.raw.em_outgoing, 1);

comingBtnContainer.setVisibility(View.INVISIBLE);
hangupBtn.setVisibility(View.VISIBLE);
String st = getResources().getString(R.string.Are_connected_to_each_other);
callStateTextView.setText(st);
EMClient.getInstance().callManager().setSurfaceView(localSurface, oppositeSurface);
handler.sendEmptyMessage(MSG_CALL_MAKE_VIDEO);
} else { // incoming call
voiceContronlLayout.setVisibility(View.INVISIBLE);
localSurface.setVisibility(View.INVISIBLE);
Uri ringUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
audioManager.setMode(AudioManager.MODE_RINGTONE);
audioManager.setSpeakerphoneOn(true);
ringtone = RingtoneManager.getRingtone(this, ringUri);
ringtone.play();
EMClient.getInstance().callManager().setSurfaceView(localSurface, oppositeSurface);
}

// get instance of call helper, should be called after setSurfaceView was called
callHelper = EMClient.getInstance().callManager().getVideoCallHelper();

EMClient.getInstance().callManager().setCameraDataProcessor(dataProcessor);
}

class YDeltaSeekBarListener implements SeekBar.OnSeekBarChangeListener {

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
dataProcessor.setYDelta((byte)(20.0f * (progress - 50) / 50.0f));
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}

}

/**
* set call state listener
*/
void addCallStateListener() {
callStateListener = new EMCallStateChangeListener() {

@Override
public void onCallStateChanged(CallState callState, final CallError error) {
switch (callState) {

case CONNECTING: // is connecting
runOnUiThread(new Runnable() {

@Override
public void run() {
callStateTextView.setText(R.string.Are_connected_to_each_other);
}

});
break;
case CONNECTED: // connected
runOnUiThread(new Runnable() {

@Override
public void run() {
callStateTextView.setText(R.string.have_connected_with);
}

});
break;

case ACCEPTED: // call is accepted
handler.removeCallbacks(timeoutHangup);
runOnUiThread(new Runnable() {

@Override
public void run() {
try {
if (soundPool != null)
soundPool.stop(streamID);
} catch (Exception e) {
}
openSpeakerOn();
((TextView)findViewById(R.id.tv_is_p2p)).setText(EMClient.getInstance().callManager().isDirectCall()
? R.string.direct_call : R.string.relay_call);
handsFreeImage.setImageResource(R.drawable.em_icon_speaker_on);
isHandsfreeState = true;
isInCalling = true;
chronometer.setVisibility(View.VISIBLE);
chronometer.setBase(SystemClock.elapsedRealtime());
// call durations start
chronometer.start();
nickTextView.setVisibility(View.INVISIBLE);
callStateTextView.setText(R.string.In_the_call);
recordBtn.setVisibility(View.VISIBLE);
callingState = CallingState.NORMAL;
// startMonitor();
}

});
break;
case NETWORK_UNSTABLE:
runOnUiThread(new Runnable() {
public void run() {
netwrokStatusVeiw.setVisibility(View.VISIBLE);
if(error == CallError.ERROR_NO_DATA){
netwrokStatusVeiw.setText(R.string.no_call_data);
}else{
netwrokStatusVeiw.setText(R.string.network_unstable);
}
}
});
break;
case NETWORK_NORMAL:

runOnUiThread(new Runnable() {
public void run() {
netwrokStatusVeiw.setVisibility(View.INVISIBLE);
}
});
break;
case VIDEO_PAUSE:
toastByUi("VIDEO_PAUSE");
break;
case VIDEO_RESUME:
toastByUi("VIDEO_RESUME");
break;
case VOICE_PAUSE:
toastByUi("VOICE_PAUSE");
break;
case VOICE_RESUME:
toastByUi("VOICE_RESUME");
break;
case DISCONNNECTED: // call is disconnected
handler.removeCallbacks(timeoutHangup);
final CallError fError = error;
runOnUiThread(new Runnable() {
private void postDelayedCloseMsg() {
uiHandler.postDelayed(new Runnable() {

@Override
public void run() {
saveCallRecord();
Animation animation = new AlphaAnimation(1.0f, 0.0f);
animation.setDuration(800);
rootContainer.startAnimation(animation);
finish();
}

}, 200);
}

@Override
public void run() {
chronometer.stop();
callDruationText = chronometer.getText().toString();
String s1 = getResources().getString(R.string.The_other_party_refused_to_accept);
String s2 = getResources().getString(R.string.Connection_failure);
String s3 = getResources().getString(R.string.The_other_party_is_not_online);
String s4 = getResources().getString(R.string.The_other_is_on_the_phone_please);
String s5 = getResources().getString(R.string.The_other_party_did_not_answer);

String s6 = getResources().getString(R.string.hang_up);
String s7 = getResources().getString(R.string.The_other_is_hang_up);
String s8 = getResources().getString(R.string.did_not_answer);
String s9 = getResources().getString(R.string.Has_been_cancelled);

if (fError == CallError.REJECTED) {
callingState = CallingState.BEREFUESD;
callStateTextView.setText(s1);
} else if (fError == CallError.ERROR_TRANSPORT) {
callStateTextView.setText(s2);
} else if (fError == CallError.ERROR_INAVAILABLE) {
callingState = CallingState.OFFLINE;
callStateTextView.setText(s3);
} else if (fError == CallError.ERROR_BUSY) {
callingState = CallingState.BUSY;
callStateTextView.setText(s4);
} else if (fError == CallError.ERROR_NORESPONSE) {
callingState = CallingState.NORESPONSE;
callStateTextView.setText(s5);
}else if (fError == CallError.ERROR_LOCAL_VERSION_SMALLER || fError == CallError.ERROR_PEER_VERSION_SMALLER){
callingState = CallingState.VERSION_NOT_SAME;
callStateTextView.setText(R.string.call_version_inconsistent);
} else {
if (isAnswered) {
callingState = CallingState.NORMAL;
if (endCallTriggerByMe) {
// callStateTextView.setText(s6);
} else {
callStateTextView.setText(s7);
}
} else {
if (isInComingCall) {
callingState = CallingState.UNANSWERED;
callStateTextView.setText(s8);
} else {
if (callingState != CallingState.NORMAL) {
callingState = CallingState.CANCED;
callStateTextView.setText(s9);
} else {
callStateTextView.setText(s6);
}
}
}
}
postDelayedCloseMsg();
}

});

break;

default:
break;
}

}
};
EMClient.getInstance().callManager().addCallStateChangeListener(callStateListener);
}
public void toastByUi(final String text){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(VideoCallActivity.this, text, Toast.LENGTH_SHORT).show();
}
});
}

@OnClick(R.id.btn_refuse_call)
public void btn_refuse_call(){
refuseBtn.setEnabled(false);
handler.sendEmptyMessage(MSG_CALL_REJECT);
}
@OnClick(R.id.btn_answer_call)
public void btn_answer_call(){
answerBtn.setEnabled(false);
openSpeakerOn();
if (ringtone != null)
ringtone.stop();

callStateTextView.setText("answering...");
handler.sendEmptyMessage(MSG_CALL_ANSWER);
handsFreeImage.setImageResource(R.drawable.em_icon_speaker_on);
isAnswered = true;
isHandsfreeState = true;
comingBtnContainer.setVisibility(View.INVISIBLE);
hangupBtn.setVisibility(View.VISIBLE);
voiceContronlLayout.setVisibility(View.VISIBLE);
localSurface.setVisibility(View.VISIBLE);
}
@OnClick(R.id.btn_hangup_call)
public void btn_hangup_call(){
hangupBtn.setEnabled(false);
chronometer.stop();
endCallTriggerByMe = true;
callStateTextView.setText(getResources().getString(R.string.hanging_up));
if(isRecording){
callHelper.stopVideoRecord();
}
handler.sendEmptyMessage(MSG_CALL_END);
}
@OnClick(R.id.iv_mute)
public void iv_mute(){
if (isMuteState) {
// resume voice transfer
muteImage.setImageResource(R.drawable.em_icon_mute_normal);
EMClient.getInstance().callManager().resumeVoiceTransfer();
isMuteState = false;
} else {
// pause voice transfer
muteImage.setImageResource(R.drawable.em_icon_mute_on);
EMClient.getInstance().callManager().pauseVoiceTransfer();
isMuteState = true;
}
}
@OnClick(R.id.iv_handsfree)
public void iv_handsfree(){
if (isHandsfreeState) {
// turn off speaker
handsFreeImage.setImageResource(R.drawable.em_icon_speaker_normal);
closeSpeakerOn();
isHandsfreeState = false;
} else {
handsFreeImage.setImageResource(R.drawable.em_icon_speaker_on);
openSpeakerOn();
isHandsfreeState = true;
}
}
@OnClick(R.id.btn_record_video)
public void btn_record_video(){
if(!isRecording){
callHelper.startVideoRecord(PathUtil.getInstance().getVideoPath().getAbsolutePath());
isRecording = true;
recordBtn.setText(R.string.stop_record);
}else{
String filepath = callHelper.stopVideoRecord();
isRecording = false;
recordBtn.setText(R.string.recording_video);
Toast.makeText(getApplicationContext(), String.format(getString(R.string.record_finish_toast), filepath), Toast.LENGTH_LONG).show();
}
}
@OnClick(R.id.root_layout)
public void root_layout(){
if (callingState == CallingState.NORMAL) {
if (bottomContainer.getVisibility() == View.VISIBLE) {
bottomContainer.setVisibility(View.GONE);
topContainer.setVisibility(View.GONE);
videoFunction.setVisibility(View.GONE);

} else {
bottomContainer.setVisibility(View.VISIBLE);
topContainer.setVisibility(View.VISIBLE);
videoFunction.setVisibility(View.VISIBLE);
}
}
}
@OnClick(R.id.btn_switch_camera)
public void btn_switch_camera(){
handler.sendEmptyMessage(MSG_CALL_SWITCH_CAMERA);
}

@Override
protected void onDestroy() {
DemoHelper.getInstance().isVideoCalling = false;
stopMonitor();
if(isRecording){
callHelper.stopVideoRecord();
isRecording = false;
}
localSurface = null;
oppositeSurface = null;
super.onDestroy();
}

@Override
public void onBackPressed() {
callDruationText = chronometer.getText().toString();
super.onBackPressed();
}

/**
* for debug & testing, you can remove this when release
*/
void startMonitor(){
new Thread(new Runnable() {
public void run() {
while(monitor){
runOnUiThread(new Runnable() {
public void run() {
monitorTextView.setText("WidthxHeight"+callHelper.getVideoWidth()+"x"+callHelper.getVideoHeight()
+ "\nDelay" + callHelper.getVideoTimedelay()
+ "\nFramerate" + callHelper.getVideoFramerate()
+ "\nLost" + callHelper.getVideoLostcnt()
+ "\nLocalBitrate" + callHelper.getLocalBitrate()
+ "\nRemoteBitrate" + callHelper.getRemoteBitrate());

}
});
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
}
}
}
}).start();
}

void stopMonitor(){
monitor = false;
}

@Override
protected void onUserLeaveHint() {
super.onUserLeaveHint();
if(isInCalling){
EMClient.getInstance().callManager().pauseVideoTransfer();
}
}

@Override
protected void onResume() {
super.onResume();
if(isInCalling){
EMClient.getInstance().callManager().resumeVideoTransfer();
}
}

}

package com.example.yangzhelin.myvideo30.activities;

import com.example.yangzhelin.myvideo30.R;
import com.hyphenate.chat.EMCallStateChangeListener;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMMessage;
import com.hyphenate.chat.EMMessage.Status;
import com.hyphenate.chat.EMTextMessageBody;

import com.hyphenate.exceptions.EMServiceNotReadyException;
import com.hyphenate.media.EMLocalSurfaceView;
import com.hyphenate.media.EMOppositeSurfaceView;
import com.hyphenate.util.EMLog;
import com.hyphenate.util.NetUtils;

import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.widget.Toast;

import butterknife.BindView;

public class CallActivity extends Activity {
protected final int MSG_CALL_MAKE_VIDEO = 0;
protected final int MSG_CALL_MAKE_VOICE = 1;
protected final int MSG_CALL_ANSWER = 2;
protected final int MSG_CALL_REJECT = 3;
protected final int MSG_CALL_END = 4;
protected final int MSG_CALL_RLEASE_HANDLER = 5;
protected final int MSG_CALL_SWITCH_CAMERA = 6;

protected boolean isInComingCall;
protected String username;
protected CallingState callingState = CallingState.CANCED;
protected String callDruationText;
protected String msgid;
protected AudioManager audioManager;
protected SoundPool soundPool;
protected Ringtone ringtone;
protected int outgoing;
protected EMCallStateChangeListener callStateListener;
@BindView(R.id.local_surface)
protected EMLocalSurfaceView localSurface;
@BindView(R.id.opposite_surface)
protected EMOppositeSurfaceView oppositeSurface;
protected boolean isAnswered = false;
protected int streamID = -1;

/**
* 0:voice call,1:video call
*/
protected int callType = 0;

@Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
audioManager = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
}

@Override
protected void onDestroy() {
if (soundPool != null)
soundPool.release();
if (ringtone != null && ringtone.isPlaying())
ringtone.stop();
audioManager.setMode(AudioManager.MODE_NORMAL);
audioManager.setMicrophoneMute(false);

if(callStateListener != null)
EMClient.getInstance().callManager().removeCallStateChangeListener(callStateListener);
releaseHandler();
super.onDestroy();
}

@Override
public void onBackPressed() {
handler.sendEmptyMessage(MSG_CALL_END);
saveCallRecord();
finish();
super.onBackPressed();
}

Runnable timeoutHangup = new Runnable() {

@Override
public void run() {
handler.sendEmptyMessage(MSG_CALL_END);
}
};

HandlerThread callHandlerThread = new HandlerThread("callHandlerThread");
{ callHandlerThread.start(); }
protected Handler handler = new Handler(callHandlerThread.getLooper()) {
@Override
public void handleMessage(Message msg) {
EMLog.d("EMCallManager CallActivity", "handleMessage ---enter--- msg.what:" + msg.what);
switch (msg.what) {
case MSG_CALL_MAKE_VIDEO:
case MSG_CALL_MAKE_VOICE:
try {
streamID = playMakeCallSounds();
if (msg.what == MSG_CALL_MAKE_VIDEO) {
EMClient.getInstance().callManager().makeVideoCall(username);
} else {
EMClient.getInstance().callManager().makeVoiceCall(username);
}

final int MAKE_CALL_TIMEOUT = 50 * 1000;
handler.removeCallbacks(timeoutHangup);
handler.postDelayed(timeoutHangup, MAKE_CALL_TIMEOUT);
} catch (EMServiceNotReadyException e) {
e.printStackTrace();
runOnUiThread(new Runnable() {
public void run() {
final String st2 = getResources().getString(R.string.Is_not_yet_connected_to_the_server);
Toast.makeText(CallActivity.this, st2, Toast.LENGTH_SHORT).show();
}
});
}
break;
case MSG_CALL_ANSWER:
if (ringtone != null)
ringtone.stop();
if (isInComingCall) {
try {
if (NetUtils.hasDataConnection(CallActivity.this)) {
EMClient.getInstance().callManager().answerCall();
isAnswered = true;
} else {
runOnUiThread(new Runnable() {
public void run() {
final String st2 = getResources().getString(R.string.Is_not_yet_connected_to_the_server);
Toast.makeText(CallActivity.this, st2, Toast.LENGTH_SHORT).show();
}
});
throw new Exception();
}
} catch (Exception e) {
e.printStackTrace();
saveCallRecord();
finish();
return;
}
}
break;
case MSG_CALL_REJECT:
if (ringtone != null)
ringtone.stop();
try {
EMClient.getInstance().callManager().rejectCall();
} catch (Exception e1) {
e1.printStackTrace();
saveCallRecord();
finish();
}
callingState = CallingState.REFUESD;
break;
case MSG_CALL_END:
if (soundPool != null)
soundPool.stop(streamID);
try {
EMClient.getInstance().callManager().endCall();
} catch (Exception e) {
saveCallRecord();
finish();
}

break;
case MSG_CALL_RLEASE_HANDLER:
try {
EMClient.getInstance().callManager().endCall();
} catch (Exception e) {
e.printStackTrace();
}
handler.removeCallbacks(timeoutHangup);
handler.removeMessages(MSG_CALL_MAKE_VIDEO);
handler.removeMessages(MSG_CALL_MAKE_VOICE);
handler.removeMessages(MSG_CALL_ANSWER);
handler.removeMessages(MSG_CALL_REJECT);
handler.removeMessages(MSG_CALL_END);
callHandlerThread.quit();
break;
case MSG_CALL_SWITCH_CAMERA:
EMClient.getInstance().callManager().switchCamera();
break;
default:
break;
}
EMLog.d("EMCallManager CallActivity", "handleMessage ---exit--- msg.what:" + msg.what);
}
};

void releaseHandler() {
handler.sendEmptyMessage(MSG_CALL_RLEASE_HANDLER);
}

/**
* play the incoming call ringtone
*
*/
protected int playMakeCallSounds() {
try {
// max volume
float audioMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
// current volume
float audioCurrentVolume = audioManager.getStreamVolume(AudioManager.STREAM_RING);
float volumeRatio = audioCurrentVolume / audioMaxVolume;

audioManager.setMode(AudioManager.MODE_RINGTONE);
audioManager.setSpeakerphoneOn(false);

// play
int id = soundPool.play(outgoing, // sound resource
0.3f, // left volume
0.3f, // right volume
1,    // priority
-1,   // loop,0 is no loop,-1 is loop forever
1);   // playback rate (1.0 = normal playback, range 0.5 to 2.0)
return id;
} catch (Exception e) {
return -1;
}
}

protected void openSpeakerOn() {
try {
if (!audioManager.isSpeakerphoneOn())
audioManager.setSpeakerphoneOn(true);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
} catch (Exception e) {
e.printStackTrace();
}
}

protected void closeSpeakerOn() {

try {
if (audioManager != null) {
// int curVolume =
// audioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
if (audioManager.isSpeakerphoneOn())
audioManager.setSpeakerphoneOn(false);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
// audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
// curVolume, AudioManager.STREAM_VOICE_CALL);

}

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* save call record
*/
protected void saveCallRecord() {
EMMessage message = null;
EMTextMessageBody txtBody = null;
if (!isInComingCall) { // outgoing call
message = EMMessage.createSendMessage(EMMessage.Type.TXT);
message.setReceipt(username);
} else {
message = EMMessage.createReceiveMessage(EMMessage.Type.TXT);
message.setFrom(username);
}

String st1 = getResources().getString(R.string.call_duration);
String st2 = getResources().getString(R.string.Refused);
String st3 = getResources().getString(R.string.The_other_party_has_refused_to);
String st4 = getResources().getString(R.string.The_other_is_not_online);
String st5 = getResources().getString(R.string.The_other_is_on_the_phone);
String st6 = getResources().getString(R.string.The_other_party_did_not_answer);
String st7 = getResources().getString(R.string.did_not_answer);
String st8 = getResources().getString(R.string.Has_been_cancelled);
switch (callingState) {
case NORMAL:
txtBody = new EMTextMessageBody(st1 + callDruationText);
break;
case REFUESD:
txtBody = new EMTextMessageBody(st2);
break;
case BEREFUESD:
txtBody = new EMTextMessageBody(st3);
break;
case OFFLINE:
txtBody = new EMTextMessageBody(st4);
break;
case BUSY:
txtBody = new EMTextMessageBody(st5);
break;
case NORESPONSE:
txtBody = new EMTextMessageBody(st6);
break;
case UNANSWERED:
txtBody = new EMTextMessageBody(st7);
break;
case VERSION_NOT_SAME:
txtBody = new EMTextMessageBody(getString(R.string.call_version_inconsistent));
default:
txtBody = new EMTextMessageBody(st8);
break;
}
// set message extension
if(callType == 0){
message.setAttribute(MESSAGE_ATTR_IS_VOICE_CALL, true);
}
else {
message.setAttribute(MESSAGE_ATTR_IS_VIDEO_CALL, true);
}
// set message body
message.addBody(txtBody);
message.setMsgId(msgid);
message.setStatus(Status.SUCCESS);

// save
EMClient.getInstance().chatManager().saveMessage(message);
}

enum CallingState {
CANCED, NORMAL, REFUESD, BEREFUESD, UNANSWERED, OFFLINE, NORESPONSE, BUSY, VERSION_NOT_SAME
}
public static final String MESSAGE_ATTR_IS_VOICE_CALL = "is_voice_call";
public static final String MESSAGE_ATTR_IS_VIDEO_CALL = "is_video_call";
}
package com.example.yangzhelin.myvideo30.activities;

import android.os.Bundle;
import android.widget.EditText;
import android.widget.Toast;
import com.example.yangzhelin.myvideo30.R;
import com.example.yangzhelin.myvideo30.ToastEvent;
import com.example.yangzhelin.myvideo30.util.IVideoManager;
import com.example.yangzhelin.myvideo30.util.VideoManager;
import com.halove.android.framework.base.BaseActivity;
import org.greenrobot.eventbus.Subscribe;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends BaseActivity  {
@BindView(R.id.username)
EditText username;
@BindView(R.id.password)
EditText password;
@BindView(R.id.to)
EditText to;
private IVideoManager videoManger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
videoManger = VideoManager.getInstance(this);
}
@OnClick(R.id.register)
void register() {
String u = username.getText().toString().trim();
String p = password.getText().toString().trim();
videoManger.register(u, p);
}
@OnClick(R.id.login)
void login() {
String u = username.getText().toString().trim();
String p = password.getText().toString().trim();
videoManger.login(u, p);
}
@OnClick(R.id.logout)
public void logout() {
videoManger.logout();
}
@OnClick(R.id.voice)
public void voice() {
toast("未开通此功能");
}
@OnClick(R.id.video)
public void video() {
String toUser = to.getText().toString();
videoManger.video(toUser);
}
@Override
protected void onDestroy() {
logout();
super.onDestroy();
}
@Subscribe
public void showMessageToUser(ToastEvent event) {
final String msg=event.text;
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
}
});
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: