Android Context.startForegroundService()然后没有调用Service.startForeground()

Android Context.startForegroundService()然后没有调用Service.startForeground(),android,service,operating-system,foreground,android-8.0-oreo,Android,Service,Operating System,Foreground,Android 8.0 Oreo,我正在安卓操作系统上使用服务类 我计划在后台使用服务 国家 如果您的应用程序的目标API级别为26或更高,系统将对使用或创建后台服务施加限制,除非应用程序本身位于前台。如果应用程序需要创建前台服务,则应用程序应调用startForegroundService() 如果使用startForegroundService(),则服务将抛出以下错误 Context.startForegroundService()没有调用 Service.startForeground() 这有什么问题吗?来自谷歌的文

我正在安卓操作系统上使用
服务

我计划在后台使用
服务

国家

如果您的应用程序的目标API级别为26或更高,系统将对使用或创建后台服务施加限制,除非应用程序本身位于前台。如果应用程序需要创建前台服务,则应用程序应调用
startForegroundService()

如果使用
startForegroundService()
,则
服务将抛出以下错误

Context.startForegroundService()没有调用
Service.startForeground()
这有什么问题吗?

来自谷歌的文档:

系统允许应用程序调用Context.startForegroundService(),即使应用程序处于后台。但是,应用程序必须在创建服务后的五秒钟内调用该服务的startForeground()方法

解决方案: 在
onCreate()
中调用
startForeground()
,用于使用
Context.startForegroundService()


另请参见:对于Android 8.0(Oreo)

我调用了
ContextCompat.startForegroundService(this,intent)
来启动该服务

在用
onCreate

 @Override
 public void onCreate() {
        super.onCreate();

        if (Build.VERSION.SDK_INT >= 26) {
            String CHANNEL_ID = "my_channel_01";
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    "Channel human readable title",
                    NotificationManager.IMPORTANCE_DEFAULT);

            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setContentTitle("")
                    .setContentText("").build();

            startForeground(1, notification);
        }
}

与startService(Intent)类似,但有一个隐含的承诺 服务将调用startForeground(int,android.app.Notification)一次 它开始运行。这项服务的时间相当 到ANR间隔执行此操作,否则系统将 自动停止服务并声明应用程序ANR

与普通startService(Intent)不同,此方法可在以下位置使用: 任何时候,无论承载服务的应用程序是否处于 前景状态

确保在onCreate()上调用
服务.startForeground(int,android.app.Notification)
,以确保它将被调用。如果您有任何情况可能阻止您这样做,那么您最好使用正常的
上下文.startService(Intent)
并调用
服务.startForeground(int,android.app.Notification)


似乎
Context.startForegroundService()
添加了一个看门狗,以确保您在销毁
Service.startForeground(int,android.app.Notification)
之前调用了
Service.startForegroundService(…)
,然后调用
Context.stopService(…),您的应用程序将崩溃
在调用
服务之前。startForeground(…)

我有一个明确的理由

我在以下位置打开了一个错误:

此上的几个错误已打开和关闭,无法修复

希望我有清晰的复制步骤能成功

谷歌团队提供的信息

这不是框架错误;这是故意的。如果应用程序使用
startForegroundService()
启动服务实例,它必须将该服务实例转换为前台状态并显示通知。如果服务实例在
startForeground()之前停止
被调用,这个承诺没有实现:这是应用程序中的一个bug

,发布其他应用程序可以直接启动的服务从根本上说是不安全的。您可以通过将该服务的所有启动操作视为需要
startForeground()
,来减轻这一点,但显然这可能不是您的想法

这里有两种不同的情况导致相同的结果

直接的语义问题是,使用
startForegroundService()
启动某项服务只是一个错误,而忽略了通过
startForeground()将其实际转换到前台
,只是:语义问题。故意将其视为应用程序错误。在将服务转换到前台之前停止服务是一个应用程序错误。这是操作的关键,也是为什么此问题被标记为“按预期工作”的原因


然而,关于这个问题的虚假检测也存在一些问题。这被视为一个真正的问题,尽管它与这个特定的bug追踪器问题是分开跟踪的。我们对投诉并不充耳不闻。

我对此研究了几天,并得到了解决方案。 现在在androido中,您可以如下设置背景限制

调用服务类的服务

Intent serviceIntent = new Intent(SettingActivity.this,DetectedService.class);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    SettingActivity.this.startForegroundService(serviceIntent);
} else {
    startService(serviceIntent);
}
服务类应该是这样的

public class DetectedService extends Service { 
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        int NOTIFICATION_ID = (int) (System.currentTimeMillis()%10000);
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForeground(NOTIFICATION_ID, new Notification.Builder(this).build());
        }


        // Do whatever you want to do here
    }
}

我也面临同样的问题,在花时间找到解决方案后,您可以在下面的代码中尝试。如果您使用
服务
,请将此代码放入onCreate中,否则请使用
意向服务
,然后将此代码放入OnHandleContent中

if (Build.VERSION.SDK_INT >= 26) {
        String CHANNEL_ID = "my_app";
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                "MyApp", NotificationManager.IMPORTANCE_DEFAULT);
        ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
        Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("")
                .setContentText("").build();
        startForeground(1, notification);
    }

提醒一下,我在这上面浪费了太多的时间。尽管我在
onCreate(…)
中第一件事就是调用
startForeground(…)
,但我还是不断得到这个异常。
最后我发现这个问题是由于使用了
通知\u ID=0
造成的。使用任何其他值似乎都可以解决这个问题。

ID设置为0时调用Android 8+时,这个错误也会发生

id int:根据NotificationManager,此通知的标识符。notify(int,notification);不能为0


之所以会出现这个问题,是因为Android框架无法保证您的服务在5秒内启动,但另一方面,框架对前台通知必须在5秒内启动有严格限制,而不检查框架是否尝试启动服务

这肯定是一个框架问题,但并非所有面临此问题的开发人员都在竭尽全力:

  • startForeground
    通知必须同时位于
    onCreate
    onStartCommand
    中,因为如果您的服务已经是crea
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        startForegroundService(intent);
    } else {
        startService(intent);
    }
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
                    .setContentTitle(getString(R.string.app_name))
                    .setContentText("SmartTracker Running")
                    .setAutoCancel(true);
            Notification notification = builder.build();
            startForeground(NOTIFICATION_ID, notification);
        } else {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                    .setContentTitle(getString(R.string.app_name))
                    .setContentText("SmartTracker is Running...")
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                    .setAutoCancel(true);
            Notification notification = builder.build();
            startForeground(NOTIFICATION_ID, notification);
        }
    
    private static final String ANDROID_CHANNEL_ID = "com.xxxx.Location.Channel";
    private static final int NOTIFICATION_ID = 555;
    
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                stopForeground(true);
            } else {
                stopForeground(true);
            }
    
       stopSelf();
    
    Intent intent = new Intent(context, YourService.class);
    intent.putExtra("request_stop", true);
    context.startService(intent);
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //call startForeground first
        if (intent != null) {
            boolean stopService = intent.getBooleanExtra("request_stop", false);
            if (stopService) {
                stopSelf();
            }
        }
    
        //Continue with the background task
        return START_STICKY;
    }
    
    if (Util.SDK_INT > 26) {
        mContext.startForegroundService(playIntent);
    } else {
        mContext.startService(playIntent);
    }
    
    mContext.startService(playIntent);
    
    PendingIntent pendingIntent=PendingIntent.getBroadcast(context,0,intent,PendingIntent.FLAG_NO_CREATE);
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && pendingIntent==null){
                context.startForegroundService(service_intent);
            }
            else
            {
                context.startService(service_intent);
            }
    }
    
    final Context applicationContext = context.getApplicationContext();
    Intent intent = new Intent(context, MusicService.class);
    applicationContext.bindService(intent, new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            if (binder instanceof MusicBinder) {
                MusicBinder musicBinder = (MusicBinder) binder;
                MusicService service = musicBinder.getService();
                if (service != null) {
                    // start a command such as music play or pause.
                    service.startCommand(command);
                    // force the service to run in foreground here.
                    // the service is already initialized when bind and auto_create.
                    service.forceForeground();
                }
            }
            applicationContext.unbindService(this);
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    }, Context.BIND_AUTO_CREATE);
    
    /**
     * Use weak reference to avoid binder service leak.
     */
     public class MusicBinder extends Binder {
    
         private WeakReference<MusicService> weakService;
    
         /**
          * Inject service instance to weak reference.
          */
         public void onBind(MusicService service) {
             this.weakService = new WeakReference<>(service);
         }
    
         public MusicService getService() {
             return weakService == null ? null : weakService.get();
         }
     }
    
    public class MusicService extends MediaBrowserServiceCompat {
    ...
        private final MusicBinder musicBind = new MusicBinder();
    ...
        @Override
        public IBinder onBind(Intent intent) {
            musicBind.onBind(this);
            return musicBind;
        }
    ...
        public void forceForeground() {
            // API lower than 26 do not need this work around.
            if (Build.VERSION.SDK_INT >= 26) {
                Intent intent = new Intent(this, MusicService.class);
                // service has already been initialized.
                // startForeground method should be called within 5 seconds.
                ContextCompat.startForegroundService(this, intent);
                Notification notification = mNotificationHandler.createNotification(this);
                // call startForeground just after startForegroundService.
                startForeground(Constants.NOTIFICATION_ID, notification);
            }
        }
    }
    
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        stopForeground(true);
    } else {
        stopSelf();
    }
    
    public class MyForegroundService extends Service {
        @Override
        public void onCreate() {
            super.onCreate();
            startForeground(...);
        }
    }
    
    Intent serviceIntent = new Intent(this, MyForegroundService.class);
    startForegroundService(serviceIntent);
    ...
    stopService(serviceIntent);
    
    private final void bringDownServiceLocked(ServiceRecord r) {
        ...
        if (r.fgRequired) {
            Slog.w(TAG_SERVICE, "Bringing down service while still waiting for start foreground: "
                      + r);
            r.fgRequired = false;
            r.fgWaiting = false;
            mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
                        AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
            mAm.mHandler.removeMessages(
                        ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
            if (r.app != null) {
                Message msg = mAm.mHandler.obtainMessage(
                    ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
                msg.obj = r.app;
                msg.getData().putCharSequence(
                    ActivityManagerService.SERVICE_RECORD_KEY, r.toString());
                mAm.mHandler.sendMessage(msg);
             }
        }
        ...
    }
    
    public class MyForegroundService extends Service {
    
        private static final String ACTION_STOP = "com.example.MyForegroundService.ACTION_STOP";
    
        private final BroadcastReceiver stopReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                context.removeStickyBroadcast(intent);
                stopForeground(true);
                stopSelf();
            }
        };
    
        @Override
        public void onCreate() {
            super.onCreate();
            startForeground(...);
            registerReceiver(
                stopReceiver, new IntentFilter(ACTION_STOP));
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            unregisterReceiver(stopReceiver);
        }
    
        public static void stop(Context context) {
            context.sendStickyBroadcast(new Intent(ACTION_STOP));
        }
    }
    
    public class Services extends Service {
    
        private static final String ANDROID_CHANNEL_ID = "com.xxxx.Location.Channel";
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                Notification.Builder builder = new Notification.Builder(this, ANDROID_CHANNEL_ID)
                        .setContentTitle(getString(R.string.app_name))
                        .setContentText("SmartTracker Running")
                        .setAutoCancel(true);
                Notification notification = builder.build();
                startForeground(1, notification);
                Log.e("home_button","home button");
            } else {
                NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                        .setContentTitle(getString(R.string.app_name))
                        .setContentText("SmartTracker is Running...")
                        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                        .setAutoCancel(true);
                Notification notification = builder.build();
                startForeground(1, notification);
                Log.e("home_button_value","home_button_value");
    
            }
            return super.onStartCommand(intent, flags, startId);
    
        }
    }
    
    import android.app.Notification;
    public class AuthenticationService extends Service {
    
        @Override
        public void onCreate() {
            super.onCreate();
            startForeground(1,new Notification());
        }
    }
    
    class TestService : Service() {
    
        override fun onCreate() {
            super.onCreate()
            Log.d(TAG, "onCreate")
    
            val nBuilder = NotificationCompat.Builder(this, "all")
                .setSmallIcon(R.drawable.ic_launcher_foreground)
                .setContentTitle("TestService")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            startForeground(1337, nBuilder.build())
        }
    
        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
            val rtn = super.onStartCommand(intent, flags, startId)
    
            if (intent?.action == STOP_ACTION) {
                Log.d(TAG, "onStartCommand -> STOP")
                stopForeground(true)
                stopSelf()
            } else {
                Log.d(TAG, "onStartCommand -> START")
            }
    
            return rtn
        }
    
        override fun onDestroy() {
            Log.d(TAG, "onDestroy")
            super.onDestroy()
        }
    
        override fun onBind(intent: Intent?): IBinder? = null
    
        companion object {
    
            private val TAG = "TestService"
            private val STOP_ACTION = "ly.zen.test.TestService.ACTION_STOP"
    
            fun start(context: Context) {
                ContextCompat.startForegroundService(context, Intent(context, TestService::class.java))
            }
    
            fun stop(context: Context) {
                val intent = Intent(context, TestService::class.java)
                intent.action = STOP_ACTION
                ContextCompat.startForegroundService(context, intent)
            }
    
        }
    
    }
    
    val nChannel = NotificationChannel("all", "All", NotificationManager.IMPORTANCE_NONE)
    val nManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    nManager.createNotificationChannel(nChannel)
    
    start_test_service.setOnClickListener {
        TestService.start(this@MainActivity)
        TestService.stop(this@MainActivity)
    }
    
    D/TestService: onCreate
    D/TestService: onStartCommand -> START
    D/TestService: onStartCommand -> STOP
    D/TestService: onDestroy
    
    context?.bindService(
            Intent(context, AudioService::class.java),
            serviceConnection, Context.BIND_AUTO_CREATE)
    ContextCompat.startForegroundService(
            context!!,
            Intent(context, AudioService::class.java).apply {
                action = CONTENT_SELECTED_ACTION
                putExtra(CONTENT_SELECTED_KEY, contentToPlay.content.apply {
                    audioUrl = uri.toString()
                })
            })
    
    private var uri: Uri = Uri.parse("")
    
    override fun onBind(intent: Intent?) =
            AudioServiceBinder().apply {
                player = ExoPlayerFactory.newSimpleInstance(
                        applicationContext,
                        AudioOnlyRenderersFactory(applicationContext),
                        DefaultTrackSelector())
            }
    
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        intent?.let {
            when (intent.action) {
                CONTENT_SELECTED_ACTION -> it.getParcelableExtra<Content>(CONTENT_SELECTED_KEY).also { content ->
                    val intentUri = Uri.parse(content.audioUrl)
                    // Checks whether to update Uri passed in Intent Bundle.
                    if (!intentUri.equals(uri)) {
                        uri = intentUri
                        player?.prepare(ProgressiveMediaSource.Factory(
                                DefaultDataSourceFactory(
                                        this,
                                        Util.getUserAgent(this, getString(app_name))))
                                .createMediaSource(uri))
                        player?.playWhenReady = true
                        // Calling 'startForeground' in 'buildNotification(...)'.          
                        buildNotification(intent.getParcelableExtra(CONTENT_SELECTED_KEY))
                    }
                }
            }
        }
        return super.onStartCommand(intent, flags, startId)
    }
    
    // Calling 'startForeground' in 'onNotificationStarted(...)'.
    private fun buildNotification(content: Content): Unit? {
        playerNotificationManager = PlayerNotificationManager.createWithNotificationChannel(
                this,
                content.title,
                app_name,
                if (!content.audioUrl.isNullOrEmpty()) 1 else -1,
                object : PlayerNotificationManager.MediaDescriptionAdapter {
                    override fun createCurrentContentIntent(player: Player?) = ...
                    override fun getCurrentContentText(player: Player?) = ...
                    override fun getCurrentContentTitle(player: Player?) = ...
                    override fun getCurrentLargeIcon(player: Player?,
                                                     callback: PlayerNotificationManager.BitmapCallback?) = ...
                },
                object : PlayerNotificationManager.NotificationListener {
                    override fun onNotificationStarted(notificationId: Int, notification: Notification) {
                        startForeground(notificationId, notification)
                    }
                    override fun onNotificationCancelled(notificationId: Int) {
                        stopForeground(true)
                        stopSelf()
                    }
                })
        return playerNotificationManager.setPlayer(player)
    }
    
    Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{1946947 u0 ...MessageService}
    
    main" prio=5 tid=1 Native
      | group="main" sCount=1 dsCount=0 flags=1 obj=0x763e01d8 self=0x7d77814c00
      | sysTid=11171 nice=-10 cgrp=default sched=0/0 handle=0x7dfe411560
      | state=S schedstat=( 1337466614 103021380 2047 ) utm=106 stm=27 core=0 HZ=100
      | stack=0x7fd522f000-0x7fd5231000 stackSize=8MB
      | held mutexes=
      #00  pc 00000000000712e0  /system/lib64/libc.so (__epoll_pwait+8)
      #01  pc 00000000000141c0  /system/lib64/libutils.so (android::Looper::pollInner(int)+144)
      #02  pc 000000000001408c  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+60)
      #03  pc 000000000012c0d4  /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)
      at android.os.MessageQueue.nativePollOnce (MessageQueue.java)
      at android.os.MessageQueue.next (MessageQueue.java:326)
      at android.os.Looper.loop (Looper.java:181)
      at android.app.ActivityThread.main (ActivityThread.java:6981)
      at java.lang.reflect.Method.invoke (Method.java)
      at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
      at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1445)
    
    SAAgentV2.requestAgent(App.app?.applicationContext, 
       MessageJobs::class.java!!.getName(), mAgentCallback)
    
    SAAgentV2.d var3 = new SAAgentV2.d(var0, var1, var2);
    
    where d defined as below
    
    private SAAdapter d;
    
    SAJobService.scheduleSCJob(SAAdapter.this.d, var11, var14, var3, var12); 
    
    private static void a(Context var0, String var1, String var2, long var3, String var5, SAPeerAgent var6) {
        ComponentName var7 = new ComponentName(var0, SAJobService.class);
        Builder var10;
        (var10 = new Builder(a++, var7)).setOverrideDeadline(3000L);
        PersistableBundle var8;
        (var8 = new PersistableBundle()).putString("action", var1);
        var8.putString("agentImplclass", var2);
        var8.putLong("transactionId", var3);
        var8.putString("agentId", var5);
        if (var6 == null) {
            var8.putStringArray("peerAgent", (String[])null);
        } else {
            List var9;
            String[] var11 = new String[(var9 = var6.d()).size()];
            var11 = (String[])var9.toArray(var11);
            var8.putStringArray("peerAgent", var11);
        }
    
        var10.setExtras(var8);
        ((JobScheduler)var0.getSystemService("jobscheduler")).schedule(var10.build());
    }
    
    private val mAgentCallback = object : SAAgentV2.RequestAgentCallback {
        override fun onAgentAvailable(agent: SAAgentV2) {
            mMessageService = agent as? MessageJobs
            App.d(Accounts.TAG, "Agent " + agent)
        }
    
        override fun onError(errorCode: Int, message: String) {
            App.d(Accounts.TAG, "Agent initialization error: $errorCode. ErrorMsg: $message")
        }
    }
    
    class MessageJobs (context:Context) : SAAgentV2(SERVICETAG, context, MessageSocket::class.java) {
    
    
        public fun release () {
    
        }
    
    
        override fun onServiceConnectionResponse(p0: SAPeerAgent?, p1: SASocket?, p2: Int) {
            super.onServiceConnectionResponse(p0, p1, p2)
            App.d(TAG, "conn resp " + p1?.javaClass?.name + p2)
    
    
        }
    
        override fun onAuthenticationResponse(p0: SAPeerAgent?, p1: SAAuthenticationToken?, p2: Int) {
            super.onAuthenticationResponse(p0, p1, p2)
            App.d(TAG, "Auth " + p1.toString())
    
        }
    
    
        override protected fun onServiceConnectionRequested(agent: SAPeerAgent) {
    
    
            }
        }
    
        override fun onFindPeerAgentsResponse(peerAgents: Array<SAPeerAgent>?, result: Int) {
        }
    
        override fun onError(peerAgent: SAPeerAgent?, errorMessage: String?, errorCode: Int) {
            super.onError(peerAgent, errorMessage, errorCode)
        }
    
        override fun onPeerAgentsUpdated(peerAgents: Array<SAPeerAgent>?, result: Int) {
    
        }
    
    }
    
    context.startForegroundService(new Intent(context, TaskQueueExecutorService.class));
    
    try {
        Thread.sleep(10000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }       
    
    new Handler(Looper.getMainLooper()).post(new Runnable() {
            public void run() {
                   context.startForegroundService(new Intent(context, 
               TaskQueueExecutorService.class));
                   try {
                       Thread.sleep(10000);
                   } catch (InterruptedException e) {
                      e.printStackTrace();
                  }       
            }
    });
    
    @Override
     public void onCreate() {
            super.onCreate();
    
            if (Build.VERSION.SDK_INT >= 26) {
                String CHANNEL_ID = "my_channel_01";
                NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                        "Channel human readable title",
                        NotificationManager.IMPORTANCE_DEFAULT);
    
                ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
    
                Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                        .setContentTitle("")
                        .setContentText("")
                        .setColor(ContextCompat.getColor(this, R.color.transparentColor))
                        .setSmallIcon(ContextCompat.getColor(this, R.color.transparentColor)).build();
    
                startForeground(1, notification);
            }
    }
    
    // Create the service connection.
    ServiceConnection connection = new ServiceConnection()
    {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {
            // The binder of the service that returns the instance that is created.
            MyService.LocalBinder binder = (MyService.LocalBinder) service;
    
            // The getter method to acquire the service.
            MyService myService = binder.getService();
    
            // getServiceIntent(context) returns the relative service intent 
            context.startForegroundService(getServiceIntent(context));
    
            // This is the key: Without waiting Android Framework to call this method
            // inside Service.onCreate(), immediately call here to post the notification.
            myService.startForeground(myNotificationId, MyService.getNotification());
    
            // Release the connection to prevent leaks.
            context.unbindService(this);
        }
    
        @Override
        public void onBindingDied(ComponentName name)
        {
            Log.w(TAG, "Binding has dead.");
        }
    
        @Override
        public void onNullBinding(ComponentName name)
        {
            Log.w(TAG, "Bind was null.");
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            Log.w(TAG, "Service is disconnected..");
        }
    };
    
    public class MyService extends Service
    {
        public class LocalBinder extends Binder
        {
            public MyService getService()
            {
                return MyService.this;
            }
        }
    
        // Create the instance on the service.
        private final LocalBinder binder = new LocalBinder();
    
        // Return this instance from onBind method.
        // You may also return new LocalBinder() which is
        // basically the same thing.
        @Nullable
        @Override
        public IBinder onBind(Intent intent)
        {
            return binder;
        }
    }
    
    // Try to bind the service
    try
    {
         context.bindService(getServiceIntent(context), connection,
                        Context.BIND_AUTO_CREATE);
    }
    catch (RuntimeException ignored)
    {
         // This is probably a broadcast receiver context even though we are calling getApplicationContext().
         // Just call startForegroundService instead since we cannot bind a service to a
         // broadcast receiver context. The service also have to call startForeground in
         // this case.
         context.startForegroundService(getServiceIntent(context));
    }
    
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    
    Context.startForegroundService() did not then call Service.startForeground();
    
    ....//some other code
    ...// API level and other device auto star service condition is already set
    stopService();
    startService();
    .....//some other code
    
    new Handler().postDelayed(()->ContextCompat.startForegroundService(activity, new Intent(activity, ChatService.class)), 500);
    
    <service
            android:name=".AudioRecorderService"
            android:enabled="true"
            android:exported="false"
            android:foregroundServiceType="microphone" />
    
    public class AService extends Service {
    
    @Override
    public void onCreate() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            startForeground(
                getForegroundNotificationId(),
                channelManager.buildBackgroundInfoNotification(getNotificationTitle(), getNotificationText()),
                ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
        } else {
            startForeground(getForegroundNotificationId(),
                channelManager.buildBackgroundInfoNotification(getNotificationTitle(), getNotificationText())
            );
        }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startForeground();
    
        if (hasQueueMoreItems()) {
            startWorkerThreads();
        } else {
            stopForeground(true);
            stopSelf();
        }
        return START_STICKY;
    }
    
    private class WorkerRunnable implements Runnable {
    
        @Override
        public void run() {
    
            while (getItem() != null && !isLoopInterrupted) {
                doSomething(getItem())   
            }
    
            waitALittle();
            stopForeground(true);
            stopSelf();
        }
    
        private void waitALittle() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    }
    
    To provide a streamlined experience for short-running foreground services on Android 12, the system can delay the display of foreground service notifications by 10 seconds for certain foreground services. This change gives short-lived tasks a chance to complete before their notifications appear.