ConsultantAudioHomeActivity.kt 36.4 KB
Newer Older
严久程 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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
严久程 committed
16
import android.support.v4.content.ContextCompat
严久程 committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30
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
严久程 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 50 51 52 53
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
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
54
import io.agora.rtc.Constants
严久程 committed
55 56
import io.agora.rtc.IRtcEngineEventHandler
import io.reactivex.Observable
严久程 committed
57
import io.reactivex.android.schedulers.AndroidSchedulers
严久程 committed
58 59 60
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.audioim_cativity_consultant_audio_home.*
YKai committed
61
import java.util.*
严久程 committed
62
import java.util.concurrent.TimeUnit
严久程 committed
63 64 65

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
            super.onJoinChannelSuccess(channel, uid, elapsed)
            LogUtil.e("[agora]$uid 加入频道回调")
YKai committed
139
            writeAgoraLog("被叫(用户)加入声网($channel)频道成功")
严久程 committed
140

严久程 committed
141
            runOnUiThread {
严久程 committed
142
                // 加入频道后再通知用户已接受
143
                //        YDLRTMClient.instances.acceptCall(mAudioMessageBean?.channelId)
144 145 146 147 148
                YDLavManager.instances.acceptCall(
                    mAudioMessageBean!!.userId!!,
                    mAudioMessageBean?.channelId,
                    Gson().toJson(mAudioMessageBean)
                )
严久程 committed
149

严久程 committed
150 151
                tv_toast.visibility = View.VISIBLE
                tv_toast.text = "连接中..."
严久程 committed
152 153 154 155

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

                connectingStatusWaitingTimeCount()
156

157
                tv_tips.visibility = View.INVISIBLE
严久程 committed
158 159 160
            }
        }

严久程 committed
161 162 163 164 165 166
        /**
         * 重新加入频道回调
         */
        override fun onRejoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
            super.onRejoinChannelSuccess(channel, uid, elapsed)
            LogUtil.e("[agora]$uid 重新加入频道回调")
YKai committed
167
            writeAgoraLog("被叫(用户)重新加入声网频道($channel)成功")
严久程 committed
168 169 170 171 172 173 174 175 176 177 178 179 180
            runOnUiThread {
                if (!isConnectSuccess) {
                    tv_toast.visibility = View.VISIBLE
                    tv_toast.text = "连接中..."


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

                    connectingStatusWaitingTimeCount()
                }
            }
        }

严久程 committed
181 182 183
        override fun onUserJoined(uid: Int, elapsed: Int) {
            super.onUserJoined(uid, elapsed)
            LogUtil.e("[agora]远端用户加入频道回调")
YKai committed
184
            writeAgoraLog("主叫(专家)加入声网频道成功")
严久程 committed
185 186
            //另一方加入频道成功
            runOnUiThread {
严久程 committed
187
                isConnectSuccess = true
严久程 committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
                //通话开始,刷新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) {
严久程 committed
203
                showToast("对方已挂断")
204 205 206 207 208
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "服务端踢人触发的回调"
                )
209

YKai committed
210
                writeAgoraLog("通话挂断:网络连接被服务器(后端)中止")
严久程 committed
211 212
                //通话结束或挂断时,上传日志文件
                uploadLog()
YKai committed
213 214 215
//                leaveChannel()
//                finish()
                close(RESULT_ANSWERED_CODE, "")
严久程 committed
216 217 218 219 220 221 222 223 224 225
            }
        }

        /**
         * 离开频道回调(自己)
         *
         */
        override fun onLeaveChannel(stats: IRtcEngineEventHandler.RtcStats?) {
            super.onLeaveChannel(stats)
            LogUtil.e("[agora]自己离开频道回调")
YKai committed
226 227
            //通知php 通话已结束
            close(RESULT_ANSWERED_CODE, "")
严久程 committed
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
        }

        /**
         * 主播离开频道回调
         * 提示有主播离开了频道(或掉线)。
         * 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 {
245 246 247 248 249
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "对方离开频道"
                )
严久程 committed
250
                showToast("对方已挂断")
YKai committed
251
                writeAgoraLog("通话接通后挂断:主叫(专家)离开频道")
严久程 committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
                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
267
            writeAgoraLog("声网警告回调码:($warn)")
严久程 committed
268 269 270 271 272
            //103:没有可用的频道资源。可能是因为服务端没法分配频道资源
            //104:查找频道超时。在加入频道时 SDK 先要查找指定的频道,出现该警告一般是因为网络太差,连接不到服务器
            //105:查找频道请求被服务器拒绝。服务器可能没有办法处理这个请求或请求是非法的
            //106:打开频道超时。查找到指定频道后,SDK 接着打开该频道,超时一般是因为网络太差,连接不到服务器
            //107:打开频道请求被服务器拒绝。服务器可能没有办法处理该请求或该请求是非法的
273 274 275 276 277 278 279 280 281 282 283 284 285
            // 声网发出警告错误码,不应该直接离开房间
//            runOnUiThread {
//                when (warn) {
//                    103, 105, 107 -> {
//                        YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 4, "收到频道回调警告信息${warn}")
//                        writeAgoraLog("通话挂断:网络异常($warn)")
//                        showToast("当前网络较差,请更换网络!")
//                        //通话结束或挂断时,上传日志文件
//                        uploadLog()
//                        close(RESULT_NOT_ANSWERED_CODE, "[agora]专家网络较差")
//                    }
//                }
//            }
严久程 committed
286 287 288 289 290 291
        }

        override fun onError(err: Int) {
            super.onError(err)
            uploadException("mRtcEventHandler-onError:errorCode--%${err}")
            LogUtil.e("[agora] 发生错误回调 =$err")
YKai committed
292
            writeAgoraLog("声网错误回调errorCode--%${err}")
293

严久程 committed
294 295 296 297 298 299 300 301 302 303 304 305 306 307
            //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
308
                        showToast("请退出应用,重新打开")
严久程 committed
309 310
                        close(RESULT_NOT_ANSWERED_CODE, "咨询师已挂断")
                    }
311
                    10 -> {
严久程 committed
312
                        showToast("当前网络较差,请更换网络")
严久程 committed
313 314 315
                        close(RESULT_NOT_ANSWERED_CODE, "专家网络较差")
                    }
                    101 -> {
严久程 committed
316
                        showToast("安装包有问题,请联系技术")
严久程 committed
317 318 319
                        close(RESULT_NOT_ANSWERED_CODE, "安装包有问题,请联系技术")
                    }
                    102 -> {
严久程 committed
320
                        showToast("频道错误,请联系技术")
严久程 committed
321 322 323
                        close(RESULT_NOT_ANSWERED_CODE, "频道错误,请联系技术")
                    }
                    123 -> {
324 325
                        //                        showToast("对方不允许接听电话,请联系客服")
                        //                        close(RESULT_NOT_ANSWERED_CODE, "该专家不允许接听电话,请联系客服")
严久程 committed
326 327 328 329
                    }
                    else -> {
                    }
                }
330 331 332 333 334
                YDLavManager.instances.callEndStatusUpdate(
                    mAudioMessageBean?.channelId!!,
                    4,
                    "频道的错误回调信息${err}"
                )
严久程 committed
335 336 337
            }
        }

严久程 committed
338 339 340 341
        override fun onNetworkQuality(uid: Int, txQuality: Int, rxQuality: Int) {
            super.onNetworkQuality(uid, txQuality, rxQuality)
            var status = -1
            var netStatus = when (uid) {
342
                0 -> {
严久程 committed
343 344 345
                    if (txQuality in 1..2 && rxQuality in 1..2) {
                        ""
                    } else if (txQuality >= 5 || rxQuality >= 5) {
346
                        "您的网络已断开"
严久程 committed
347
                    } else {
348
                        status = if (txQuality >= 4 || rxQuality >= 4) {
严久程 committed
349 350 351 352
                            0
                        } else {
                            1
                        }
353
                        "您的网络状况不佳"
严久程 committed
354 355
                    }
                }
356
                else -> {
严久程 committed
357 358 359
                    if (txQuality in 1..2 && rxQuality in 1..2) {
                        ""
                    } else if (txQuality >= 5 || rxQuality >= 5) {
360
                        "对方的网络已断开"
严久程 committed
361
                    } else {
362
                        status = if (txQuality >= 4 || rxQuality >= 4) {
严久程 committed
363 364 365 366
                            0
                        } else {
                            1
                        }
367
                        "对方的网络状况不佳"
严久程 committed
368 369 370 371 372 373
                    }
                }
            }

            showNetStatus(netStatus, status)
        }
严久程 committed
374 375 376 377 378 379 380 381 382 383 384 385
    }

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

严久程 committed
387 388 389
        //0.未接听 1.已接听
        const val STATUS_NOT_ANSWERED = 0
        const val STATUS_ANSWERED = 1
390

严久程 committed
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
        //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()
        //初始化传感器
        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
425
                writeAgoraLog("收到邀请通话消息内容:$json")
严久程 committed
426
                mAudioMessageBean = Gson().fromJson(json, AudioMessageBean::class.java)
严久程 committed
427

严久程 committed
428 429
                if (YDLavManager.sdkStatus != Constants.CONNECTION_STATE_CONNECTED) {
                    writeAgoraLog("RMT状态:${YDLavManager.sdkStatus},重新登录RMT")
430 431
                    val uid =
                        ModularServiceManager.provide(IUserService::class.java).getUserInfo()?.uid
严久程 committed
432 433 434 435 436
                    YDLavManager.instances.login(uid) { _isSuccess, _msg ->
                        writeAgoraLog("登录RTM的uid=${uid}")
                        val result = if (_isSuccess) "RMT登录成功" else "RMT登录失败:$_msg"
                        writeAgoraLog(result)
                    }
严久程 committed
437 438
                } else {
                    writeAgoraLog("当前RMT状态:${YDLavManager.sdkStatus}")
严久程 committed
439
                }
严久程 committed
440 441 442 443 444 445 446 447 448 449 450 451
            }
        } else {
            close(RESULT_NOT_ANSWERED_CODE, "通话异常")
            return
        }
    }

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

        localPowerManager = getSystemService(POWER_SERVICE) as PowerManager?
452 453 454 455
        localWakeLock = localPowerManager!!.newWakeLock(
            PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK,
            "yidianling"
        )
严久程 committed
456 457 458 459 460 461
    }

    /**
     * 初始化界面用户信息
     */
    private fun initUser() {
严久程 committed
462
        var userName = "咨询用户"
严久程 committed
463 464 465 466 467 468 469 470 471 472 473 474 475
        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
476
            userId = mAudioMessageBean!!.userId?.toInt() ?: -1
严久程 committed
477 478 479 480
        } else {
            iv_head.setBackgroundResource(R.drawable.audioim_head_place_hold_pic)
        }
        tv_name.text = userName
YKai committed
481
        writeAgoraLog("用户接收电话界面开启")
严久程 committed
482 483 484 485 486 487 488 489 490 491 492
    }

    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()
493
        mPlayer = AudioPlayer(this, true)
严久程 committed
494 495 496 497 498 499 500 501 502 503 504
        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
505
        writeAgoraLog("获取声网token")
严久程 committed
506 507 508 509 510 511 512
        //获取频道token
        mPresenter.getChannelToken(mAudioMessageBean, false)
    }

    override fun channelTokenResponse(token: String?, needJoinChannel: Boolean) {
        if (TextUtils.isEmpty(token)) {
            LogUtil.e("[agora]token not null")
严久程 committed
513
            showToast("通话频道不存在")
严久程 committed
514 515 516 517
            finish()
            return
        }
        this.channelToken = token
严久程 committed
518
        writeAgoraLog("返回的声网token=$channelToken")
严久程 committed
519 520 521 522 523 524
        if (needJoinChannel) {
            //权限申请
            requestPermission()
        }
    }

严久程 committed
525 526 527 528 529 530 531 532 533 534 535
    /**
     * 更新ui
     */
    private fun updateUI() {
        tv_toast.visibility = View.VISIBLE
        tv_toast.text = "正在建立连接..."

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

严久程 committed
536 537 538 539
    //申请音频权限
    @SuppressLint("CheckResult")
    private fun requestPermission() {
        val rxPermissions = RxPermissions(this)
540 541 542 543 544 545 546 547 548
        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))
严久程 committed
549

550 551 552 553 554
                    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                    val uri = Uri.fromParts("package", packageName, null)
                    intent.data = uri
                    startActivity(intent)
                    finish()
严久程 committed
555 556
                }
            }
557
        }
严久程 committed
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
    }

    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)) {
            LogUtil.e("[agora] joinChannel:$account")
586 587 588 589
            voiceManage?.getVoiceApi()?.joinChannel(
                channelToken
                    ?: "", mAudioMessageBean!!.channelId!!, "Extra Optional Data", account
            )
严久程 committed
590 591 592 593
        }
    }

    override fun executeFinish() {
严久程 committed
594
        showToast("对方已挂断")
严久程 committed
595 596 597 598 599 600 601 602 603 604
        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
605 606


607 608 609
        totalDisposable =
            Observable.interval(0, 1, TimeUnit.SECONDS).subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread()).subscribe({
YKai committed
610 611 612 613
                    tv_remain_time.text = DateUtils.formatTime(it.toString())
                }, {
                    close(RESULT_NOT_ANSWERED_CODE, "对方异常")
                })
严久程 committed
614 615 616 617 618 619 620 621 622 623
    }

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

    private fun showStopService() {
严久程 committed
624
        if (status == STATUS_NOT_ANSWERED) {
625
            YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 2, "被叫主动拒绝")
YKai committed
626
            writeAgoraLog("通话未接通挂断:用户主动挂断")
严久程 committed
627 628 629
            //当未接听 直接挂断 要发送给老师一条消息
            close(RESULT_NOT_ANSWERED_CODE, "用户已挂断")
        } else if (status == STATUS_ANSWERED) {
630
            YDLavManager.instances.callEndStatusUpdate(mAudioMessageBean?.channelId!!, 3, "被叫主动拒绝")
严久程 committed
631
            writeAgoraLog("通话接通后挂断:专家主动挂断")
严久程 committed
632 633
            //正常接听 挂断电话 需要重置信令管理类状态
            close(RESULT_ANSWERED_CODE, "")
严久程 committed
634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
        }
    }

    override fun listenStatusPushResponse() {
    }

    /**
     * 挂断
     */
    fun hangUpClick(view: View) {
        if (Utils.isFastClick()) {
            //防止连击
            return
        }
        showStopService()
YKai committed
649
        writeAgoraLog("用户点击挂断按钮")
650 651 652 653 654
        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_refuse_click",
            YdlCommonRouterManager.getYdlCommonRoute().getUid().toString(),
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
严久程 committed
655 656 657 658 659 660 661 662 663 664 665 666 667
    }

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

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

        executeCall(true)


674 675 676 677 678
        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_answer_click",
            YdlCommonRouterManager.getYdlCommonRoute().getUid().toString(),
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
严久程 committed
679 680 681 682 683 684 685 686 687 688
    }

    /**
     * 执行接听操作
     */
    override fun executeCall(canExcute: Boolean) {
        stopPlaying()
        //停止震动
        VibratorUtil.StopVibrate(this)
        if (!canExcute) {
严久程 committed
689
            showToast("对方已挂断")
严久程 committed
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727
            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()
728 729 730 731 732
        sensorManager!!.registerListener(
            this,
            sensorManager!!.getDefaultSensor(Sensor.TYPE_PROXIMITY),
            SensorManager.SENSOR_DELAY_NORMAL
        )
严久程 committed
733

734 735 736 737 738
        ActionCountUtils.count(
            "shengwang_popup_layer_page|shengwang_popup_layer_page_visit",
            "",
            uid = YdlCommonRouterManager.getYdlCommonRoute().getUid().toString()
        )
严久程 committed
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
    }

    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
764 765 766 767 768 769 770
    /**
     * 显示自定义弹窗
     */
    private fun showToast(msg: String?) {
        runOnUiThread {
            ToastHelper.show(msg ?: "")
        }
严久程 committed
771 772
    }

严久程 committed
773 774 775 776 777 778 779 780 781 782
    /**
     * 网络状态
     */
    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) {
783 784 785 786 787 788
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(
                        ContextCompat.getDrawable(
                            this,
                            R.drawable.av_audio_wifi_normal
                        ), null, null, null
                    )
严久程 committed
789 790
                }
                if (status == 1) {
791 792 793 794 795 796
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(
                        ContextCompat.getDrawable(
                            this,
                            R.drawable.av_audio_wifi_better
                        ), null, null, null
                    )
严久程 committed
797 798 799 800 801 802 803 804 805
                }
                if (status == -1) {
                    tv_nte_status.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
                }
                tv_nte_status.visibility = View.VISIBLE
            }
        }
    }

严久程 committed
806 807
    //关闭本页面
    fun close(code: Int, msg: String) {
严久程 committed
808 809
        runOnUiThread {
            LogUtil.e("[agora]close(code:$code,msg:$msg)")
YKai committed
810 811
            //上传日志文件
            uploadLog()
严久程 committed
812 813 814
            stopMusic()
            //播放结束音频
            playFinishMusic()
815 816 817 818 819 820 821 822 823 824
            when (code) {
                RESULT_ANSWERED_CODE -> {
                    //已接听,正常挂断
                    //离开频道
                    leaveChannel()
                }
                RESULT_NOT_ANSWERED_CODE -> {
                    callStatus = 2
                    uploadException("被叫拒绝", zhu = "")
                    //未接听,直接挂断 发送消息
825 826 827 828 829 830
                    //        YDLRTMClient.instances.refuseCall(mAudioMessageBean?.channelId)
                    YDLavManager.instances.refuseCall(
                        mAudioMessageBean!!.userId!!,
                        mAudioMessageBean?.channelId,
                        Gson().toJson(mAudioMessageBean)
                    )
831 832 833 834 835 836
                }
                RESULT_USER_CANCEL -> {
                    callStatus = 1
                    uploadException("主叫取消", zhu = "")
                    showToast("对方已挂断")
                }
严久程 committed
837
            }
严久程 committed
838 839
            ActivityManager.getInstance().removeStack(activity = this)
            LogUtil.e("[agora]页面移除")
严久程 committed
840
            finish()
严久程 committed
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
        }
    }

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

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

    /**
     * 播放结束音频
     */
    private fun playFinishMusic() {
        if (mPlayer == null) {
865
            mPlayer = AudioPlayer(this, true)
严久程 committed
866 867
        }
        mPlayer!!.setDataSource(R.raw.audioim_hand_down_music)
868
        //        mPlayer!!.switchPlayType(true)
严久程 committed
869 870 871 872 873 874 875
        mPlayer!!.start(isLooping = false, isSetOnCompletionListener = false)
    }

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

严久程 committed
876
    /**
877
     *连接中状态倒计时:15s后如果还是处于连接中,则直接退出当前页面
严久程 committed
878 879 880
     */
    private fun connectingStatusWaitingTimeCount() {
        if (connectingStatusDisposable == null) {
881 882
            connectingStatusDisposable =
                Observable.interval(0, 1, TimeUnit.SECONDS).subscribeOn(Schedulers.computation())
883
                    .take(16).observeOn(AndroidSchedulers.mainThread()).subscribe({}, {}, {
YKai committed
884 885 886 887 888 889 890 891 892 893 894
                        if (!isConnectSuccess) {
                            YDLavManager.instances.callEndStatusUpdate(
                                mAudioMessageBean?.channelId!!,
                                1,
                                "被叫加入频道后主叫未加入超时"
                            )
                            writeAgoraLog("通话未接通挂断:连接中的状态超过5s自动挂断")
                            showToast("用户已挂断")
                            close(RESULT_NOT_ANSWERED_CODE, "")
                        }
                    })
严久程 committed
895 896 897
        }
    }

严久程 committed
898 899 900 901 902 903 904 905
    /**
     * 离开频道
     */
    private fun leaveChannel() {
        uploadException("", "zhu", "108")
        if (totalDisposable != null) {
            totalDisposable!!.dispose()
        }
严久程 committed
906 907 908 909 910

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

严久程 committed
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
        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
947 948 949 950 951
                AudioLogUtils.writeAgoraLog(
                    "$content-------Time:${AudioLogUtils.format.format(
                        Calendar.getInstance().time
                    )}", "consult.log"
                )
严久程 committed
952 953
            } catch (e: Exception) {
            }
954
        }.subscribeOn(Schedulers.io()).subscribe()
严久程 committed
955 956
    }

957 958
    fun uploadExceptionStatus(msg: String, status: Int) {
        callStatus = status
ydl committed
959
        uploadException(msg, zhu = "zhu", eventType = "108")
严久程 committed
960 961 962 963 964
    }

    /**
     * 上传错误日志
     */
965
    private fun uploadException(message: String, zhu: String = "", eventType: String = "99") {
严久程 committed
966
        var time: String = (System.currentTimeMillis() / 1000).toString()
967 968
        var uid: String =
            ModularServiceManager.provide(IUserService::class.java).getUserInfo()?.uid!!
严久程 committed
969
        var payLoad = PayLoad(mAudioMessageBean?.channelId ?: "0", time, uid, "1", "999", message)
970 971
        var connectException =
            ConnectExceptionCommand(time + zhu, "2", eventType, payLoad, callStatus)
ydl committed
972
        YDLavManager.instances.uploadException(connectException, null)
严久程 committed
973 974 975 976 977 978 979 980 981 982 983 984 985
    }

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

    override fun onDestroy() {
        LogUtil.e("http-------------onDestory")
        leaveChannel()
        voiceDestory()
严久程 committed
986
        isConnectSuccess = false
严久程 committed
987 988 989 990 991
        status = STATUS_NOT_ANSWERED
        hasUpLoadLog = false
        EventBus.getDefault().unregister(this)
        if (ActivityManager.getActivitySize() == 1) {
            try {
992
                //                startActivity(MainActivity.newIntent(this, false))
993 994
                ARouter.getInstance().build("/main/main").addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    .navigation()
严久程 committed
995 996 997 998 999 1000 1001
            } catch (e: Exception) {

            }
        }
        super.onDestroy()
    }
}