Фоновый сервис для Android Oreo

Как продолжить фоновый сервис в Android Oreo, не показывая точку уведомлений? я продолжаю свою фоновую службу, используя уведомление, но я не хочу показывать уведомление для работающей службы.

2 ответа

Решение

Если бы вы где-то здесь правильно прочитали Документацию по Android Oreo 8.0, возможно, вы не разместили этот вопрос здесь.

Шаг 1: Убедитесь, что вы запускаете службу в качестве переднего плана Service как указано в приведенном ниже коде

ContextCompat.startForegroundService(mainActivity, new Intent(getContext(), GpsServices.class));
ContextCompat.startForegroundService(mainActivity, new Intent(getContext(), BluetoothService.class));
ContextCompat.startForegroundService(mainActivity, new Intent(getContext(), BackgroundApiService.class));

Шаг 2: Используйте уведомление, чтобы показать, что ваш сервис работает. Добавьте ниже строку кода в onCreate метод Service,

@Override
public void onCreate() {
    ...
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForeground(NOTIFICATION_ID, notification);
    }
    ...
}

Шаг 3: Удалить notification когда служба остановлена ​​или уничтожена.

@Override
public void onDestroy() {
    ...
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
          stopForeground(true); //true will remove notification
    }
    ...
}

Одна проблема с этим решением состоит в том, что оно будет продолжать показывать notification до вашего Service работает на всех устройствах под управлением Android Oreo 8.0.

Я уверен, что это решение будет работать, даже когда приложение находится в фоновом режиме или в состоянии уничтожения.

ВАЖНОЕ ПРИМЕЧАНИЕ: ПОКАЗЫВАНИЕ УВЕДОМЛЕНИЯ ДЛЯ ЗАПУСКА СЕРВИСА НА ФОНЕ (ПРИЛОЖЕНИЕ В ФОНЕ ИЛИ УДАЛЕННОМ СОСТОЯНИИ) ОБЯЗАТЕЛЬНО В ANDROID OREO 8.0. Вы не можете бежать с ним ТАК ЧТО РЕКОМЕНДУЕТСЯ, ЧТО ВЫ ДЕЛАЕТЕ НЕОБХОДИМЫЕ ИЗМЕНЕНИЯ В ВАШЕМ ПРИЛОЖЕНИИ, ЧТОБЫ СДЕЛАТЬ ЭТО РАБОТУ ПРАВИЛЬНО В СООТВЕТСТВИИ С ЛУЧШИМИ ПРАКТИКАМИ, СЛЕДУЮЩИМИ ИЛИ СПРОСОВАННЫМИ ANDROID.

Я надеюсь, что это может помочь решить вашу проблему.

Это невозможно в этом API version (26). ОС Android автоматически закрывает ваш сервис, если вы запускаете его, не показывая пользователю уведомления.

Если вы нацеливаетесь API >= 26 система будет налагать ограничения на ваш сервис для запуска в фоновом режиме, если ваша деятельность на переднем плане. Как только ваша деятельность переходит в фоновый режим, служба будет остановлена, когда система обнаружит, что она работает в фоновом режиме.

Используя StartForegroundService() метод, который вы предоставляете это разрешение для запуска службы в фоновом режиме, даже если действие не выполняется. Должен также после того, как служба была создана, служба должна вызвать ее startForeground() метод в течение пяти секунд.

Этот код работал у меня. Для начала убедитесь:

1- Определите службу в манифесте

2- Определите разрешение в манифесте

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

3- Убедитесь, что вы запустили службу раньше.

У вашей службы должно быть уведомление. Будьте осторожны, ваше уведомление должно иметь ChannelID!

эта страница может помочь вам:

Как создать собственный макет уведомлений в Android?

Android как показать уведомление на экране

Теперь вставьте следующий код в свою службу

@Override
    public void onCreate() {
        super.onCreate();
            try {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    startForeground(" your Notification ID ", notification);
                }
            } catch (Exception e) {
                Log.e(" Error --->> ", e.getMessage());
            }
    }

после этого добавьте этот код:

@Override
public ComponentName startForegroundService(Intent service) {
    return super.startForegroundService(service);
}

и это:

@Override
public void onDestroy() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        stopForeground(true);
    }
}
By using WindowManager and WindoService it is possible.
#AndroidMainifest.xml
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.org.backgroundserviceonoreo">
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    ....
    <service android:name= ".ChatheadService" />    
    </manifest>
#MainActivity
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Build;
    import android.provider.Settings;  
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    public class MainActivity extends AppCompatActivity {
    public static final int PERMISSION_REQUEST_CODE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // We need run time permission greater than Marcello
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        && !Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+ getPackageName()));
            startActivityForResult(intent, PERMISSION_REQUEST_CODE);
        } else {
            showChatHead();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode,resultCode,data);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            showChatHead();
        }
    }

    public  void showChatHead() {
        startService(new Intent(MainActivity.this, ChatheadService.class));
    }
    }

#ChatheadService
    import android.app.Service;
    import android.content.Intent;
    import android.graphics.PixelFormat;
    import android.os.Build;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.WindowManager;

    public class ChatheadService extends Service {
    private WindowManager windowManager;
    private View chatHeadView;

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

    @Override
    public void onCreate() {
        super.onCreate();
        chatHeadView = LayoutInflater.from(this).inflate(R.layout.chat_head, null);
        int LAYOUT_FLAG;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            LAYOUT_FLAG = WindowManager.LayoutParams.TYPE_PHONE;
        }
        final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                LAYOUT_FLAG,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSPARENT
        );
        params.gravity = Gravity.TOP | Gravity.LEFT;
        params.x = 0;
        params.y = 100;

        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        windowManager.addView(chatHeadView, params);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i= 0;i<100;i++) {
                    try {
                        Thread.sleep(1000);
                        Log.d("Tag", "run "+String.valueOf(i));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (chatHeadView != null) {
            windowManager.removeView(chatHeadView);
        }
    }
    }

#chat_head

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="65dp"
    android:id="@+id/chathead_buble"
    android:layout_height="wrap_content">
    <!--Make sure your image View visibility gone-->
    <ImageView
        android:visibility="invisible"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:id="@+id/chathead_imageView"
        android:src="@mipmap/ic_launcher_round"
        />
     </RelativeLayout>
Другие вопросы по тегам