I'm making an Android app for personal use that uses porcupine to detect a custom wakeword and start google assistant.
The app is fully functioning except for the ForegroundService: whenever my app loses focus the ForegroundService remains active but it stops detecting any wakeword, however when it regains focus it works fine.
This is my Service class:
class PorcupineService : Service() {
private val accessKey = "nuh uh"
private var porcupineManager: PorcupineManager? = null
private val notificationId = "zingaraccia"
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate() {
super.onCreate()
val notification = Notification.Builder(this, notificationId)
.setContentTitle("Zingaraccia Companion")
.setContentText("Pronta a zingarare!")
.setSmallIcon(R.mipmap.ic_launcher)
.build()
this.startForeground(1, notification)
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
try {
porcupineManager = PorcupineManager.Builder()
.setAccessKey(accessKey)
.setKeywordPath("models/zingaraccia.ppn")
.setModelPath("models/porcupine_params_it.pv")
.setSensitivity(0.7f)
.build(
applicationContext
) {
// start google assistant
val inten = Intent(Intent.ACTION_VOICE_COMMAND)
inten.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(inten)
}
porcupineManager!!.start()
} catch (e: PorcupineException) {
Log.e("PORCUPINE_SERVICE", e.toString())
}
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(intent: Intent): IBinder? {
return null
}
override fun onDestroy() {
try {
porcupineManager!!.stop()
porcupineManager!!.delete()
} catch (e: Exception) {
Log.e("PORCUPINE", e.toString())
}
super.onDestroy()
}
and this is my android manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/Theme.Zingaraccia"
tools:targetApi="31">
<service
android:name=".PorcupineService"
android:enabled="true"
android:foregroundServiceType="microphone"/>
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.Zingaraccia">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
What should I do?
Edit: this is my build.gradle.kts
plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
}
android {
namespace = "com.spartacus04.zingaraccia"
compileSdk = 34
defaultConfig {
applicationId = "com.spartacus04.zingaraccia"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
implementation("ai.picovoice:porcupine-android:3.0.1")
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
}
Solved by tweaking the class a bit and using an AccessibilityService instead of a normal Service.