Локальные уведомления в приложении Android не отображаются, когда приложение находится в фоновом режиме или закрыто - PullRequest
0 голосов
/ 06 ноября 2019

Я сгенерировал локальные уведомления, используя Service. Когда приложение открыто, окно уведомлений работает правильно, и они отображаются. Но когда приложение переходит в фоновый режим или получает закрытые уведомления, они не отображаются. Когда я снова открываю свое приложение, отображаются все уведомления.

Я прошел через множество тем об этой проблеме. Поэтому я попробовал startForeground, AlarmManager, BroadcastReceiver и ничего не помогает. Тем не менее локальные уведомления отображаются, только если приложение открыто. Я выяснил, что когда я установил параметры батареи для запуска моего приложения в фоновом режиме в настройках телефона, то он работает правильно, и уведомления отображаются. Но пользователь не будет знать, что он должен сделать это.

MyService:

public class MyService2 extends Service {

private boolean running = true;
private MyAsyncTask myAsyncTask;

@Override
public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
}

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

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    startForeground(1, showAndGetNotification(getApplicationContext(), "Twoja aplikacja działa w tle", "", new Intent(getApplicationContext(), MainActivity.class)));
    myAsyncTask = new MyAsyncTask();
    myAsyncTask.execute();
    return START_STICKY;
}

public void onDestroy() {
    super.onDestroy();
    stopForeground(true);
    stopSelf();
    if (myAsyncTask != null) {
        myAsyncTask.cancel(true);
    }
    running = false;
    SharedPreferences sharedPref = getSharedPreferences("service", Activity.MODE_PRIVATE);
    boolean fromAppStop = sharedPref.getBoolean("fromAppStop", false);
    if (!fromAppStop) {
        Intent broadcastIntent = new Intent(this, SensorRestarterBroadcastReceiver.class);
        sendBroadcast(broadcastIntent);
    }
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putBoolean("fromAppStop", false);
    editor.commit();
}

private class MyAsyncTask extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... voids) {
        try {
            while (running) {
                List<Map<String, String>> medicinesToTake = getMedicinesToTake();
                for (Map<String, String> medicineToTake : medicinesToTake) {
                    String medicineName = medicineToTake.keySet().toArray()[0].toString();
                    Thread.sleep(countSleepToNextTake(medicineToTake.get(medicineName)));
                    doAlarm("Czas na lek", medicineName, medicineName);
                }
                Thread.sleep(countLeftTimeForNextDay());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
}

private void doAlarm(String title, String medicineName, String body) {
    Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
    intent.putExtra("title", title);
    intent.putExtra("medicineName", medicineName);
    intent.putExtra("body", body);
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    int id = generateUniqueId();
    PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), id, intent, PendingIntent.FLAG_CANCEL_CURRENT);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pendingIntent);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pendingIntent);
    } else {
        alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pendingIntent);
    }
}

public Notification showAndGetNotification(Context context, String title, String body, Intent intent) {
    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    Date now = new Date();
    int notificationId = Integer.parseInt(new SimpleDateFormat("ddHHmmss", Locale.UK).format(now)) + new Random().nextInt();
    //String channelId = "channel-01";
    String channelId = UUID.randomUUID().toString();
    String channelName = "Channel Name";
    int importance = NotificationManager.IMPORTANCE_HIGH;

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        NotificationChannel mChannel = new NotificationChannel(
                channelId, channelName, importance);
        notificationManager.createNotificationChannel(mChannel);
    }

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setAutoCancel(true)
            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
            .setContentText(body);

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addNextIntent(intent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
            generateUniqueId(),
            PendingIntent.FLAG_UPDATE_CURRENT
    );
    mBuilder.setContentIntent(resultPendingIntent);

    notificationManager.notify(notificationId, mBuilder.build());

    return mBuilder.build();
}

private int generateUniqueId() {
    UUID idOne = UUID.randomUUID();
    String str = "" + idOne;
    int uid = str.hashCode();
    String filterStr = "" + uid;
    str = filterStr.replaceAll("-", "");
    return Integer.parseInt(str);
}
}

MyAlarmReceiver:

public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
    String medicineName = intent.getStringExtra("medicineName");
    String body = intent.getStringExtra("body");

    Intent notificationIntent = null;
    String title = intent.getStringExtra("title");
    if (title.equals("Czas na lek")) {
        notificationIntent = new Intent(context, TimeForMedicineActivity.class);
        notificationIntent.putExtra("medicineName", medicineName);
    } else if (title.equals("Twój lek się skończył")) {
        notificationIntent = new Intent(context, AddOrDeleteMyMedicineActivity.class);
    } else if (title.equals("Twój lek się kończy")) {
        notificationIntent = new Intent(context, MainActivity.class);
    }

    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    Date now = new Date();
    int notificationId = Integer.parseInt(new SimpleDateFormat("ddHHmmss", Locale.UK).format(now)) + new Random().nextInt();
    String channelId = UUID.randomUUID().toString();
    String channelName = "Channel Name";
    int importance = NotificationManager.IMPORTANCE_HIGH;

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        NotificationChannel mChannel = new NotificationChannel(
                channelId, channelName, importance);
        notificationManager.createNotificationChannel(mChannel);
    }

    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, channelId)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentTitle(title)
            .setAutoCancel(true)
            .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
            .setContentText(body);

    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addNextIntent(notificationIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(
            generateUniqueId(),
            PendingIntent.FLAG_UPDATE_CURRENT
    );
    mBuilder.setContentIntent(resultPendingIntent);

    notificationManager.notify(notificationId, mBuilder.build());
}


private int generateUniqueId() {
    UUID idOne = UUID.randomUUID();
    String str = "" + idOne;
    int uid = str.hashCode();
    String filterStr = "" + uid;
    str = filterStr.replaceAll("-", "");
    return Integer.parseInt(str);
}
}

1 Ответ

0 голосов
/ 06 ноября 2019

Проблема с MIUI OS, которую использует Huawei. Он нарушает спецификацию Android, согласно которой службы, использующие startForeground, должны рассматриваться как передний план.

У меня та же проблема в моем приложении. Я не нашел лучшего решения, кроме как определить, запущено ли приложение по MIUI, а затем открыть предупреждение, сообщающее пользователю, что, если он хочет использовать передний план, ему следует вручную открыть настройки батареи и добавить приложение в исключение.

Вы можете попробовать

        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        if (!pm.isIgnoringBatteryOptimizations(packageName)) {
            intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
            intent.setData(Uri.parse("package:" + packageName));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }

с

<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>

, но это, вероятно, не будет работать на MIUI.

...