Служба переднего плана получает сбой и перезапускается, когда пользователь убивает приложение (Nougat)

Я столкнулся с проблемой здесь, когда я хочу, чтобы служба переднего плана работала до тех пор, пока ее задача не будет завершена, и как только задача будет завершена, служба переднего плана должна остановиться. Но проблема здесь в том, что даже если его служба Foreground Service убивается, когда пользователь закрывает приложение только в версии Nougat. Я проверил Marshamallow, Oreo, версию Android pie, сценарий работает нормально. Но в телефоне Nougat и MI этот сценарий работает некорректно.

Ниже приведен служебный код, который я использую в качестве демонстрации.

public class MyForeGroundService  extends Service {
    private static final String TAG_FOREGROUND_SERVICE = "FOREGROUND_SERVICE";

    public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE";

    public static final String ACTION_STOP_FOREGROUND_SERVICE = "ACTION_STOP_FOREGROUND_SERVICE";


    public static final String PRIMARY_CHANNEL = "default";

    public MyForeGroundService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG_FOREGROUND_SERVICE, "My foreground service onCreate().");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if(intent != null)
        {
            String action = intent.getAction();

            switch (action)
            {
                case ACTION_START_FOREGROUND_SERVICE:
                    startForegroundService();
                    Toast.makeText(getApplicationContext(), "Foreground service is started.", Toast.LENGTH_LONG).show();
                    break;
                case ACTION_STOP_FOREGROUND_SERVICE:
                    stopForegroundService();
                    Toast.makeText(getApplicationContext(), "Foreground service is stopped.", Toast.LENGTH_LONG).show();
                    break;

            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    /* Used to build and start foreground service. */
    private void startForegroundService()
    {

        NotificationCompat.Builder mBuilder = notificationBuilder();
        // Start foreground service.
        startForeground(1, mBuilder.build());


        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent();
                intent.setAction("SERVICE_CONNECTED");
                LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

            }
        },10000);
    }

    private void stopForegroundService()
    {
        Log.d(TAG_FOREGROUND_SERVICE, "Stop foreground service.");

        // Stop foreground service and remove the notification.
        stopForeground(true);

        // Stop the foreground service.
        stopSelf();
    }



    public NotificationCompat.Builder  notificationBuilder(){
        NotificationCompat.Builder mBuilder=  new NotificationCompat.Builder(this, PRIMARY_CHANNEL)
                .setContentTitle("Dummy Title")
                .setContentText("Dummy Message")
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText("Big text Message"
                        ))
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mBuilder.setSmallIcon(R.drawable.app_icon_white);
            mBuilder.setColor(getResources().getColor(R.color.theme_color));
        } else {
            mBuilder.setSmallIcon(R.drawable.app_icon_white);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = getResources().getString(R.string.feroz_channel_name);
            String description = getResources().getString(R.string.feroz_channel_description);
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(PRIMARY_CHANNEL, name, importance);
            channel.enableLights(true);
            channel.setLightColor(getResources().getColor(R.color.theme_color));
            channel.enableVibration(true);
            channel.setDescription(description);

            NotificationManager notificationManager1 = getSystemService(NotificationManager.class);
            notificationManager1.createNotificationChannel(channel);
        }


        Intent stopIntent = new Intent(this, MyForeGroundService.class);
        stopIntent.setAction(ACTION_STOP_FOREGROUND_SERVICE);
        PendingIntent stopPlayIntent = PendingIntent.getService(this, 0, stopIntent, 0);
        mBuilder.addAction(R.drawable.ic_launcher_new,"STOP",stopPlayIntent);
        Intent intent = new Intent(this, CreateForegroundServiceActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,  PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(pendingIntent);
         mBuilder.setUsesChronometer(true);

        return mBuilder;
    }
}

Ниже приведен код, который запускает службу из активности

startServiceButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(CreateForegroundServiceActivity.this, MyForeGroundService.class);
                intent.setAction(MyForeGroundService.ACTION_START_FOREGROUND_SERVICE);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    startForegroundService(intent);
                } else {
                    startService(intent);
                }          
            }
        });

        Button stopServiceButton = (Button)findViewById(R.id.stop_foreground_service_button);
        stopServiceButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(CreateForegroundServiceActivity.this, MyForeGroundService.class);
                intent.setAction(MyForeGroundService.ACTION_STOP_FOREGROUND_SERVICE);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    startForegroundService(intent);
                } else {
                    startService(intent);
                } 
            }
        });

Я думаю, что startForeGroundService работает хорошо, но startService работает не так, как ожидалось. Поведение настолько сбивает с толку, когда я убиваю приложение, служба переднего плана перезапускается, но если я открываю приложение и нажимаю кнопку, чтобы остановить службу, я вижу намерение, отправленное в службу. Но все равно сервис работает.

Это телефон lenovo, на котором перезапускается служба

PS: Мне нужна служба, которая работает около 10 минут, независимо от того, находится ли приложение в фоновом режиме или нет. Его не следует перезапускать любой ценой. Например, если я играю музыку из фона, она должна воспроизводиться до конца. он должен остановиться, как только закончится музыка. Я не хочу, чтобы он перезапускался. Ниже приведены журналы, когда я запускаю службу нажатием кнопки и убиваю приложение:

2019-02-15 13:35:56.091 11120-11120/sample.androido.com.myapplication D/MyForeGroundService: My foreground service onCreate().
2019-02-15 13:36:01.956 1459-3975/? W/ActivityManager: Scheduling restart of crashed service sample.androido.com.myapplication/.services.MyForeGroundService in 1000ms
2019-02-15 13:36:02.975 1459-1509/? I/ActivityManager: Start proc 11170:sample.androido.com.myapplication/u0a154 for service sample.androido.com.myapplication/.services.MyForeGroundService
2019-02-15 13:36:03.674 11170-11170/? D/MyForeGroundService: My foreground service onCreate().

person Feroz Siddiqui    schedule 15.02.2019    source источник


Ответы (1)


Из официальной документации Android < / a> для startForegroundService() метода.

Обратите внимание, что вызов этого метода не переводит службу в начальное состояние, даже если имя звучит так. Вы всегда должны сначала вызывать ContextWrapper.startService (Intent), чтобы сообщить системе, что она должна поддерживать работу службы, а затем использовать этот метод, чтобы сообщить ей, чтобы она продолжала работать интенсивнее.

Согласно приведенному выше утверждению, вы должны сначала вызвать startService(), а затем startForegroundService()

person Vivek Mishra    schedule 15.02.2019
comment
Итак, вы хотите сказать, что я должен сначала вызвать оба метода, а затем запустить Foreground? - person Feroz Siddiqui; 15.02.2019
comment
если возможно, вивек, не могли бы вы предоставить фрагмент кода, пожалуйста - person Feroz Siddiqui; 15.02.2019
comment
Прочтите ссылку, которую я добавил, вы поймете, что вам нужно кодировать - person Vivek Mishra; 15.02.2019
comment
ContextWrapper cw = новый ContextWrapper (CreateForegroundServiceActivity.this); cw.startService (намерение); я сделал это, но не помог - person Feroz Siddiqui; 15.02.2019
comment
vivek может проверить журналы, обновленные, о которых идет речь, также как и при сбое и перезапуске службы - person Feroz Siddiqui; 15.02.2019
comment
@FerozSiddiqui, почему вы генерируете исключение в своем методе onBind ()? Это может быть причиной сбоя вашего сервиса - person Vivek Mishra; 15.02.2019
comment
у меня нет привязанной услуги, что мне делать? Я вернул значение null, но служба по-прежнему аварийно завершает работу - person Feroz Siddiqui; 15.02.2019
comment
удалите onBindMethod (). Вы не создаете связанную службу, поэтому это не требуется - person Vivek Mishra; 15.02.2019
comment
но для расширения класса обслуживания требуется реализация onBindMethod - person Feroz Siddiqui; 15.02.2019
comment
В этом случае вы можете просто вернуть null из метода onBind () - person Vivek Mishra; 15.02.2019
comment
да, я сделал, но все еще сервис падает в приложении и перезапускается - person Feroz Siddiqui; 15.02.2019
comment
Я не могу опубликовать здесь его большой, поэтому размещен в моем github gist. Посмотрите gist.github.com/Feroz-Istar/. Я вижу какое-то исключение в пользовательском интерфейсе телефонной системы на com.android.systemui.statusbar.NotificationData.remove (NotificationData.java:296), есть исключение с нулевым указателем - person Feroz Siddiqui; 15.02.2019
comment
Итак, что вы делаете в этом классе данных уведомлений? - person Vivek Mishra; 15.02.2019
comment
это не я, его журналы устройства, которые выдают исключение. Когда приложение убито, уведомление исчезает, а затем снова появляется. Исключение составляет com.android.systemui с устройства lenovo. Я не понимаю, почему это происходит именно на этом устройстве, в то время как с остальными моими устройствами все работает нормально. - person Feroz Siddiqui; 15.02.2019
comment
Еще одна вещь, которую я видел, это то, что вам может потребоваться включить multidex в вашем приложении, я также вижу, что некоторые классы не найдены исключениями. - person Vivek Mishra; 15.02.2019
comment
Я также включаю multi dex, но служба переднего плана перезапускается - person Feroz Siddiqui; 15.02.2019