konair
konair

Reputation: 27

Notifications are delayed in Android 8.0+

I experience delays with pushes for Android O. Notifications are delayed or even aren't shown at all. It happens in both states: foreground and background. But there is no such problem for any other android version. I've provided notification channels for api 26+. Tried to change priority, to disable battery optimisation. But nothing worked.

Now my implementation for urban airship looks like:

public class UrbanAirshipWrapper {
    private static class MyNotificationFactory extends DefaultNotificationFactory {
        public MyNotificationFactory(@NonNull Context context) {
            super(context);

            if (Build.VERSION.SDK_INT >= 26) {
                String channelId = "defaultChannel";
                NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
                NotificationChannel channel = new NotificationChannel(channelId, context.getString(R.string.notification_default_channel), NotificationManager.IMPORTANCE_DEFAULT);

                channel.setSound(null, null);
                if (notificationManager != null) {
                    notificationManager.createNotificationChannel(channel);
                    setNotificationChannel(channelId);
                }
            }

            setSmallIconId(R.drawable.ic_notification);
            setColor(ContextCompat.getColor(context, R.color.notification));
        }

        @Override
        public NotificationCompat.Builder extendBuilder(@NonNull NotificationCompat.Builder builder, @NonNull PushMessage message, int notificationId) {
            if (notificationAllowed(message)) {
                return soundBuilder(builder, message);
            } else {
                return null; // preventing notification
            }
        }


        private boolean notificationAllowed(@NonNull PushMessage message) {
            Bundle pushBundle = message.getPushBundle();
            String centerId = pushBundle.getString(CENTER_ID);
            String objectNumber = pushBundle.getString(OBJECT_NUMBER);
            String type = pushBundle.getString(NOTIFICATION_TYPE);

            // not allowed arm_error for currently visible area
            if (TYPE_ARM_ERROR.equals(type) || TYPE_DISARM_ERROR.equals(type)) {
                if (centerId != null && objectNumber != null && (centerId + objectNumber).equals(sCurrentCenterPlusObject)) {
                    return false;
                }
            }

            return true; // allowed by default
        }

        private NotificationCompat.Builder soundBuilder(@NonNull NotificationCompat.Builder builder, @NonNull PushMessage message) {
            Bundle pushBundle = message.getPushBundle();
            String sound = pushBundle.getString(SOUND);

            if (TextUtils.isEmpty(sound)) {
                if (Build.VERSION.SDK_INT < 26) {
                    builder.setSound(null);
                } else {
                    RingtoneManager.getRingtone(getContext(), Settings.System.DEFAULT_NOTIFICATION_URI).play();
                }
            } else {
                Uri uri = Uri.parse("android.resource://" + getContext().getPackageName() + "/raw/" + sound);

                if (Build.VERSION.SDK_INT < 26) {
                    builder.setSound(uri);
                } else {
                    RingtoneManager.getRingtone(getContext(), uri).play();
                }
            }

            return builder;
        }
    }

    public static String sCurrentCenterPlusObject;

    private UrbanAirshipWrapper() { }

    @SuppressWarnings("deprecation")
    public static void initialize(Application application, String prodAppKey, String prodAppSecret, String gcmSender) {
        AirshipConfigOptions options = new AirshipConfigOptions.Builder()
            .setInProduction(true)
            .setProductionAppKey(prodAppKey)
            .setProductionAppSecret(prodAppSecret)
            .setGcmSender(gcmSender).build();

        UAirship.takeOff(application, options);
        UAirship.shared().getPushManager().setUserNotificationsEnabled(true);
        UAirship.shared().getPushManager().setNotificationFactory(new MyNotificationFactory(application));
    }
}

Notifications were sent via GCM and it's just data messages without any images. But I get the following error when push shows with delay:

01-25 21:58:46.336 27657-27910/com.example.app W/EnhancedIntentService: Service took too long to process intent: com.google.android.c2dm.intent.RECEIVE App may get closed.

I think that it can be a source of the problem. I've already tried to disable my custom notification factory. Also I disabled receiver and services that relate with notifications. But problem's still there.

Is there any way to fix this?

Upvotes: 1

Views: 2834

Answers (1)

konair
konair

Reputation: 27

I've found the solution. In my case problem was in google services plugin. I tried to remove it from build.gradle. And it worked. Notifications began to arrive just in time.

// This line causes the problem in my build.gradle
apply plugin: 'com.google.gms.google-services'

Also I found that GcmReceiver had received notifications in time even if I didn't disable google services plugin. So if you experience this type of problems, solution may be somewhere around GcmReceiver.

In my case with assistance of urbanairship's team I came to the following workaround.

<receiver
    android:name="com.urbanairship.push.GcmPushReceiver"
    android:permission="com.google.android.c2dm.permission.SEND">

    <intent-filter android:priority="100">
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="${applicationId}" />
    </intent-filter>
</receiver>

You need to add this in your manifest. It will bump the priority of the UA receiver.

Upvotes: 0

Related Questions