ConsultantAudioHomeActivity.kt 41.5 KB
Newer Older
严久程 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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
刘鹏 committed
19
import androidx.core.content.ContextCompat
严久程 committed
20 21 22 23 24 25 26 27 28 29 30
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
严久程 committed
31
import com.ydl.audioim.utils.DateUtils
严久程 committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
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.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.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
50
import com.ydl.ydlcommon.utils.log.AliYunLogConfig
51
import com.ydl.ydlcommon.utils.log.AliYunRichLogsHelper
严久程 committed
52 53 54 55
import com.ydl.ydlcommon.utils.log.LogHelper
import com.ydl.ydlcommon.utils.remind.ToastHelper
import com.yidianling.user.api.service.IUserService
import de.greenrobot.event.EventBus
严久程 committed
56
import io.agora.rtc.Constants
严久程 committed
57 58
import io.agora.rtc.IRtcEngineEventHandler
import io.reactivex.Observable
严久程 committed
59
import io.reactivex.android.schedulers.AndroidSchedulers
严久程 committed
60 61 62
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.audioim_cativity_consultant_audio_home.*
YKai committed
63
import java.util.*
严久程 committed
64
import java.util.concurrent.TimeUnit
严久程 committed
65 66 67

/**
 * @author jiucheng
YKai committed
68
 * @描述: 咨询声网通话页面(用户接受电话界面)
严久程 committed
69 70 71 72
 * @Copyright Copyright (c) 2018
 * @Company 壹点灵
 * @date 2018/10/30
 */
严久程 committed
73
@Route(path = "/av/ConsultantAudioHomeActivity")
74 75 76
class ConsultantAudioHomeActivity :
    BaseMvpActivity<IConsultantAudioHomeActivityContract.View, IConsultantAudioHomeActivityContract.Presenter>(),
    IConsultantAudioHomeActivityContract.View, SensorEventListener {
严久程 committed
77 78 79

    //语音管理类
    private var voiceManage: YDLVoiceManager? = null
80

严久程 committed
81 82
    //音视频数据
    private var mAudioMessageBean: AudioMessageBean? = null
83

严久程 committed
84 85
    //音频播放
    private var mPlayer: AudioPlayer? = null
86

严久程 committed
87 88
    //当前状态 0.未接听 1.已接听
    public var status = STATUS_NOT_ANSWERED
89

严久程 committed
90 91
    //电源管理对象
    private var localPowerManager: PowerManager? = null
92

严久程 committed
93 94 95 96 97 98 99 100
    //电源锁
    private var localWakeLock: PowerManager.WakeLock? = null
    private var sensorManager: SensorManager? = null

    /**
     * 通话开始时间(接通)
     */
    private var callStartTime: Long? = null
101

严久程 committed
102 103 104 105
    /**
     * 本次倾述倒计时
     */
    private var totalDisposable: Disposable? = null
严久程 committed
106
    private var connectingStatusDisposable: Disposable? = null
严久程 committed
107 108

    //频道管理器
109
    //    private var channelManager: ChannelManager? = null
严久程 committed
110 111 112 113

    //频道token
    private var channelToken: String? = null
    private var hasUpLoadLog = false
114
    private var callStatus: Int = -1
严久程 committed
115
    private var userId = -1
严久程 committed
116 117 118 119 120

    /**
     * 是否连接成功
     */
    private var isConnectSuccess: Boolean = false
121

严久程 committed
122 123 124 125 126 127 128 129 130 131 132
    /**
     * 事件回调 (SDK 通过指定的事件通知应用程序 SDK 的运行事件,如: 加入或离开频道,新用户加入频道等)
     */
    private val mRtcEventHandler = object : IYDLVoiceEventHandler() {

        /**
         * 远端用户静音回调
         * @param uid 用户 ID
         * @param muted 该用户是否静音:true: 该用户已静音音频 false: 该用户已取消音频静音
         */
        override fun onUserMuteAudio(uid: Int, muted: Boolean) {
刘鹏 committed
133
            callEventSave("80", "uid:${uid}  开启了静音 = ${muted}")
严久程 committed
134 135 136
//            runOnUiThread {
//                showToast("对方静音了,提醒他打开!")
//            }
严久程 committed
137 138 139 140
        }

        override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
            super.onJoinChannelSuccess(channel, uid, elapsed)
刘鹏 committed
141 142
            callEventSave("40", "uid:${uid}  加入声网($channel)频道成功")

严久程 committed
143
            LogUtil.e("[agora]$uid 加入频道回调")
YKai committed
144
            writeAgoraLog("被叫(用户)加入声网($channel)频道成功")
刘鹏 committed
145 146
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "被叫(用户)加入声网($channel)频道成功")
严久程 committed
147
            runOnUiThread {
严久程 committed
148
                // 加入频道后再通知用户已接受
149
                //        YDLRTMClient.instances.acceptCall(mAudioMessageBean?.channelId)
150 151 152 153 154
                YDLavManager.instances.acceptCall(
                    mAudioMessageBean!!.userId!!,
                    mAudioMessageBean?.channelId,
                    Gson().toJson(mAudioMessageBean)
                )
严久程 committed
155

严久程 committed
156 157
                tv_toast.visibility = View.VISIBLE
                tv_toast.text = "连接中..."
严久程 committed
158 159 160 161

                voiceManage!!.getVoiceApi().setEnableSpeakerphone(false)

                connectingStatusWaitingTimeCount()
162

163
                tv_tips.visibility = View.INVISIBLE
严久程 committed
164 165 166
            }
        }

严久程 committed
167 168 169 170 171
        /**
         * 重新加入频道回调
         */
        override fun onRejoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
            super.onRejoinChannelSuccess(channel, uid, elapsed)
刘鹏 committed
172 173
            callEventSave("70", "uid:${uid}  被叫(用户${uid})重新加入声网频道($channel)成功")

严久程 committed
174
            LogUtil.e("[agora]$uid 重新加入频道回调")
YKai committed
175
            writeAgoraLog("被叫(用户)重新加入声网频道($channel)成功")
176 177
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "被叫(用户)重新加入声网频道($channel)成功")
178

严久程 committed
179 180 181 182 183 184 185 186 187 188 189 190 191
            runOnUiThread {
                if (!isConnectSuccess) {
                    tv_toast.visibility = View.VISIBLE
                    tv_toast.text = "连接中..."


                    voiceManage!!.getVoiceApi().setEnableSpeakerphone(false)

                    connectingStatusWaitingTimeCount()
                }
            }
        }

严久程 committed
192 193
        override fun onUserJoined(uid: Int, elapsed: Int) {
            super.onUserJoined(uid, elapsed)
194
            callEventSave("40", "uid:${uid}  主叫(专家)加入声网频道成功")
刘鹏 committed
195

严久程 committed
196
            LogUtil.e("[agora]远端用户加入频道回调")
YKai committed
197
            writeAgoraLog("主叫(专家)加入声网频道成功")
198
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "主叫(专家)加入声网频道成功")
199

严久程 committed
200 201
            //另一方加入频道成功
            runOnUiThread {
严久程 committed
202
                isConnectSuccess = true
严久程 committed
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
                //通话开始,刷新ui开始倒计时
                updateStartUi()
                status = STATUS_ANSWERED
                //接通开始回调
                callStartTime = System.currentTimeMillis()
            }
        }

        override fun onRtcStats(stats: IRtcEngineEventHandler.RtcStats?) {
        }

        override fun onConnectionStateChanged(state: Int, reason: Int) {
            super.onConnectionStateChanged(state, reason)
            // 3 网络连接被服务器中止  该情况现在是因为后端踢人逻辑
            if (reason == 3) {
218
                callEventSave("60", "通话挂断:网络连接被服务器(后端)中止")
刘鹏 committed
219

严久程 committed
220
                showToast("对方已挂断")
221 222 223 224 225
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "服务端踢人触发的回调"
                )
226

YKai committed
227
                writeAgoraLog("通话挂断:网络连接被服务器(后端)中止")
严久程 committed
228 229
                //通话结束或挂断时,上传日志文件
                uploadLog()
YKai committed
230 231 232
//                leaveChannel()
//                finish()
                close(RESULT_ANSWERED_CODE, "")
严久程 committed
233 234 235 236 237 238 239 240 241
            }
        }

        /**
         * 离开频道回调(自己)
         *
         */
        override fun onLeaveChannel(stats: IRtcEngineEventHandler.RtcStats?) {
            super.onLeaveChannel(stats)
242
            callEventSave("52", "自己离开频道回调")
刘鹏 committed
243

严久程 committed
244
            LogUtil.e("[agora]自己离开频道回调")
245
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "自己离开频道回调")
246

YKai committed
247 248
            //通知php 通话已结束
            close(RESULT_ANSWERED_CODE, "")
严久程 committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
        }

        /**
         * 主播离开频道回调
         * 提示有主播离开了频道(或掉线)。
         * 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 主播离开频道回调")
刘鹏 committed
265 266
            when (elapsed) {
                0 -> {
267
                    callEventSave("52", "用户主动离开")
刘鹏 committed
268 269 270 271 272 273 274 275 276 277 278 279
                }
                1 -> {
                    callEventSave(
                        "60",
                        "因过长时间收不到对方数据包,超时掉线。注意:由于 SDK 使用的是不可靠通道,也有可能对方主动离开本方没收到对方离开消息而误判为超时掉线"
                    )

                }
                2 -> {
                    callEventSave("60", "用户身份从主播切换为观众(直播模式下)")
                }
            }
严久程 committed
280
            runOnUiThread {
281 282 283 284 285
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "对方离开频道"
                )
严久程 committed
286
                showToast("对方已挂断")
YKai committed
287
                writeAgoraLog("通话接通后挂断:主叫(专家)离开频道")
刘鹏 committed
288 289
                AliYunRichLogsHelper.getInstance()
                    .sendRichLog(AliYunLogConfig.AGORA, "通话接通后挂断:主叫(专家)离开频道")
290

严久程 committed
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
                if (null != totalDisposable) {
                    totalDisposable!!.dispose()
                }
                //通知php 通话已结束
                close(RESULT_ANSWERED_CODE, "")
            }
        }

        override fun onWarning(warn: Int) {
            super.onWarning(warn)
            // 过滤1031 录制声音模糊
            if (warn != 1031) {
                uploadException("mRtcEventHandler-onWarning:warnCode--%${warn}")
            }
            LogUtil.e("[agora]发生警告回调=$warn")
YKai committed
306
            writeAgoraLog("声网警告回调码:($warn)")
307
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "声网警告回调码:($warn)")
308

严久程 committed
309 310 311 312 313
            //103:没有可用的频道资源。可能是因为服务端没法分配频道资源
            //104:查找频道超时。在加入频道时 SDK 先要查找指定的频道,出现该警告一般是因为网络太差,连接不到服务器
            //105:查找频道请求被服务器拒绝。服务器可能没有办法处理这个请求或请求是非法的
            //106:打开频道超时。查找到指定频道后,SDK 接着打开该频道,超时一般是因为网络太差,连接不到服务器
            //107:打开频道请求被服务器拒绝。服务器可能没有办法处理该请求或该请求是非法的
314 315 316 317 318 319 320 321 322 323 324 325 326
            // 声网发出警告错误码,不应该直接离开房间
//            runOnUiThread {
//                when (warn) {
//                    103, 105, 107 -> {
//                        YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 4, "收到频道回调警告信息${warn}")
//                        writeAgoraLog("通话挂断:网络异常($warn)")
//                        showToast("当前网络较差,请更换网络!")
//                        //通话结束或挂断时,上传日志文件
//                        uploadLog()
//                        close(RESULT_NOT_ANSWERED_CODE, "[agora]专家网络较差")
//                    }
//                }
//            }
严久程 committed
327 328 329 330 331 332
        }

        override fun onError(err: Int) {
            super.onError(err)
            uploadException("mRtcEventHandler-onError:errorCode--%${err}")
            LogUtil.e("[agora] 发生错误回调 =$err")
YKai committed
333
            writeAgoraLog("声网错误回调errorCode--%${err}")
刘鹏 committed
334 335
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "声网错误回调errorCode--%${err}")
336

严久程 committed
337 338 339 340 341 342 343 344 345 346 347 348 349 350
            //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 -> {
严久程 committed
351
                        showToast("请退出应用,重新打开")
严久程 committed
352
                        close(RESULT_NOT_ANSWERED_CODE, "咨询师已挂断")
刘鹏 committed
353
                        callEventSave(
354
                            "80",
刘鹏 committed
355 356 357
                            "err:${err} 3:SDK 初始化失败|7:SDK 尚未初始化|109:当前使用的 Token 过期|110:生成的 Token 无效"
                        )

严久程 committed
358
                    }
359
                    10 -> {
360
                        callEventSave("80", "err:${err} 专家网络较差")
严久程 committed
361
                        showToast("当前网络较差,请更换网络")
严久程 committed
362 363 364
                        close(RESULT_NOT_ANSWERED_CODE, "专家网络较差")
                    }
                    101 -> {
365
                        callEventSave("80", "err:${err} 不是有效的 APP ID")
严久程 committed
366
                        showToast("安装包有问题,请联系技术")
严久程 committed
367 368 369
                        close(RESULT_NOT_ANSWERED_CODE, "安装包有问题,请联系技术")
                    }
                    102 -> {
370
                        callEventSave("80", "err:${err} 不是有效的 频道名")
刘鹏 committed
371

严久程 committed
372
                        showToast("频道错误,请联系技术")
严久程 committed
373 374 375
                        close(RESULT_NOT_ANSWERED_CODE, "频道错误,请联系技术")
                    }
                    123 -> {
376
                        callEventSave("80", "err:${err}此用户被服务器禁止")
刘鹏 committed
377

378 379
                        //                        showToast("对方不允许接听电话,请联系客服")
                        //                        close(RESULT_NOT_ANSWERED_CODE, "该专家不允许接听电话,请联系客服")
严久程 committed
380 381 382 383
                    }
                    else -> {
                    }
                }
384 385 386 387 388
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "频道的错误回调信息${err}"
                )
严久程 committed
389 390
            }
        }
刘鹏 committed
391

392 393 394
        //本地音频状态监听
        override fun onLocalAudioStateChanged(localVideoState: Int, error: Int) {
            super.onLocalAudioStateChanged(localVideoState, error)
395
            writeAgoraLog("本地音频回调$error")
396
        }
刘鹏 committed
397

严久程 committed
398 399 400 401
        override fun onNetworkQuality(uid: Int, txQuality: Int, rxQuality: Int) {
            super.onNetworkQuality(uid, txQuality, rxQuality)
            var status = -1
            var netStatus = when (uid) {
402
                0 -> {
严久程 committed
403 404 405
                    if (txQuality in 1..2 && rxQuality in 1..2) {
                        ""
                    } else if (txQuality >= 5 || rxQuality >= 5) {
406
                        "您的网络已断开"
严久程 committed
407
                    } else {
408
                        status = if (txQuality >= 4 || rxQuality >= 4) {
严久程 committed
409 410 411 412
                            0
                        } else {
                            1
                        }
413
                        "您的网络状况不佳"
严久程 committed
414 415
                    }
                }
416
                else -> {
严久程 committed
417 418 419
                    if (txQuality in 1..2 && rxQuality in 1..2) {
                        ""
                    } else if (txQuality >= 5 || rxQuality >= 5) {
420
                        "对方的网络已断开"
严久程 committed
421
                    } else {
422
                        status = if (txQuality >= 4 || rxQuality >= 4) {
严久程 committed
423 424 425 426
                            0
                        } else {
                            1
                        }
427
                        "对方的网络状况不佳"
严久程 committed
428 429 430 431 432 433
                    }
                }
            }

            showNetStatus(netStatus, status)
        }
严久程 committed
434 435 436 437 438 439 440 441 442 443 444 445
    }

    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"
446

严久程 committed
447 448 449
        //0.未接听 1.已接听
        const val STATUS_NOT_ANSWERED = 0
        const val STATUS_ANSWERED = 1
450

严久程 committed
451 452 453 454 455 456 457 458
        //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)
459 460
        callEventSave("30", "进入接听界面")

严久程 committed
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
        //状态栏颜色
        setWindowStatusBarColor()
        //点亮屏幕 并解锁
        ConsultantAudioUtils.wakeUpAndUnlock(this)
        //页面传递数据初始化
        getParam()
        //初始化传感器
        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)) {
严久程 committed
487
                writeAgoraLog("收到邀请通话消息内容:$json")
严久程 committed
488
                mAudioMessageBean = Gson().fromJson(json, AudioMessageBean::class.java)
严久程 committed
489

严久程 committed
490
                if (YDLavManager.sdkStatus != Constants.CONNECTION_STATE_CONNECTED) {
刘鹏 committed
491 492
                    callEventSave("90", "RMT状态:${YDLavManager.sdkStatus},重新登录RMT")

严久程 committed
493
                    writeAgoraLog("RMT状态:${YDLavManager.sdkStatus},重新登录RMT")
494 495
                    val uid =
                        ModularServiceManager.provide(IUserService::class.java).getUserInfo()?.uid
严久程 committed
496 497 498 499 500
                    YDLavManager.instances.login(uid) { _isSuccess, _msg ->
                        writeAgoraLog("登录RTM的uid=${uid}")
                        val result = if (_isSuccess) "RMT登录成功" else "RMT登录失败:$_msg"
                        writeAgoraLog(result)
                    }
严久程 committed
501 502
                } else {
                    writeAgoraLog("当前RMT状态:${YDLavManager.sdkStatus}")
严久程 committed
503
                }
严久程 committed
504 505
            }
        } else {
刘鹏 committed
506 507
            callEventSave("90", "通话异常")

严久程 committed
508 509 510 511 512 513 514 515 516 517
            close(RESULT_NOT_ANSWERED_CODE, "通话异常")
            return
        }
    }

    @SuppressLint("InvalidWakeLockTag")
    private fun initSensorManager() {
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager?

        localPowerManager = getSystemService(POWER_SERVICE) as PowerManager?
518 519 520 521
        localWakeLock = localPowerManager!!.newWakeLock(
            PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
            "yidianling"
        )
严久程 committed
522 523 524 525 526 527
    }

    /**
     * 初始化界面用户信息
     */
    private fun initUser() {
严久程 committed
528
        var userName = "咨询用户"
严久程 committed
529 530 531 532 533 534 535 536 537 538 539 540 541
        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)
            }
严久程 committed
542
            userId = mAudioMessageBean!!.userId?.toInt() ?: -1
严久程 committed
543 544 545 546
        } else {
            iv_head.setBackgroundResource(R.drawable.audioim_head_place_hold_pic)
        }
        tv_name.text = userName
YKai committed
547
        writeAgoraLog("用户接收电话界面开启")
刘鹏 committed
548 549
        callEventSave("90", "用户接收电话界面开启")

严久程 committed
550 551 552 553 554 555 556 557 558 559 560
    }

    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()
561
        mPlayer = AudioPlayer(this, true)
严久程 committed
562 563 564 565 566 567 568 569 570 571 572
        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() {
严久程 committed
573
        writeAgoraLog("获取声网token")
严久程 committed
574 575 576 577 578 579
        //获取频道token
        mPresenter.getChannelToken(mAudioMessageBean, false)
    }

    override fun channelTokenResponse(token: String?, needJoinChannel: Boolean) {
        if (TextUtils.isEmpty(token)) {
刘鹏 committed
580 581
            callEventSave("90", "通话频道不存在")

严久程 committed
582
            LogUtil.e("[agora]token not null")
583
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "token isEmpty ")
584

严久程 committed
585
            showToast("通话频道不存在")
严久程 committed
586 587 588 589
            finish()
            return
        }
        this.channelToken = token
严久程 committed
590
        writeAgoraLog("返回的声网token=$channelToken")
严久程 committed
591 592 593 594 595 596
        if (needJoinChannel) {
            //权限申请
            requestPermission()
        }
    }

严久程 committed
597 598 599 600 601 602 603 604 605 606 607
    /**
     * 更新ui
     */
    private fun updateUI() {
        tv_toast.visibility = View.VISIBLE
        tv_toast.text = "正在建立连接..."

        rl_call.visibility = View.GONE
        rl_hands_free.visibility = View.VISIBLE
    }

严久程 committed
608 609 610 611
    //申请音频权限
    @SuppressLint("CheckResult")
    private fun requestPermission() {
        val rxPermissions = RxPermissions(this)
612 613 614
        rxPermissions.requestEach(Manifest.permission.RECORD_AUDIO).subscribe { permission ->
            when {
                //权限已申请 进行初始化操作
刘鹏 committed
615 616 617 618
                permission.granted -> {
                    init()
                    callEventSave("90", "申请音频权限成功")
                }
619
                //权限为申请 重新申请
刘鹏 committed
620 621 622 623
                permission.shouldShowRequestPermissionRationale -> {
                    requestPermission()
                    callEventSave("90", "权限 重新申请")
                }
624 625 626
                //跳转设置界面
                else -> {
                    ToastHelper.show(getString(R.string.audioim_need_storage_permission_hint))
严久程 committed
627

628 629 630 631 632
                    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                    val uri = Uri.fromParts("package", packageName, null)
                    intent.data = uri
                    startActivity(intent)
                    finish()
严久程 committed
633 634
                }
            }
635
        }
严久程 committed
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
    }

    private fun init() {
        //初始化语音
        initializeAgoraEngine()
        joinChannel()
    }

    /**
     * 语音通话 初始化
     */
    private fun initializeAgoraEngine() {
        /**
         * 创建一个实例
         * param appId            应用id
         * param mRtcEventHandler 事件回调(SDK 通过指定的事件通知应用程序 SDK 的运行事件,如: 加入或离开频道,新用户加入频道等)
         */
        voiceManage = YDLVoiceManager(this, BuildConfig.AGORA_APPID, mRtcEventHandler)
        voiceManage!!.init()
    }

    /**
     * 加入频道
     */
    private fun joinChannel() {
        val account = YdlCommonRouterManager.getYdlCommonRoute().getUid()
        if (!TextUtils.isEmpty(mAudioMessageBean?.channelId)) {
刘鹏 committed
663 664
            callEventSave("40", "加入频道joinChannel:$account")

严久程 committed
665
            LogUtil.e("[agora] joinChannel:$account")
刘鹏 committed
666 667
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "joinChannel:$account")
668

669 670 671 672
            voiceManage?.getVoiceApi()?.joinChannel(
                channelToken
                    ?: "", mAudioMessageBean!!.channelId!!, "Extra Optional Data", account
            )
严久程 committed
673 674 675 676
        }
    }

    override fun executeFinish() {
677
        callEventSave("51", "对方已挂断")
刘鹏 committed
678

严久程 committed
679
        showToast("对方已挂断")
严久程 committed
680 681 682 683 684 685 686 687 688 689
        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
严久程 committed
690 691


692 693 694
        totalDisposable =
            Observable.interval(0, 1, TimeUnit.SECONDS).subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread()).subscribe({
YKai committed
695 696 697 698
                    tv_remain_time.text = DateUtils.formatTime(it.toString())
                }, {
                    close(RESULT_NOT_ANSWERED_CODE, "对方异常")
                })
严久程 committed
699 700 701 702 703 704 705 706 707 708
    }

    /**
     * 通话结束
     */
    private fun callFinish() {
        status = STATUS_NOT_ANSWERED
    }

    private fun showStopService() {
严久程 committed
709
        if (status == STATUS_NOT_ANSWERED) {
710
            YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 2, "被叫主动拒绝")
711
            callEventSave("51", "通话未接通挂断:用户主动挂断")
刘鹏 committed
712

YKai committed
713
            writeAgoraLog("通话未接通挂断:用户主动挂断")
严久程 committed
714 715 716
            //当未接听 直接挂断 要发送给老师一条消息
            close(RESULT_NOT_ANSWERED_CODE, "用户已挂断")
        } else if (status == STATUS_ANSWERED) {
717
            callEventSave("51", "通话接通后挂断:专家主动挂断")
刘鹏 committed
718

719
            YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 3, "被叫主动拒绝")
严久程 committed
720
            writeAgoraLog("通话接通后挂断:专家主动挂断")
严久程 committed
721 722
            //正常接听 挂断电话 需要重置信令管理类状态
            close(RESULT_ANSWERED_CODE, "")
严久程 committed
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737
        }
    }

    override fun listenStatusPushResponse() {
    }

    /**
     * 挂断
     */
    fun hangUpClick(view: View) {
        if (Utils.isFastClick()) {
            //防止连击
            return
        }
        showStopService()
738
        callEventSave("52", "用户点击挂断按钮")
刘鹏 committed
739

YKai committed
740
        writeAgoraLog("用户点击挂断按钮")
741 742 743 744 745
        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_refuse_click",
            YdlCommonRouterManager.getYdlCommonRoute().getUid().toString(),
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
严久程 committed
746 747 748 749 750 751 752 753 754 755 756 757 758
    }

    /**
     * 接听
     */
    fun onCall(view: View) {
        if (Utils.isFastClick()) {
            //防止连击
            return
        }

        //调用接口判断邀请专家的用户当前是否在频道内,如果在,则专家加入频道,如果不在,则提示用户已挂断
        //更改逻辑:现在是专家先进频道,这个接口暂时只作为参考
759 760
        //        presenter.userIsInChannel(mAudioMessageBean?.channelId ?: "", mAudioMessageBean?.userId
        //                ?: "")
严久程 committed
761 762

        executeCall(true)
刘鹏 committed
763
        callEventSave("90", "用户点击接听按钮")
严久程 committed
764 765


766 767 768 769 770
        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_answer_click",
            YdlCommonRouterManager.getYdlCommonRoute().getUid().toString(),
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
严久程 committed
771 772 773 774 775 776 777 778 779 780
    }

    /**
     * 执行接听操作
     */
    override fun executeCall(canExcute: Boolean) {
        stopPlaying()
        //停止震动
        VibratorUtil.StopVibrate(this)
        if (!canExcute) {
781
            callEventSave("51", "对方已挂断")
刘鹏 committed
782

严久程 committed
783
            showToast("对方已挂断")
严久程 committed
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
            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()
822 823 824 825 826
        sensorManager!!.registerListener(
            this,
            sensorManager!!.getDefaultSensor(Sensor.TYPE_PROXIMITY),
            SensorManager.SENSOR_DELAY_NORMAL
        )
严久程 committed
827

828 829 830 831 832
        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_page_visit",
            "",
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
严久程 committed
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
    }

    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()
                    }
                }
            }
        }
    }

严久程 committed
858 859 860 861 862 863 864
    /**
     * 显示自定义弹窗
     */
    private fun showToast(msg: String?) {
        runOnUiThread {
            ToastHelper.show(msg ?: "")
        }
严久程 committed
865 866
    }

严久程 committed
867 868 869 870 871 872 873 874 875 876
    /**
     * 网络状态
     */
    private fun showNetStatus(msg: String, status: Int = 0) {
        runOnUiThread {
            if (TextUtils.isEmpty(msg)) {
                tv_nte_status.visibility = View.GONE
            } else {
                tv_nte_status.text = msg
                if (status == 0) {
877 878 879 880 881 882
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(
                        ContextCompat.getDrawable(
                            this,
                            R.drawable.av_audio_wifi_normal
                        ), null, null, null
                    )
严久程 committed
883 884
                }
                if (status == 1) {
885 886 887 888 889 890
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(
                        ContextCompat.getDrawable(
                            this,
                            R.drawable.av_audio_wifi_better
                        ), null, null, null
                    )
严久程 committed
891 892 893 894 895 896 897 898 899
                }
                if (status == -1) {
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
                }
                tv_nte_status.visibility = View.VISIBLE
            }
        }
    }

严久程 committed
900 901
    //关闭本页面
    fun close(code: Int, msg: String) {
严久程 committed
902 903
        runOnUiThread {
            LogUtil.e("[agora]close(code:$code,msg:$msg)")
904 905
            AliYunRichLogsHelper.getInstance()
                .sendRichLog(AliYunLogConfig.AGORA, "close(code:$code,msg:$msg)")
906

YKai committed
907 908
            //上传日志文件
            uploadLog()
严久程 committed
909 910 911
            stopMusic()
            //播放结束音频
            playFinishMusic()
912 913 914 915 916 917 918 919 920 921
            when (code) {
                RESULT_ANSWERED_CODE -> {
                    //已接听,正常挂断
                    //离开频道
                    leaveChannel()
                }
                RESULT_NOT_ANSWERED_CODE -> {
                    callStatus = 2
                    uploadException("被叫拒绝", zhu = "")
                    //未接听,直接挂断 发送消息
922 923 924 925 926 927
                    //        YDLRTMClient.instances.refuseCall(mAudioMessageBean?.channelId)
                    YDLavManager.instances.refuseCall(
                        mAudioMessageBean!!.userId!!,
                        mAudioMessageBean?.channelId,
                        Gson().toJson(mAudioMessageBean)
                    )
928 929 930 931 932 933
                }
                RESULT_USER_CANCEL -> {
                    callStatus = 1
                    uploadException("主叫取消", zhu = "")
                    showToast("对方已挂断")
                }
严久程 committed
934
            }
严久程 committed
935 936
            ActivityManager.getInstance().removeStack(activity = this)
            LogUtil.e("[agora]页面移除")
937
            AliYunRichLogsHelper.getInstance().sendRichLog(AliYunLogConfig.AGORA, "页面移除")
严久程 committed
938
            finish()
严久程 committed
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
        }
    }

    private fun stopMusic() {
        //停止播放音乐
        stopPlaying()
        //停止震动
        VibratorUtil.StopVibrate(AudioHomeActivity@ this)
    }

    /**
     * 停止播放
     */
    private fun stopPlaying() {
        if (mPlayer != null) {
            mPlayer!!.pause()
        }
    }

    /**
     * 播放结束音频
     */
    private fun playFinishMusic() {
        if (mPlayer == null) {
963
            mPlayer = AudioPlayer(this, true)
严久程 committed
964 965
        }
        mPlayer!!.setDataSource(R.raw.audioim_hand_down_music)
966
        //        mPlayer!!.switchPlayType(true)
严久程 committed
967 968 969 970 971 972 973
        mPlayer!!.start(isLooping = false, isSetOnCompletionListener = false)
    }

    fun onEventMainThread(event: AudioHomeEvent) {
        stopMusic()
    }

严久程 committed
974
    /**
975
     *连接中状态倒计时:15s后如果还是处于连接中,则直接退出当前页面
严久程 committed
976 977 978
     */
    private fun connectingStatusWaitingTimeCount() {
        if (connectingStatusDisposable == null) {
979 980
            connectingStatusDisposable =
                Observable.interval(0, 1, TimeUnit.SECONDS).subscribeOn(Schedulers.computation())
981
                    .take(16).observeOn(AndroidSchedulers.mainThread()).subscribe({}, {}, {
YKai committed
982 983 984 985 986 987 988 989 990 991 992
                        if (!isConnectSuccess) {
                            YDLavManager.instances.callEndStatusUpdate(
                                mAudioMessageBean?.channelId!!,
                                1,
                                "被叫加入频道后主叫未加入超时"
                            )
                            writeAgoraLog("通话未接通挂断:连接中的状态超过5s自动挂断")
                            showToast("用户已挂断")
                            close(RESULT_NOT_ANSWERED_CODE, "")
                        }
                    })
严久程 committed
993 994 995
        }
    }

严久程 committed
996 997 998 999 1000 1001 1002 1003
    /**
     * 离开频道
     */
    private fun leaveChannel() {
        uploadException("", "zhu", "108")
        if (totalDisposable != null) {
            totalDisposable!!.dispose()
        }
严久程 committed
1004 1005 1006 1007 1008

        if (connectingStatusDisposable != null) {
            connectingStatusDisposable!!.dispose()
        }

严久程 committed
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
        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 {
YKai committed
1045
                AudioLogUtils.writeAgoraLog(
1046 1047 1048 1049 1050
                    "$content-------Time:${
                        AudioLogUtils.format.format(
                            Calendar.getInstance().time
                        )
                    }", "consult.log"
YKai committed
1051
                )
严久程 committed
1052 1053
            } catch (e: Exception) {
            }
1054
        }.subscribeOn(Schedulers.io()).subscribe()
严久程 committed
1055 1056
    }

1057 1058
    fun uploadExceptionStatus(msg: String, status: Int) {
        callStatus = status
ydl committed
1059
        uploadException(msg, zhu = "zhu", eventType = "108")
严久程 committed
1060 1061 1062 1063 1064
    }

    /**
     * 上传错误日志
     */
1065
    private fun uploadException(message: String, zhu: String = "", eventType: String = "99") {
严久程 committed
1066
        var time: String = (System.currentTimeMillis() / 1000).toString()
1067 1068
        var uid: String =
            ModularServiceManager.provide(IUserService::class.java).getUserInfo()?.uid!!
严久程 committed
1069
        var payLoad = PayLoad(mAudioMessageBean?.channelId ?: "0", time, uid, "1", "999", message)
1070 1071
        var connectException =
            ConnectExceptionCommand(time + zhu, "2", eventType, payLoad, callStatus)
ydl committed
1072
        YDLavManager.instances.uploadException(connectException, null)
严久程 committed
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
    }

    private fun uploadLog() {
        if (!hasUpLoadLog) {
            hasUpLoadLog = true
            LogHelper.getInstance().uploadLog(false)
        }
    }

    override fun onDestroy() {
        LogUtil.e("http-------------onDestory")
        leaveChannel()
        voiceDestory()
严久程 committed
1086
        isConnectSuccess = false
严久程 committed
1087 1088 1089 1090 1091
        status = STATUS_NOT_ANSWERED
        hasUpLoadLog = false
        EventBus.getDefault().unregister(this)
        if (ActivityManager.getActivitySize() == 1) {
            try {
1092
                //                startActivity(MainActivity.newIntent(this, false))
1093 1094
                ARouter.getInstance().build("/main/main").addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    .navigation()
严久程 committed
1095 1096 1097 1098 1099 1100
            } catch (e: Exception) {

            }
        }
        super.onDestroy()
    }
刘鹏 committed
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114

    /**
     *  倾诉日志
     * @param session 通话业务id
     * @param status 状态:01通话中(不影响通话的事件) 10:拨打 20未拨通 30未接通 40 接通 50挂断 60断线 70重连 80 呼叫方信号 90 被呼叫方信号
     * @param res 上报的详细
     * @param line 载体:1.网易 2.中国移动(双呼)3.联通 4.华为 5.糖猫-联通 7:声网 8:微信 10:新移动
     * */
    private fun callEventSave(
        status: String,
        res: String,
        session: String? = channelToken,
        line: String = "7"
    ) {
1115
        YDLavManager.instances.callEventSave(status, res, session, line)
刘鹏 committed
1116
    }
严久程 committed
1117
}