expo: facebookScheme on Standalone Android is broken, CustomTabActivity doesn't do anything.

🐛 Bug Report

Summary of Issue

  • Cross-post from this forum post.
  • The facebookScheme on standalone Android resolves to a CustomTabActivity that is completely blank and doesn’t do anything.

Environment - output of expo diagnostics & the platform(s) you’re targeting

  Expo CLI 3.24.2 environment info:
    System:
      OS: Windows 10 10.0.18362
    Binaries:
      Node: 12.18.2 - C:\Program Files\nodejs\node.EXE
      Yarn: 1.21.1 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
      npm: 6.14.5 - C:\Program Files\nodejs\npm.CMD
    npmPackages:
      expo: ~38.0.8 => 38.0.9
      react: ~16.11.0 => 16.11.0
      react-dom: ~16.11.0 => 16.11.0
      react-native: https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz => 0.62.2
      react-native-web: ~0.11.7 => 0.11.7

Reproducible Demo

Code is reduced to a single file, one package (expo-auth-session), and only adding the facebook* properties to app.json. See this post.

APK download (available up to 29 days of this post).

Steps to Reproduce

  • expo init minimal typescript
  • expo install expo-auth-session
  • create new facebook project, add login, add https://auth.expo.io/@user/slug
  • copy code from reproducible post
  • make a standalone build

Expected Behavior vs Actual Behavior

  • Web: it works
  • Expo client: it works (using proxy)
  • Android standalone client: clicking “continue” OR “cancel” returns to a second activity with just the app title in an appbar.

Reproduce by running:

adb shell am start -W -a android.intent.action.VIEW -d "fb<FACEBOOKID>://authorize?code=invalid&state=a01bCdEFJK" com.example.app

Other things

Because I had not seen this issue anywhere else, I suspected this was a me problem; but I think it might not be. It’s also not unique to expo-auth-session, as you can tell by the shellscript reproduction.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 6
  • Comments: 52 (8 by maintainers)

Most upvoted comments

Now with EAS Build, you can create custom dev clients and builds that have modified AndroidManifest.xml files. In this case, I would suggest adding the FB scheme directly to the manifest and avoid using facebookScheme which would generate the extra activity that is used in expo-facebook.

withAndroidScheme.js

const { AndroidConfig, withAndroidManifest } = require("@expo/config-plugins");

const withAndroidScheme = (config, scheme) =>
  withAndroidManifest(config, (config) => {
    if (!AndroidConfig.Scheme.hasScheme(scheme, config.modResults)) {
      config.modResults = AndroidConfig.Scheme.appendScheme(
        scheme,
        config.modResults
      );
    }
    return config;
  });

module.exports = withAndroidScheme;

Then in your app.json

{
  "expo": {
    "plugins": [
      ["./withAndroidScheme", "fbMyCustomScheme"]
    ]
  }
}

If you use the vscode-expo extension, you can use <kbd>⌘⇧P</kbd> and type “Expo: Preview modifier” then select “android.manifest” to see a preview of what the AndroidManifest.xml will look like after you build with eas build -p android or expo run:android.

There is no workaround to prevent the double activity. The only workaround is to eject and fix AndroidManifest.xml manually.

I have used android-manifest.plugin.js method and removed customTabActivity and added my FACEBOOK_CLIENT_ID fbscheme manually here. This seems to fix the issue:

module.exports = function withCustomConfig(config) {
	return withAndroidManifest(config, async (config) => {
		const fbscheme = 'fb' + config.extra.FACEBOOK_CLIENT_ID
		if (!AndroidConfig.Scheme.hasScheme(fbscheme, config.modResults)) {
			config.modResults = AndroidConfig.Scheme.appendScheme(
				fbscheme,
				config.modResults
			)
		}
		config.modResults.manifest.application[0].activity =
			config.modResults.manifest.application[0].activity.filter(
				(item) => item.$['android:name'] !== 'com.facebook.CustomTabActivity'
			)
		return config
	})
}

in app.config.js:

import { withAndroidManifest } from "@expo/config-plugins";

const withCustomConfig = (config) => withAndroidManifest(config, async (config) => {
  config.modResults.manifest.application[0].activity = config.modResults.manifest.application[0].activity.filter(
    (item) => item.$['android:name'] !== 'com.facebook.CustomTabActivity'
  );
  return config;
});

export default ({ config }) => ({
  ...
  facebookScheme: 'fb...',
  plugins: [[withCustomConfig]],
  ...
});

npx uri-scheme add fb...

expo prebuild -p android

Does anyone have any knews on the matter? Any workarounds ?

FYI, the same issue is present in expo-authentication (https://docs.expo.dev/guides/authentication/). Two activities generated. One will work, one doesn’t.

I was able to make this work for me by:

  • not using expo-facebook
  • using the withAndroidScheme plugin
  • making sure there is NO Facebook scheme value in app json
  • using proxy for iOS

Thank you @SleeplessByte. Now it’s working but like what you said, it will show 2 activities. Any trick on how to resolve this?

In managed mode you can’t resolve it. It’s because both packages add schemas into the AndroidManifest.xml.

As far as I can tell, it would seem that facebook auth-session may not work with Android standalone apps in their current form. The custom activity is required for expo-facebook to work properly. Perhaps we could try making expo-auth-session require expo-facebook to work on Android 🤔