我只有运行android 11的三星设备才会崩溃。很明显,应用程序正在调用startForegroundService(intent),并要求我发布通知,让用户知道我正在运行前台服务,但是这个对startForegroundService(intent)的调用从来没有在应用程序源代码中进行过,三星是否有可能定制了android 11,并在我调用startService(intent)时自动调用了startForegroundService(intent)?
堆栈跟踪
Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{4ab4323 u0 {app package name}/{library package name}.player.PlayerService}
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2240)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loop (Looper.java:246)
android.app.ActivityThread.main (ActivityThread.java:8506)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:602)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1130)我使用context.startService(intent)启动服务,服务在应用程序的OnResume中启动,上下文是应用程序上下文。
下面也是在清单中声明服务的方式
<service
android:name=".player.PlayerService"
android:exported="false"
android:foregroundServiceType="mediaPlayback"
android:stopWithTask="false">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</service>更新:我找到了调用startForegroundService(Intent)的原因,我使用了来自android的以下接收器来帮助处理诸如耳机按钮之类的动作控制设备,所以自从我将应用程序转换为androidx之后,它就开始使用新的MediaButtonReceiver。
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>这是接收方接收到事件时执行的代码。
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null
|| !Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())
|| !intent.hasExtra(Intent.EXTRA_KEY_EVENT)) {
Log.d(TAG, "Ignore unsupported intent: " + intent);
return;
}
ComponentName mediaButtonServiceComponentName =
getServiceComponentByAction(context, Intent.ACTION_MEDIA_BUTTON);
if (mediaButtonServiceComponentName != null) {
intent.setComponent(mediaButtonServiceComponentName);
startForegroundService(context, intent);
return;
}
ComponentName mediaBrowserServiceComponentName = getServiceComponentByAction(context,
MediaBrowserServiceCompat.SERVICE_INTERFACE);
if (mediaBrowserServiceComponentName != null) {
PendingResult pendingResult = goAsync();
Context applicationContext = context.getApplicationContext();
MediaButtonConnectionCallback connectionCallback =
new MediaButtonConnectionCallback(applicationContext, intent, pendingResult);
MediaBrowserCompat mediaBrowser = new MediaBrowserCompat(applicationContext,
mediaBrowserServiceComponentName, connectionCallback, null);
connectionCallback.setMediaBrowser(mediaBrowser);
mediaBrowser.connect();
return;
}
throw new IllegalStateException("Could not find any Service that handles "
+ Intent.ACTION_MEDIA_BUTTON + " or implements a media browser service.");
}您可以看到它实际上启动了前台服务,我仍然在调查崩溃,但至少我知道在应用程序中启动了前台服务。
而且,这次崩溃并不像我想的那样只发生在三星,据报告,三星的崩溃是因为它是来自android平台的一次崩溃,其他同样的事故发生的频率较低,所以他们在火堆上的崩溃名单上。
发布于 2021-03-24 15:34:21
更新
可能原因
在提供了更多代码之后,还不清楚是否在startForeground()中调用PlayerService。看来你没有,这就是为什么你看到了坠机。另一方面,如果这次崩溃只发生在Android 11上,那么您可能也会遇到不同的问题。
样本代码
我只是制作了一个简单的应用程序来重现PlayerService的崩溃,如果startForeground()没有被调用的话。也许这会对你有帮助。
app/build.gradle
添加依赖项以使用androidx MediaButtonReceiver
...
implementation "androidx.media:media:1.2.1"
...AndroidManifest.xml
...
<service
android:name=".PlayerService"
android:exported="false"
android:foregroundServiceType="mediaPlayback"
android:stopWithTask="false">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</service>
<receiver android:name="androidx.media.session.MediaButtonReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
...MainActivity.java
模拟媒体按钮事件,如下所示
...
@Override
protected void onResume() {
super.onResume();
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.setClass(this, MediaButtonReceiver.class);
intent.putExtra(Intent.EXTRA_KEY_EVENT, "test");
sendBroadcast(intent);
}
... PlayerService.java
public class PlayerService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
MediaButtonReceiver.handleIntent(null, intent);
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}修复
通过将startForeground()添加到onCreate()中,问题得到了解决。请注意,我准备参数和使用该方法的方式是--一种只使用的草案。有关详细信息,请查阅正式文档这里。
...
@Override
public void onCreate() {
super.onCreate();
Notification testNotification = new Notification();
int testId = 1;
startForeground(testId, testNotification);
}
...发布于 2021-03-02 09:02:25
对于一些需要访问location、microphone、mediaProjection、phoneCall、camera、dataSync、connectedDevice和mediaPlayback的前台服务,在调用服务中的startForeground时,必须在清单中指定"foregroundServiceType",并为服务设置ServiceInfo。我想这解决了你的问题。
编辑
您应该在服务的service中像这样启动您的onStartCommand:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q){
startForeground(NOTIFICATION_ID, notification)
}
else{
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
}你要这么做吗?
https://stackoverflow.com/questions/66435767
复制相似问题