AudioHomeActivity.kt 36.9 KB
Newer Older
洪国微 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
package com.ydl.audioim

import android.Manifest
import android.annotation.SuppressLint
import android.app.Service
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.media.MediaPlayer
import android.net.Uri
import android.os.Handler
import android.os.PowerManager
import android.os.Vibrator
import android.provider.Settings
import android.support.v4.content.ContextCompat
import android.text.TextUtils
import android.view.View
import android.view.animation.AccelerateInterpolator
import com.alibaba.android.arouter.facade.annotation.Route
import com.google.gson.Gson
import com.tbruyelle.rxpermissions2.RxPermissions
import com.ydl.ydl_av.messge_service.ChannelManager
import com.ydl.ydl_av.messge_service.YDLRTMClient
import com.ydl.ydl_av.messge_service.bean.RTMMesssage
import com.ydl.ydl_av.messge_service.callback.CallListener
import com.ydl.ydl_av.messge_service.callback.ChannelListener
import com.ydl.ydl_av.messge_service.response.CallLocalResponse
import com.ydl.ydl_av.messge_service.response.CallRemoteResponse
import com.ydl.ydl_av.messge_service.response.ChannelMember
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_av.chat.bean.AudioMessageBean
import com.ydl.audioim.contract.IAudioHomeActivityContract
41
import com.ydl.audioim.http.command.*
洪国微 committed
42 43 44 45
import com.ydl.audioim.player.AudioPlayer
import com.ydl.audioim.presenter.AudioHomePresenterImpl
import com.ydl.audioim.utils.DateUtils
import com.ydl.audioim.widget.AxbConfirmDialog
46
import com.ydl.burypointlib.ToastUtil
洪国微 committed
47 48 49 50
import com.ydl.webview.H5Params
import com.ydl.webview.NewH5Activity
import com.ydl.webview.RefreshWebEvent
import com.ydl.ydlcommon.base.BaseMvpActivity
51
import com.ydl.ydlcommon.modular.ModularServiceManager
洪国微 committed
52
import com.ydl.ydlcommon.router.YdlCommonRouterManager
53
import com.ydl.ydlcommon.utils.LogUtil
洪国微 committed
54
import com.ydl.ydlcommon.utils.StatusBarUtils
55
import com.ydl.ydlcommon.utils.remind.ToastHelper
56
import com.yidianling.user.api.service.IUserService
洪国微 committed
57 58 59 60 61 62
import de.greenrobot.event.EventBus
import io.agora.rtc.IRtcEngineEventHandler
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
63
import kotlinx.android.synthetic.main.audioim_activity_audio_home.*
洪国微 committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
import java.util.concurrent.TimeUnit


/**
 * @author jiucheng
 * @描述: 声网通话页面
 * @Copyright Copyright (c) 2018
 * @Company 壹点灵
 * @date 2018/10/30
 */
@Route(path = "/av/AudioHomeActivity")
class AudioHomeActivity : BaseMvpActivity<IAudioHomeActivityContract.View, IAudioHomeActivityContract.Presenter>(),IAudioHomeActivityContract.View, SensorEventListener {

    /**
     * 专家头像地址
     */
    private var expertHeadUrl: String? = null
    /**
     * 专家姓名
     */
    private var expertName: String? = null
    /**
     * 专家文案
     */
    private var expertTips: String? = null
    /**
     * 声网点对点聊天房间id
     */
    private var channelId: String? = null
    /**
     * 通话开始时间(接通)
     */
    private var callStartTime:Long? = null
    /**
     * 倾诉剩余时长(时长单位s,eg:剩余2min15s,返回135)
     */
    private var remainTime: String? = null
    /**
     *聆听者id(不是聆听者的uid)
     */
    private var listenId: String? = null
    /**
     * token
     */
    private var token: String? = null
    /**
     * commentUrl 评价页URL
     */
    private var commentUrl: String? = null
    /**
     * callId
     */
    private var callId: String? = null
    /**
     * relation_id
     */
    private var relationId: String? = null
    /**
     * listenerUid专家uid
     */
    private var listenerUid: String? = null
    /**
     * 倾述总时长
     */
    private var totalDuration: Int? = 0
    /**
     * 本地记录的当前剩余时间
     */
    private var localRemainTime: Int? = 0
    /**
     * 60s自动挂断倒计时
     */
    private var waitDisposable: Disposable? = null
    /**
     * 45s倒计时
     */
    private var disposable: Disposable? = null
    /**
     * 本次倾述倒计时
     */
    private var totalDisposable: Disposable? = null
    /**
     * 是否连接成功
     */
    private var isConnectSuccess: Boolean = false
    //电源管理对象
    private var localPowerManager: PowerManager? = null
    //电源锁
    private var localWakeLock: PowerManager.WakeLock? = null
    private var sensorManager: SensorManager? = null
    private var axbPhone: String? = null
    //是否跳转到拨号页面
    private var isJumpDail: Boolean = false
    private var mPlayer: AudioPlayer? = null
    private var vibrator: Vibrator? = null
    private var handler: Handler? = null
    //声网
    private var voiceManage: YDLVoiceManager? = null

    //频道管理器
    private var channelManager : ChannelManager? = null

何天远 committed
166 167
    private var isLeavelChannel:Boolean = false

洪国微 committed
168 169 170 171 172 173 174 175 176 177
    /**
     * 声网事件回调 (SDK 通过指定的事件通知应用程序 SDK 的运行事件,如: 加入或离开频道,新用户加入频道等)
     */
    private val mRtcEventHandler = object : IYDLVoiceEventHandler() {

        override fun onUserMuteAudio(uid: Int, muted: Boolean) {
        }

        override fun onWarning(warn: Int) {
            super.onWarning(warn)
178
            uploadException("mRtcEventHandler-onWarning:warnCode--%${warn}")
洪国微 committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
            //103:没有可用的频道资源。可能是因为服务端没法分配频道资源
            //104:查找频道超时。在加入频道时 SDK 先要查找指定的频道,出现该警告一般是因为网络太差,连接不到服务器
            //105:查找频道请求被服务器拒绝。服务器可能没有办法处理这个请求或请求是非法的
            //106:打开频道超时。查找到指定频道后,SDK 接着打开该频道,超时一般是因为网络太差,连接不到服务器
            //107:打开频道请求被服务器拒绝。服务器可能没有办法处理该请求或该请求是非法的
            LogUtil.e("[agora]发生警告回调$warn")
            runOnUiThread {
                when (warn) {
                    103, 104, 105, 106, 107 -> {
                        showToast("当前网络较差,请更换网络!")
                        leaveChannel()
                    }
                }
            }
        }

        override fun onError(err: Int) {
            super.onError(err)
197
            uploadException("mRtcEventHandler-onError:errorCode--%${err}")
洪国微 committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
            //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:此用户被服务器禁止
            LogUtil.e("[agora]发生错误回调$err")
            runOnUiThread {
                when (err) {
                    3, 7, 109, 110 -> {
                        showToast("请退出应用,重新打开")
                        leaveChannel()
                    }
                    10, 17 -> {
                        showToast("当前网络较差,请更换网络")
                        leaveChannel()
                    }
                    101 -> {
                        showToast("安装包有问题,请联系技术")
                        leaveChannel()
                    }
                    102 -> {
                        showToast("频道错误,请联系技术")
                        leaveChannel()
                    }
                    123 -> {
                        showToast("当前用户不允许接听电话,请联系客服")
                        leaveChannel()
                    }
                    else -> {
                        //异常关闭
                        leaveChannel()
                    }
                }
            }
        }

        override fun onApiCallExecuted(error: Int, api: String?, result: String?) {
            super.onApiCallExecuted(error, api, result)
            LogUtil.e("[agora]$api 已执行回调 $result")
        }


        override fun onJoinChannelSuccess(channel: String?, uid: Int, elapsed: Int) {
            super.onJoinChannelSuccess(channel, uid, elapsed)
            LogUtil.e("[agora]$uid 用户声网加入频道成功:channel=$channel")
            //更新ui
            onJoinChannelSuccess()
        }

徐健 committed
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
        override fun onRtcStats(stats: IRtcEngineEventHandler.RtcStats?) {
            super.onRtcStats(stats)
            //因为用户端直接加入了频道,防止该回调执行时,专家还未加入频道,因此在连接成功之后,才进行频道人数判断
            if (isConnectSuccess && null != stats?.users && stats.users == 1) {
                com.yidianling.common.tools.ToastUtil.toastShort("专家已挂断")
                leaveChannel()
            }
        }

        override fun onConnectionStateChanged(state: Int, reason: Int) {
            super.onConnectionStateChanged(state, reason)
            // 3 网络连接被服务器中止  该情况现在是因为后端踢人逻辑
            if (reason == 3) {
                com.yidianling.common.tools.ToastUtil.toastShort("专家已挂断")
                leaveChannel()
            }
        }

洪国微 committed
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
        override fun onLeaveChannel(stats: IRtcEngineEventHandler.RtcStats?) {
            super.onLeaveChannel(stats)
            LogUtil.e("[agora]离开频道回调")
        }

        override fun onLastmileQuality(quality: Int) {
            super.onLastmileQuality(quality)
            LogUtil.e("[agora]网络质量报告回调${quality}")
        }

        override fun onConnectionInterrupted() {
            super.onConnectionInterrupted()
            LogUtil.e("[agora]连接中断回调")
        }

        override fun onUserJoined(uid: Int, elapsed: Int) {
            super.onUserJoined(uid, elapsed)
            LogUtil.e("[agora]远端用户/主播加入频道回调")
            runOnUiThread {
                //另一方加入频道成功
                connectSuccess()
            }

        }

        override fun onUserOffline(uid: Int, elapsed: Int) {
            super.onUserOffline(uid, elapsed)
            LogUtil.e("[agora]远端用户$uid 离开频道回调")
            showToast("专家已挂断")

            if (totalDisposable != null) {
                totalDisposable!!.dispose()
            }
            handler!!.postDelayed({
                //另一方离开频道
                updateExpertStatus(false, 1)
            }, 500)
        }
    }
    //

312 313 314 315 316 317 318 319 320 321 322
    /**
     * 上传错误日志
     */
    private fun uploadException(message: String) {
        var time: String = (System.currentTimeMillis() / 1000).toString()
        var uid: String = ModularServiceManager.provide(IUserService::class.java).getUserInfo()?.uid!!
        var payLoad = PayLoad(channelId?:"0", time, uid, "1", "999", message)
        var connectException = ConnectExceptionCommand(time, "2", "99", payLoad)
        getPresenter().connectException(connectException)
    }

洪国微 committed
323 324 325 326 327
    override fun createPresenter(): IAudioHomeActivityContract.Presenter {
        return AudioHomePresenterImpl()
    }

    override fun layoutResId(): Int {
328
        return R.layout.audioim_activity_audio_home
洪国微 committed
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
    }

    override fun initDataAndEvent() {
        //状态栏颜色
        setWindowStatusBarColor()
        //初始化传感器
        initSensorManager()
        //页面传递数据初始化
        initIntentData()
        //view初始化
        initView()
        //设置信令的回调
        setCallBack()
        //点击事件
        setClickEvent()
        //权限申请
        requestPermission()
    }

    private fun setWindowStatusBarColor() {
349
        StatusBarUtils.setWindowStatusBarColor(this, R.color.audioim_color_40353535)
洪国微 committed
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
    }

    @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 initIntentData() {
        expertHeadUrl = intent.getStringExtra(IntentConstants.INTENT_EXPERT_HEAD_URL)
        expertName = intent.getStringExtra(IntentConstants.INTENT_EXPERT_NAME)
        expertTips = intent.getStringExtra(IntentConstants.INTENT_EXPERT_TIPS)
        totalDuration = intent.getStringExtra(IntentConstants.INTENT_TOTAL_DURATION).toInt()
        channelId = intent.getStringExtra(IntentConstants.INTENT_ROOM_ID)
        remainTime = intent.getStringExtra(IntentConstants.INTENT_REMAIN_TIME)
        callId = intent.getStringExtra(IntentConstants.INTENT_CALL_ID)
        relationId = intent.getStringExtra(IntentConstants.INTENT_RELATION_ID)
        token = intent.getStringExtra(IntentConstants.INTENT_TOKEN)
        listenerUid = intent.getStringExtra(IntentConstants.INTENT_LISTENER_UID)
        listenId = intent.getStringExtra(IntentConstants.INTENT_LISTEN_ID)
        commentUrl = intent.getStringExtra(IntentConstants.INTENT_COMMENT_URL)

        localRemainTime = remainTime?.toInt()
        handler = Handler()
        vibrator = getSystemService(Service.VIBRATOR_SERVICE) as Vibrator?
    }

    private fun initView() {
        tv_change_route.isEnabled = false
        //水波纹view初始化
        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))
        //挂断按钮默认不可点击
        iv_hang_up.isEnabled = false
        //设置默认关闭扬声器
        iv_hands_free.isSelected = false

        tv_name.text = expertName
        tv_tips.text = expertTips

        tv_remain_time.text = DateUtils.formatTime(remainTime)

        if (!TextUtils.isEmpty(expertHeadUrl)) {
            var option = SimpleImageOpConfiger()
400 401
            option.errorPic = R.drawable.audioim_head_place_hold_pic
            option.loadingPic = R.drawable.audioim_head_place_hold_pic
洪国微 committed
402 403 404 405 406 407 408
            option.transform = 0
            YDLImageCacheManager.showImage(this, expertHeadUrl, iv_head, option)
        }
    }

    private fun setClickEvent() {
        //切换线路
409
        tv_change_route.setOnClickListener { showChooseDialog(1) }
洪国微 committed
410 411 412 413
        //挂断
        iv_hang_up.setOnClickListener {
            if (isConnectSuccess) {
                updateExpertStatus(false, 1)
徐健 committed
414
                userCloseCalling()
洪国微 committed
415 416 417 418 419 420 421 422
            } else {
                userCloseCalling()
            }
        }
        //免提
        iv_hands_free.setOnClickListener {
            if (iv_hands_free.isSelected) {
                iv_hands_free.isSelected = false
423
                iv_hands_free.setImageResource(R.drawable.audioim_img_hands_free_unuse)
洪国微 committed
424 425
            } else {
                iv_hands_free.isSelected = true
426
                iv_hands_free.setImageResource(R.drawable.audioim_img_hands_free)
洪国微 committed
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
            }

            //已经接通
            if (isConnectSuccess) {
                //是否开启外放
                voiceManage!!.getVoiceApi().setEnableSpeakerphone(iv_hands_free.isSelected)
            } else {
                //未接通
                if (mPlayer != null) {
                    mPlayer!!.switchPlayType(iv_hands_free.isSelected)
                }
            }
        }
    }

    private fun setCallBack() {

        YDLRTMClient.instances.setCallListener(object :CallListener{
            override fun onCallRecivedByPeer(response: CallLocalResponse?) {
                //返回给主叫:被叫已收到呼叫邀请
                LogUtil.i("[agora]${response?.calleeId}已收到呼叫邀请,频道号${response?.ChannelId}")
            }

            override fun onCallAccepted(response: CallLocalResponse?) {
                //返回给主叫
                LogUtil.i("[agora]${response?.calleeId}已接收呼叫邀请")
            }

            override fun onCallRefused(response: CallLocalResponse?) {
                //返回给主叫
                LogUtil.i("[agora]${response?.calleeId}已拒绝呼叫邀请")
458
                ToastUtil.showToast(applicationContext,"对方已挂断")
洪国微 committed
459 460 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 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
                leaveChannel()
            }

            override fun onCallCanceled(response: CallLocalResponse?) {
                //返回给主叫
                LogUtil.i("[agora]主叫已取消呼叫邀请")
            }

            override fun onCallFailure(response: CallLocalResponse?) {
                //返回给主叫
                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?) {
                //返回给被叫
                LogUtil.i("[agora]来自主叫${response?.callerId}的呼叫邀请进程失败:${response?.response}")
            }

            override fun onOtherMsg(error: String?) {
                LogUtil.i("[agora]其它消息:${error}")
            }
        })
        channelManager = YDLRTMClient.instances.createChannelManager(channelId,object :ChannelListener{
            override fun onMemberCountUpdated(memberCount: Int) {
                //频道人数更新
                LogUtil.i("[agora]当前频道人数:$memberCount")
            }

            override fun onMessageReceived(message: RTMMesssage?, member: ChannelMember?) {
                //接到频道消息
                LogUtil.i("[agora]接到${member?.channelId}频道${member?.userId}的消息:"+message?.text)
            }

            override fun onMemberJoined(member: ChannelMember?) {
                //新用户加入频道
                LogUtil.i("[agora]新用户加入${member?.channelId}频道:${member?.userId}")
            }

            override fun onMemberLeft(member: ChannelMember?) {
                LogUtil.i("[agora]有用户离开${member?.channelId}频道:${member?.userId}")
            }
        })
    }

    /**
     * 请求权限
     */
a  
洪国微 committed
526
    @SuppressLint("CheckResult")
洪国微 committed
527 528 529 530 531 532 533 534 535
    private fun requestPermission() {
        val rxPermissions = RxPermissions(this)
        rxPermissions.requestEach(Manifest.permission.RECORD_AUDIO)
                .subscribe { permission ->
                    if (permission.granted) {
                        init()
                    } else if (permission.shouldShowRequestPermissionRationale) {
                        requestPermission()
                    } else {
洪国微 committed
536 537 538

                        ToastHelper.show(getString(R.string.audioim_need_storage_permission_hint))

洪国微 committed
539 540 541 542 543 544 545 546 547
                        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                        val uri = Uri.fromParts("package", packageName, null)
                        intent.data = uri
                        startActivity(intent)
                        finish()
                    }
                }
    }

a  
洪国微 committed
548
    @SuppressLint("CheckResult")
洪国微 committed
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578
    private fun init() {
        wave_view.start()
        //初始化声网
        initializeAgoraEngine()
        //发起呼叫
        var msgBean = AudioMessageBean(
                1,
                channelId!!,
                YdlCommonRouterManager.getYdlCommonRoute().getUid().toString(),
                YdlCommonRouterManager.getYdlCommonRoute().getUserInfo()!!.headUrl,
                YdlCommonRouterManager.getYdlCommonRoute().getUserInfo()!!.userName,
                remainTime!!.toInt(),
                relationId,
                callId,
                null,
                channelId
        )
        YDLRTMClient.instances.call(listenerUid!!,channelId,Gson().toJson(msgBean))
        //开始25s等待倒计时
        Observable.interval(0, 100, TimeUnit.MILLISECONDS)
                .subscribeOn(Schedulers.computation())
                .take(253)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    progress_view.setProgress(it.toFloat() / 2.5f)
                }, {
                    LogUtil.d(it.message)
                }, {
                    waittingStatus()
                    if (!isConnectSuccess){
洪国微 committed
579
//                        iv_hang_up.setImageResource(R.mipmap.audioim_ico_close)
洪国微 committed
580 581 582 583 584
                        //关闭音乐
                        stopPlaying()
                        //提示切换传统线路
                        //发送消息通知专家用户已挂断
                        YDLRTMClient.instances.cancelCall(listenerUid,channelId)
585
                        showChooseDialog(2)
洪国微 committed
586 587
                    }
                })
588
        //加入频道135
洪国微 committed
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
        joinChannel()
        //双重保险:加入频道成功,通过服务端发推送给专家
        noticeServerPush(true)
    }

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

    /**
     * 声网加入频道
     */
    private fun joinChannel() {
        voiceManage!!.getVoiceApi().joinChannel(token!!, channelId!!, "Extra Optional Data", YdlCommonRouterManager.getYdlCommonRoute().getUid())
    }

    /**
     * 用户主动挂断(包括:60s专家未接听自动挂断)
     * 注意:这个方法只在专家还未接听的状态才能调用
     *
     */
    private fun userCloseCalling() {
        //发送消息通知专家用户已挂断
        YDLRTMClient.instances.cancelCall(listenerUid,channelId)
        handler!!.postDelayed({
            leaveChannel()
        }, 100)
    }

    /**
     * 更新专家状态
     *@param isSwitchAxb 是否切换axb
     * @param finishStatus 状态值:     0:开始         1:结束
     */
    private fun updateExpertStatus(isSwitchAxb: Boolean, finishStatus: Int) {
        if (isSwitchAxb){
            dialPhone()
        }

徐健 committed
640
        if (finishStatus == 0) {
洪国微 committed
641 642
            callStartTime = System.currentTimeMillis()
        }
徐健 committed
643 644 645 646 647 648 649 650 651 652 653 654 655 656

//        if(finishStatus==1){
//            var param = ConnectFinishCommand(listenerUid!!, relationId!!, "0",
//                    remainTime!!.toInt() - localRemainTime!!, callId!!,
//                    "0","0","$callStartTime",
//                    "${System.currentTimeMillis()}",3)
//            mPresenter.connectFinish(param)
//        }else{
//            接通开始回调
//            callStartTime = System.currentTimeMillis()
//            var param = ConnectStartCommand(listenerUid!!, relationId!!,  callId!!,
//                    "${System.currentTimeMillis()}","3","0","0","0","0")
//            mPresenter.connectStart(param)
//        }
洪国微 committed
657 658 659 660 661
    }

    /**
     * 线路选择弹窗
     */
662
    private fun showChooseDialog(type:Int) {
洪国微 committed
663

664
        val dialog = AxbConfirmDialog(mContext,type, object : AxbConfirmDialog.OnClickEnsureListener {
洪国微 committed
665 666 667
            override fun onClickEnsure() {
                switchAXB()
            }
668 669

            override fun onClose() {
徐健 committed
670 671 672 673 674
                // 如果声网未连接成功,切换axb的弹框是自动弹出的,当关闭弹框的时候,执行用户挂断操作
                // 如果声网连接成功,点击右上角按钮弹出切换axb弹框,但是关闭时用户不执行挂断操作
                if (!isConnectSuccess) {
                    userCloseCalling()
                }
675
            }
洪国微 committed
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
        })
        dialog.show()
    }

    /**
     * 切换成axb路线请求
     */
    private fun switchAXB() {
        mPresenter.getAXBPhone(ConnectCommand(listenId!!,"1"))
    }

    /**
     * 切换axb网络请求结果:axb电话
     *w
     */
    override fun switchAXBResponse(axbPhone: String) {
        this.axbPhone = axbPhone
        isJumpDail = true
        if (isConnectSuccess) {
            //已经连接成功,切换axb时需要更新专家状态
            updateExpertStatus(true, 1)
        } else {
            //未连接成功,切换axb时:需发送消息通知专家端用户已挂断
            //发送消息通知专家用户已挂断
            YDLRTMClient.instances.cancelCall(listenerUid,channelId)
            leaveChannel()
        }
    }


    /**
     * 跳转拨号界面
     */
    override fun dialPhone() {
        var phoneIntent = Intent(Intent.ACTION_DIAL, Uri.parse("tel:$axbPhone"))
        startActivity(phoneIntent)
712
        finish()
洪国微 committed
713 714 715 716 717 718 719 720 721
    }


    /**
     * 30s等待完成,专家未接听
     */
    private fun waittingStatus() {
        //挂断按钮可点击
        iv_hang_up.isEnabled = true
722
        iv_hang_up.setImageResource(R.drawable.audioim_img_hang_up)
洪国微 committed
723 724 725 726 727 728 729 730
        if (!isConnectSuccess) {
            //页面等待文案调整
            tv_waiting.visibility = View.GONE
            tv_change_doctor.text = "对方暂无应答,正在为您切换线路重播"
            tv_change_doctor.visibility = View.VISIBLE
        }
        //切换线路按钮可见
        tv_change_route.isEnabled = true
洪国微 committed
731 732

        tv_change_route.setTextColor(ContextCompat.getColor(this, R.color.platform_white))
733
        tv_change_route.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(this, R.drawable.audioim_img_choose_arrow), null)
洪国微 committed
734

洪国微 committed
735 736 737 738 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 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
    }

    /**
     * 加入语音聊天频道成功
     */
    private fun onJoinChannelSuccess() {
        dismissProgressView()

        playWaitingMusic()

        //45s倒计时逻辑
//        disposable = Observable.interval(0, 1, TimeUnit.SECONDS)
//                .subscribeOn(Schedulers.computation())
//                .take(45)
//                .observeOn(AndroidSchedulers.mainThread())
//                .subscribe({
//                }, {
//                    LogUtil.d(it.message)
//                }, {
//                    if (!isConnectSuccess) {
//                        tv_change_doctor.visibility = View.VISIBLE
//                    }
//                })

        //60超时倒计时逻辑
//        waitDisposable = Observable.interval(0, 1, TimeUnit.SECONDS)
//                .subscribeOn(Schedulers.computation())
//                .take(60)
//                .observeOn(AndroidSchedulers.mainThread())
//                .subscribe({
//                }, {
//                    LogUtil.d(it.message)
//                }, {
//                    if (!isConnectSuccess) {
//                        ActivityManager.getInstance().finishActivity(NewH5Activity::class.java!!)
//                        showToast("专家未接听")
//                        userCloseCalling()
//                    }
//                })
    }

    /**
     * 播放等待音频
     */
    private fun playWaitingMusic() {
        if (mPlayer == null) {
            mPlayer = AudioPlayer(this)
        }
        if ((Math.random() * 10 + 1).toInt() >= 5) {
784
            mPlayer!!.setTwoDataAndStart(R.raw.audioim_audio_music_1, R.raw.audioim_loop_music)
洪国微 committed
785
        } else {
786
            mPlayer!!.setTwoDataAndStart(R.raw.audioim_audio_music_2, R.raw.audioim_loop_music)
洪国微 committed
787 788 789 790 791 792 793 794 795 796
        }
    }

    /**
     * 播放结束音频,音频播放结束后,自动关闭页面
     */
    private fun playFinishMusic() {
        if (mPlayer == null) {
            mPlayer = AudioPlayer(this)
        }
797
        mPlayer!!.setDataSource(R.raw.audioim_hand_down_music)
洪国微 committed
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 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 858 859 860 861 862 863 864 865 866 867
        mPlayer!!.switchPlayType(iv_hands_free.isSelected)
        mPlayer!!.setCompletionListener(MediaPlayer.OnCompletionListener {
            //通话剩余时间不足60s时,默认
            if (localRemainTime!! < 60 && !TextUtils.isEmpty(commentUrl)) {
                val h5Params = H5Params(commentUrl!!, "评价")
                NewH5Activity.start(this@AudioHomeActivity, h5Params)
            }
            if (isJumpDail) {
                //跳转拨号界面
                dialPhone()
            }
            finish()
        })
        mPlayer!!.start(false, true)
    }

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

    /**
     * sdk通话链接成功
     */
    private fun connectSuccess() {
        isConnectSuccess = true

        //通知服务端,此次通话已经接通,服务端开始订单
        updateExpertStatus(false, 0)

        if (waitDisposable != null) {
            waitDisposable!!.dispose()
        }
        if (disposable != null) {
            disposable!!.dispose()
        }

        stopPlaying()
        vibrator!!.vibrate(1000)

        //等待状态的相关ui隐藏(挂断按钮的倒计时不清除,挂断按钮必须在30s后才能点击)
        tv_change_doctor.visibility = View.GONE
        tv_waiting.visibility = View.GONE
        //显示通话相关ui
        rl_remain_time.visibility = View.VISIBLE

        showToast("已接通")

        tv_tips.visibility = View.GONE

        //剩余倾诉时长倒计时
        totalDisposable = Observable.interval(0, 1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.computation())
                .take(remainTime!!.toLong() + 1)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    localRemainTime = remainTime!!.toInt() - it.toInt()
                    if (localRemainTime == 180) {
                        playNoticeMusic(3)
                    }
                    if (localRemainTime == 60) {
                        playNoticeMusic(1)
                    }
                    if (localRemainTime!! <= 60) {
                        if (tv_change_route.isEnabled) {
                            tv_change_route.isEnabled = false
868 869
                            tv_change_route.setTextColor(ContextCompat.getColor(this, R.color.audioim_color_50ffffff))
                            tv_change_route.setCompoundDrawablesWithIntrinsicBounds(null, null, ContextCompat.getDrawable(this, R.drawable.audioim_img_choose_arrow_unuse), null)
洪国微 committed
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
                        }
                    }
                    tv_remain_time.text = DateUtils.formatTime(localRemainTime.toString())
                }, {
                    LogUtil.d(it.message)
                }, {
                    //注意:自动挂断时,如果对方离开频道的回调已经触发,就不要再重复调用接口
                    showToast("通话已结束")
                    updateExpertStatus(false, 1)
                })
    }

    /**
     * 剩余3min和1min时提示音
     * @param min 1 :还剩1min   3:还剩3min
     *
     */
    private fun playNoticeMusic(min: Int) {
        if (mPlayer == null) {
            mPlayer = AudioPlayer(this)
        }
        if (3 == min) {
892
            mPlayer!!.setDataSource(R.raw.audioim_last_3_min)
洪国微 committed
893
        } else {
894
            mPlayer!!.setDataSource(R.raw.audioim_last_1_min)
洪国微 committed
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
        }
        mPlayer!!.switchPlayType(iv_hands_free.isSelected)
        mPlayer!!.start(false, false)
    }

    /**
     * 用户加入频道后
     *通知服务端发送推送
     * 通知专家加入频道
     * 这个功能已经有用信令通知,为了解决专家信令掉线的问题,增加推送逻辑
     *
     * @param isCall true 拨打   false 取消拨打
     */
    private fun noticeServerPush(isCall: Boolean) {
        var msgBean = AudioMessageBean(
                1,
                channelId!!,
                YdlCommonRouterManager.getYdlCommonRoute().getUid().toString(),
                YdlCommonRouterManager.getYdlCommonRoute().getUserInfo()!!.headUrl,
                YdlCommonRouterManager.getYdlCommonRoute().getUserInfo()!!.userName,
                remainTime!!.toInt(),
                relationId,
                callId,
                null,
                channelId
        )
        var cmd = NoticePushCommand()
徐健 committed
922
        cmd.data = msgBean
洪国微 committed
923 924 925 926 927 928 929 930 931 932 933 934 935 936
        cmd.pushId = listenerUid
        if (isCall) {
            cmd.status = "CALL"
        } else {
            cmd.status = "CALL_OFF"
        }
        mPresenter.noticeServerPush(cmd)
    }


    /**
     * 声网离开频道
     */
    private fun leaveChannel() {
何天远 committed
937 938 939 940 941 942 943 944
        if (!isLeavelChannel) {
            isLeavelChannel = true
            //刷新h5页面
            EventBus.getDefault().post(RefreshWebEvent(false))
            stopPlaying()
            //播放结束音频
            playFinishMusic()
        }
洪国微 committed
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
    }

    override fun onResume() {
        super.onResume()
        sensorManager!!.registerListener(this, sensorManager!!.getDefaultSensor(Sensor.TYPE_PROXIMITY), SensorManager.SENSOR_DELAY_NORMAL)
    }

    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 showToast(msg: String?) {
        runOnUiThread {
            //  tv_toast.visibility = View.VISIBLE
////            tv_toast.text = msg
////            tv_toast.postDelayed({
////                tv_toast.visibility = View.GONE
////            }, 1000)
987
            ToastHelper.show(msg?:"")
洪国微 committed
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 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 1045 1046 1047 1048 1049 1050 1051 1052 1053
        }
    }

    override fun showProgressView() {
        try {
            showProgressDialog()
        }catch (e : Exception){
            e.printStackTrace()
        }

    }

    override fun dismissProgressView() {
        try {
            dismissProgressDialog()
        }catch (e:Exception){
            e.printStackTrace()
        }

    }

    override fun finishActivity() {
        leaveChannel()
    }

    override fun onDestroy() {
        super.onDestroy()
        if (handler != null) {
            handler = null
        }

        if (waitDisposable != null) {
            waitDisposable!!.dispose()
        }
        if (disposable != null) {
            disposable!!.dispose()
        }
        if (totalDisposable != null) {
            totalDisposable!!.dispose()
        }
        if (sensorManager != null) {
            sensorManager!!.unregisterListener(this)
        }
        //唤醒设备
        if (localWakeLock != null && localWakeLock!!.isHeld) {
            localWakeLock!!.release()
        }
        sensorManager = null
        localWakeLock = null
        localPowerManager = null

        if (null != voiceManage && null != voiceManage!!.getVoiceApi()) {
            voiceManage!!.getVoiceApi().leaveChannel()
            voiceManage!!.getVoiceApi().destroy()
            voiceManage = null
        }

        if (mPlayer != null) {
            mPlayer!!.clear()
        }
    }

    //重写物理返回按钮
    override fun onBackPressed() {
    }
}