From d1a968cca992bc694f8b23ef1d22195ab25a3cab Mon Sep 17 00:00:00 2001 From: Angelika Serwa Date: Fri, 14 Jun 2024 11:41:09 +0200 Subject: [PATCH] Add foreground service in android example --- app/build.gradle | 6 +- app/src/main/AndroidManifest.xml | 24 +++++- .../fishjamandroidexample/CameraService.kt | 75 +++++++++++++++++++ .../fishjamandroidexample/MainActivity.kt | 3 +- .../fishjamandroidexample/RoomViewModel.kt | 15 ++++ 5 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/com/example/fishjamandroidexample/CameraService.kt diff --git a/app/build.gradle b/app/build.gradle index 5ff89f2..91297e5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,12 +7,12 @@ plugins { android { namespace 'com.example.fishjamandroidexample' - compileSdk 33 + compileSdk 34 defaultConfig { applicationId "com.example.fishjamandroidexample" minSdk 24 - targetSdk 33 + targetSdk 34 versionCode 1 versionName "1.0" @@ -57,7 +57,7 @@ android { dependencies { - implementation 'androidx.core:core-ktx:1.10.1' + implementation 'androidx.core:core-ktx:1.13.1' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1' implementation 'androidx.activity:activity-compose:1.7.1' implementation platform('androidx.compose:compose-bom:2022.10.00') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index eba6f96..866822f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,17 @@ + xmlns:tools="http://schemas.android.com/tools" > + + + + + + + + + + tools:targetApi="31" > + + + + android:theme="@style/Theme.FishjamAndroidExample" > diff --git a/app/src/main/java/com/example/fishjamandroidexample/CameraService.kt b/app/src/main/java/com/example/fishjamandroidexample/CameraService.kt new file mode 100644 index 0000000..817a5ba --- /dev/null +++ b/app/src/main/java/com/example/fishjamandroidexample/CameraService.kt @@ -0,0 +1,75 @@ +package com.example.fishjamandroidexample + +import android.app.ForegroundServiceStartNotAllowedException +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.Service +import android.content.Intent +import android.content.pm.PackageManager +import android.content.pm.ServiceInfo +import android.os.Build +import android.os.IBinder +import androidx.core.app.NotificationCompat +import androidx.core.app.ServiceCompat +import androidx.core.content.ContextCompat + +class CameraService : Service() { + private fun startForeground() { + // Before starting the service as foreground check that the app has the + // appropriate runtime permissions. In this case, verify that the user has + // granted the CAMERA permission. + val cameraPermission = + ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) + if (cameraPermission == PackageManager.PERMISSION_DENIED) { + // Without camera permissions the service cannot run in the foreground + // Consider informing user or updating your app UI if visible. + stopSelf() + return + } + + try { + val channelID = "FISHJAM_NOTIFICATION_CHANNEL" + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // Create the NotificationChannel. + val name = "Fishjam notification channel" + val importance = NotificationManager.IMPORTANCE_DEFAULT + val mChannel = NotificationChannel(channelID, name, importance) + // Register the channel with the system. You can't change the importance + // or other notification behaviors after this. + val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager + notificationManager.createNotificationChannel(mChannel) + } + val notification = NotificationCompat.Builder(this, channelID) + // Create the notification to display while the service is running + .setContentTitle("Fishjam is running") + .build() + ServiceCompat.startForeground( + /* service = */ this, + /* id = */ 100, // Cannot be 0 + /* notification = */ notification, + /* foregroundServiceType = */ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA + } else { + 0 + }, + ) + } catch (e: Exception) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S + && e is ForegroundServiceStartNotAllowedException + ) { + // App not in a valid state to start foreground service + // (e.g. started from bg) + } + // ... + } + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + startForeground() + return START_STICKY + } + override fun onBind(intent: Intent): IBinder? { + return null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/fishjamandroidexample/MainActivity.kt b/app/src/main/java/com/example/fishjamandroidexample/MainActivity.kt index a23d97d..0e52169 100644 --- a/app/src/main/java/com/example/fishjamandroidexample/MainActivity.kt +++ b/app/src/main/java/com/example/fishjamandroidexample/MainActivity.kt @@ -102,7 +102,8 @@ class MainActivity : ComponentActivity() { rememberMultiplePermissionsState( listOf( Manifest.permission.RECORD_AUDIO, - Manifest.permission.CAMERA + Manifest.permission.CAMERA, + Manifest.permission.POST_NOTIFICATIONS ) ) diff --git a/app/src/main/java/com/example/fishjamandroidexample/RoomViewModel.kt b/app/src/main/java/com/example/fishjamandroidexample/RoomViewModel.kt index 193cbfb..a22c37d 100644 --- a/app/src/main/java/com/example/fishjamandroidexample/RoomViewModel.kt +++ b/app/src/main/java/com/example/fishjamandroidexample/RoomViewModel.kt @@ -1,6 +1,8 @@ package com.example.fishjamandroidexample import android.app.Application +import android.content.Intent +import android.os.Build import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.fishjamdev.client.Config @@ -40,6 +42,15 @@ class RoomViewModel(application: Application) : setupTracks() } + override fun onCleared() { + super.onCleared() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val intent = + Intent(getApplication().applicationContext, CameraService::class.java) + getApplication().applicationContext.stopService(intent) + } + } + fun disconnect() { localVideoTrack?.stop() localVideoTrack = null @@ -75,6 +86,10 @@ class RoomViewModel(application: Application) : ) } emitParticipants() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val intent = Intent(getApplication().applicationContext, CameraService::class.java) + getApplication().applicationContext.startForegroundService(intent) + } } override fun onJoinError(metadata: Any) {