video-straming-android-changes
parent
95b00dd67d
commit
e76ecf172f
@ -0,0 +1,385 @@
|
|||||||
|
package com.hmg.hmgDr.ui.fragment
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.opengl.GLSurfaceView
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.*
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel
|
||||||
|
import com.hmg.hmgDr.Model.GetSessionStatusModel
|
||||||
|
import com.hmg.hmgDr.Model.SessionStatusModel
|
||||||
|
import com.hmg.hmgDr.R
|
||||||
|
import com.hmg.hmgDr.ui.VideoCallActivity
|
||||||
|
import com.hmg.hmgDr.ui.VideoCallContract.VideoCallPresenter
|
||||||
|
import com.hmg.hmgDr.ui.VideoCallContract.VideoCallView
|
||||||
|
import com.hmg.hmgDr.ui.VideoCallPresenterImpl
|
||||||
|
import com.opentok.android.*
|
||||||
|
import com.opentok.android.PublisherKit.PublisherListener
|
||||||
|
import pub.devrel.easypermissions.AfterPermissionGranted
|
||||||
|
import pub.devrel.easypermissions.AppSettingsDialog
|
||||||
|
import pub.devrel.easypermissions.EasyPermissions
|
||||||
|
import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class VideoCallFragment : Fragment(), PermissionCallbacks, Session.SessionListener, PublisherListener,
|
||||||
|
SubscriberKit.VideoListener, VideoCallView {
|
||||||
|
|
||||||
|
lateinit var videoCallPresenter: VideoCallPresenter
|
||||||
|
|
||||||
|
private var mSession: Session? = null
|
||||||
|
private var mPublisher: Publisher? = null
|
||||||
|
private var mSubscriber: Subscriber? = null
|
||||||
|
|
||||||
|
private var mVolHandler: Handler? = null
|
||||||
|
private var mConnectedHandler: Handler? = null
|
||||||
|
private var mVolRunnable: Runnable? = null
|
||||||
|
private var mConnectedRunnable: Runnable? = null
|
||||||
|
|
||||||
|
private var mPublisherViewContainer: FrameLayout? = null
|
||||||
|
private var mSubscriberViewContainer: RelativeLayout? = null
|
||||||
|
private var controlPanel: RelativeLayout? = null
|
||||||
|
|
||||||
|
private var apiKey: String? = null
|
||||||
|
private var sessionId: String? = null
|
||||||
|
private var token: String? = null
|
||||||
|
private var appLang: String? = null
|
||||||
|
private var baseUrl: String? = null
|
||||||
|
|
||||||
|
private var isSwitchCameraClicked = false
|
||||||
|
private var isCameraClicked = false
|
||||||
|
private var isSpeckerClicked = false
|
||||||
|
private var isMicClicked = false
|
||||||
|
|
||||||
|
private var mCallBtn: ImageView? = null
|
||||||
|
private var mCameraBtn: ImageView? = null
|
||||||
|
private var mSwitchCameraBtn: ImageView? = null
|
||||||
|
private var mspeckerBtn: ImageView? = null
|
||||||
|
private var mMicBtn: ImageView? = null
|
||||||
|
|
||||||
|
private val progressBar: ProgressBar? = null
|
||||||
|
private val countDownTimer: CountDownTimer? = null
|
||||||
|
private val progressBarTextView: TextView? = null
|
||||||
|
private val progressBarLayout: RelativeLayout? = null
|
||||||
|
|
||||||
|
private var isConnected = false
|
||||||
|
|
||||||
|
private var sessionStatusModel: GetSessionStatusModel? = null
|
||||||
|
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
requireActivity().setTheme(R.style.AppTheme)
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
requestPermissions()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View? {
|
||||||
|
|
||||||
|
val view = inflater.inflate(R.layout.activity_video_call, container, false)
|
||||||
|
|
||||||
|
Objects.requireNonNull(requireActivity().actionBar)!!.hide()
|
||||||
|
initUI(view)
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
if (mSession == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mSession!!.onPause()
|
||||||
|
if (requireActivity().isFinishing) {
|
||||||
|
disconnectSession()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (mSession == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mSession!!.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
disconnectSession()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
private fun initUI(view: View) {
|
||||||
|
mPublisherViewContainer = view.findViewById<FrameLayout>(R.id.local_video_view_container)
|
||||||
|
mSubscriberViewContainer = view.findViewById<RelativeLayout>(R.id.remote_video_view_container)
|
||||||
|
|
||||||
|
arguments?.run {
|
||||||
|
apiKey = getString("apiKey")
|
||||||
|
sessionId = getString("sessionId")
|
||||||
|
token = getString("token")
|
||||||
|
appLang = getString("appLang")
|
||||||
|
baseUrl = getString("baseUrl")
|
||||||
|
sessionStatusModel = getParcelable("sessionStatusModel")
|
||||||
|
}
|
||||||
|
|
||||||
|
controlPanel = view.findViewById<RelativeLayout>(R.id.control_panel)
|
||||||
|
videoCallPresenter = VideoCallPresenterImpl(this, baseUrl)
|
||||||
|
mCallBtn = view.findViewById<ImageView>(R.id.btn_call)
|
||||||
|
mCameraBtn = view.findViewById<ImageView>(R.id.btn_camera)
|
||||||
|
mSwitchCameraBtn = view.findViewById<ImageView>(R.id.btn_switch_camera)
|
||||||
|
mspeckerBtn = view.findViewById<ImageView>(R.id.btn_specker)
|
||||||
|
mMicBtn = view.findViewById<ImageView>(R.id.btn_mic)
|
||||||
|
|
||||||
|
// progressBarLayout=findViewById(R.id.progressBar);
|
||||||
|
// progressBar=findViewById(R.id.progress_bar);
|
||||||
|
// progressBarTextView=findViewById(R.id.progress_bar_text);
|
||||||
|
// progressBar.setVisibility(View.GONE);
|
||||||
|
hiddenButtons()
|
||||||
|
checkClientConnected()
|
||||||
|
mSubscriberViewContainer!!.setOnTouchListener { v: View?, event: MotionEvent? ->
|
||||||
|
controlPanel!!.visibility = View.VISIBLE
|
||||||
|
mVolHandler!!.removeCallbacks(mVolRunnable!!)
|
||||||
|
mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
if (appLang == "ar") {
|
||||||
|
progressBarLayout!!.layoutDirection = View.LAYOUT_DIRECTION_RTL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkClientConnected() {
|
||||||
|
mConnectedHandler = Handler((Looper.getMainLooper()))
|
||||||
|
mConnectedRunnable = Runnable {
|
||||||
|
if (!isConnected) {
|
||||||
|
videoCallPresenter.callClintConnected(sessionStatusModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mConnectedHandler!!.postDelayed(mConnectedRunnable!!, (55 * 1000).toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hiddenButtons() {
|
||||||
|
mVolHandler = Handler()
|
||||||
|
mVolRunnable = Runnable { controlPanel!!.visibility = View.GONE }
|
||||||
|
mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String?>, grantResults: IntArray) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
|
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPermissionsGranted(requestCode: Int, perms: List<String?>) {
|
||||||
|
Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPermissionsDenied(requestCode: Int, perms: List<String?>) {
|
||||||
|
Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size)
|
||||||
|
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
|
||||||
|
AppSettingsDialog.Builder(this)
|
||||||
|
.setTitle(getString(R.string.title_settings_dialog))
|
||||||
|
.setRationale(getString(R.string.rationale_ask_again))
|
||||||
|
.setPositiveButton(getString(R.string.setting))
|
||||||
|
.setNegativeButton(getString(R.string.cancel))
|
||||||
|
.setRequestCode(RC_SETTINGS_SCREEN_PERM)
|
||||||
|
.build()
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterPermissionGranted(RC_VIDEO_APP_PERM)
|
||||||
|
private fun requestPermissions() {
|
||||||
|
val perms = arrayOf(Manifest.permission.INTERNET, Manifest.permission.CAMERA)
|
||||||
|
if (EasyPermissions.hasPermissions(requireContext(), *perms)) {
|
||||||
|
try {
|
||||||
|
mSession = Session.Builder(context, apiKey, sessionId).build()
|
||||||
|
mSession!!.setSessionListener(this)
|
||||||
|
mSession!!.connect(token)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EasyPermissions.requestPermissions(this, getString(R.string.remaining_ar), RC_VIDEO_APP_PERM, *perms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConnected(session: Session?) {
|
||||||
|
Log.i(TAG, "Session Connected")
|
||||||
|
mPublisher = Publisher.Builder(requireContext()).build()
|
||||||
|
mPublisher!!.setPublisherListener(this)
|
||||||
|
mPublisherViewContainer!!.addView(mPublisher!!.view)
|
||||||
|
if (mPublisher!!.getView() is GLSurfaceView) {
|
||||||
|
(mPublisher!!.getView() as GLSurfaceView).setZOrderOnTop(true)
|
||||||
|
}
|
||||||
|
mSession!!.publish(mPublisher)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisconnected(session: Session) {
|
||||||
|
Log.d(TAG, "onDisconnected: disconnected from session " + session.sessionId)
|
||||||
|
mSession = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(session: Session, opentokError: OpentokError) {
|
||||||
|
Log.d(TAG, "onError: Error (" + opentokError.message + ") in session " + session.sessionId)
|
||||||
|
Toast.makeText(requireContext(), "Session error. See the logcat please.", Toast.LENGTH_LONG).show()
|
||||||
|
requireActivity().finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStreamReceived(session: Session, stream: Stream) {
|
||||||
|
Log.d(TAG, "onStreamReceived: New stream " + stream.streamId + " in session " + session.sessionId)
|
||||||
|
if (mSubscriber != null) {
|
||||||
|
isConnected = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isConnected = true
|
||||||
|
subscribeToStream(stream)
|
||||||
|
videoCallPresenter.callChangeCallStatus(ChangeCallStatusRequestModel(3, sessionStatusModel!!.doctorId, sessionStatusModel!!.generalid, token, sessionStatusModel!!.vcid))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStreamDropped(session: Session, stream: Stream) {
|
||||||
|
Log.d(TAG, "onStreamDropped: Stream " + stream.streamId + " dropped from session " + session.sessionId)
|
||||||
|
if (mSubscriber == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (mSubscriber!!.stream == stream) {
|
||||||
|
mSubscriberViewContainer!!.removeView(mSubscriber!!.view)
|
||||||
|
mSubscriber!!.destroy()
|
||||||
|
mSubscriber = null
|
||||||
|
}
|
||||||
|
disconnectSession()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStreamCreated(publisherKit: PublisherKit?, stream: Stream) {
|
||||||
|
Log.d(TAG, "onStreamCreated: Own stream " + stream.streamId + " created")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStreamDestroyed(publisherKit: PublisherKit?, stream: Stream) {
|
||||||
|
Log.d(TAG, "onStreamDestroyed: Own stream " + stream.streamId + " destroyed")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(publisherKit: PublisherKit?, opentokError: OpentokError) {
|
||||||
|
Log.d(VideoCallFragment.TAG, "onError: Error (" + opentokError.message + ") in publisher")
|
||||||
|
Toast.makeText(requireContext(), "Session error. See the logcat please.", Toast.LENGTH_LONG).show()
|
||||||
|
requireActivity().finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onVideoDataReceived(subscriberKit: SubscriberKit?) {
|
||||||
|
mSubscriber!!.setStyle(BaseVideoRenderer.STYLE_VIDEO_SCALE, BaseVideoRenderer.STYLE_VIDEO_FILL)
|
||||||
|
mSubscriberViewContainer!!.addView(mSubscriber!!.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onVideoDisabled(subscriberKit: SubscriberKit?, s: String?) {}
|
||||||
|
|
||||||
|
override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) {}
|
||||||
|
|
||||||
|
override fun onVideoDisableWarning(subscriberKit: SubscriberKit?) {}
|
||||||
|
|
||||||
|
override fun onVideoDisableWarningLifted(subscriberKit: SubscriberKit?) {}
|
||||||
|
|
||||||
|
private fun subscribeToStream(stream: Stream) {
|
||||||
|
mSubscriber = Subscriber.Builder(requireContext(), stream).build()
|
||||||
|
mSubscriber!!.setVideoListener(this)
|
||||||
|
mSession!!.subscribe(mSubscriber)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun disconnectSession() {
|
||||||
|
if (mSession == null) {
|
||||||
|
requireActivity().setResult(Activity.RESULT_CANCELED)
|
||||||
|
requireActivity().finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (mSubscriber != null) {
|
||||||
|
mSubscriberViewContainer!!.removeView(mSubscriber!!.view)
|
||||||
|
mSession!!.unsubscribe(mSubscriber)
|
||||||
|
mSubscriber!!.destroy()
|
||||||
|
mSubscriber = null
|
||||||
|
}
|
||||||
|
if (mPublisher != null) {
|
||||||
|
mPublisherViewContainer!!.removeView(mPublisher!!.view)
|
||||||
|
mSession!!.unpublish(mPublisher)
|
||||||
|
mPublisher!!.destroy()
|
||||||
|
mPublisher = null
|
||||||
|
}
|
||||||
|
mSession!!.disconnect()
|
||||||
|
countDownTimer?.cancel()
|
||||||
|
videoCallPresenter.callChangeCallStatus(ChangeCallStatusRequestModel(16, sessionStatusModel!!.doctorId, sessionStatusModel!!.generalid, token, sessionStatusModel!!.vcid))
|
||||||
|
requireActivity().finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSwitchCameraClicked(view: View?) {
|
||||||
|
if (mPublisher != null) {
|
||||||
|
isSwitchCameraClicked = !isSwitchCameraClicked
|
||||||
|
mPublisher!!.cycleCamera()
|
||||||
|
val res = if (isSwitchCameraClicked) R.drawable.flip_disapled else R.drawable.flip_enabled
|
||||||
|
mSwitchCameraBtn!!.setImageResource(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onCameraClicked(view: View?) {
|
||||||
|
if (mPublisher != null) {
|
||||||
|
isCameraClicked = !isCameraClicked
|
||||||
|
mPublisher!!.publishVideo = !isCameraClicked
|
||||||
|
val res = if (isCameraClicked) R.drawable.video_disanabled else R.drawable.video_enabled
|
||||||
|
mCameraBtn!!.setImageResource(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSpeckerClicked(view: View?) {
|
||||||
|
if (mSubscriber != null) {
|
||||||
|
isSpeckerClicked = !isSpeckerClicked
|
||||||
|
mSubscriber!!.subscribeToAudio = !isSpeckerClicked
|
||||||
|
val res = if (isSpeckerClicked) R.drawable.audio_disabled else R.drawable.audio_enabled
|
||||||
|
mspeckerBtn!!.setImageResource(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onMicClicked(view: View?) {
|
||||||
|
if (mPublisher != null) {
|
||||||
|
isMicClicked = !isMicClicked
|
||||||
|
mPublisher!!.publishAudio = !isMicClicked
|
||||||
|
val res = if (isMicClicked) R.drawable.mic_disabled else R.drawable.mic_enabled
|
||||||
|
mMicBtn!!.setImageResource(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onCallClicked(view: View?) {
|
||||||
|
disconnectSession()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCallSuccessful(sessionStatusModel: SessionStatusModel) {
|
||||||
|
if (sessionStatusModel.sessionStatus == 2 || sessionStatusModel.sessionStatus == 3) {
|
||||||
|
val returnIntent = Intent()
|
||||||
|
returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel)
|
||||||
|
requireActivity().setResult(Activity.RESULT_OK, returnIntent)
|
||||||
|
requireActivity().finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCallChangeCallStatusSuccessful(sessionStatusModel: SessionStatusModel?) {}
|
||||||
|
|
||||||
|
override fun onFailure() {}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun newInstance(args: Bundle) =
|
||||||
|
VideoCallFragment().apply {
|
||||||
|
arguments = args
|
||||||
|
}
|
||||||
|
|
||||||
|
private val TAG = VideoCallActivity::class.java.simpleName
|
||||||
|
|
||||||
|
private const val RC_SETTINGS_SCREEN_PERM = 123
|
||||||
|
private const val RC_VIDEO_APP_PERM = 124
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue