3

I have an app that is supposed to intercept incoming calls, compare phone number with list created by the user and make silent mode if the caller is in this list, so I need my app to work always even if it was not launched by user. I tried a Service which is starting in my App class, I also call startForeground method within onStartCommand section and return START_STICKY. However, swiping away my app in app manager completely kills it without any allusion on recreating or background work, all functions that were working on app being launched or in "hide" state are not working anymore (until I tap on service notification, it opens the app again). What am I missing? I need my app to remain functional even if it is not launched so app could always compare incoming calls and decide to switch to "Do not disturb" mode.

Here is the my Service class code:

class BackgroundWorkService : Service() {

private val NOTIF_ID = 1
private val NOTIF_CHANNEL_ID = "CHANNEL_ID"


override fun onBind(intent: Intent): IBinder? {
    return null
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    initChannel(this)
    startServiceForeground()
    return START_STICKY
}

private fun initChannel(context: Context) {
    if (Build.VERSION.SDK_INT < 26) { return }

    val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    val channel = NotificationChannel(
        NOTIF_CHANNEL_ID,
        "Channel for service",
        NotificationManager.IMPORTANCE_DEFAULT
    )
    channel.description = "Channel description"
    notificationManager.createNotificationChannel(channel)
}

private fun startServiceForeground() {
    val notificationIntent = Intent(this, MainActivity::class.java)
    val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0)

    startForeground(
        NOTIF_ID, NotificationCompat.Builder(
            this,
            NOTIF_CHANNEL_ID
        )
            .setOngoing(true)
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setContentTitle(getString(R.string.app_name))
            .setContentText("Service is running background")
            .setContentIntent(pendingIntent)
            .build()
    )
}

Here is where I'm starting the service:

class App : Application() {

override fun onCreate() {
    super.onCreate()
    startService(Intent(this, BackgroundWorkService::class.java))
}

}

EDIT:

Manifest is also updated:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.donotbotherme">

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<application
    android:name=".app.App"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.DoNotBotherMe">

    <service
        android:name=".app.BackgroundWorkService"
        android:enabled="true"
        android:exported="true" />

    <activity android:name=".view.MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
FarVoyager
  • 49
  • 4

1 Answers1

1

I have found a solution for this case after some more searches and conversations. The main fact I missed is that Android does not permit any app to work in background, instead you can create BroadcastReceiver, register it in Manifest and determine its intent-filter, then simply place the code you want to be executed in onReceive method of your BroadcastReceiver class. When the intent-filter is triggered your app will launch, execute the code and then kill itself.

Summarizing, to make you app to do some of its functions even while closed, you need to:

  1. Create your BroadcastReceiver class (simply inherit your class from BroadcastReceiver);

  2. Register it in your Manifest (here is my example):

    <receiver android:name=".viewmodel.CallListener"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
    </receiver>
    
  3. Place the code you want to execute in onReceive body in your BroadcastReceiver class.

Hope this solution will help somebody.

FarVoyager
  • 49
  • 4