ronald_s56
ronald_s56

Reputation: 321

Android NotificationChannel compatability with older API

I'm new to android development and Java, and I'm slightly confused about the handling of backwards compatibility when using classes that have been introduced in the latest versions.

I've checked out the android support library and see the various XXXCompat classes available. For the ones I've looked at they appear to pretty much branch on VERSION.SDK_INT and call a new api or an old api.

I am using a support library (com.android.support:support-v4:27.1.1) version that is targeted for a newer api than my targetSdkVersion (25). I was under the impression this was the intended use case? to be able to write code with newer api's but have it work when targeting older sdk.

If so, how is this possible? For instance ContextCompat is has the following for startForegroundService

public static void startForegroundService(@NonNull Context context, 
@NonNull Intent intent) {
    if (VERSION.SDK_INT >= 26) {
        context.startForegroundService(intent);
    } else {
        context.startService(intent);
    }
}

However in the version I am targeting the Context doesn't have the method startForegroundService. If paste this if block into my code, it fails to compile with java: cannot find symbol ....

I can only assume that even if you compiled against a newer api (such that it could resolve the symbols), if those symbols don't exist at runtime, as long a they are not called it is not a problem?

So this is fine for api calls that are abstracted by the XXXCompat classes, but when using new classes like NotificationChannel. I can only import this if upping my targetSdkVersion to > 26. So assuming I do this, then this class is available. All uses of it that I have seen do

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
   NotificationChannel channel = ...
}

Does this mean that at runtime, for lower Build.VERSION.SDK_INT the symbol NotificationChannel will not exist? and if I attempted to instantiate this class it on a lower android version, it would crash?

Upvotes: 2

Views: 1299

Answers (1)

Jure Sencar
Jure Sencar

Reputation: 624

Before Oreo, you can just start your service. For Oreo and higher, the service needs to run in foreground and thus post a notification upon service start otherwise it gets destroyed.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    startForegroundService(intent)
} else {
    startService(intent)
}

To post notification in Oreo and above you need to create a notification channel, before Oreo you just add your channel id to the notification builder (no need to create a channel). Snippet code from service:

String channelId = "myAppChannel"

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    // build notification channel
    createNotificationChannel(channelId, ...)
}

NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId)

// Build your notification
Notification notification = notificationBuilder
        .setOngoing(true)
        .setSmallIcon(icon)
        .setCategory(Notification.CATEGORY_SERVICE)
        .build()

// post notification belonging to this service
startForeground(NOTIFICATION_ID, notification)

When you create createNotificationChannel function, just annotate it with @RequiresApi(26).

Upvotes: 2

Related Questions