Change targetSdkVersion for stripe-react-native >= 0.2.4?

Hi, we have an important issue:

Stripe crashes the app when opening the paymentSheet for the first time: Crash android when initPaymentSheet is initialized · Issue #603 · stripe/stripe-react-native · GitHub. It’s a frustrating experience.

As said in the issue, this is fixed in 0.2.4 but to install >=0.2.4, it’s required targetSdkVersion >= 31, as said in [android] Version 0.2.4 requires targetSdkVersion = 31 · Issue #812 · stripe/stripe-react-native · GitHub. Expo still on targetSdkVersion 30 and maybe it will take some/many months until it’s upgraded.

As recommended by @charliecruzan-stripe, I could try to increase it via an EAS plugin, but I don’t have a clue on how to do it. I read the docs many times but still it’s something off my skills and understanding for now, and I don’t really want to do something wrong and mess my app in unknown ways.

Is there a EAS plugin to increase it? Would it work or I would face other issues?

Hi @srbrahma

EDIT: There is now a built-in way to update the targetSdkVersion etc.

You could try something like this:

Note: This plugin is not perfect. It should be marked “dangerous” because it manually modifies build.gradle.

See also the app.plugin.js and related files in the packages in:

Thanks for the quick reply, @wodin!

I will try it in a few days.

Hi @wodin!

I changed your code a little.

As noticed by @jordzawada here, we have to change in this case, both compileSdkVersion and targetSdkVersion instead of minSdkVersion. (source).

In my improvement, we can change minSdkVersion, compileSdkVersion and targetSdkVersion.

plugins/withAndroidSdkVersions.js

const {
  withProjectBuildGradle,
  withPlugins,
} = require('@expo/config-plugins');

function setMinSdkVersion(buildGradle, targetVersion) {
  const regexpCurrentVersion = /\bminSdkVersion\s*=\s*(\d+)/;
  const match = buildGradle.match(regexpCurrentVersion);

  if (match) {
    const version = parseInt(match[1], 10);

    if (version < targetVersion) {
      buildGradle = buildGradle.replace(
        /\bminSdkVersion\s*=\s*\d+/,
        `minSdkVersion = ${targetVersion}`
      );
    } else {
      console.warn(`WARN: minSdkVersion is already >= ${version}`);
    }
  }

  return buildGradle;
}

function setCompileSdkVersion(buildGradle, targetVersion) {
  const regexpCurrentVersion = /\bcompileSdkVersion\s*=\s*(\d+)/;
  const match = buildGradle.match(regexpCurrentVersion);

  if (match) {
    const version = parseInt(match[1], 10);

    if (version < targetVersion) {
      buildGradle = buildGradle.replace(
        /\bcompileSdkVersion\s*=\s*\d+/,
        `compileSdkVersion = ${targetVersion}`
      );
    } else {
      console.warn(`WARN: compileSdkVersion is already >= ${version}`);
    }
  }

  return buildGradle;
}

function setTargetSdkVersion(buildGradle, targetVersion) {
  const regexpCurrentVersion = /\btargetSdkVersion\s*=\s*(\d+)/;
  const match = buildGradle.match(regexpCurrentVersion);

  if (match) {
    const version = parseInt(match[1], 10);

    if (version < targetVersion) {
      buildGradle = buildGradle.replace(
        /\btargetSdkVersion\s*=\s*\d+/,
        `targetSdkVersion = ${targetVersion}`
      );
    } else {
      console.warn(`WARN: targetSdkVersion is already >= ${version}`);
    }
  }

  return buildGradle;
}

const withAndroidSdkVersions = (config, {
  minSdkVersion,
  compileSdkVersion,
  targetSdkVersion
} = {}) => {
  return withProjectBuildGradle(config, (config) => {
    if (config.modResults.language !== 'groovy')
      throw new Error("Can't use withAndroidSdkVersions EAS Plugin as build.gradle is not groovy");

    if (minSdkVersion)
      config.modResults.contents = setMinSdkVersion(config.modResults.contents, minSdkVersion);
    if (compileSdkVersion)
      config.modResults.contents = setCompileSdkVersion(config.modResults.contents, compileSdkVersion);
    if (targetSdkVersion)
      config.modResults.contents = setTargetSdkVersion(config.modResults.contents, targetSdkVersion);

    return config;
  });
};

module.exports = (config, props) =>
  withPlugins(config, [
    [withAndroidSdkVersions, props],
  ]);

app.json

 "plugins": [
      [
        "./plugins/withAndroidSdkVersions.js",
        {
          // minSdkVersion: 24,
          "compileSdkVersion": 31,
          "targetSdkVersion": 31
        }
      ],
]

Feel free to share it. Maybe I will make this a npm package, although may not be too useful.

1 Like

Hello @srbrahma , I implemented your solution but am still unable to solve the underlying issue i.e., the app crash when stripe’s initializePaymentSheet is executed for the first time, and there’s no crash in the second attempt. I updated @stripe/stripe-react-native version to 0.2.4 , Expo SDK version 44 & targetSdkVersion 31. I Ran expo prebuild and then expo start, app still crashes on the checkout page.

Moreover, When I built apk using EAS Build, I’m unable to install the app on my physical device, it says “There was a problem parsing the package”

I’d be glad if you can help me, Thank you!

Hi @srbrahma

I’ve found out about an even easier way. Not sure how long this has existed:

There’s something called AndroidConfig.Version.withBuildScriptExtMinimumVersion in @expo/config-plugins. I think the easiest way to use it is from app.config.js.

I have a normal app.json and then in addition to that I have an app.config.js which overrides some things in app.json for dev/preview builds and also so that i don’t have to store an access key in Git. The plugins section is the relevant part to this discussion:

import "dotenv/config";

// For setting Android min/compile/target SdkVersions
import { AndroidConfig } from "@expo/config-plugins";

function app_variant(base, dev, preview) {
  switch (process.env.APP_VARIANT) {
    case "development":
      return `${base}${dev}`;
    case "preview":
      return `${base}${preview}`;
    default:
      return base;
  }
}

export default function ({ config }) {
  return {
    ...config,
    name: app_variant(config.name, " (Dev)", " (Preview)"),
    android: {
      ...config.android,
      package: app_variant(config.android.package, ".dev", ".preview"),
    },
    ios: {
      ...config.ios,
      bundleIdentifier: app_variant(config.ios.bundleIdentifier, ".dev", ".preview"),
    },
    extra: {
      accessKey: process.env.accessKey,
    },
    // Set Android min/compile/target SdkVersions
    plugins: [
      [
        AndroidConfig.Version.withBuildScriptExtMinimumVersion,
        {
          name: "minSdkVersion",
          minVersion: 24,
        },
      ],
      [
        AndroidConfig.Version.withBuildScriptExtMinimumVersion,
        {
          name: "compileSdkVersion",
          minVersion: 31,
        },
      ],
      [
        AndroidConfig.Version.withBuildScriptExtMinimumVersion,
        {
          name: "targetSdkVersion",
          minVersion: 31,
        },
      ],
    ],
  };
}
1 Like

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.