Context.startForegroundService()随后仅在Android 11三星设备上调用Service.startForeground()

Context.startForegroundService()随后仅在Android 11三星设备上调用Service.startForeground(),android,android-service,samsung-mobile,android-11,Android,Android Service,Samsung Mobile,Android 11,只有运行安卓11的三星设备才会出现这种崩溃。显然,应用程序正在调用startForegroundService(intent)并要求我发布通知,让用户知道我正在运行前台服务,但应用程序源代码中从未调用过startForegroundService(intent),三星是否有可能定制安卓11,并在我调用startService(intent)时自动调用startForegroundService(intent) 堆栈跟踪 Context.startForegroundService() did n

只有运行安卓11的三星设备才会出现这种崩溃。显然,应用程序正在调用
startForegroundService(intent)
并要求我发布通知,让用户知道我正在运行前台服务,但应用程序源代码中从未调用过
startForegroundService(intent)
,三星是否有可能定制安卓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>
这是当接收器接收到事件时执行的代码

@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.");
    }
你可以看到它实际上启动了一个前台服务,我仍在调查崩溃情况,但至少我知道应用程序中启动了一个前台服务


而且,这次崩溃不仅仅发生在三星,就像我想的那样,crashlytics报道说三星一起崩溃是因为它是来自android平台的崩溃,相同崩溃的其他实例发生的频率较低,因此它们在firebase的崩溃列表中排名靠后。

对于一些前台服务,它们需要执行需要访问
位置
麦克风
媒体投影
电话
摄像机
数据同步
connectedDevice
mediaPlayback
,在服务中调用
startForeground
时,必须在清单中指定
“foregroundServiceType”
,并为服务设置
ServiceInfo
。我认为这解决了你的问题

编辑

您应该在服务的
onstart命令中这样启动
服务

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q){
            startForeground(NOTIFICATION_ID, notification)
        }
        else{
            startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
        }
if(Build.VERSION.SDK\u INT更新
可能原因
在您提供了更多代码之后,仍然不清楚您是否在
PlayerService
中调用
startForeground()
。看起来您没有,这就是为什么您会看到崩溃。另一方面,如果此崩溃只发生在Android 11上,那么您可能也会遇到不同的问题

示例代码 我刚刚制作了一个简单的应用程序,如果没有调用
startForeground()
的话,可以为
PlayerService
重现一个崩溃。也许它会对你有所帮助

app/build.gradle 添加依赖项以使用androidx
MediaButtonReceiver

 <receiver android:name="androidx.media.session.MediaButtonReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>
 </receiver>
...
implementation "androidx.media:media:1.2.1" 
...
AndroidManifest.xml PlayerService.java 修理 通过将
startForeground()
添加到
onCreate()
中,问题得到了解决。请注意,我准备参数和使用方法的方式是仅草案。有关详细信息,请查看官方文档

...
    <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>   
...
...
@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);
}
... 
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;
    }
}
...
    @Override
    public void onCreate() {
        super.onCreate();

        Notification testNotification = new Notification();
        int testId = 1;
        startForeground(testId, testNotification);
    }
...