android oreo的后台服务

时间:2017-11-04 11:59:19

标签: java android push-notification android-service android-8.0-oreo

如何在没有显示通知点的情况下在android Oreo中继续后台服务?我使用通知继续我的后台服务,但我不想显示运行服务的通知。

4 个答案:

答案 0 :(得分:23)

如果您已在here的某处正确阅读 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的{​​{1}}方法中添加以下代码行。

Service
  

第3步:停止或销毁服务时删除@Override public void onCreate() { ... if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForeground(NOTIFICATION_ID, notification); } ... }

notification

此解决方案的一个问题是,在 Android Oreo 8.0 上运行的所有设备上运行@Override public void onDestroy() { ... if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { stopForeground(true); //true will remove notification } ... } 之前,它会一直显示notification

我确信即使应用程序处于后台或处于终止状态,此解决方案也能正常运行。

  

重要提示:显示在背景中运行服务的通知(背景或杀死状态下的应用程序)在ANDROID OREO 8.0中是强制性的。你无法远行。所以建议您您根据最佳做法按照ANDROID的要求,对您的应用程序进行必要的更改以使其正常工作。

我希望这可能有助于解决您的问题。

答案 1 :(得分:3)

这在API version (26)及更高版本中是不可能的。如果您在未向用户显示通知的情况下运行Android OS,Android OS会自动关闭您的服务。

如果您定位API >= 26,系统会对您的服务施加限制,以便在后台运行,除非您的活动位于前台。一旦您的活动进入后台,当系统发现它在后台运行时,服务将终止(请参阅Background service limitations)。

通过使用startForegroundService()方法,即使活动未运行,您也可以在后台运行该服务。 必须在创建服务后,服务必须在五秒钟内调用其startForeground()方法。

答案 2 :(得分:1)

此代码对我有用。首先,请确保:

1-在清单中定义服务

2-在清单中定义权限

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

3-确保您之前已经启动了服务。

  

您的服务应有一条通知。你要注意   您的通知必须具有ChannelID!

     

此页面可以为您提供帮助:

     

How to create a Custom Notification Layout in android?

     

Android how to show notification on screen

现在将以下代码粘贴到您的服务中

@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);
    }
}

答案 3 :(得分:0)

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>