From 057a06fffbc82fb69bc5115b4af976dc51ef9142 Mon Sep 17 00:00:00 2001 From: mosazaid Date: Mon, 5 Jul 2021 17:07:28 +0300 Subject: [PATCH] adding custom notification with actions --- android/app/src/debug/AndroidManifest.xml | 65 ++++- android/app/src/main/AndroidManifest.xml | 2 +- .../main/kotlin/com/hmg/hmgDr/MainActivity.kt | 20 +- .../hmg/hmgDr/Service/SessionStatusAPI.java | 6 +- .../VideoStreamFloatingWidgetService.kt | 265 ++++++++++++++++-- .../ChangeCallStatusRequestModel.java | 2 +- .../GetSessionStatusModel.java | 2 +- .../hmg/hmgDr/model/NotificationDataModel.kt | 16 ++ .../hmg/hmgDr/model/NotificationVideoModel.kt | 35 +++ .../{Model => model}/SessionStatusModel.java | 2 +- .../com/hmg/hmgDr/ui/VideoCallContract.java | 6 +- .../hmg/hmgDr/ui/VideoCallPresenterImpl.java | 6 +- .../hmgDr/ui/fragment/VideoCallFragment.kt | 7 +- .../com/hmg/hmgDr/util/NotificationUtil.kt | 42 +++ .../src/main/res/drawable/ic_arrow_bottom.xml | 5 + .../src/main/res/drawable/ic_arrow_top.xml | 5 + .../app/src/main/res/drawable/ic_end_call.xml | 5 + .../src/main/res/layout/notifi_video_view.xml | 91 ++++++ 18 files changed, 527 insertions(+), 55 deletions(-) rename android/app/src/main/kotlin/com/hmg/hmgDr/{Model => model}/ChangeCallStatusRequestModel.java (99%) rename android/app/src/main/kotlin/com/hmg/hmgDr/{Model => model}/GetSessionStatusModel.java (99%) create mode 100644 android/app/src/main/kotlin/com/hmg/hmgDr/model/NotificationDataModel.kt create mode 100644 android/app/src/main/kotlin/com/hmg/hmgDr/model/NotificationVideoModel.kt rename android/app/src/main/kotlin/com/hmg/hmgDr/{Model => model}/SessionStatusModel.java (98%) create mode 100644 android/app/src/main/kotlin/com/hmg/hmgDr/util/NotificationUtil.kt create mode 100644 android/app/src/main/res/drawable/ic_arrow_bottom.xml create mode 100644 android/app/src/main/res/drawable/ic_arrow_top.xml create mode 100644 android/app/src/main/res/drawable/ic_end_call.xml create mode 100644 android/app/src/main/res/layout/notifi_video_view.xml 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