Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
YDL-Component-Medical
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
杨凯
YDL-Component-Medical
Commits
2326a717
Commit
2326a717
authored
Mar 19, 2020
by
严久程
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
咨询加声网
parent
71ff661f
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
1539 additions
and
28 deletions
+1539
-28
AndroidManifest.xml
m-audioim/src/main/AndroidManifest.xml
+12
-5
AudioHomeActivity.kt
m-audioim/src/main/java/com/ydl/audioim/AudioHomeActivity.kt
+6
-4
YDLavManager.kt
m-audioim/src/main/java/com/ydl/audioim/YDLavManager.kt
+85
-0
IAudioHomeActivityContract.kt
m-audioim/src/main/java/com/ydl/audioim/contract/IAudioHomeActivityContract.kt
+0
-5
AudioNetAPi.kt
m-audioim/src/main/java/com/ydl/audioim/http/AudioNetAPi.kt
+8
-0
AudioHomePresenterImpl.kt
m-audioim/src/main/java/com/ydl/audioim/presenter/AudioHomePresenterImpl.kt
+0
-14
ConsultantAudioHomeActivity.kt
m-audioim/src/main/java/com/ydl/consultantim/ConsultantAudioHomeActivity.kt
+944
-0
ListenTokenBean.kt
m-audioim/src/main/java/com/ydl/consultantim/bean/ListenTokenBean.kt
+13
-0
ListenTokenCmd.kt
m-audioim/src/main/java/com/ydl/consultantim/command/ListenTokenCmd.kt
+32
-0
IConsultantAudioHomeActivityContract.kt
m-audioim/src/main/java/com/ydl/consultantim/contract/IConsultantAudioHomeActivityContract.kt
+70
-0
AudioHomeEvent.java
m-audioim/src/main/java/com/ydl/consultantim/event/AudioHomeEvent.java
+17
-0
ConsultantAudioHomeModelImpl.kt
m-audioim/src/main/java/com/ydl/consultantim/model/ConsultantAudioHomeModelImpl.kt
+15
-0
ConsultantAudioHomePresenterImpl.kt
m-audioim/src/main/java/com/ydl/consultantim/presenter/ConsultantAudioHomePresenterImpl.kt
+59
-0
ConsultantAudioUtils.kt
m-audioim/src/main/java/com/ydl/consultantim/utils/ConsultantAudioUtils.kt
+43
-0
VibratorUtil.java
m-audioim/src/main/java/com/ydl/consultantim/utils/VibratorUtil.java
+45
-0
audioim_audio_home_img_answer.png
m-audioim/src/main/res/drawable-xhdpi/audioim_audio_home_img_answer.png
+0
-0
audioim_cativity_consultant_audio_home.xml
m-audioim/src/main/res/layout/audioim_cativity_consultant_audio_home.xml
+190
-0
audioim_call_music.mp3
m-audioim/src/main/res/raw/audioim_call_music.mp3
+0
-0
No files found.
m-audioim/src/main/AndroidManifest.xml
View file @
2326a717
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"com.ydl.audioim"
>
package=
"com.ydl.audioim"
>
<uses-permission
android:name=
"android.permission.VIBRATE"
/>
<uses-permission
android:name=
"android.permission.DISABLE_KEYGUARD"
/>
<uses-permission
android:name=
"android.permission.VIBRATE"
/>
<application>
<activity
android:name=
".AudioHomeActivity"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
android:screenOrientation=
"portrait"
/>
android:name=
".AudioHomeActivity"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
android:screenOrientation=
"portrait"
/>
<activity
android:name=
"com.ydl.consultantim.ConsultantAudioHomeActivity"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
android:screenOrientation=
"portrait"
/>
</application>
</manifest>
m-audioim/src/main/java/com/ydl/audioim/AudioHomeActivity.kt
View file @
2326a717
...
...
@@ -70,7 +70,7 @@ import java.util.concurrent.TimeUnit
/**
* @author jiucheng
* @描述: 声网通话页面
* @描述:
倾诉
声网通话页面
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/30
...
...
@@ -632,13 +632,15 @@ class AudioHomeActivity :
.
subscribeOn
(
Schedulers
.
computation
())
.
take
(
303
)
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribe
({
var
result
=
it
.
toFloat
()
/
2.5f
.
subscribe
({
var
result
=
it
.
toFloat
()
/
2.5f
progress_view
.
setProgress
(
result
)
if
(
result
>=
100f
&&
!
iv_hang_up
.
isEnabled
)
{
//挂断按钮可点击
iv_hang_up
.
isEnabled
=
true
iv_hang_up
.
setImageResource
(
R
.
drawable
.
audioim_img_hang_up
)
}},{},{})
}
},
{},
{})
//开始60s等待倒计时
waitDisposable
=
Observable
.
interval
(
0
,
100
,
TimeUnit
.
MILLISECONDS
)
...
...
@@ -1139,7 +1141,7 @@ class AudioHomeActivity :
ModularServiceManager
.
provide
(
IUserService
::
class
.
java
).
getUserInfo
()
?.
uid
!!
var
payLoad
=
PayLoad
(
channelId
?:
"0"
,
time
,
uid
,
"1"
,
"999"
,
message
)
var
connectException
=
ConnectExceptionCommand
(
time
+
zhu
,
"2"
,
"99"
,
payLoad
)
getPresenter
().
connect
Exception
(
connectException
)
YDLavManager
.
instances
.
upload
Exception
(
connectException
)
}
...
...
m-audioim/src/main/java/com/ydl/audioim/YDLavManager.kt
View file @
2326a717
...
...
@@ -9,6 +9,10 @@ import com.ydl.ydl_av.messge_service.callback.InitListener
import
com.ydl.ydl_av.messge_service.callback.LoginCallback
import
com.ydl.ydl_av.messge_service.request.LoginParam
import
com.ydl.audioim.http.AudioApiRequestUtil
import
com.ydl.audioim.http.command.ConnectExceptionCommand
import
com.ydl.ydl_av.messge_service.callback.CallListener
import
com.ydl.ydl_av.messge_service.response.CallLocalResponse
import
com.ydl.ydl_av.messge_service.response.CallRemoteResponse
import
com.ydl.ydlcommon.utils.LogUtil
import
com.ydl.ydlcommon.utils.log.LogHelper
import
io.reactivex.android.schedulers.AndroidSchedulers
...
...
@@ -32,6 +36,71 @@ class YDLavManager {
fun
init
(
context
:
Context
,
appId
:
String
){
YDLRTMClient
.
instances
.
init
(
context
,
appId
,
listener
)
//设置回调
setCallback
()
}
fun
setCallback
()
{
YDLRTMClient
.
instances
.
setCallListener
(
object
:
CallListener
{
override
fun
onCallRecivedByPeer
(
response
:
CallLocalResponse
?)
{
//返回给主叫:被叫已收到呼叫邀请
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]${response?.calleeId}已收到呼叫邀请,频道号${response?.ChannelId}"
)
}
override
fun
onCallAccepted
(
response
:
CallLocalResponse
?,
msg
:
String
?)
{
//返回给主叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]${response?.calleeId}已接收呼叫邀请"
)
}
override
fun
onCallRefused
(
response
:
CallLocalResponse
?,
msg
:
String
?)
{
//返回给主叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]${response?.calleeId}已拒绝呼叫邀请"
)
}
override
fun
onCallCanceled
(
response
:
CallLocalResponse
?)
{
//返回给主叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]主叫已取消呼叫邀请"
)
}
override
fun
onCallFailure
(
response
:
CallLocalResponse
?,
errorCode
:
Int
)
{
//返回给主叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]呼叫${response?.calleeId}用户失败:${response?.response}"
)
}
override
fun
onRemoteInvitationReceived
(
response
:
CallRemoteResponse
?)
{
//返回给被叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]收到来自${response?.callerId}的呼叫邀请"
)
receivedCall
(
response
?.
content
)
}
override
fun
onRemoteInvitationAccepted
(
response
:
CallRemoteResponse
?)
{
//返回给被叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]接受来自${response?.callerId}的呼叫成功"
)
}
override
fun
onRemoteInvitationRefused
(
response
:
CallRemoteResponse
?)
{
//返回给被叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]已拒绝来自${response?.callerId}的呼叫"
)
}
override
fun
onRemoteInvitationCanceled
(
response
:
CallRemoteResponse
?)
{
//返回给被叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]主叫${response?.callerId}已取消呼叫邀请"
)
closePage
(
true
)
}
override
fun
onRemoteInvitationFailure
(
response
:
CallRemoteResponse
?,
errorCode
:
Int
)
{
//返回给被叫
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]来自主叫${response?.callerId}的呼叫邀请进程失败:${response?.response}"
)
//关闭页面
closePage
(
true
)
}
override
fun
onOtherMsg
(
error
:
String
?)
{
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"[agora]其它消息:${error}"
)
}
})
}
@SuppressLint
(
"CheckResult"
)
...
...
@@ -86,6 +155,22 @@ class YDLavManager {
}
/**
* RTM登录异常,上传错误日志 msg
* 声网出现异常,上传错误日志 connectException
*/
@SuppressLint
(
"CheckResult"
)
fun
uploadException
(
connectException
:
ConnectExceptionCommand
)
{
AudioApiRequestUtil
.
connectException
(
connectException
)
.
subscribeOn
(
Schedulers
.
io
())
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribe
({
},
{
com
.
yidianling
.
common
.
tools
.
LogUtil
.
e
(
"agora"
,
"声网上传异常与错误日志接口调用失败:"
+
it
.
message
)
})
}
/**
* 实时消息全局监听
*/
private
val
listener
=
object
:
InitListener
{
...
...
m-audioim/src/main/java/com/ydl/audioim/contract/IAudioHomeActivityContract.kt
View file @
2326a717
...
...
@@ -71,11 +71,6 @@ interface IAudioHomeActivityContract {
*/
// fun connectFinish(param: ConnectFinishCommand)
/**
* 通话异常
*/
fun
connectException
(
param
:
ConnectExceptionCommand
)
/**
* 通知服务端发送推送
...
...
m-audioim/src/main/java/com/ydl/audioim/http/AudioNetAPi.kt
View file @
2326a717
...
...
@@ -2,6 +2,7 @@ package com.ydl.audioim.http
import
com.ydl.audioim.bean.AgoraTokenResponse
import
com.ydl.audioim.bean.ConnectBean
import
com.ydl.consultantim.bean.ListenTokenBean
import
com.ydl.ydlcommon.base.config.YDL_DOMAIN
import
com.ydl.ydlcommon.base.config.YDL_DOMAIN_JAVA
import
com.ydl.ydlcommon.data.http.BaseAPIResponse
...
...
@@ -61,4 +62,10 @@ interface AudioNetAPi {
@GET
(
"im/getAgoraToken"
)
fun
getAgoraToken
():
Observable
<
BaseAPIResponse
<
AgoraTokenResponse
>>
//获取token
@FormUrlEncoded
@POST
(
"listen/token"
)
fun
listenToken
(
@FieldMap
map
:
Map
<
String
,
String
>):
Observable
<
BaseResponse
<
ListenTokenBean
>>
}
\ No newline at end of file
m-audioim/src/main/java/com/ydl/audioim/presenter/AudioHomePresenterImpl.kt
View file @
2326a717
...
...
@@ -66,20 +66,6 @@ class AudioHomePresenterImpl : BasePresenter<IAudioHomeActivityContract.View, IA
// })
// }
@SuppressLint
(
"CheckResult"
)
override
fun
connectException
(
param
:
ConnectExceptionCommand
)
{
mModel
.
connectException
(
param
)
.
subscribeOn
(
Schedulers
.
io
())
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
doOnSubscribe
{
}
.
doAfterTerminate
{
}
.
subscribe
({
},
{
e
->
LogUtil
.
e
(
e
.
message
)
})
}
/**
* 登录声网
...
...
m-audioim/src/main/java/com/ydl/consultantim/ConsultantAudioHomeActivity.kt
0 → 100644
View file @
2326a717
package
com.ydl.consultantim
import
android.Manifest
import
android.annotation.SuppressLint
import
android.content.Context
import
android.content.Intent
import
android.graphics.Color
import
android.graphics.Paint
import
android.hardware.Sensor
import
android.hardware.SensorEvent
import
android.hardware.SensorEventListener
import
android.hardware.SensorManager
import
android.net.Uri
import
android.os.PowerManager
import
android.provider.Settings
import
android.text.TextUtils
import
android.view.View
import
android.view.animation.AccelerateInterpolator
import
com.alibaba.android.arouter.facade.annotation.Route
import
com.alibaba.android.arouter.launcher.ARouter
import
com.google.gson.Gson
import
com.tbruyelle.rxpermissions2.RxPermissions
import
com.ydl.audioim.BuildConfig
import
com.ydl.audioim.R
import
com.ydl.audioim.YDLavManager
import
com.ydl.audioim.http.command.ConnectExceptionCommand
import
com.ydl.audioim.http.command.PayLoad
import
com.ydl.audioim.player.AudioPlayer
import
com.ydl.audioim.utils.AudioLogUtils
import
com.ydl.consultantim.contract.IConsultantAudioHomeActivityContract
import
com.ydl.consultantim.event.AudioHomeEvent
import
com.ydl.consultantim.presenter.ConsultantAudioHomePresenterImpl
import
com.ydl.consultantim.utils.ConsultantAudioUtils
import
com.ydl.consultantim.utils.VibratorUtil
import
com.ydl.ydl_av.chat.bean.AudioMessageBean
import
com.ydl.ydl_av.messge_service.YDLRTMClient
import
com.ydl.ydl_av.voice.listener.IYDLVoiceEventHandler
import
com.ydl.ydl_av.voice.manager.YDLVoiceManager
import
com.ydl.ydl_image.config.SimpleImageOpConfiger
import
com.ydl.ydl_image.manager.YDLImageCacheManager
import
com.ydl.ydl_router.manager.YDLRouterManager
import
com.ydl.ydlcommon.base.BaseMvpActivity
import
com.ydl.ydlcommon.modular.ModularServiceManager
import
com.ydl.ydlcommon.router.YdlCommonRouterManager
import
com.ydl.ydlcommon.utils.ActivityManager
import
com.ydl.ydlcommon.utils.LogUtil
import
com.ydl.ydlcommon.utils.StatusBarUtils
import
com.ydl.ydlcommon.utils.Utils
import
com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import
com.ydl.ydlcommon.utils.log.LogHelper
import
com.ydl.ydlcommon.utils.remind.ToastHelper
import
com.ydl.ydlcommon.view.dialog.CommonDialog
import
com.yidianling.common.tools.RxActivityTool
import
com.yidianling.common.tools.ToastUtil
import
com.yidianling.user.api.service.IUserService
import
de.greenrobot.event.EventBus
import
io.agora.rtc.IRtcEngineEventHandler
import
io.reactivex.Observable
import
io.reactivex.disposables.Disposable
import
io.reactivex.schedulers.Schedulers
import
kotlinx.android.synthetic.main.audioim_cativity_consultant_audio_home.*
import
org.reactivestreams.Subscription
/**
* @author jiucheng
* @描述: 咨询声网通话页面
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/30
*/
@Route
(
path
=
"/av/AudioHomeActivity"
)
class
ConsultantAudioHomeActivity
:
BaseMvpActivity
<
IConsultantAudioHomeActivityContract
.
View
,
IConsultantAudioHomeActivityContract
.
Presenter
>(),
IConsultantAudioHomeActivityContract
.
View
,
SensorEventListener
{
//语音管理类
private
var
voiceManage
:
YDLVoiceManager
?
=
null
//音视频数据
private
var
mAudioMessageBean
:
AudioMessageBean
?
=
null
//音频播放
private
var
mPlayer
:
AudioPlayer
?
=
null
//当前状态 0.未接听 1.已接听
public
var
status
=
STATUS_NOT_ANSWERED
//电源管理对象
private
var
localPowerManager
:
PowerManager
?
=
null
//电源锁
private
var
localWakeLock
:
PowerManager
.
WakeLock
?
=
null
private
var
sensorManager
:
SensorManager
?
=
null
/**
* 通话开始时间(接通)
*/
private
var
callStartTime
:
Long
?
=
null
/**
* 本次倾述倒计时
*/
private
var
totalDisposable
:
Disposable
?
=
null
private
var
ensureDialog
:
CommonDialog
?
=
null
//频道管理器
// private var channelManager: ChannelManager? = null
//频道token
private
var
channelToken
:
String
?
=
null
private
var
hasUpLoadLog
=
false
private
var
dialog
:
CommonDialog
?
=
null
/**
* 事件回调 (SDK 通过指定的事件通知应用程序 SDK 的运行事件,如: 加入或离开频道,新用户加入频道等)
*/
private
val
mRtcEventHandler
=
object
:
IYDLVoiceEventHandler
()
{
/**
* 远端用户静音回调
* @param uid 用户 ID
* @param muted 该用户是否静音:true: 该用户已静音音频 false: 该用户已取消音频静音
*/
override
fun
onUserMuteAudio
(
uid
:
Int
,
muted
:
Boolean
)
{
runOnUiThread
{
showLongToast
(
"[agora]对方静音了,提醒他打开!"
)
}
}
override
fun
onJoinChannelSuccess
(
channel
:
String
?,
uid
:
Int
,
elapsed
:
Int
)
{
super
.
onJoinChannelSuccess
(
channel
,
uid
,
elapsed
)
LogUtil
.
e
(
"[agora]$uid 加入频道回调"
)
// 加入频道后再通知用户已接受
YDLRTMClient
.
instances
.
acceptCall
(
mAudioMessageBean
?.
channelId
)
runOnUiThread
{
tv_toast
.
visibility
=
View
.
VISIBLE
tv_toast
.
text
=
"连接中..."
}
}
override
fun
onUserJoined
(
uid
:
Int
,
elapsed
:
Int
)
{
super
.
onUserJoined
(
uid
,
elapsed
)
LogUtil
.
e
(
"[agora]远端用户加入频道回调"
)
//另一方加入频道成功
runOnUiThread
{
//通话开始,刷新ui开始倒计时
updateStartUi
()
status
=
STATUS_ANSWERED
//接通开始回调
callStartTime
=
System
.
currentTimeMillis
()
}
}
override
fun
onRtcStats
(
stats
:
IRtcEngineEventHandler
.
RtcStats
?)
{
if
(
null
!=
stats
?.
users
&&
stats
.
users
==
1
)
{
ToastUtil
.
toastShort
(
"用户已挂断"
)
//通话结束或挂断时,上传日志文件
uploadLog
()
leaveChannel
()
}
}
override
fun
onConnectionStateChanged
(
state
:
Int
,
reason
:
Int
)
{
super
.
onConnectionStateChanged
(
state
,
reason
)
// 3 网络连接被服务器中止 该情况现在是因为后端踢人逻辑
if
(
reason
==
3
)
{
ToastUtil
.
toastShort
(
"用户已挂断"
)
//通话结束或挂断时,上传日志文件
uploadLog
()
leaveChannel
()
}
}
/**
* 离开频道回调(自己)
*
*/
override
fun
onLeaveChannel
(
stats
:
IRtcEngineEventHandler
.
RtcStats
?)
{
super
.
onLeaveChannel
(
stats
)
LogUtil
.
e
(
"[agora]自己离开频道回调"
)
//通话结束或挂断时,上传日志文件
uploadLog
()
runOnUiThread
{
//通知php 通话已结束
close
(
RESULT_ANSWERED_CODE
,
""
)
}
}
/**
* 主播离开频道回调
* 提示有主播离开了频道(或掉线)。
* SDK 判断用户离开频道(或掉线)的依据是超时:在一定时间内(20 秒)没有收到对方的任何数据包,判定为对方掉线。
* 在网络较差的情况下,可能会有误报。建议可靠的掉线检测应该由信令来做
* @param uid 主播 ID
* @param reason 离线原因:
* USER_OFFLINE_QUIT(0):用户主动离开
* USER_OFFLINE_DROPPED(1):因过长时间收不到对方数据包,超时掉线。注意:由于 SDK 使用的是不可靠通道,也有可能对方主动离开本方没收到对方离开消息而误判为超时掉线
* USER_OFFLINE_BECOME_AUDIENCE(2):用户身份从主播切换为观众(直播模式下)
*/
override
fun
onUserOffline
(
uid
:
Int
,
elapsed
:
Int
)
{
super
.
onUserOffline
(
uid
,
elapsed
)
LogUtil
.
e
(
"[agora]$uid 主播离开频道回调"
)
runOnUiThread
{
showLongToast
(
"用户已挂断"
)
//通话结束或挂断时,上传日志文件
uploadLog
()
if
(
null
!=
totalDisposable
)
{
totalDisposable
!!
.
dispose
()
}
//通知php 通话已结束
close
(
RESULT_ANSWERED_CODE
,
""
)
}
}
/**
* 重新加入频道回调
*/
override
fun
onRejoinChannelSuccess
(
channel
:
String
?,
uid
:
Int
,
elapsed
:
Int
)
{
super
.
onRejoinChannelSuccess
(
channel
,
uid
,
elapsed
)
LogUtil
.
e
(
"[agora]$uid 重新加入频道回调"
)
}
/**
* 网络质量报告回调
* 报告本地用户的网络质量。当你调用 enableLastmileTest 之后,该回调函数每 2 秒触发一次
*/
override
fun
onLastmileQuality
(
quality
:
Int
)
{
super
.
onLastmileQuality
(
quality
)
}
override
fun
onWarning
(
warn
:
Int
)
{
super
.
onWarning
(
warn
)
// 过滤1031 录制声音模糊
if
(
warn
!=
1031
)
{
uploadException
(
"mRtcEventHandler-onWarning:warnCode--%${warn}"
)
}
LogUtil
.
e
(
"[agora]发生警告回调=$warn"
)
//103:没有可用的频道资源。可能是因为服务端没法分配频道资源
//104:查找频道超时。在加入频道时 SDK 先要查找指定的频道,出现该警告一般是因为网络太差,连接不到服务器
//105:查找频道请求被服务器拒绝。服务器可能没有办法处理这个请求或请求是非法的
//106:打开频道超时。查找到指定频道后,SDK 接着打开该频道,超时一般是因为网络太差,连接不到服务器
//107:打开频道请求被服务器拒绝。服务器可能没有办法处理该请求或该请求是非法的
runOnUiThread
{
when
(
warn
)
{
103
,
104
,
105
,
106
,
107
->
{
showLongToast
(
"当前网络较差,请更换网络!"
)
//通话结束或挂断时,上传日志文件
uploadLog
()
close
(
RESULT_NOT_ANSWERED_CODE
,
"[agora]专家网络较差"
)
}
}
}
}
override
fun
onError
(
err
:
Int
)
{
super
.
onError
(
err
)
uploadException
(
"mRtcEventHandler-onError:errorCode--%${err}"
)
LogUtil
.
e
(
"[agora] 发生错误回调 =$err"
)
//3:SDK 初始化失败。Agora 建议尝试以下处理方法
//7:SDK 尚未初始化,就调用其 API。请确认在调用 API 之前已创建 RtcEngine 对象并完成初始化
//10:API 调用超时。有些 API 调用需要 SDK 返回结果,如果 SDK 处理时间过长,超过 10 秒没有返回,会出现此错误
//17:加入频道被拒绝。一般有以下原因:
//用户已进入频道,再次调用加入频道的 API,例如 joinChannel,会返回此错误。停止调用该方法即可。
//用户在做 Echo 测试时尝试加入频道。等待 Echo test 结束后再加入频道即可。
//101:不是有效的 APP ID。请更换有效的 APP ID 重新加入频道
//102:不是有效的 频道名。请更换有效的频道名重新加入频道
//109:当前使用的 Token 过期,不再有效
//110:生成的 Token 无效
//123:此用户被服务器禁止
runOnUiThread
{
when
(
err
)
{
3
,
7
,
109
,
110
->
{
showLongToast
(
"请退出应用,重新打开"
)
close
(
RESULT_NOT_ANSWERED_CODE
,
"咨询师已挂断"
)
}
10
,
17
->
{
showLongToast
(
"当前网络较差,请更换网络"
)
close
(
RESULT_NOT_ANSWERED_CODE
,
"专家网络较差"
)
}
101
->
{
showLongToast
(
"安装包有问题,请联系技术"
)
close
(
RESULT_NOT_ANSWERED_CODE
,
"安装包有问题,请联系技术"
)
}
102
->
{
showLongToast
(
"频道错误,请联系技术"
)
close
(
RESULT_NOT_ANSWERED_CODE
,
"频道错误,请联系技术"
)
}
123
->
{
showLongToast
(
"当前用户不允许接听电话,请联系客服"
)
close
(
RESULT_NOT_ANSWERED_CODE
,
"该专家不允许接听电话,请联系客服"
)
}
else
->
{
}
}
}
}
}
override
fun
createPresenter
():
IConsultantAudioHomeActivityContract
.
Presenter
{
return
ConsultantAudioHomePresenterImpl
()
}
override
fun
layoutResId
():
Int
{
return
R
.
layout
.
audioim_cativity_consultant_audio_home
}
companion
object
{
const
val
PARAM
:
String
=
"param"
//0.未接听 1.已接听
const
val
STATUS_NOT_ANSWERED
=
0
const
val
STATUS_ANSWERED
=
1
//666.未接听,直接挂断 667.已接听,正常挂断 668:未接听,用户端取消了
const
val
RESULT_NOT_ANSWERED_CODE
=
666
const
val
RESULT_ANSWERED_CODE
=
667
const
val
RESULT_USER_CANCEL
=
668
}
override
fun
initDataAndEvent
()
{
EventBus
.
getDefault
().
register
(
this
)
//状态栏颜色
setWindowStatusBarColor
()
//点亮屏幕 并解锁
ConsultantAudioUtils
.
wakeUpAndUnlock
(
this
)
//页面传递数据初始化
getParam
()
//设置信令的回调
setCallback
()
//初始化传感器
initSensorManager
()
initUser
()
initData
()
//获取声网频道号
getChannelToken
()
}
private
fun
setWindowStatusBarColor
()
{
StatusBarUtils
.
setWindowStatusBarColor
(
this
,
R
.
color
.
audioim_color_40353535
)
}
private
fun
getParam
()
{
if
(
null
==
intent
)
{
close
(
RESULT_NOT_ANSWERED_CODE
,
"通话异常"
)
return
}
if
(
null
!=
intent
.
getStringExtra
(
PARAM
))
{
val
json
=
intent
.
getStringExtra
(
PARAM
)
if
(!
TextUtils
.
isEmpty
(
json
))
{
writeAgoraLog
(
json
)
mAudioMessageBean
=
Gson
().
fromJson
(
json
,
AudioMessageBean
::
class
.
java
)
}
}
else
{
close
(
RESULT_NOT_ANSWERED_CODE
,
"通话异常"
)
return
}
}
private
fun
setCallback
()
{
/**
* RTC 回调 在[YDLavManager.setCallback]中注册使用
*/
// YDLRTMClient.instances.setCallListener(object : CallListener {
// override fun onCallRecivedByPeer(response: CallLocalResponse?) {
// //返回给主叫:被叫已收到呼叫邀请
// LogUtil.I("[agora]${response?.calleeId}已收到呼叫邀请,频道号${response?.ChannelId}")
// }
//
// override fun onCallAccepted(response: CallLocalResponse?, msg: String?) {
// //返回给主叫
// LogUtil.I("[agora]${response?.calleeId}已接受呼叫邀请")
// }
//
// override fun onCallRefused(response: CallLocalResponse?, msg: String?) {
// //返回给主叫
// LogUtil.I("[agora]${response?.calleeId}已拒绝呼叫邀请")
// }
//
// override fun onCallCanceled(response: CallLocalResponse?) {
// //返回给主叫
// LogUtil.I("[agora]主叫已取消呼叫邀请")
// }
//
// override fun onCallFailure(response: CallLocalResponse?, errorCode: Int) {
// //返回给主叫
// LogUtil.I("[agora]呼叫${response?.calleeId}用户失败:${response?.response}")
//
// }
//
// override fun onRemoteInvitationReceived(response: CallRemoteResponse?) {
// //返回给被叫
// LogUtil.I("[agora]收到来自${response?.callerId}的呼叫邀请")
// }
//
// override fun onRemoteInvitationAccepted(response: CallRemoteResponse?) {
// //返回给被叫
// LogUtil.I("[agora]接受来自${response?.callerId}的呼叫成功")
// }
//
// override fun onRemoteInvitationRefused(response: CallRemoteResponse?) {
// //返回给被叫
// LogUtil.I("[agora]已拒绝来自${response?.callerId}的呼叫")
// }
//
// override fun onRemoteInvitationCanceled(response: CallRemoteResponse?) {
// //返回给被叫
// LogUtil.I("[agora]主叫${response?.callerId}已取消呼叫邀请")
// }
//
// override fun onRemoteInvitationFailure(response: CallRemoteResponse?, errorCode: Int) {
// //返回给被叫
// LogUtil.I("[agora]来自主叫${response?.callerId}的呼叫邀请进程失败:${response?.response}")
// }
//
// override fun onOtherMsg(error: String?) {
// LogUtil.I("[agora]其它消息:${error}")
// }
// })
// channelManager = YDLRTMClient.instances.createChannelManager(mAudioMessageBean?.channelId, object : ChannelListener {
// override fun onMemberCountUpdated(memberCount: Int) {
// //频道人数更新
// com.yidianling.common.tools.LogUtil.i("[agora]当前频道人数:$memberCount")
// }
//
// override fun onMessageReceived(message: RTMMesssage?, member: ChannelMember?) {
// //接到频道消息
// com.yidianling.common.tools.LogUtil.i("[agora]接到${member?.channelId}频道${member?.userId}的消息:" + message?.text)
// }
//
// override fun onMemberJoined(member: ChannelMember?) {
// //新用户加入频道
// com.yidianling.common.tools.LogUtil.i("[agora]新用户加入${member?.channelId}频道:${member?.userId}")
// }
//
// override fun onMemberLeft(member: ChannelMember?) {
// com.yidianling.common.tools.LogUtil.i("[agora]有用户离开${member?.channelId}频道:${member?.userId}")
// }
// })
}
@SuppressLint
(
"InvalidWakeLockTag"
)
private
fun
initSensorManager
()
{
sensorManager
=
getSystemService
(
Context
.
SENSOR_SERVICE
)
as
SensorManager
?
localPowerManager
=
getSystemService
(
POWER_SERVICE
)
as
PowerManager
?
localWakeLock
=
localPowerManager
!!
.
newWakeLock
(
PowerManager
.
PROXIMITY_SCREEN_OFF_WAKE_LOCK
,
"yidianling"
)
}
/**
* 初始化界面用户信息
*/
private
fun
initUser
()
{
var
userName
=
"倾诉用户"
if
(
null
!=
mAudioMessageBean
)
{
if
(!
TextUtils
.
isEmpty
(
mAudioMessageBean
!!
.
userName
))
{
userName
=
mAudioMessageBean
!!
.
userName
!!
}
if
(!
TextUtils
.
isEmpty
(
mAudioMessageBean
!!
.
userIcon
))
{
var
option
=
SimpleImageOpConfiger
()
option
.
errorPic
=
R
.
drawable
.
audioim_head_place_hold_pic
option
.
loadingPic
=
R
.
drawable
.
audioim_head_place_hold_pic
option
.
transform
=
0
YDLImageCacheManager
.
showImage
(
this
,
mAudioMessageBean
!!
.
userIcon
,
iv_head
,
option
)
}
else
{
iv_head
.
setBackgroundResource
(
R
.
drawable
.
audioim_head_place_hold_pic
)
}
}
else
{
iv_head
.
setBackgroundResource
(
R
.
drawable
.
audioim_head_place_hold_pic
)
}
tv_name
.
text
=
userName
}
private
fun
initData
()
{
wave_view
.
setDuration
(
6000
)
wave_view
.
setStyle
(
Paint
.
Style
.
STROKE
)
wave_view
.
setSpeed
(
1000
)
wave_view
.
setColor
(
Color
.
WHITE
)
wave_view
.
setInitialRadius
(
140f
)
wave_view
.
setInterpolator
(
AccelerateInterpolator
(
1.2f
))
//启动背景动画
wave_view
.
start
()
mPlayer
=
AudioPlayer
(
this
)
mPlayer
!!
.
setDataSource
(
R
.
raw
.
audioim_call_music
)
mPlayer
!!
.
start
(
isLooping
=
true
,
isSetOnCompletionListener
=
false
)
//间接性震动手机
VibratorUtil
.
vibrate
(
AudioHomeActivity
@
this
,
longArrayOf
(
1000
,
1000
,
1000
,
1000
),
true
)
}
/**
* //获取声网频道号
*/
private
fun
getChannelToken
()
{
//获取频道token
mPresenter
.
getChannelToken
(
mAudioMessageBean
,
false
)
}
override
fun
channelTokenResponse
(
token
:
String
?,
needJoinChannel
:
Boolean
)
{
if
(
TextUtils
.
isEmpty
(
token
))
{
LogUtil
.
e
(
"[agora]token not null"
)
ToastUtil
.
toastShort
(
"通话频道不存在"
)
finish
()
return
}
this
.
channelToken
=
token
if
(
needJoinChannel
)
{
//权限申请
requestPermission
()
}
}
//申请音频权限
@SuppressLint
(
"CheckResult"
)
private
fun
requestPermission
()
{
val
rxPermissions
=
RxPermissions
(
this
)
rxPermissions
.
requestEach
(
Manifest
.
permission
.
RECORD_AUDIO
)
.
subscribe
{
permission
->
when
{
//权限已申请 进行初始化操作
permission
.
granted
->
init
()
//权限为申请 重新申请
permission
.
shouldShowRequestPermissionRationale
->
requestPermission
()
//跳转设置界面
else
->
{
ToastHelper
.
show
(
getString
(
R
.
string
.
audioim_need_storage_permission_hint
))
val
intent
=
Intent
(
Settings
.
ACTION_APPLICATION_DETAILS_SETTINGS
)
val
uri
=
Uri
.
fromParts
(
"package"
,
packageName
,
null
)
intent
.
data
=
uri
startActivity
(
intent
)
finish
()
}
}
}
}
private
fun
init
()
{
//初始化语音
initializeAgoraEngine
()
joinChannel
()
}
/**
* 语音通话 初始化
*/
private
fun
initializeAgoraEngine
()
{
/**
* 创建一个实例
* param appId 应用id
* param mRtcEventHandler 事件回调(SDK 通过指定的事件通知应用程序 SDK 的运行事件,如: 加入或离开频道,新用户加入频道等)
*/
voiceManage
=
YDLVoiceManager
(
this
,
BuildConfig
.
AGORA_APPID
,
mRtcEventHandler
)
voiceManage
!!
.
init
()
//默认听筒模式
voiceManage
!!
.
getVoiceApi
().
setEnableSpeakerphone
(
false
)
}
/**
* 更新ui
*/
private
fun
updateUI
()
{
rl_call
.
visibility
=
View
.
GONE
rl_hands_free
.
visibility
=
View
.
VISIBLE
}
/**
* 加入频道
*/
private
fun
joinChannel
()
{
val
account
=
YdlCommonRouterManager
.
getYdlCommonRoute
().
getUid
()
if
(!
TextUtils
.
isEmpty
(
mAudioMessageBean
?.
channelId
))
{
LogUtil
.
e
(
"[agora] joinChannel:$account"
)
voiceManage
?.
getVoiceApi
()
?.
joinChannel
(
channelToken
?:
""
,
mAudioMessageBean
!!
.
channelId
!!
,
"Extra Optional Data"
,
account
)
}
}
override
fun
executeFinish
()
{
//通话结束或挂断时,上传日志文件
uploadLog
()
ToastUtil
.
toastShort
(
"用户已挂断"
)
close
(
RESULT_ANSWERED_CODE
,
""
)
}
/**
* 通话开始后更新ui
*/
private
fun
updateStartUi
()
{
tv_toast
.
text
=
"已接通"
tv_toast
.
postDelayed
({
tv_toast
.
visibility
=
View
.
GONE
},
500
)
rl_remain_time
.
visibility
=
View
.
VISIBLE
}
/**
* 通话结束
*/
private
fun
callFinish
()
{
status
=
STATUS_NOT_ANSWERED
}
/**
* 显示终止服务弹窗
*/
private
fun
showStopService
()
{
if
(
null
==
dialog
)
{
dialog
=
CommonDialog
(
this
)
.
setTitle
(
"温馨提示"
)
.
setMessage
(
"中途挂断可能会影响您在倾听专家榜的排名和曝光率,要谨慎选择哦!"
)
.
setLeftOnclick
(
"点错了"
,
null
)
.
setRightClick
(
"挂断"
)
{
if
(
status
==
STATUS_NOT_ANSWERED
)
{
//通话结束或挂断时,上传日志文件
uploadLog
()
//当未接听 直接挂断 要发送给用户一条消息
close
(
RESULT_NOT_ANSWERED_CODE
,
"咨询师已挂断"
)
}
else
if
(
status
==
STATUS_ANSWERED
)
{
//正常接听 挂断电话 需要重置信令管理类状态
close
(
RESULT_ANSWERED_CODE
,
""
)
}
}
.
setCancelAble
(
true
)
}
if
(
null
!=
dialog
&&
!
isFinishing
)
{
dialog
!!
.
show
()
}
}
override
fun
listenStatusPushResponse
()
{
}
/**
* 挂断
*/
fun
hangUpClick
(
view
:
View
)
{
if
(
Utils
.
isFastClick
())
{
//防止连击
return
}
showStopService
()
ActionCountUtils
.
count
(
"shengwang_popup_layer_page|shengwang_popup_layer_refuse_click"
,
YdlCommonRouterManager
.
getYdlCommonRoute
().
getUid
().
toString
(),
uid
=
YdlCommonRouterManager
.
getYdlCommonRoute
().
getUid
().
toString
()
)
}
/**
* 接听
*/
fun
onCall
(
view
:
View
)
{
if
(
Utils
.
isFastClick
())
{
//防止连击
return
}
//调用接口判断邀请专家的用户当前是否在频道内,如果在,则专家加入频道,如果不在,则提示用户已挂断
//更改逻辑:现在是专家先进频道,这个接口暂时只作为参考
// presenter.userIsInChannel(mAudioMessageBean?.channelId ?: "", mAudioMessageBean?.userId
// ?: "")
executeCall
(
true
)
ActionCountUtils
.
count
(
"shengwang_popup_layer_page|shengwang_popup_layer_answer_click"
,
YdlCommonRouterManager
.
getYdlCommonRoute
().
getUid
().
toString
(),
uid
=
YdlCommonRouterManager
.
getYdlCommonRoute
().
getUid
().
toString
()
)
}
/**
* 执行接听操作
*/
override
fun
executeCall
(
canExcute
:
Boolean
)
{
stopPlaying
()
//停止震动
VibratorUtil
.
StopVibrate
(
this
)
if
(!
canExcute
)
{
ToastUtil
.
toastShort
(
"用户已挂断"
)
finish
()
}
else
{
if
(
null
!=
mAudioMessageBean
)
{
updateUI
()
//专家先加入频道,然后再接受用户邀请,保证专家比用户先加入频道
if
(!
TextUtils
.
isEmpty
(
channelToken
))
{
//权限申请完成后加入频道
requestPermission
()
}
else
{
//获取频道token
mPresenter
.
getChannelToken
(
mAudioMessageBean
)
}
}
}
}
/**
* 打开扬声器 true:开启 false:关闭(听筒)
*/
fun
onSwitchSpeakerphoneClicked
(
view
:
View
)
{
view
.
isSelected
=
!
view
.
isSelected
if
(
view
.
isSelected
)
{
//扬声器模式
iv_hands_free
.
setImageResource
(
R
.
drawable
.
audioim_img_hands_free
)
}
else
{
//听筒模式
iv_hands_free
.
setImageResource
(
R
.
drawable
.
audioim_img_hands_free_unuse
)
}
LogUtil
.
e
(
"http---------------isSelected="
+
!
view
.
isSelected
)
if
(
null
==
voiceManage
||
null
==
voiceManage
!!
.
getVoiceApi
())
{
return
}
voiceManage
!!
.
getVoiceApi
().
setEnableSpeakerphone
(
view
.
isSelected
)
}
override
fun
onResume
()
{
super
.
onResume
()
sensorManager
!!
.
registerListener
(
this
,
sensorManager
!!
.
getDefaultSensor
(
Sensor
.
TYPE_PROXIMITY
),
SensorManager
.
SENSOR_DELAY_NORMAL
)
ActionCountUtils
.
count
(
"shengwang_popup_layer_page|shengwang_popup_layer_page_visit"
,
""
,
uid
=
YdlCommonRouterManager
.
getYdlCommonRoute
().
getUid
().
toString
()
)
}
override
fun
onAccuracyChanged
(
sensor
:
Sensor
?,
accuracy
:
Int
)
{
}
override
fun
onSensorChanged
(
event
:
SensorEvent
?)
{
val
values
=
event
!!
.
values
when
(
event
.
sensor
.
type
)
{
Sensor
.
TYPE_PROXIMITY
->
{
if
(
values
[
0
]
==
0.0f
)
{
//贴近手机
if
(!
localWakeLock
!!
.
isHeld
)
{
localWakeLock
!!
.
acquire
()
}
}
else
{
//离开手机
//唤醒设备
if
(
localWakeLock
!!
.
isHeld
)
{
localWakeLock
!!
.
release
()
}
}
}
}
}
private
fun
showLongToast
(
msg
:
String
)
{
ToastUtil
.
toastLong
(
AudioHomeActivity
@
this
,
msg
)
}
private
fun
showShortToast
(
msg
:
String
)
{
ToastUtil
.
toastLong
(
AudioHomeActivity
@
this
,
msg
)
}
//关闭本页面
fun
close
(
code
:
Int
,
msg
:
String
)
{
LogUtil
.
e
(
"[agora]close(code:$code,msg:$msg)"
)
if
(
status
==
STATUS_ANSWERED
)
{
//不再做操作,原先为调用接口
}
stopMusic
()
//播放结束音频
playFinishMusic
()
if
(
code
==
RESULT_ANSWERED_CODE
)
{
//已接听,正常挂断
//离开频道
leaveChannel
()
}
else
if
(
code
==
RESULT_NOT_ANSWERED_CODE
)
{
//未接听,直接挂断 发送消息
YDLRTMClient
.
instances
.
refuseCall
(
mAudioMessageBean
?.
channelId
)
}
else
if
(
code
==
RESULT_USER_CANCEL
)
{
// ToastUtils.toastShort(this, "用户已挂断")
}
finish
()
}
private
fun
stopMusic
()
{
//停止播放音乐
stopPlaying
()
//停止震动
VibratorUtil
.
StopVibrate
(
AudioHomeActivity
@
this
)
}
/**
* 停止播放
*/
private
fun
stopPlaying
()
{
if
(
mPlayer
!=
null
)
{
mPlayer
!!
.
pause
()
}
}
/**
* 播放结束音频
*/
private
fun
playFinishMusic
()
{
if
(
mPlayer
==
null
)
{
mPlayer
=
AudioPlayer
(
this
)
}
mPlayer
!!
.
setDataSource
(
R
.
raw
.
audioim_hand_down_music
)
// mPlayer!!.switchPlayType(true)
mPlayer
!!
.
start
(
isLooping
=
false
,
isSetOnCompletionListener
=
false
)
}
fun
onEventMainThread
(
event
:
AudioHomeEvent
)
{
stopMusic
()
}
/**
* 离开频道
*/
private
fun
leaveChannel
()
{
uploadException
(
""
,
"zhu"
,
"108"
)
if
(
totalDisposable
!=
null
)
{
totalDisposable
!!
.
dispose
()
}
if
(
null
!=
voiceManage
&&
null
!=
voiceManage
!!
.
getVoiceApi
())
{
voiceManage
!!
.
getVoiceApi
().
leaveChannel
()
voiceManage
!!
.
getVoiceApi
().
destroy
()
voiceManage
=
null
}
if
(
mPlayer
!=
null
)
{
mPlayer
!!
.
clear
()
}
if
(
null
!=
sensorManager
)
{
sensorManager
!!
.
unregisterListener
(
this
)
}
//唤醒设备
if
(
null
!=
localWakeLock
&&
localWakeLock
!!
.
isHeld
)
{
localWakeLock
!!
.
release
()
}
sensorManager
=
null
localWakeLock
=
null
localPowerManager
=
null
}
private
fun
voiceDestory
()
{
if
(
null
!=
voiceManage
&&
null
!=
voiceManage
!!
.
getVoiceApi
())
{
voiceManage
!!
.
getVoiceApi
().
destroy
()
}
voiceManage
=
null
}
/**
* 重写返回键逻辑:屏蔽返回键
*/
override
fun
onBackPressed
()
{
}
private
fun
writeAgoraLog
(
content
:
String
)
{
Observable
.
create
<
Any
>
{
try
{
AudioLogUtils
.
writeAgoraLog
(
content
)
}
catch
(
e
:
Exception
)
{
}
}.
subscribeOn
(
Schedulers
.
io
())
.
subscribe
()
}
/**
* 上传错误日志
*/
private
fun
uploadException
(
message
:
String
,
zhu
:
String
=
""
,
eventType
:
String
=
"99"
)
{
var
time
:
String
=
(
System
.
currentTimeMillis
()
/
1000
).
toString
()
var
uid
:
String
=
ModularServiceManager
.
provide
(
IUserService
::
class
.
java
).
getUserInfo
()
?.
uid
!!
var
payLoad
=
PayLoad
(
mAudioMessageBean
?.
channelId
?:
"0"
,
time
,
uid
,
"1"
,
"999"
,
message
)
var
connectException
=
ConnectExceptionCommand
(
time
+
zhu
,
"2"
,
eventType
,
payLoad
)
YDLavManager
.
instances
.
uploadException
(
connectException
)
}
private
fun
uploadLog
()
{
if
(!
hasUpLoadLog
)
{
hasUpLoadLog
=
true
LogHelper
.
getInstance
().
uploadLog
(
false
)
}
}
fun
showEnsureDialog
()
{
runOnUiThread
{
//停止震动
VibratorUtil
.
StopVibrate
(
this
)
if
(
ensureDialog
==
null
)
{
ensureDialog
=
CommonDialog
(
this
)
.
setMessage
(
"用户已结束通话"
)
.
setRightClick
(
"确定"
)
{
finish
()
}
.
setCancleIsVisibility
(
View
.
GONE
)
.
setCancelAble
(
false
)
}
if
(
null
!=
ensureDialog
&&
!
isFinishing
)
{
ensureDialog
!!
.
show
()
}
}
}
override
fun
onDestroy
()
{
LogUtil
.
e
(
"http-------------onDestory"
)
leaveChannel
()
voiceDestory
()
status
=
STATUS_NOT_ANSWERED
hasUpLoadLog
=
false
EventBus
.
getDefault
().
unregister
(
this
)
if
(
ActivityManager
.
getActivitySize
()
==
1
)
{
try
{
// startActivity(MainActivity.newIntent(this, false))
ARouter
.
getInstance
().
build
(
"/main/main"
)
.
addFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
)
.
navigation
()
}
catch
(
e
:
Exception
)
{
}
}
super
.
onDestroy
()
}
}
m-audioim/src/main/java/com/ydl/consultantim/bean/ListenTokenBean.kt
0 → 100644
View file @
2326a717
package
com.ydl.consultantim.bean
/**
* @author yuanWai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/11/9
*/
data class
ListenTokenBean
(
val
token
:
String
?,
val
expired
:
String
?,
val
type
:
String
?)
\ No newline at end of file
m-audioim/src/main/java/com/ydl/consultantim/command/ListenTokenCmd.kt
0 → 100644
View file @
2326a717
package
com.ydl.consultantim.command
import
com.ydl.ydlcommon.data.http.BaseCommand
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2020/3/19
*/
data class
ListenTokenCmd
(
/**
* 类别 TOKEN|SIGNAL_TOKEN
*/
var
type
:
String
?
=
null
,
/**
* 账号(就是uid)
* 如果是SIGNAL_TOKEN 则需要传递该参数
*/
var
account
:
String
?
=
null
,
/**
* 频道ID
*/
var
channelId
:
String
?
=
null
,
/**
* 过期时间
*/
var
expired
:
String
?
=
null
)
:
BaseCommand
()
\ No newline at end of file
m-audioim/src/main/java/com/ydl/consultantim/contract/IConsultantAudioHomeActivityContract.kt
0 → 100644
View file @
2326a717
package
com.ydl.consultantim.contract
import
com.ydl.ydl_av.chat.bean.AudioMessageBean
import
com.ydl.ydlcommon.mvp.base.IModel
import
com.ydl.ydlcommon.mvp.base.IPresenter
import
com.ydl.ydlcommon.mvp.base.IView
/**
* @author jiucheng
* @描述:声网倾诉首页约束类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/30
*/
interface
IConsultantAudioHomeActivityContract
{
interface
View
:
IView
{
fun
listenStatusPushResponse
()
fun
channelTokenResponse
(
token
:
String
?,
needJoinChannel
:
Boolean
)
// 执行接听操作
// canExcute是否执行
fun
executeCall
(
canExcute
:
Boolean
)
// 关闭当前页面,并提示用户已挂断
fun
executeFinish
()
}
interface
Presenter
:
IPresenter
<
View
>
{
/**
* 通话开始(更新专家状态)
* @param param 请求参数
* @param isSwitchAxb 是否切换axb
*/
// fun connectStart(param: ConnectStartCommand)
/**
* 通话结束(更新专家状态)
* @param param 请求参数
* @param isSwitchAxb 是否切换axb
*/
// fun connectFinish(param: ConnectFinishCommand)
/**
* 获取频道token
*
*/
fun
getChannelToken
(
mAudioMessageBean
:
AudioMessageBean
?,
needJoinChannel
:
Boolean
=
true
)
/**
* 判断用户是否在频道中
*/
fun
userIsInChannel
(
channelName
:
String
,
agoraUid
:
String
)
}
interface
Model
:
IModel
{
/**
* 通话开始回调(更新专家状态)
*/
// fun connectStart(param: ConnectStartCommand)
/**
* 通话结束(更新专家状态)
*/
// fun connectFinish(param: ConnectFinishCommand)
}
}
m-audioim/src/main/java/com/ydl/consultantim/event/AudioHomeEvent.java
0 → 100644
View file @
2326a717
package
com
.
ydl
.
consultantim
.
event
;
/**
* @author yuanWai
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/11/19
*/
public
class
AudioHomeEvent
{
//1.发送停止播放电话铃声和震动
public
int
type
;
public
AudioHomeEvent
(
int
type
){
this
.
type
=
type
;
}
}
m-audioim/src/main/java/com/ydl/consultantim/model/ConsultantAudioHomeModelImpl.kt
0 → 100644
View file @
2326a717
package
com.ydl.consultantim.model
import
com.ydl.consultantim.contract.IConsultantAudioHomeActivityContract
/**
* @author jiucheng
* @描述:声网通话页面数据实现类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/30
*/
class
ConsultantAudioHomeModelImpl
:
IConsultantAudioHomeActivityContract
.
Model
{
}
m-audioim/src/main/java/com/ydl/consultantim/presenter/ConsultantAudioHomePresenterImpl.kt
0 → 100644
View file @
2326a717
package
com.ydl.consultantim.presenter
import
com.ydl.consultantim.command.ListenTokenCmd
import
com.ydl.consultantim.contract.IConsultantAudioHomeActivityContract
import
com.ydl.consultantim.model.ConsultantAudioHomeModelImpl
import
com.ydl.ydl_av.chat.bean.AudioMessageBean
import
com.ydl.ydlcommon.modular.ModularServiceManager
import
com.ydl.ydlcommon.mvp.base.BasePresenter
import
com.yidianling.user.api.service.IUserService
/**
* @author jiucheng
* @描述:声网通话页面逻辑实现类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/10/30
*/
class
ConsultantAudioHomePresenterImpl
:
BasePresenter
<
IConsultantAudioHomeActivityContract
.
View
,
IConsultantAudioHomeActivityContract
.
Model
>(),
IConsultantAudioHomeActivityContract
.
Presenter
{
override
fun
userIsInChannel
(
channelName
:
String
,
agoraUid
:
String
)
{
// RetrofitUtils.userIsInChannel(channelName, agoraUid)
// .subscribeOn(Schedulers.io())
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe({
// view.executeCall(it.data)
// }, {
// LogUtil.e("agora", "专家进入前判断用户是否在频道内接口异常:" + it.message)
// })
}
override
fun
getChannelToken
(
msgBean
:
AudioMessageBean
?,
needJoinChannel
:
Boolean
)
{
if
(
ModularServiceManager
.
provide
(
IUserService
::
class
.
java
).
isLogin
())
{
if
(
null
!=
ModularServiceManager
.
provide
(
IUserService
::
class
.
java
).
getUserInfo
())
{
val
acount
=
ModularServiceManager
.
provide
(
IUserService
::
class
.
java
).
getUserInfo
()
?.
uid
val
tokenParam
=
ListenTokenCmd
()
tokenParam
.
type
=
"TOKEN"
tokenParam
.
account
=
acount
.
toString
()
tokenParam
.
uid
=
acount
.
toString
()
tokenParam
.
channelId
=
msgBean
?.
channelId
//todo
// RetrofitUtils.listenToken(tokenParam)
// .subscribeOn(Schedulers.io())
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe({
// view.channelTokenResponse(it.data.token, needJoinChannel)
// }, {
// RetrofitUtils.handleError(it)
// })
}
}
}
override
fun
createModel
():
IConsultantAudioHomeActivityContract
.
Model
{
return
ConsultantAudioHomeModelImpl
()
}
}
m-audioim/src/main/java/com/ydl/consultantim/utils/ConsultantAudioUtils.kt
0 → 100644
View file @
2326a717
package
com.ydl.consultantim.utils
import
android.annotation.SuppressLint
import
android.app.KeyguardManager
import
android.content.Context
import
android.os.PowerManager
/**
* @author jiucheng
* @描述:
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2020/3/19
*/
class
ConsultantAudioUtils
{
companion
object
{
/**
* 唤醒手机屏幕并解锁
*/
@SuppressLint
(
"InvalidWakeLockTag"
)
fun
wakeUpAndUnlock
(
context
:
Context
)
{
// 获取电源管理器对象
val
pm
=
context
.
applicationContext
.
getSystemService
(
Context
.
POWER_SERVICE
)
as
PowerManager
val
screenOn
=
pm
.
isScreenOn
if
(!
screenOn
)
{
// 获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag
val
wl
=
pm
.
newWakeLock
(
PowerManager
.
ACQUIRE_CAUSES_WAKEUP
or
PowerManager
.
SCREEN_BRIGHT_WAKE_LOCK
,
"bright"
)
wl
.
acquire
(
10000
)
// 点亮屏幕
wl
.
release
()
// 释放
}
// 屏幕解锁
val
keyguardManager
=
context
.
applicationContext
.
getSystemService
(
Context
.
KEYGUARD_SERVICE
)
as
KeyguardManager
val
keyguardLock
=
keyguardManager
.
newKeyguardLock
(
"unLock"
)
// 屏幕锁定
keyguardLock
.
reenableKeyguard
()
keyguardLock
.
disableKeyguard
()
// 解锁
}
}
}
\ No newline at end of file
m-audioim/src/main/java/com/ydl/consultantim/utils/VibratorUtil.java
0 → 100644
View file @
2326a717
package
com
.
ydl
.
consultantim
.
utils
;
import
android.app.Activity
;
import
android.app.Service
;
import
android.os.Vibrator
;
/**
* @author yuanWai
* @描述:震动工具类
* @Copyright Copyright (c) 2018
* @Company 壹点灵
* @date 2018/11/16
*/
public
class
VibratorUtil
{
/**
* final Activity activity :调用该方法的Activity实例 long milliseconds :震动的时长,单位是毫秒
* long[] pattern :自定义震动模式 。数组中数字的含义依次是[静止时长,震动时长,静止时长,震动时长。。。]时长的单位是毫秒
* boolean isRepeat : 是否反复震动,如果是true,反复震动,如果是false,只震动一次
*/
// 一直震动多少秒
public
static
void
vibrate
(
final
Activity
activity
,
long
milliseconds
)
{
Vibrator
vib
=
(
Vibrator
)
activity
.
getSystemService
(
Service
.
VIBRATOR_SERVICE
);
assert
vib
!=
null
;
vib
.
vibrate
(
milliseconds
);
}
// 按照我们传进去的数组进行间歇性的震动
public
static
void
vibrate
(
final
Activity
activity
,
long
[]
pattern
,
boolean
isRepeat
)
{
Vibrator
vib
=
(
Vibrator
)
activity
.
getSystemService
(
Service
.
VIBRATOR_SERVICE
);
assert
vib
!=
null
;
vib
.
vibrate
(
pattern
,
isRepeat
?
1
:
-
1
);
}
// 停止震动
public
static
void
StopVibrate
(
final
Activity
activity
)
{
Vibrator
vib
=
(
Vibrator
)
activity
.
getSystemService
(
Service
.
VIBRATOR_SERVICE
);
assert
vib
!=
null
;
vib
.
cancel
();
}
}
m-audioim/src/main/res/drawable-xhdpi/audioim_audio_home_img_answer.png
0 → 100644
View file @
2326a717
7.8 KB
m-audioim/src/main/res/layout/audioim_cativity_consultant_audio_home.xml
0 → 100644
View file @
2326a717
<?xml version="1.0" encoding="utf-8"?>
<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"
android:background=
"@color/platform_color_80353535"
>
<RelativeLayout
android:id=
"@+id/rl_head"
android:layout_width=
"250dp"
android:layout_height=
"250dp"
android:layout_centerHorizontal=
"true"
android:layout_marginTop=
"74dp"
>
<com.ydl.ydlcommon.view.WaveView
android:id=
"@+id/wave_view"
android:layout_width=
"250dp"
android:layout_height=
"250dp"
android:layout_centerInParent=
"true"
/>
<ImageView
android:layout_width=
"126dp"
android:layout_height=
"126dp"
android:layout_centerInParent=
"true"
android:background=
"@drawable/audioim_head_background"
/>
<ImageView
android:id=
"@+id/iv_head"
android:layout_width=
"120dp"
android:layout_height=
"120dp"
android:layout_centerInParent=
"true"
android:scaleType=
"centerCrop"
android:src=
"@drawable/audioim_head_place_hold_pic"
/>
</RelativeLayout>
<TextView
android:id=
"@+id/tv_name"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_below=
"@+id/rl_head"
android:layout_centerHorizontal=
"true"
android:layout_marginTop=
"-20dp"
android:textColor=
"@color/white"
android:textSize=
"26sp"
tools:text=
"用户"
/>
<!--自定义弹窗-->
<TextView
android:id=
"@+id/tv_toast"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_below=
"@+id/tv_name"
android:layout_centerHorizontal=
"true"
android:layout_marginTop=
"34dp"
android:background=
"@drawable/audioim_toast_view_background"
android:elevation=
"6dp"
android:paddingLeft=
"11dp"
android:paddingTop=
"4dp"
android:paddingRight=
"11dp"
android:paddingBottom=
"4dp"
android:textColor=
"@color/white"
android:visibility=
"gone"
tools:text=
"连接中..."
tools:visibility=
"visible"
/>
<!-- 倾诉剩余时间-->
<RelativeLayout
android:id=
"@+id/rl_remain_time"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_above=
"@+id/rl_hang_up"
android:layout_marginBottom=
"20dp"
android:visibility=
"gone"
tools:visibility=
"visible"
>
<TextView
android:id=
"@+id/tv_notes"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerHorizontal=
"true"
android:text=
"本次倾诉时间还有"
android:textColor=
"@color/platform_color_30FFFFFF"
android:textSize=
"12sp"
/>
<TextView
android:id=
"@+id/tv_remain_time"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_below=
"@+id/tv_notes"
android:layout_centerHorizontal=
"true"
android:text=
"23:23"
android:textColor=
"@color/white"
android:textSize=
"20sp"
/>
</RelativeLayout>
<!--挂断按钮-->
<RelativeLayout
android:id=
"@+id/rl_hang_up"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentBottom=
"true"
android:layout_marginLeft=
"72dp"
android:layout_marginBottom=
"18dp"
android:onClick=
"hangUpClick"
>
<ImageView
android:id=
"@+id/iv_hang_up"
android:layout_width=
"66dp"
android:layout_height=
"66dp"
android:layout_centerHorizontal=
"true"
android:src=
"@drawable/audioim_img_hang_up"
android:visibility=
"visible"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_below=
"@+id/iv_hang_up"
android:layout_centerHorizontal=
"true"
android:layout_marginTop=
"9dp"
android:text=
"挂断"
android:textColor=
"@color/white"
android:textSize=
"12sp"
/>
</RelativeLayout>
<!-- 接听按钮-->
<RelativeLayout
android:id=
"@+id/rl_call"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentRight=
"true"
android:layout_alignParentBottom=
"true"
android:layout_marginRight=
"72dp"
android:layout_marginBottom=
"18dp"
android:onClick=
"onCall"
>
<ImageView
android:id=
"@+id/iv_hands_call"
android:layout_width=
"66dp"
android:layout_height=
"66dp"
android:src=
"@drawable/audioim_audio_home_img_answer"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_below=
"@+id/iv_hands_call"
android:layout_centerHorizontal=
"true"
android:layout_marginTop=
"9dp"
android:text=
"接听"
android:textColor=
"@color/white"
android:textSize=
"12sp"
/>
</RelativeLayout>
<!-- 免提按钮-->
<RelativeLayout
android:id=
"@+id/rl_hands_free"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentRight=
"true"
android:layout_alignParentBottom=
"true"
android:layout_marginRight=
"72dp"
android:layout_marginBottom=
"18dp"
android:onClick=
"onSwitchSpeakerphoneClicked"
android:visibility=
"gone"
>
<ImageView
android:id=
"@+id/iv_hands_free"
android:layout_width=
"66dp"
android:layout_height=
"66dp"
android:src=
"@drawable/audioim_img_hands_free_unuse"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_below=
"@+id/iv_hands_free"
android:layout_centerHorizontal=
"true"
android:layout_marginTop=
"9dp"
android:text=
"免提"
android:textColor=
"@color/white"
android:textSize=
"12sp"
/>
</RelativeLayout>
</RelativeLayout>
\ No newline at end of file
m-audioim/src/main/res/raw/audioim_call_music.mp3
0 → 100644
View file @
2326a717
File added
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment