make floating video screen

video-stream-floating
mosazaid 4 years ago
parent 8bfb37d4c0
commit 7cc25f6101

@ -12,6 +12,9 @@
<uses-permission android:name="android.permission.CALL_PHONE" />
<!-- Permission required to draw floating widget over other apps -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
@ -41,7 +44,13 @@
</intent-filter>
</activity>
<service android:name = ".Service.VideoStreamContainerService"/>
<!-- <service android:name = ".Service.VideoStreamContainerService"-->
<!-- android:enabled="true"-->
<!-- android:exported="false"/>-->
<service android:name = ".Service.VideoStreamFloatingWidgetService"
android:enabled="true"
android:exported="false"/>
<!--
Don't delete the meta-data below.

@ -5,18 +5,20 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.provider.Settings
import android.util.Log
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.Toast
import androidx.annotation.NonNull
import com.google.gson.GsonBuilder
import com.hmg.hmgDr.Model.GetSessionStatusModel
import com.hmg.hmgDr.Model.SessionStatusModel
import com.hmg.hmgDr.Service.VideoStreamContainerService
import com.hmg.hmgDr.Service.VideoStreamFloatingWidgetService
import com.hmg.hmgDr.ui.VideoCallResponseListener
import com.hmg.hmgDr.ui.fragment.VideoCallFragment
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
@ -27,15 +29,17 @@ import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
VideoCallResponseListener {
/* Permission request code to draw over other apps */
private val DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE = 1222
private val CHANNEL = "Dr.cloudSolution/videoCall"
private lateinit var methodChannel: MethodChannel
private var result: MethodChannel.Result? = null
private var call: MethodCall? = null
private val LAUNCH_VIDEO: Int = 1
private var dialogFragment: VideoCallFragment? = null
private var serviceIntent: Intent? = null
private var videoStreamService: VideoStreamContainerService? = null
private var videoStreamService: VideoStreamFloatingWidgetService? = null
private var bound = false
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
@ -67,15 +71,21 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
val isRecording = call.argument<Boolean>("isRecording")
val sessionStatusModel =
GetSessionStatusModel(VC_ID, tokenID, generalId, doctorId, patientName, isRecording!!)
GetSessionStatusModel(
VC_ID,
tokenID,
generalId,
doctorId,
patientName,
isRecording!!
)
openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel)
}
"closeVideoCall" -> {
dialogFragment?.onCallClicked()
// videoStreamService?.closeVideoCall()
videoStreamService?.closeVideoCall()
}
"onCallConnected" -> {
@ -86,91 +96,97 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
}
}
private fun openVideoCall(apiKey: String?, sessionId: String?, token: String?, appLang: String?, baseUrl: String?, sessionStatusModel: GetSessionStatusModel) {
if (dialogFragment == null) {
val arguments = Bundle()
arguments.putString("apiKey", apiKey)
arguments.putString("sessionId", sessionId)
arguments.putString("token", token)
arguments.putString("appLang", appLang)
arguments.putString("baseUrl", baseUrl)
arguments.putParcelable("sessionStatusModel", sessionStatusModel)
val transaction = supportFragmentManager.beginTransaction()
dialogFragment = VideoCallFragment.newInstance(arguments)
dialogFragment?.let {
it.setCallListener(this)
it.isCancelable = true
if (it.isAdded){
it.dismiss()
}else {
it.show(transaction, "dialog")
}
private fun openVideoCall(
apiKey: String?,
sessionId: String?,
token: String?,
appLang: String?,
baseUrl: String?,
sessionStatusModel: GetSessionStatusModel
) {
val arguments = Bundle()
arguments.putString("apiKey", apiKey)
arguments.putString("sessionId", sessionId)
arguments.putString("token", token)
arguments.putString("appLang", appLang)
arguments.putString("baseUrl", baseUrl)
arguments.putParcelable("sessionStatusModel", sessionStatusModel)
// start service
// serviceIntent = Intent(this@MainActivity, VideoStreamContainerService::class.java)
serviceIntent = Intent(this@MainActivity, VideoStreamFloatingWidgetService::class.java)
serviceIntent?.run {
putExtras(arguments)
}
checkFloatingWidgetPermission()
}
}
} else if (!dialogFragment!!.isVisible) {
val transaction = supportFragmentManager.beginTransaction()
dialogFragment!!.show(transaction, "dialog")
private fun checkFloatingWidgetPermission() {
//Check if the application has draw over other apps permission or not?
//This permission is by default available for API<23. But for API > 23
//you have to ask for the permission in runtime.
//Check if the application has draw over other apps permission or not?
//This permission is by default available for API<23. But for API > 23
//you have to ask for the permission in runtime.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
//If the draw over permission is not available open the settings screen
//to grant the permission.
val intent = Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:$packageName")
)
startActivityForResult(intent, DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE)
} else { //If permission is granted start floating widget service
startFloatingWidgetService()
}
}
// private fun openVideoCall(
// apiKey: String?,
// sessionId: String?,
// token: String?,
// appLang: String?,
// baseUrl: String?,
// sessionStatusModel: GetSessionStatusModel
// ) {
//
// val arguments = Bundle()
// arguments.putString("apiKey", apiKey)
// arguments.putString("sessionId", sessionId)
// arguments.putString("token", token)
// arguments.putString("appLang", appLang)
// arguments.putString("baseUrl", baseUrl)
// arguments.putParcelable("sessionStatusModel", sessionStatusModel)
//
//// showSoftKeyBoard(null)
// // start service
// serviceIntent = Intent(this@MainActivity, VideoStreamContainerService::class.java)
// serviceIntent?.run {
// putExtras(arguments)
// startService(this)
// }
//// bindService()
// }
private fun startFloatingWidgetService() {
startService(serviceIntent)
bindService()
}
/* override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
var asd = "";
if (requestCode == LAUNCH_VIDEO) {
if (resultCode == Activity.RESULT_OK) {
val result : SessionStatusModel? = data?.getParcelableExtra("sessionStatusNotRespond")
val callResponse : HashMap<String, String> = HashMap()
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
/*if (requestCode == LAUNCH_VIDEO) {
if (resultCode == Activity.RESULT_OK) {
val result : SessionStatusModel? = data?.getParcelableExtra("sessionStatusNotRespond")
val callResponse : HashMap<String, String> = HashMap()
val sessionStatus : HashMap<String, String> = HashMap()
val gson = GsonBuilder().serializeNulls().create()
val sessionStatus : HashMap<String, String> = HashMap()
val gson = GsonBuilder().serializeNulls().create()
callResponse["callResponse"] = "CallNotRespond"
val jsonRes = gson.toJson(result)
callResponse["sessionStatus"] = jsonRes
callResponse["callResponse"] = "CallNotRespond"
val jsonRes = gson.toJson(result)
callResponse["sessionStatus"] = jsonRes
this.result?.success(callResponse)
}
if (resultCode == Activity.RESULT_CANCELED) {
val callResponse : HashMap<String, String> = HashMap()
callResponse["callResponse"] = "CallEnd"
this.result?.success(callResponse)
}
if (resultCode == Activity.RESULT_CANCELED) {
val callResponse : HashMap<String, String> = HashMap()
callResponse["callResponse"] = "CallEnd"
result?.success(callResponse)
}
}
}*/
result?.success(callResponse)
}
} else*/ if (requestCode == DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE) {
//Check if the permission is granted or not.
if (resultCode == RESULT_OK)
//If permission granted start floating widget service
startFloatingWidgetService()
else
//Permission is not available then display toast
Toast.makeText(
this,
"Draw over other app permission not available. App won\\'t work without permission. Please try again.",
Toast.LENGTH_SHORT
).show()
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}
override fun onCallFinished(resultCode: Int, intent: Intent?) {
dialogFragment = null
if (resultCode == Activity.RESULT_OK) {
val result: SessionStatusModel? = intent?.getParcelableExtra("sessionStatusNotRespond")
val callResponse: HashMap<String, String> = HashMap()
@ -197,14 +213,9 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
}
}
// stopService(serviceIntent)
// unbindService()
// videoStreamService!!.serviceRunning = false
}
override fun errorHandle(message: String) {
dialogFragment = null
// Toast.makeText(this, message, Toast.LENGTH_LONG).show()
stopService(serviceIntent)
unbindService()
videoStreamService!!.serviceRunning = false
}
override fun minimizeVideoEvent(isMinimize: Boolean) {
@ -228,53 +239,41 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
// unbindService()
// }
// private fun bindService() {
// serviceIntent?.run {
// if (videoStreamService != null && !videoStreamService!!.serviceRunning){
// startService(this)
// }
// bindService(this, serviceConnection, Context.BIND_AUTO_CREATE)
// videoStreamService?.serviceRunning = true
// }
// }
//
// private fun unbindService() {
// if (bound) {
// videoStreamService!!.videoCallResponseListener = null // unregister
private fun bindService() {
serviceIntent?.run {
if (videoStreamService != null && !videoStreamService!!.serviceRunning) {
startService(this)
}
bindService(this, serviceConnection, Context.BIND_AUTO_CREATE)
videoStreamService?.serviceRunning = true
}
}
private fun unbindService() {
if (bound) {
videoStreamService!!.videoCallResponseListener = null // unregister
// videoStreamService!!.mActivity = null
// unbindService(serviceConnection)
// bound = false
// }
// }
//
// private val serviceConnection: ServiceConnection = object : ServiceConnection {
// override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
unbindService(serviceConnection)
bound = false
}
}
private val serviceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
// val binder: VideoStreamContainerService.VideoStreamBinder =
// service as VideoStreamContainerService.VideoStreamBinder
// videoStreamService = binder.service
// bound = true
// videoStreamService!!.videoCallResponseListener = this@MainActivity // register
val binder: VideoStreamFloatingWidgetService.VideoStreamBinder =
service as VideoStreamFloatingWidgetService.VideoStreamBinder
videoStreamService = binder.service
bound = true
videoStreamService!!.videoCallResponseListener = this@MainActivity // register
// videoStreamService!!.mActivity = this@MainActivity // register
// }
//
// override fun onServiceDisconnected(name: ComponentName?) {
// bound = false
// }
//
// }
// code to hide soft keyboard
fun hideSoftKeyBoard(editBox: EditText?) {
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(editBox?.windowToken, 0)
}
}
override fun onServiceDisconnected(name: ComponentName?) {
bound = false
}
// code to show soft keyboard
private fun showSoftKeyBoard(editBox: EditText?) {
val inputMethodManager = this.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
editBox?.requestFocus()
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
}
}

@ -98,16 +98,17 @@ class VideoCallFragment : DialogFragment(), PermissionCallbacks, Session.Session
private lateinit var mSwitchCameraBtn: ImageView
private lateinit var mspeckerBtn: ImageView
private lateinit var mMicBtn: ImageView
private lateinit var patientName: TextView
private lateinit var cmTimer: Chronometer
private var elapsedTime: Long = 0
private var resume = false
private val progressBar: ProgressBar? = null
private val countDownTimer: CountDownTimer? = null
private val progressBarTextView: TextView? = null
private val progressBarLayout: RelativeLayout? = null
private val
progressBarLayout: RelativeLayout? = null
private var isConnected = false

@ -2,6 +2,9 @@ package com.hmg.hmgDr.util
import android.content.Context
import android.util.DisplayMetrics
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import io.flutter.embedding.android.FlutterFragmentActivity
object ViewsUtil {
@ -30,4 +33,18 @@ object ViewsUtil {
displayMetrics.widthPixels.toFloat()
}
}
// code to hide soft keyboard
fun hideSoftKeyBoard(context: Context, editBox: EditText?) {
val imm = context.getSystemService(FlutterFragmentActivity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(editBox?.windowToken, 0)
}
// code to show soft keyboard
private fun showSoftKeyBoard(context: Context, editBox: EditText?) {
val inputMethodManager = context.getSystemService(FlutterFragmentActivity.INPUT_METHOD_SERVICE) as InputMethodManager
editBox?.requestFocus()
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0)
}
}

@ -5,8 +5,8 @@ const ONLY_NUMBERS = "[0-9]";
const ONLY_LETTERS = "[a-zA-Z &'\"]";
const ONLY_DATE = "[0-9/]";
const BASE_URL_LIVE_CARE = 'https://livecare.hmg.com/';
// const BASE_URL = 'https://hmgwebservices.com/';
const BASE_URL = 'https://uat.hmgwebservices.com/';
const BASE_URL = 'https://hmgwebservices.com/';
// const BASE_URL = 'https://uat.hmgwebservices.com/';
const PHARMACY_ITEMS_URL = "Services/Lists.svc/REST/GetPharmcyItems_Region_enh";
const PHARMACY_LIST_URL = "Services/Patients.svc/REST/GetPharmcyList";
const PATIENT_PROGRESS_NOTE_URL = "Services/DoctorApplication.svc/REST/GetProgressNoteForInPatient";

@ -29,12 +29,13 @@ class VideoCallService extends BaseService {
DoctorProfileModel doctorProfile =
await getDoctorProfile(isGetProfile: true);
await VideoChannel.openVideoCallScreen(
kToken: startCallRes.openTokenID,
kSessionId: startCallRes.openSessionID,
kApiKey:'46209962',
// kToken: "T1==cGFydG5lcl9pZD00NzI0Nzk1NCZzaWc9NGIyZDljOTY3YjFiNWU1YzUzNzFmMjIyNjJmNmEzY2Y5NzZjOTdlYzpzZXNzaW9uX2lkPTFfTVg0ME56STBOemsxTkg1LU1UWXlNekEyTlRRMU9EVXhObjVrVFRoMFlVdFJXaXRYTWpadFZGZHFhSGxZVGpOdE1UVi1mZyZjcmVhdGVfdGltZT0xNjIzMDY1NDk1Jm5vbmNlPTAuMjM2Mjk0NTIwMTkyOTA4OTcmcm9sZT1wdWJsaXNoZXImZXhwaXJlX3RpbWU9MTYyNTY1NzQ5NCZpbml0aWFsX2xheW91dF9jbGFzc19saXN0PQ==",
// kSessionId: "1_MX40NzI0Nzk1NH5-MTYyMzA2NTQ1ODUxNn5kTTh0YUtRWitXMjZtVFdqaHlYTjNtMTV-fg",
// kApiKey:'47247954',
// TODO MOSA TEST
// kToken: startCallRes.openTokenID,
// kSessionId: startCallRes.openSessionID,
// kApiKey:'46209962',
kToken: "T1==cGFydG5lcl9pZD00NzI0Nzk1NCZzaWc9NGIyZDljOTY3YjFiNWU1YzUzNzFmMjIyNjJmNmEzY2Y5NzZjOTdlYzpzZXNzaW9uX2lkPTFfTVg0ME56STBOemsxTkg1LU1UWXlNekEyTlRRMU9EVXhObjVrVFRoMFlVdFJXaXRYTWpadFZGZHFhSGxZVGpOdE1UVi1mZyZjcmVhdGVfdGltZT0xNjIzMDY1NDk1Jm5vbmNlPTAuMjM2Mjk0NTIwMTkyOTA4OTcmcm9sZT1wdWJsaXNoZXImZXhwaXJlX3RpbWU9MTYyNTY1NzQ5NCZpbml0aWFsX2xheW91dF9jbGFzc19saXN0PQ==",
kSessionId: "1_MX40NzI0Nzk1NH5-MTYyMzA2NTQ1ODUxNn5kTTh0YUtRWitXMjZtVFdqaHlYTjNtMTV-fg",
kApiKey:'47247954',
vcId: patient.vcId,
isRecording: isRecording,
patientName: patient.fullName ??

@ -338,28 +338,29 @@ class _HomeScreenState extends State<HomeScreen> {
text:
"${TranslationBase.of(context).liveCare}\n${TranslationBase.of(context).patients}",
onTap: () {
// PatiantInformtion patient = PatiantInformtion(
// patientStatusType: 43,
// episodeNo: 0,
// vcId: 42342,
// fullName: "mosa test",
// dateofBirth: "2000-05-01 10:42:35.790004"
// );
// Navigator.of(context).pushNamed(PATIENTS_PROFILE, arguments: {
// "patient": patient,
// "patientType": "0",
// "isSearch": false,
// "isInpatient": false,
// "arrivalType": "0",
// "isSearchAndOut": false,
// "isFromLiveCare": true,
// });
Navigator.push(
context,
FadePage(
page: LiveCarePatientScreen(),
),
// TODO MOSA TEST
PatiantInformtion patient = PatiantInformtion(
patientStatusType: 43,
episodeNo: 0,
vcId: 42342,
fullName: "mosa test",
dateofBirth: "2000-05-01 10:42:35.790004"
);
Navigator.of(context).pushNamed(PATIENTS_PROFILE, arguments: {
"patient": patient,
"patientType": "0",
"isSearch": false,
"isInpatient": false,
"arrivalType": "0",
"isSearchAndOut": false,
"isFromLiveCare": true,
});
// Navigator.push(
// context,
// FadePage(
// page: LiveCarePatientScreen(),
// ),
// );
},
));
changeColorIndex();

@ -301,18 +301,19 @@ class _PatientProfileScreenState extends State<PatientProfileScreen> with Single
: TranslationBase.of(context).initiateCall,
disabled: isCallStarted || model.state == ViewState.BusyLocal,
onPressed: () async {
// AppPermissionsUtils
// .requestVideoCallPermission(
// context: context,
// onTapGrant: () {
// locator<VideoCallService>()
// .openVideo(
// model.startCallRes,
// patient,
// model.startCallRes != null ? model.startCallRes.isRecording : true, callConnected,
// callDisconnected);
// });
if (isCallFinished) {
// TODO MOSA TEST
AppPermissionsUtils
.requestVideoCallPermission(
context: context,
onTapGrant: () {
locator<VideoCallService>()
.openVideo(
model.startCallRes,
patient,
model.startCallRes != null ? model.startCallRes.isRecording : true, callConnected,
callDisconnected);
});
/*if (isCallFinished) {
Navigator.push(
context,
MaterialPageRoute(
@ -354,7 +355,7 @@ class _PatientProfileScreenState extends State<PatientProfileScreen> with Single
callDisconnected);
});
}
}
}*/
},
),
),

Loading…
Cancel
Save