I create app in react native, that needs to run foreground service containing native code. The service itself works well but after killing main application process (by pressing square button and swiping the app away) - it sometimes returns without any complications on launch from icon or notification but it oftens displays blank screen (without any activity launched) and prints handleWindowVisibility: no activity for token android.os.BinderProxy in logcat. I've been googling it for a few hours but there is little feedback on that matter and nothing seems to work for me.
The class I use to communicate through RCT Bridge
@ReactMethod
fun init() {
val service = Intent(context, MyService::class.java)
service.action = SERVICE_ACTION_EXECUTE
if(!isMyServiceRunning(MyService::class.java)) {
Log.i("MyService", "Starting new service")
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(service)
} else {
context.startService(service)
}
}
val serviceConnection = object: ServiceConnection {
override fun onServiceConnected(p0: ComponentName?, binder: IBinder?) {
myService = (binder as MyService.LocalBinder).getService()
myService?.bindClient(this@Integrator)
}
override fun onServiceDisconnected(p0: ComponentName?) {
myService?.unbindClient()
}
}
context.bindService(service, serviceConnection, Context.BIND_AUTO_CREATE)
}
private fun isMyServiceRunning(serviceClass: Class<*>): Boolean {
val manager: ActivityManager? =
context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager?
for (service in manager?.getRunningServices(Int.MAX_VALUE)!!) {
if (serviceClass.name == service.service.className) {
return true
}
}
return false
}
My foreground service:
@RequiresApi(api = Build.VERSION_CODES.O)
private fun createNotificationChannel() {
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val name: CharSequence =
getString(R.string.app_name)
val channel =
NotificationChannel(NOTIFICATION_CHANNEL_ID, name, NotificationManager.IMPORTANCE_LOW)
notificationManager.createNotificationChannel(channel)
}
private fun buildNotification(): Notification {
val intent = Intent(applicationContext, MainActivity::class.java)
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, intent, 0)
if(notificationBuilder == null) {
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
notificationBuilder = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(pendingIntent)
.setCategory(Notification.CATEGORY_SERVICE)
.setOngoing(true)
}
// Set Exit button action
val exitIntent =
Intent(applicationContext, MyService::class.java).setAction(SERVICE_ACTION_STOP)
notificationBuilder!!.addAction(
android.R.drawable.ic_delete,
getString(R.string.close),
PendingIntent.getService(applicationContext, 0, exitIntent, 0)
)
return notificationBuilder!!.build()
}
override fun onCreate() {
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
createNotificationChannel()
val notification = buildNotification()
startForeground(NOTIFICATION_FOREGROUND_SERVICE_ID, notification)
val action = intent?.action
if(action != null){
when(action) {
SERVICE_ACTION_EXECUTE -> {
Log.d(TAG, "Service executed")
executor.execute(IncomingIntentRouter(intent))
}
SERVICE_ACTION_STOP -> {
Log.d(TAG, "Service stopped")
stopService()
}
}
} else {
Log.d(TAG, "Got null onStartCommand() action")
}
return START_STICKY
}
Android manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config"
android:extractNativeLibs="true">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".MyService" />
</application>