React native with foreground service - handleWindowVisibility: no activity for token android.os.BinderProxy

Viewed 113

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>
0 Answers
Related