Skip to content

Using Remote Config with Chinese users

Flutter, Firebase, China2 min read

I had a little bit of a scare last week so I thought I'd write a blog post about it. It's about using Firebase's Remote Config(or A/B testing) if you have Chinese users. In short, it won't work properly with most of them and even worse it might cause crashes or issues in your app.

Last week I decided there was some metrics I wanted to A/B test in one of my production iOS apps. This particular app has a lot of mainland Chinese users but at the time I didn't really think too hard about this because I had read that some Google Services(like AdMob for instance) work okay these days. I already had Firebase Analytics and Crashlytics implemented in the app and those seemed to be working fine for Chinese users.

So I just went ahead and implemented Remote Config. The app that I'm talking about is a Flutter app so I used the firebase_remote_config package(you can find it here). I also awaited activateFetched like the example used in the README:

1final defaults = <String, dynamic>{'welcome': 'default welcome'};
2await remoteConfig.setDefaults(defaults);
4await remoteConfig.fetch(expiration: const Duration(hours: 5));
5await remoteConfig.activateFetched();
6print('welcome message: ' + remoteConfig.getString('welcome'));

Everything seemed to be working fine, so I made a release build and submitted it for App Review. It passed the review that night with no issues...

Then I woke up the next morning and started getting some annoyed emails/reviews in Chinese. The app would start but get stuck on the splash screen(seemingly only for Chinese users). It took me about 10 minutes or so to think through the issue and realize that there was a chance the endpoints for Remote Config might be blocked in China - and it seems like that was the case. I was able to also confirm the non-fatal crashes with the Crashlytics dashboard.

Crashlytics Dashboard

The error I was seeing was Non-fatal Exception: Exception: Unable to fetch remote config. And this is the solution that I quickly cobbled together after researching the issue with Google:

1_setupRemoteConfig() async {
2 try {
3 final remoteConfig = await RemoteConfig.instance;
4 final defaults = <String, dynamic>{'show_purchase_details': false};
5 await remoteConfig.setDefaults(defaults);
6 await remoteConfig.fetch(expiration: Duration(hours: 5));
7 await remoteConfig.activateFetched();
8 } on FetchThrottledException catch (_) {
9 logger.d("Unable to fetch remote config details...");
10 }

I should probably also mention, I know the above method is an async method but I don't await it anymore where I call it(I did await it in the version that was causing crashes). I can only assume that because the endpoint the package is trying to access is blocked in China it times out and throws FetchThrottledException.

Apart from this isolated issue Remote Config seems to be working pretty well and I'm excitedly awaiting some A/B test results as I write this. I think I might write another post later on about implementing the firebase_remote_config package too.