【问题标题】:Context.startForegroundService did not then call Service.startForeground: Alternative solutionContext.startForegroundService 没有然后调用 Service.startForeground:替代解决方案
【发布时间】:2019-04-29 15:17:38
【问题描述】:

注意:这个问题假设您知道将服务绑定到上下文。

制作中的每个人都知道这个问题,甚至一些拥有 Android Oreo 或 Pie 设备的用户也知道。异常如下所示:

Fatal Exception: android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground()
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1792)
   at android.os.Handler.dispatchMessage(Handler.java:106)
   at android.os.Looper.loop(Looper.java:164)
   at android.app.ActivityThread.main(ActivityThread.java:6523)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)

当您拨打Context.startForegroundService(Intent) 时,您还必须拨打Service.startForeground(int, Notification) 在 5 秒内(即使您的手机可能甚至无法启动您的服务,但由于某种原因成为您的错)或您的应用程序将冻结或从 Android 框架抛出异常。经过进一步思考,我制定了一个解决方案。

由于Context.startForegroundService(Intent) 不保证该服务将在 5 秒内创建并且是一个异步操作,所以我认为是这样的:

// Starts service.
public static void startService(Context context)
{
    // If the context is null, bail.
    if (context == null)
        return;

    // This is the same as checking Build.VERSION.SDK_INT >= Build.VERSION_CODES_O
    if (Utilities.ATLEAST_OREO)
    {
        Log.w(TAG, "startForegroundService");

        // 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.createNotification(context) is static
                // for other purposes.
                myService.startForeground(19982, MyService.createNotification(context));

                // Release the connection to prevent leaks.
                context.unbindService(this);
            }

            @Override
            public void onServiceDisconnected(ComponentName name)
            {

            }
        };

        // 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));
        }
    }
    else
    {
        // Normal stuff below API 26.
        Log.w(TAG, "startService");
        context.startService(getServiceIntent(context));
    }
}

从启动服务的活动调用此函数。有趣的是:它可以工作并且不会抛出异常。我已经在模拟器上进行了测试,我的设备也是 Oreo,我想确认这是防止此异常的最佳方法不会发生。

我的问题是:这是实际创建前台服务的好方法吗?有什么想法吗?谢谢你们的cmets。

【问题讨论】:

  • 你在AndroidManifest文件中添加FOREGROUND_SERVICE权限了吗?
  • 是的,当然。事实并非如此。
  • 大家有什么想法吗?我认为这是一个重要的案例。

标签: android android-service android-service-binding foreground-service


【解决方案1】:

根据codelab,看起来是在Android 9.0+上实现前台服务的正确方法

【讨论】:

    猜你喜欢
    • 2019-01-09
    • 2018-03-29
    • 2018-03-04
    • 2017-11-09
    • 2019-12-07
    • 1970-01-01
    • 2018-05-16
    • 2019-09-17
    相关资源
    最近更新 更多