Android 12 crash: Exception: startForegroundService() not allowed due to mAllowStartForeground false
xKRUTOIx opened this issue · 4 comments
Hello, I noticed new crash in crashlytics and it comes from this package, it happens only with android 12 in background.
I use the latest version 3.0.2 of this library, build the app target sdk 31. I'm making an app where people talk to each other via voice and this library helps me to keep the app alive when they talk in background.
Stack trace:
Fatal Exception: java.lang.RuntimeException: Unable to start service com.voximplant.foregroundservice.VIForegroundService@369a06b with Intent { act=com.voximplant.foregroundservice.service_start cmp=my_app_name/com.voximplant.foregroundservice.VIForegroundService (has extras) }: android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service my_app_name/com.voximplant.foregroundservice.VIForegroundService
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:5110)
at android.app.ActivityThread.access$2100(ActivityThread.java:310)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2319)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8663)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
I have poor Java knowledge and moreover I wasn't able to reproduce the crash so I can't even attempt to blindly fix it because I won't be able to understand whether it helped or not 🤔
I use this custom hook to create and stop foreground service, basically when user hides the app it runs the service, when user opens the app it stops the service and that's it.
const useForegroundService = () => {
// This hook returns latest appState
const appState = useAppState();
const startForegroundService = async () => {
const notificationConfig = {
channelId: 'channelId',
id: 3456,
title: 'title',
text: 'text',
icon: 'ic_icon',
};
try {
await VIForegroundService.getInstance().startService(
notificationConfig,
);
} catch (e) {
console.error(e);
}
};
useEffect(() => {
if (Platform.Version >= 26) {
// Since the foreground service must display a notification,
// for Android 8+ it is required to create a notification channel first:
const channelConfig = {
id: 'channelId',
name: 'name',
description: 'description',
enableVibration: false,
};
VIForegroundService.getInstance().createNotificationChannel(
channelConfig,
);
}
}, []);
useEffect(() => {
if (appState === 'active') {
VIForegroundService.getInstance()
.stopService()
.catch(() => {});
} else {
startForegroundService();
}
return () => {
VIForegroundService.getInstance()
.stopService()
.catch(() => {});
};
}, [appState]);
};
By any chance do you guys know how to prevent this crash or maybe I'm using this library wrongly?
Hello @xKRUTOIx !
We cannot reproduce this issue. The issue may be caused by some reasons, for additional information please read this article “Restrictions on background starts”
We recommend you run Foreground Service after your call is started, stop the service when the call is ended and do it in the active app state. It is not required to switch the service each time when the app is in the «background - active» state.
Also, if you want to stop the service from the background state, you can provide the «button» property to «notificationConfig» , after that add a handler for stop service callback that will be invoked when the button is pressed.
For example:
import VIForegroundService from ‘@voximplant/react-native-foreground-service’;
const service = useRef(VIForegroundService.getInstance());
const notificationConfig = {
// add this property to notificationConfig
// and you will be have button with own action handler
button: ‘Hangup’,
};
// subscribe on foreground notification button pressed event
const subscribeForegroundServiceEvent = () => {
service.current?.on(‘VIForegroundServiceButtonPressed’, () => {
HangUpMyCall();
});
};
@pe1ros thanks for the response :)
We recommend you run Foreground Service after your call is started, stop the service when the call is ended and do it in the active app state. It is not required to switch the service each time when the app is in the «background - active» state.
For some reason I wanted to make it "smarter" and start the service only when its needed (e.g. in background). Although I love your idea, it's very likely will solve my issue, thanks!
I'm going to release the app and if it will solve the crash I'll close the issue, does it sound good?
For me helped adding next changes.
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" android:minSdkVersion="34" />
<service android:name="com.voximplant.foregroundservice.VIForegroundService" android:foregroundServiceType="mediaPlayback" android:exported="false"/>
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
startForeground((int)notificationConfig.getDouble("id"), notification);
} else {
startForeground((int)notificationConfig.getDouble("id"), notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
}
// startForeground((int)notificationConfig.getDouble("id"), notification);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getReactApplicationContext().registerReceiver(foregroundReceiver, filter, Context.RECEIVER_EXPORTED);
}else {
getReactApplicationContext().registerReceiver(foregroundReceiver, filter);
}