因为每个来这里的人都遭受着同样的痛苦,我想分享我的解决方法,之前没有人尝试过(在这个问题中)。我可以向您保证,它是工作的,甚至在一个停止的断点上确认这个方法。
问题是调用服务。start前台(id, notification)来自服务本身,对吧?不幸的是,Android框架不保证调用服务。Service.onCreate()中的start前台(id, notification)在5秒内,但无论如何都会抛出异常,所以我想出了这种方法。
Bind the service to a context with a binder from the service before calling Context.startForegroundService()
If the bind is successful, call Context.startForegroundService() from the service connection and immediately call Service.startForeground() inside the service connection.
IMPORTANT NOTE: Call the Context.bindService() method inside a try-catch because in some occasions the call can throw an exception, in which case you need to rely on calling Context.startForegroundService() directly and hope it will not fail. An example can be a broadcast receiver context, however getting application context does not throw an exception in that case, but using the context directly does.
这甚至可以在我绑定服务后和触发“startForeground”调用之前等待断点时工作。等待3-4秒不会触发异常,而5秒后会抛出异常。(如果设备不能在5秒内执行两行代码,那么就该把它扔进垃圾桶了。)
因此,首先创建一个服务连接。
// 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;
}
}
然后,尝试从该上下文中绑定服务。如果成功,它将从您正在使用的服务连接调用serviceconnection . onserviceconnconnected()方法。然后,处理上面所示代码中的逻辑。示例代码如下所示:
// 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));
}
它似乎在我开发的应用程序上工作,所以当你尝试时它应该也能工作。