YoussefHenna / expo-enode-link-sdk

An Expo Module integration for Enode's Link SDK
MIT License
7 stars 2 forks source link

Android Crash on Start, AppCompat issue #20

Open JHelar opened 3 weeks ago

JHelar commented 3 weeks ago

What?

The following error happens on Android once you call the start method resulting in an app crash:

Error inflating class androidx.appcompat.widget.AppCompatImageView
  android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
  android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3922)
  android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
  android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:139)
  android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:96)
  android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
  android.os.Handler.dispatchMessage(Handler.java:106)
  android.os.Looper.loopOnce(Looper.java:205)
  android.os.Looper.loop(Looper.java:294)
  android.app.ActivityThread.main(ActivityThread.java:8177)
  java.lang.reflect.Method.invoke(Native Method)
  com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
  com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)

Solution

Since the latest bump of the io.enode:linkkit version to 1.0.0 from 0.10.0, you need to add a default app theme to AndroidManifest.xml according to Enode docs:

<application
        android:theme="@style/Theme.MaterialComponents.DayNight.NoActionBar"

Fix

We solved it locally by creating an expo plugin that injected the theme attributes to the application and activity elements:

withEnodeLinkSDKThemeFix.js

const { withAndroidManifest } = require('@expo/config-plugins');

const ANDROID_THEME = '@style/Theme.MaterialComponents.DayNight.NoActionBar';

/**
 * @param {import('@expo/config-plugins').AndroidManifest} androidManifest
 * @returns
 */
function addAndroidMaterialThemeAttributes(androidManifest) {
  const manifest = androidManifest.manifest;
  if (!Array.isArray(manifest['application'])) {
    console.warn('addAndroidMaterialThemeAttributes: No application array in manifest?');
    return androidManifest;
  }

  const application = manifest['application'].find((item) => item.$['android:name'] === '.MainApplication');
  if (!application) {
    console.warn('addAndroidMaterialThemeAttributes: No .MainApplication?');
    return androidManifest;
  }

  const activity = application.activity.find((item) => item.$['android:name'] === '.MainActivity');
  if (!activity) {
    console.warn('addAndroidMaterialThemeAttributes: No .MainActivity?');
    return androidManifest;
  }

  activity.$['android:theme'] = ANDROID_THEME;
  application.$['android:theme'] = ANDROID_THEME;

  return androidManifest;
}

module.exports = function withEnodeLinkSDKThemeFix(config) {
  return withAndroidManifest(config, (config) => {
    config.modResults = addAndroidMaterialThemeAttributes(config.modResults);
    return config;
  });
};

app.json

{
plugins: [
  [
    'expo-build-properties',
    {
      android: {
        minSdkVersion: 24,
      },
    },
  ],
  ['./withEnodeLinkSDKThemeFix', {}],
 ]
}

Perhaps this disclaimer should be added to the README or if it could somehow be incorporated into the library it self?

bjornevik commented 6 days ago

When I opened the PR to upgrade to 1.0 I was basing the change off an email from Enode stating that no changes should be necessary when upgrading. Should've double checked the actual docs 😅

I don't know if this could be handled by the package itself @YoussefHenna? I did try through manually editing the AndroidManifest.xml file and running patch-package, but that just led to build errors. May be possible to do something with a Styles.xml-file seeing as the app theme is the actual problem, but I don't really have the time to look into it.

I did find the following solution whilst searching around https://github.com/expo/expo/issues/19563#issuecomment-1576437572. I believe it's slightly safer than directly modifying the mainActivity and mainApplication fields in the AndroidManifest.xml, as I noticed Expo noted in their documentation that mods.android.mainActivity and mods.android.mainApplication are "dangerous" modifications, but I don't really think it applies in this case.

Anyways, I've verified that the custom app theme solution works for me:

withCustomAppTheme.js

const { withAndroidStyles } = require('expo/config-plugins');

function withCustomAppTheme(config, customAppTheme) {
  return withAndroidStyles(config, (config) => {
    let modified = false;
    const styles = config.modResults;
    styles.resources.style.map((style) => {
      if (style.$.name === 'AppTheme') {
        if (!modified) {
          style.$.parent = customAppTheme;
          modified = true;
        } else {
          styles.resources.style.splice(
            styles.resources.style.indexOf(style),
            1
          );
        }
      }
    });
    return config;
  });
}
module.exports = withCustomAppTheme;

app.json

"plugins": [
  [
    "./withCustomAppTheme", "Theme.MaterialComponents.DayNight.NoActionBar"
  ],
]
antoniaverdier01 commented 5 hours ago

Hello everyone, thank you for the ideas on how to solve this issue! After including the solution from @JHelar I am able to link through the Enode SDK again without my application crashing. Unfortunately, adding the new theme to the AndroidManifest.xml leads to problems with the native elements of my application's UI.

  1. The status bar displayed in Enode's linking UI is displayed in blue, although it should be white or black depending on whether the user uses light or dark mode. In the rest of the application, the status bar color is still as expected.

    status bar enode
  2. The Alert component (from react-native) uses a wrong text color for the button which is displayed in the bottom right corner of the Alert. The button is still there and clickable, but as the text color is white on a white background, it can't be seen. I assume that this has something to do with light/dark mode, but as the rest of the component is correctly set to light mode, I can't figure out what is going wrong. The alert shown below is displayed when the Enode linking flow is being left by clicking the "x" at the top right corner, but applies to all Alerts shown throughout the application after adding the new theme.

    status bar enode

I have tested this on an Android emulator with API level 33 and checked that I have correctly set the theme to @style/Theme.MaterialComponents.DayNight.NoActionBar.

Any hints on which changes are additionally necessary to ensure that the UI is working as expected are highly appreciated! Thank you for your help.