应用程序关闭时,Android 推送通知不起作用

est*_*con 6 android push-notification server-sent-events android-8.0-oreo

我正在使用OkSse订阅我的服务器发送事件。

每当服务器发送新消息时,无论应用程序处于前台、最小化还是完全关闭,都应显示通知。

通知在最小化或在前台时按预期工作,但在完全关闭时,这仅适用于某些设备品牌

研究了一下,我发现:

此问题仅在小米、Oppo、一加、Vivo、联想、华为、三星等制造商的手机上发现。

WhatsApp, Facebook, Slack, Gmail, etc..即使应用程序关闭,如何显示通知?

我不使用FCM,只是订阅Sse

我也有清单:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<receiver android:name="com.goparty.communication.NotificationsAlarmReceiver">
    <intent-filter>
        <action android:name="android.media.action.DISPLAY_NOTIFICATION" />
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

更新

我设法通过使用IntentServiceand使其工作,BroadcastReceiver但是这会因Oreo版本而崩溃。

经过更多的阅读我发现JobIntentServiceIntentService当定位Android O和上面的替换。

过渡到JobIntentService非常简单,但同样,当我关闭应用程序时,我的解决方案不起作用。

通知的全部目的是即使在应用程序关闭时也能正常工作。

IntentService通过发送broadcast带有我的服务的新意图在后台使用工作。

我正在做同样的事情JobIntentService,但没有运气。

这是我的代码:

public class NotificationService extends JobIntentService {

    private static final int JOB_ID = 1;
    private NotificationManager notificationManager;

    public static void enqueueWork(Context context, Intent intent) {
        enqueueWork(context, NotificationService.class, JOB_ID, intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Logger.logGoParty(getClass().getSimpleName() + "#onCreate");
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Logger.logGoParty("Running in background.");
        sendBroadcast(new Intent(getApplicationContext(), NotificationService.class));
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        Logger.logGoParty(getClass().getSimpleName() + "#onHandleWork");
        Logger.logGoParty("Sse initialized");

        Request request = new Request.Builder().url("the sse url").build();
        OkSse okSse = new OkSse();

        ServerSentEvent sse = okSse.newServerSentEvent(request, new ServerSentEvent.Listener() {
            @Override
            public void onOpen(ServerSentEvent sse, Response response) {
                Logger.logGoParty(response.toString());
            }

            @Override
            public void onMessage(ServerSentEvent sse, String id, String event, String message) {
                Logger.logGoParty("Sse#onMessage: " + message);
                try {
                    JSONObject promoJson = new JSONObject(message);

                    sendNotification(...);

                } catch (JSONException e) {
                    Logger.logGoParty("JSONException: " + e.toString());
                }
            }
                // ...
        });
    }

    private void sendNotification(String promoImageUrl, String notificationContent, String title) {

        try {
            URL url = new URL(promoImageUrl);
            Bitmap bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());


            NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
            style.bigPicture(bitmap);

            Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

            Intent intent = new Intent(this, MapsActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
            intent.putExtra("page-to-open", "promotions");
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);


            NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, GoParty.PROMO_CHANNEL_ID)
                    .setSmallIcon(R.mipmap.ic_launcher_round)
                    .setContentTitle(title)
                    .setAutoCancel(true)
                    .setSound(defaultSound)
                    .setContentText(notificationContent)
                    .setContentIntent(pendingIntent)
                    .setStyle(style)
                    .setLargeIcon(bitmap)
                    .setWhen(System.currentTimeMillis())
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setCategory(NotificationCompat.CATEGORY_MESSAGE);

            notificationManager.notify(0, notificationBuilder.build());

            Log.i("GoParty", "Notification sent ----- ");

        } catch (MalformedURLException e) {
            Logger.logGoParty(e.toString());
        } catch (IOException e) {
            Logger.logGoParty(e.toString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

通知接收者:

public class NotificationReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        Intent notificationIntent = new Intent(context, NotificationService.class);
        NotificationService.enqueueWork(context, notificationIntent);
    }
}
Run Code Online (Sandbox Code Playgroud)

显现:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.goparty">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />


    <application
        android:name=".scopes.application.GoParty"
        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/AppTheme">

        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps"
            android:screenOrientation="portrait">
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.goparty.LoginActivity" />
        </activity>

        <service
            android:name=".jobs.NotificationService"
            android:permission="android.permission.BIND_JOB_SERVICE" />

        <receiver android:name=".receivers.NotificationReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

    </application>

</manifest>
Run Code Online (Sandbox Code Playgroud)

小智 2

您的方法:使用 OkSse 进行通知意味着需要不断运行后台服务。

问题一:Android后台服务限制链接

JobIntentService内部将使用 JobService,并且它不会是持续运行的服务。由于执行时间限制,它不会无动于衷地运行。它将停止并重新安排稍后继续执行。所以在你的情况下,这是行不通的。

问题 2:小米、Oppo、一加、Vivo、联想、华为、三星的设备有电池优化检查,导致 JobIntentService 停止。

解决方案:

1)运行前台服务,这很丑陋,不推荐

2)强烈推荐Firebase 高优先级通知链接

我已经在上述设备上实现了它,即使应用程序设置为电池优化模式,您也会收到通知。