Фоновый сервис для 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!
эта страница может помочь вам:
Теперь вставьте следующий код в свою службу
@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>