1

Android アプリのコード ベースを継承しましたが、特にローカル通知の問題に直面しています。

アイデアは、ユーザーが通知を希望するイベントの何分前にリマインダー設定も考慮して、将来スケジュールされる各イベントの通知を送信することです。

通知が初めてスローされた後、ユーザーがイベントの開始前にアプリを開くと、通知がもう一度スローされることを除いて、すべてが正常に機能します。これは、(イベント開始日 - リマインダー) とイベント開始日の間にアプリが開かれるたびに発生します。

私はすでにこれを見ましたが、これ運が悪いです。サービスを使用するとまさにこの問題が発生する可能性があり、それを削除することを提案する人もいますが、アプリを閉じたときにも通知をスローする必要があるため、これが必要だと思います.

現在、コードの構造は次のとおりです。

編集 - TabBarActivity の説明を更新

TabBarActivity 内には、AlarmManager をスケジュールするメソッドscheduleTravelNotificationがあります。このメソッドは、ローカル データベースに新しいイベントが追加されるたびに、または既存のイベントが更新された場合に実行されます。TabBarActivity は、このメソッドを onCreate および onResume メソッド内で実行します。TabBarActivity は、通知 - onclick イベントのターゲットでもあります。

private static void scheduleTravelNotification(Context context, RouteItem routeItem) {

    long currentTime = System.currentTimeMillis();
    int alarmTimeBefore = routeItem.getAlarmTimeBefore();
    long alarmTime = routeItem.getStartTime() - (alarmTimeBefore * 1000 * 60);

    if(alarmTimeBefore < 0){
        return;
    }

    if(alarmTime < currentTime){
        return;
    }

    Intent actionOnClickIntent = new Intent(context, TravelNotificationReceiver.class);
    PendingIntent travelServiceIntent = PendingIntent.getBroadcast(context, System.currentTimeMillis(), actionOnClickIntent, PendingIntent.FLAG_ONE_SHOT);

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(alarmTime);
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), travelServiceIntent);

    Log.e("NEXT ALARM", "Time: " + String.valueOf(calendar.getTimeInMillis()));
}

これはTravelNotificationReceiver.java です(BroadcastReceiver の代わりに LocalBroadcastReceiver を使用する必要がありますか?)

public class TravelNotificationReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e("RECEIVER", "received TravelNotification request");
        Intent notificationIntent = new Intent(context, TravelNotificationService.class);
        context.startService(notificationIntent);
    }
}

TravelNotificationService.javaは、Type = "Travel"、flags = 0、title = "something"、text = "something else" としてNotificationService.java設定を拡張します。

public abstract class NotificationService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        sendNotification();
        return super.onStartCommand(intent, flags, startId);
    }

    public abstract String setNotificationType();
    public abstract int setNotificationFlags();
    public abstract String setNotificationTitle();
    public abstract String setNotificationText();

    /**
     * Executes all the logic to init the service, prepare and send the notification
     */
    private void sendNotification() {

        int flags = setNotificationFlags();
        String type = setNotificationType();

        NotificationHelper.logger(type, "Received request");

        // Setup notification manager, intent and pending intent
        NotificationManager manager = (NotificationManager) this.getApplicationContext().getSystemService(this.getApplicationContext().NOTIFICATION_SERVICE);
        Intent intentAction = new Intent(this.getApplicationContext(), TabBarActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this.getApplicationContext(), 0, intentAction, flags);

        // Prepares notification
        String title = setNotificationTitle();
        String text = setNotificationText();
        Notification notification = NotificationHelper.buildNotification(getApplicationContext(), title, text, pendingIntent);

        // Effectively send the notification
        manager.notify(101, notification);

        NotificationHelper.logger(type, "Notified");
    }
}

編集 - NotificationHelper.buildNotification のコードは次のとおりです。

    public static Notification buildNotification(Context context, String title, String text, PendingIntent pendingIntent) {

        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);

        builder.setAutoCancel(true);
        builder.setContentText(text);
        builder.setContentTitle(title);
        builder.setContentIntent(pendingIntent);
        builder.setSmallIcon(R.mipmap.launcher);
        builder.setCategory(Notification.CATEGORY_MESSAGE);
        builder.setVisibility(Notification.VISIBILITY_PUBLIC);

        return builder.build();
    }

答えてくれてありがとう!

編集これも見ましが、受け入れられた回答はありませんが、この投稿では、すでに if(alarmTime < currentTime){ return; で管理されていると思われることを示唆しています。} scheduleTravelNotification で

4

4 に答える 4

0

user3137702 の回答と同様に、通知送信メソッドがヒットするたびにチェックされ、アプリケーション/アクティビティ コードから管理される APPISINFORGROUND の静的ブール値を持つことができます。

ユーザーが言ったように、アプリ/サービスのライフサイクルが原因で、 onStartCommand メソッドが奇妙なタイミングで呼び出されている可能性があります。

または、レシーバーがコードから他の場所で呼び出されていないことを確認してください。

于 2015-12-15T16:26:38.520 に答える
0

これは正確な問題ではないかもしれませんが、一見すると、サービスの有効期間中に何度も実行できる onStartCommand() で通知を送信しています。たとえば、サービス開始コマンドを「盲目的に」発行した場合" アクティビティの onCreate では、アクティビティが (再) 作成されるたびに発生します。

これを処理するには、いくつかのオプションがあります。

1 つは、サービスのプロパティとしてブール値フラグを作成し、デフォルトを false にして、通知を送信する前にチェックすることです。false の場合は通知を送信して true に設定し、既に true の場合は通知を送信しません。

もう 1 つは、サービスが既に実行されているかどうかを確認することです。実行されている場合は、最初からサービス開始コマンドを送信しないでください。これはどこでも行うのは面倒であり、DRY に違反する可能性があるため、このルートを取る場合は、サービスが実行されているかどうかを確認し、実行されていない場合は開始し、代わりにそれを呼び出すサービス クラスに静的メソッドを作成することをお勧めします。サービスを明示的に開始します。

于 2015-12-15T16:18:50.527 に答える
0

問題を引き起こしているのは NotificationHelper クラスである可能性があります。このクラスのコードを共有してください。

通知が自動キャンセルに設定されていない可能性があります。通知ビルダーに setAutoCancel() メソッドが含まれているかどうかを確認してください。

Notification notification = new Notification.Builder(this).setAutoCancel(true).build();
于 2015-12-16T12:19:19.447 に答える