diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index 317d0290..23a5488a 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -1,7 +1,64 @@
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 7c18e957..2bd477be 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -10,7 +10,7 @@
FlutterApplication and put your custom class here.
-->
-
+
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt
index 670facf1..e20eef1e 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt
@@ -14,9 +14,8 @@ import android.util.Log
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.model.GetSessionStatusModel
+import com.hmg.hmgDr.model.SessionStatusModel
import com.hmg.hmgDr.Service.VideoStreamFloatingWidgetService
import com.hmg.hmgDr.ui.VideoCallResponseListener
import io.flutter.embedding.android.FlutterFragmentActivity
@@ -115,6 +114,7 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
serviceIntent = Intent(this@MainActivity, VideoStreamFloatingWidgetService::class.java)
serviceIntent?.run {
putExtras(arguments)
+ action = VideoStreamFloatingWidgetService.ACTION_START_CALL
}
checkFloatingWidgetPermission()
}
@@ -145,6 +145,13 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
bindService()
}
+ override fun onDestroy() {
+ super.onDestroy()
+ if (bound) {
+ unbindService()
+ }
+ }
+
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
/*if (requestCode == LAUNCH_VIDEO) {
if (resultCode == Activity.RESULT_OK) {
@@ -230,7 +237,13 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
} else {
super.onBackPressed()
}
+ }
+ override fun onPause() {
+ if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) {
+ videoStreamService!!.onMinimizedClicked()
+ }
+ super.onPause()
}
// override fun onStart() {
@@ -279,5 +292,4 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
}
}
-
}
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/SessionStatusAPI.java b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/SessionStatusAPI.java
index e507650e..7c458b25 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/SessionStatusAPI.java
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/SessionStatusAPI.java
@@ -1,8 +1,8 @@
package com.hmg.hmgDr.Service;
-import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel;
-import com.hmg.hmgDr.Model.GetSessionStatusModel;
-import com.hmg.hmgDr.Model.SessionStatusModel;
+import com.hmg.hmgDr.model.ChangeCallStatusRequestModel;
+import com.hmg.hmgDr.model.GetSessionStatusModel;
+import com.hmg.hmgDr.model.SessionStatusModel;
import retrofit2.Call;
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt
index 1ff2a2c2..f79f23a4 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt
@@ -1,10 +1,10 @@
package com.hmg.hmgDr.Service
import android.annotation.SuppressLint
-import android.app.Activity
-import android.app.Service
+import android.app.*
import android.content.Context
import android.content.Intent
+import android.graphics.BitmapFactory
import android.graphics.PixelFormat
import android.graphics.Point
import android.opengl.GLSurfaceView
@@ -13,20 +13,25 @@ import android.util.Log
import android.view.*
import android.widget.*
import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.view.GestureDetectorCompat
-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.model.ChangeCallStatusRequestModel
+import com.hmg.hmgDr.model.GetSessionStatusModel
+import com.hmg.hmgDr.model.NotificationVideoModel
+import com.hmg.hmgDr.model.SessionStatusModel
import com.hmg.hmgDr.ui.VideoCallContract
import com.hmg.hmgDr.ui.VideoCallPresenterImpl
import com.hmg.hmgDr.ui.VideoCallResponseListener
import com.hmg.hmgDr.util.DynamicVideoRenderer
+import com.hmg.hmgDr.util.NotificationUtil
import com.hmg.hmgDr.util.ViewsUtil
import com.opentok.android.*
import kotlin.math.ceil
+
class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
PublisherKit.PublisherListener,
SubscriberKit.VideoListener, VideoCallContract.VideoCallView {
@@ -39,6 +44,14 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
private const val RC_SETTINGS_SCREEN_PERM = 123
private const val RC_VIDEO_APP_PERM = 124
+ const val CHANNEL_DEFAULT_IMPORTANCE = "Video_stream_channel"
+ const val CHANNEL_DEFAULT_NAME = "Video cAll"
+ const val ONGOING_NOTIFICATION_ID = 1
+
+
+ const val ACTION_START_CALL = "com.hmg.hmgDr.Service.action.startCall"
+ const val ACTION_MINIMIZE_CALL = "com.hmg.hmgDr.Service.action.minimizeCall"
+ const val ACTION_END_CALL = "com.hmg.hmgDr.Service.action.endCall"
}
private lateinit var windowManagerParams: WindowManager.LayoutParams
@@ -111,35 +124,52 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
private val serviceBinder: IBinder = VideoStreamBinder()
+ // Notification variables
+ private lateinit var mNotificationManagerCompat: NotificationManagerCompat
+
override fun onBind(intent: Intent?): IBinder {
return serviceBinder
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
- if (intent != null && intent.extras != null) {
- arguments = intent.extras
-
- arguments?.run {
- apiKey = getString("apiKey")
- sessionId = getString("sessionId")
- token = getString("token")
- appLang = getString("appLang")
- baseUrl = getString("baseUrl")
- sessionStatusModel = getParcelable("sessionStatusModel")
- if (sessionStatusModel != null)
- isRecording = sessionStatusModel!!.isRecording
- }
+ if (intent != null) {
+
+ val action = intent.action
- //init WindowManager
- mWindowManager = getSystemService(WINDOW_SERVICE) as WindowManager
+ if (action == ACTION_START_CALL) {
+ if (intent.extras != null) {
+ arguments = intent.extras
+ arguments?.run {
+ apiKey = getString("apiKey")
+ sessionId = getString("sessionId")
+ token = getString("token")
+ appLang = getString("appLang")
+ baseUrl = getString("baseUrl")
+ sessionStatusModel = getParcelable("sessionStatusModel")
+ if (sessionStatusModel != null)
+ isRecording = sessionStatusModel!!.isRecording
+ }
- getWindowManagerDefaultDisplay()
+ //init WindowManager
+ mWindowManager = getSystemService(WINDOW_SERVICE) as WindowManager
- //Init LayoutInflater
- val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ getWindowManagerDefaultDisplay()
+
+ //Init LayoutInflater
+ val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
+
+ addFloatingWidgetView(inflater)
+ handleDragDialog()
+
+ addForegroundService()
+ }
+ } else if (action == ACTION_END_CALL) {
+ closeVideoCall()
+ } else if (action == ACTION_MINIMIZE_CALL) {
+ if (!isFullScreen)
+ onMinimizedClicked()
+ }
- addFloatingWidgetView(inflater)
- handleDragDialog()
}
// Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show()
return START_STICKY
@@ -308,7 +338,10 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
videoCallPresenter.callClintConnected(sessionStatusModel)
}
}
- mConnectedHandler!!.postDelayed(mConnectedRunnable!!, (10 * 1000).toLong()) // TODO MOSA return from 10 to 55
+ mConnectedHandler!!.postDelayed(
+ mConnectedRunnable!!,
+ (55 * 1000).toLong()
+ )
}
private fun handleVideoViewHeight() {
@@ -726,6 +759,7 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
private fun disconnectSession() {
if (mSession == null) {
videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED)
+ stopForeground(true)
stopSelf()
return
}
@@ -753,6 +787,7 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
sessionStatusModel!!.vcid
)
)
+ stopForeground(true)
stopSelf()
}
@@ -865,6 +900,7 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
disconnectSession()
videoCallResponseListener?.onCallFinished(Activity.RESULT_OK, returnIntent)
stopSelf()
+ stopForeground(true)
}
}
@@ -889,6 +925,158 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
).toInt()
}
+ private fun addForegroundService() {
+ mNotificationManagerCompat = NotificationManagerCompat.from(applicationContext)
+ val areNotificationsEnabled = mNotificationManagerCompat.areNotificationsEnabled()
+ if (!areNotificationsEnabled) {
+ Toast.makeText(
+ this,
+ "You need to enable notifications for this app",
+ Toast.LENGTH_SHORT
+ ).show()
+ // Links to this app's notification settings
+ openNotificationSettingsForApp()
+ return
+ }
+ generateBigTextStyleNotification()
+ }
+
+ private fun generateBigTextStyleNotification() {
+ val notificationData: NotificationVideoModel =
+ NotificationVideoModel(
+ sessionStatusModel!!.patientName,
+ "Tap to return to call",
+ CHANNEL_DEFAULT_IMPORTANCE,
+ CHANNEL_DEFAULT_NAME,
+ "Video call stream background",
+ mSummaryText = "timer"
+ )
+ // 1. Create/Retrieve Notification Channel for O and beyond devices (26+).
+ val notificationChannelId: String =
+ NotificationUtil.createNotificationChannel(this, notificationData)
+
+ // 2. Build the BIG_TEXT_STYLE.
+ val bigTextStyle =
+ NotificationCompat.BigTextStyle() // Overrides ContentText in the big form of the template.
+ .bigText(notificationData.mBigText) // Overrides ContentTitle in the big form of the template.
+ .setBigContentTitle(notificationData.mBigContentTitle) // Summary line after the detail section in the big form of the template.
+ // Note: To improve readability, don't overload the user with info. If Summary Text
+ // doesn't add critical information, you should skip it.
+ .setSummaryText(notificationData.mSummaryText)
+
+ // 3. Set up main Intent for notification.
+ val pendingIntent: PendingIntent =
+ Intent(this, VideoStreamFloatingWidgetService::class.java)
+ .let { notificationIntent ->
+ notificationIntent.action = ACTION_MINIMIZE_CALL
+ PendingIntent.getService(this, 0, notificationIntent, 0)
+ }
+
+ // 4. Create additional Actions (Intents) for the Notification.
+ // Dismiss Action.
+ val endCallPendingIntent: PendingIntent =
+ Intent(this, VideoStreamFloatingWidgetService::class.java).apply {
+ action = ACTION_END_CALL
+ }
+ .let { notificationIntent ->
+ PendingIntent.getService(this, 0, notificationIntent, 0)
+ }
+// val endCallAction = NotificationCompat.Action.Builder(
+// R.drawable.ic_end_call,
+// "End Call",
+// endCallPendingIntent
+// )
+// .build()
+
+ // 5. Build and issue the notification.
+ // Notification Channel Id is ignored for Android pre O (26).
+
+
+ // 5. Build and issue the notification.
+ // Notification Channel Id is ignored for Android pre O (26).
+ val notificationCompatBuilder = notificationChannelId?.let {
+ NotificationCompat.Builder(
+ applicationContext, it
+ )
+ }
+
+ // notification's layout
+ val mRemoteViews = RemoteViews(packageName, R.layout.notifi_video_view)
+ mRemoteViews.setImageViewResource(R.id.iv_icon, R.mipmap.ic_launcher)
+ // notification's title
+ mRemoteViews.setTextViewText(R.id.notify_title, notificationData.mContentTitle)
+ // notification's content
+ mRemoteViews.setTextViewText(R.id.notify_content, notificationData.mContentText)
+ mRemoteViews.setOnClickPendingIntent(R.id.btn_end, endCallPendingIntent)
+
+ val notification: Notification = notificationCompatBuilder
+ // BIG_TEXT_STYLE sets title and content for API 16 (4.1 and after).
+ .setStyle(bigTextStyle)
+ // Title for API <16 (4.0 and below) devices.
+ .setContentTitle(notificationData.mBigContentTitle)
+ // Content for API <24 (7.0 and below) devices.
+ .setContentText(notificationData.mContentText)
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setLargeIcon(
+ BitmapFactory.decodeResource(
+ resources,
+ R.mipmap.ic_launcher
+ )
+ )
+ .setCustomContentView(mRemoteViews)
+ .setCustomBigContentView(mRemoteViews)
+ .setContentIntent(pendingIntent)
+ .setDefaults(NotificationCompat.DEFAULT_ALL)
+ // Set primary color (important for Wear 2.0 Notifications).
+ .setColor(ContextCompat.getColor(applicationContext, R.color.colorPrimary))
+ .setCategory(Notification.CATEGORY_SERVICE)
+ .setPriority(notificationData.mPriority)
+ .setVisibility(notificationData.mChannelLockscreenVisibility)
+// .addAction(endCallAction)
+ .build()
+
+ mNotificationManagerCompat.notify(ONGOING_NOTIFICATION_ID, notification)
+
+ startForeground(ONGOING_NOTIFICATION_ID, notification)
+ /*val notification: Notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ Notification.Builder(this, CHANNEL_DEFAULT_IMPORTANCE)
+ .setContentTitle("")
+ .setContentText("")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setContentIntent(pendingIntent)
+ .setOngoing(true)
+ .build()
+ } else {
+ Notification.Builder(this)
+ .setContentTitle("")
+ .setContentText("")
+ .setSmallIcon(R.mipmap.ic_launcher)
+ .setOngoing(true)
+ .setContentIntent(pendingIntent)
+ .build()
+ }
+ // Notification ID cannot be 0.
+ */
+ }
+
+ /**
+ * IMPORTANT NOTE: You should not do this action unless the user takes an action to see your
+ * Notifications like this sample demonstrates. Spamming users to re-enable your notifications
+ * is a bad idea.
+ */
+ private fun openNotificationSettingsForApp() {
+ // Links to this app's notification settings.
+ val intent = Intent()
+ intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
+ intent.putExtra("app_package", packageName)
+ intent.putExtra("app_uid", applicationInfo.uid)
+
+ // for Android 8 and above
+ intent.putExtra("android.provider.extra.APP_PACKAGE", packageName)
+ startActivity(intent)
+ }
+
+
/**
* OnTouch actions
*/
@@ -1001,7 +1189,11 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
mParams.x =
(szWindow.x - current_x_cord * current_x_cord - videoCallContainer.width).toInt()
- mWindowManager?.updateViewLayout(floatingWidgetView, mParams)
+ try {
+ mWindowManager?.updateViewLayout(floatingWidgetView, mParams)
+ } catch (e: Exception) {
+ Log.e("windowManagerUpdate", "${e.localizedMessage}.")
+ }
val x = szWindow.x - current_x_cord
object : CountDownTimer(500, 5) {
//get params of Floating Widget view
@@ -1014,13 +1206,21 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
mParams.x =
(szWindow.x - current_x_cord * current_x_cord * step - videoCallContainer.width).toInt()
- mWindowManager?.updateViewLayout(floatingWidgetView, mParams)
+ try {
+ mWindowManager?.updateViewLayout(floatingWidgetView, mParams)
+ } catch (e: Exception) {
+ Log.e("windowManagerUpdate", "${e.localizedMessage}.")
+ }
}
override fun onFinish() {
mParams.x = -(szWindow.x - videoCallContainer.width)
- mWindowManager?.updateViewLayout(floatingWidgetView, mParams)
+ try {
+ mWindowManager?.updateViewLayout(floatingWidgetView, mParams)
+ } catch (e: Exception) {
+ Log.e("windowManagerUpdate", "${e.localizedMessage}.")
+ }
}
}.start()
}
@@ -1042,7 +1242,12 @@ class VideoStreamFloatingWidgetService : Service(), Session.SessionListener,
mParams.x =
(szWindow.x + current_x_cord * current_x_cord * step - videoCallContainer.width).toInt()
- mWindowManager?.updateViewLayout(floatingWidgetView, mParams)
+ try {
+ mWindowManager?.updateViewLayout(floatingWidgetView, mParams)
+ } catch (e: Exception) {
+ Log.e("windowManagerUpdate", "${e.localizedMessage}.")
+ }
+
}
override fun onFinish() {
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Model/ChangeCallStatusRequestModel.java b/android/app/src/main/kotlin/com/hmg/hmgDr/model/ChangeCallStatusRequestModel.java
similarity index 99%
rename from android/app/src/main/kotlin/com/hmg/hmgDr/Model/ChangeCallStatusRequestModel.java
rename to android/app/src/main/kotlin/com/hmg/hmgDr/model/ChangeCallStatusRequestModel.java
index 5fcdb611..c7993d5f 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/Model/ChangeCallStatusRequestModel.java
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/model/ChangeCallStatusRequestModel.java
@@ -1,4 +1,4 @@
-package com.hmg.hmgDr.Model;
+package com.hmg.hmgDr.model;
import android.os.Parcel;
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Model/GetSessionStatusModel.java b/android/app/src/main/kotlin/com/hmg/hmgDr/model/GetSessionStatusModel.java
similarity index 99%
rename from android/app/src/main/kotlin/com/hmg/hmgDr/Model/GetSessionStatusModel.java
rename to android/app/src/main/kotlin/com/hmg/hmgDr/model/GetSessionStatusModel.java
index 9e2e1cf4..32b3a96c 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/Model/GetSessionStatusModel.java
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/model/GetSessionStatusModel.java
@@ -1,4 +1,4 @@
-package com.hmg.hmgDr.Model;
+package com.hmg.hmgDr.model;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/model/NotificationDataModel.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/model/NotificationDataModel.kt
new file mode 100644
index 00000000..bc025132
--- /dev/null
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/model/NotificationDataModel.kt
@@ -0,0 +1,16 @@
+package com.hmg.hmgDr.model
+
+/** Represents standard data needed for a Notification. */
+open class NotificationDataModel(
+ // Standard notification values:
+ var mContentTitle: String,
+ var mContentText: String,
+ var mPriority: Int ,
+ // Notification channel values (O and above):
+ var mChannelId: String,
+ var mChannelName: CharSequence,
+ var mChannelDescription: String,
+ var mChannelImportance: Int ,
+ var mChannelEnableVibrate: Boolean ,
+ var mChannelLockscreenVisibility: Int
+)
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/model/NotificationVideoModel.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/model/NotificationVideoModel.kt
new file mode 100644
index 00000000..78c15a91
--- /dev/null
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/model/NotificationVideoModel.kt
@@ -0,0 +1,35 @@
+package com.hmg.hmgDr.model
+
+import android.app.NotificationManager
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.core.app.NotificationCompat
+
+class NotificationVideoModel constructor(
+ mContentTitle: String,
+ mContentText: String,
+ mChannelId: String,
+ mChannelName: CharSequence,
+ mChannelDescription: String,
+ mPriority: Int = NotificationCompat.PRIORITY_DEFAULT,
+ mChannelImportance: Int = NotificationManager.IMPORTANCE_DEFAULT,
+ mChannelEnableVibrate: Boolean = false,
+ mChannelLockscreenVisibility: Int = NotificationCompat.VISIBILITY_PUBLIC,
+ // Unique data for this Notification.Style:
+ var mBigContentTitle: String = mContentTitle,
+ val mBigText: String = mContentText,
+ val mSummaryText: String
+
+) : NotificationDataModel(
+ mContentTitle,
+ mContentText,
+ mPriority,
+ mChannelId,
+ mChannelName,
+ mChannelDescription,
+ mChannelImportance,
+ mChannelEnableVibrate,
+ mChannelLockscreenVisibility
+) {
+
+}
\ No newline at end of file
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Model/SessionStatusModel.java b/android/app/src/main/kotlin/com/hmg/hmgDr/model/SessionStatusModel.java
similarity index 98%
rename from android/app/src/main/kotlin/com/hmg/hmgDr/Model/SessionStatusModel.java
rename to android/app/src/main/kotlin/com/hmg/hmgDr/model/SessionStatusModel.java
index 51b0b1ee..fe309922 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/Model/SessionStatusModel.java
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/model/SessionStatusModel.java
@@ -1,4 +1,4 @@
-package com.hmg.hmgDr.Model;
+package com.hmg.hmgDr.model;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallContract.java b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallContract.java
index 2b099551..8b615e69 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallContract.java
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallContract.java
@@ -1,8 +1,8 @@
package com.hmg.hmgDr.ui;
-import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel;
-import com.hmg.hmgDr.Model.GetSessionStatusModel;
-import com.hmg.hmgDr.Model.SessionStatusModel;
+import com.hmg.hmgDr.model.ChangeCallStatusRequestModel;
+import com.hmg.hmgDr.model.GetSessionStatusModel;
+import com.hmg.hmgDr.model.SessionStatusModel;
public interface VideoCallContract {
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallPresenterImpl.java b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallPresenterImpl.java
index ea2128ba..63cf8c27 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallPresenterImpl.java
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/VideoCallPresenterImpl.java
@@ -1,8 +1,8 @@
package com.hmg.hmgDr.ui;
-import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel;
-import com.hmg.hmgDr.Model.GetSessionStatusModel;
-import com.hmg.hmgDr.Model.SessionStatusModel;
+import com.hmg.hmgDr.model.ChangeCallStatusRequestModel;
+import com.hmg.hmgDr.model.GetSessionStatusModel;
+import com.hmg.hmgDr.model.SessionStatusModel;
import com.hmg.hmgDr.Service.AppRetrofit;
import com.hmg.hmgDr.Service.SessionStatusAPI;
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt
index 061356ac..b020ed29 100644
--- a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt
@@ -11,7 +11,6 @@ import android.graphics.Point
import android.graphics.drawable.ColorDrawable
import android.opengl.GLSurfaceView
import android.os.*
-import android.util.DisplayMetrics
import android.util.Log
import android.view.*
import android.widget.*
@@ -21,9 +20,9 @@ import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.view.GestureDetectorCompat
import androidx.fragment.app.DialogFragment
-import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel
-import com.hmg.hmgDr.Model.GetSessionStatusModel
-import com.hmg.hmgDr.Model.SessionStatusModel
+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.VideoCallContract.VideoCallPresenter
import com.hmg.hmgDr.ui.VideoCallContract.VideoCallView
diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/util/NotificationUtil.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/util/NotificationUtil.kt
new file mode 100644
index 00000000..13d6bd19
--- /dev/null
+++ b/android/app/src/main/kotlin/com/hmg/hmgDr/util/NotificationUtil.kt
@@ -0,0 +1,42 @@
+package com.hmg.hmgDr.util
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.graphics.Color
+import android.os.Build
+import com.hmg.hmgDr.model.NotificationDataModel
+
+object NotificationUtil {
+
+ fun createNotificationChannel(context: Context, notificationDataModel: NotificationDataModel): String{
+ // The id of the channel.
+ val channelId: String = notificationDataModel.mChannelId
+
+ // NotificationChannels are required for Notifications on O (API 26) and above.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ // The user-visible name of the channel.
+ val channelName: CharSequence = notificationDataModel.mChannelName
+ // The user-visible description of the channel.
+ val channelDescription: String = notificationDataModel.mChannelDescription
+ val channelImportance: Int = notificationDataModel.mChannelImportance
+ val channelEnableVibrate: Boolean = notificationDataModel.mChannelEnableVibrate
+ val channelLockscreenVisibility: Int = notificationDataModel.mChannelLockscreenVisibility
+
+ // Initializes NotificationChannel.
+ val notificationChannel = NotificationChannel(channelId, channelName, channelImportance)
+ notificationChannel.description = channelDescription
+ notificationChannel.enableVibration(channelEnableVibrate)
+ notificationChannel.lightColor = Color.BLUE
+ notificationChannel.lockscreenVisibility = channelLockscreenVisibility
+
+ // Adds NotificationChannel to system. Attempting to create an existing notification
+ // channel with its original values performs no operation, so it's safe to perform the
+ // below sequence.
+ val notificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(notificationChannel)
+ }
+ return channelId
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/res/drawable/ic_arrow_bottom.xml b/android/app/src/main/res/drawable/ic_arrow_bottom.xml
new file mode 100644
index 00000000..1aeaa998
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_arrow_bottom.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_arrow_top.xml b/android/app/src/main/res/drawable/ic_arrow_top.xml
new file mode 100644
index 00000000..1d112693
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_arrow_top.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_end_call.xml b/android/app/src/main/res/drawable/ic_end_call.xml
new file mode 100644
index 00000000..724ce9db
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_end_call.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/android/app/src/main/res/layout/notifi_video_view.xml b/android/app/src/main/res/layout/notifi_video_view.xml
new file mode 100644
index 00000000..3afd925b
--- /dev/null
+++ b/android/app/src/main/res/layout/notifi_video_view.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file