Skip to content

Commit

Permalink
[android][tools] fix expo go versioning issues on android (expo#22950)
Browse files Browse the repository at this point in the history
# Why

fix expo-go android versioning for sdk 49
close ENG-8955

# How

- [tools] fix for react-native monorepo changes
- [tools] update manifest-merger because the original one doesn't support java 17. since the new manifest-merger has kotlin runtime and the jar takes about 35MB. rather than committing a prebuilt jar, now we build manifest-merger from source.
- [tools] since expo#22609 we don't have `package` in libraries' AndroidManifest.xml, the manifest-merger still requires the `package`, so we have to temporarily put the `package` back during manifest merging. (the `package` name is generated from `namespace` in build.gradle)
- [tools] the original jarjar uses outdated [ASM](https://asm.ow2.io/) and it doesn't support bytecode generated by kotlin. react-native now has some kotlin code, and the original jarjar cannot transform package name from those kotlin classes. i've tried to rebuild a jarjar from [this revision](google/jarjar@e11d563). this requires some manual steps like updating ASM libs and install ant builder. so i still commit the prebuilt jarjar in this pr.
- [updates] force casting for `UpdateEntity` to deal with kotlin smart casting from versioned to unversioned kernel class. (i'll leave inline comment for this)
- [expo-modules-core's `android-annotation`] the project stays in a place that does not support versioning yet. in this pr i just keep it as an unversionable project. cc @lukmccall 

# Test Plan

`et add-sdk -p android -s 49.0.0` + android versioned expo-go + sdk 49 NCL smoke test
  • Loading branch information
Kudo authored Jun 22, 2023
1 parent a9c42bb commit 71ea603
Show file tree
Hide file tree
Showing 39 changed files with 577 additions and 90 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ xcuserdata
/android/**/local.properties
/android/captures
/android/expoview/libs/ReactAndroid-temp
/android/versioned-react-native/packages
/android/versioned-react-native/ReactAndroid
/android/versioned-react-native/ReactCommon
/android/versioned-react-native/codegen
/android/versioned-react-native/sdks
ReactAndroid-temp.aar
/android/prebuiltHermes
/android/versioned-abis/**/*.aar
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ buildscript {
dbFlowVersion = '4.2.4'
buildToolsVersion = '33.0.0'
kotlinVersion = '1.8.10'
gradlePluginVersion = '7.4.1'
gradlePluginVersion = '7.4.2'
gradleDownloadTaskVersion = '5.0.1'
repositoryUrl = "file:${System.env.HOME}/.m2/repository/"

Expand Down
6 changes: 6 additions & 0 deletions android/expoview/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,12 @@ dependencies {
// expo-application
api 'com.android.installreferrer:installreferrer:1.0'

// expo-blur
implementation 'com.github.Dimezis:BlurView:version-2.0.3'

// expo-modules-core android-annotation
api project(':expo-modules-core$android-annotation')

// expo-store-review
implementation "com.google.android.play:review:2.0.1"
implementation "com.google.android.play:review-ktx:2.0.0"
Expand Down
6 changes: 3 additions & 3 deletions android/versioned-react-native/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

buildscript {
ext {
gradlePluginVersion = '7.1.1'
kotlinVersion = '1.6.10'
gradlePluginVersion = '7.4.2'
kotlinVersion = '1.8.10'
}
repositories {
google()
Expand All @@ -12,7 +12,7 @@ buildscript {
}
dependencies {
classpath "com.android.tools.build:gradle:${gradlePluginVersion}"
classpath 'de.undercouch:gradle-download-task:4.1.2'
classpath 'de.undercouch:gradle-download-task:5.0.1'
classpath "com.facebook.react:react-native-gradle-plugin"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"

Expand Down
3 changes: 3 additions & 0 deletions android/versioned-react-native/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64

android.useAndroidX=true
android.enableJetifier=true

# Remove this workaround when upgrading to [email protected]
kotlin.jvm.target.validation.mode=warning
Binary file modified android/versioned-react-native/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
6 changes: 6 additions & 0 deletions android/versioned-react-native/gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"

# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi

# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
Expand Down
7 changes: 4 additions & 3 deletions android/versioned-react-native/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
includeBuild('../../react-native-lab/react-native/packages/react-native-gradle-plugin/')
include ':ReactAndroid'
include ':ReactAndroid:hermes-engine'
project(':ReactAndroid:hermes-engine').projectDir = new File(rootDir, 'ReactAndroid/hermes-engine')
include ':packages:react-native:ReactAndroid'
project(':packages:react-native:ReactAndroid').projectDir = new File(rootDir, 'packages/react-native/ReactAndroid')
include ':packages:react-native:ReactAndroid:hermes-engine'
project(':packages:react-native:ReactAndroid:hermes-engine').projectDir = new File(rootDir, 'packages/react-native/ReactAndroid/hermes-engine')
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import expo.modules.core.ModuleRegistryDelegate
import expo.modules.core.Promise
import expo.modules.core.interfaces.ExpoMethod
import expo.modules.updates.db.entity.AssetEntity
import expo.modules.updates.db.entity.UpdateEntity
import expo.modules.updates.launcher.Launcher.LauncherCallback
import expo.modules.updates.loader.*
import expo.modules.updates.loader.FileDownloader.RemoteUpdateDownloadCallback
Expand All @@ -23,7 +24,7 @@ import java.util.Date

// these unused imports must stay because of versioning
/* ktlint-disable no-unused-imports */

import expo.modules.updates.UpdatesConfiguration
/* ktlint-enable no-unused-imports */

/**
Expand Down Expand Up @@ -317,9 +318,15 @@ class UpdatesModule(
} else {
updatesServiceLocal.resetSelectionPolicy()
updateInfo.putBoolean("isNew", true)

// We need the explicit casting here because when in versioned expo-updates,
// the UpdateEntity and UpdatesModule are in different package namespace,
// Kotlin cannot do the smart casting for that case.
val updateEntity = loaderResult.updateEntity as UpdateEntity

updateInfo.putString(
"manifestString",
loaderResult.updateEntity.manifest.toString()
updateEntity.manifest.toString()
)
updatesServiceLocal.stateMachine?.processEvent(
UpdatesStateEvent.DownloadCompleteWithUpdate(loaderResult.updateEntity.manifest)
Expand Down
7 changes: 6 additions & 1 deletion tools/src/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ export const ANDROID_DIR = Directories.getAndroidDir();
export const TEMPLATES_DIR = Directories.getTemplatesDir();
export const PACKAGES_DIR = Directories.getPackagesDir();
export const VERSIONED_RN_IOS_DIR = Directories.getVersionedReactNativeIosDir();
export const REACT_NATIVE_SUBMODULE_DIR = Directories.getReactNativeSubmoduleDir();
export const REACT_NATIVE_SUBMODULE_MONOREPO_ROOT = Directories.getReactNativeSubmoduleDir();
export const REACT_NATIVE_SUBMODULE_DIR = path.join(
REACT_NATIVE_SUBMODULE_MONOREPO_ROOT,
'packages',
'react-native'
);

// Vendored dirs
export const ANDROID_VENDORED_DIR = path.join(ANDROID_DIR, 'vendored');
Expand Down
12 changes: 12 additions & 0 deletions tools/src/Packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,18 @@ export class Package {
return match?.[1] ?? null;
}

get androidPackageNamespace(): string | null {
if (!this.isSupportedOnPlatform('android')) {
return null;
}
const buildGradle = fs.readFileSync(
path.join(this.path, this.androidSubdirectory, 'build.gradle'),
'utf8'
);
const match = buildGradle.match(/^\s+namespace\s*=?\s*['"]([\w.]+)['"]/m);
return match?.[1] ?? null;
}

get changelogPath(): string {
return path.join(this.path, 'CHANGELOG.md');
}
Expand Down
2 changes: 1 addition & 1 deletion tools/src/vendoring/config/expoGoConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const config: VendoringTargetConfig = {
async preReadPodspecHookAsync(podspecPath: string): Promise<string> {
const reaUtilsPath = path.join(podspecPath, '..', 'scripts', 'reanimated_utils.rb');
assert(fs.existsSync(reaUtilsPath), 'Cannot find `reanimated_utils`.');
const rnForkPath = path.join(REACT_NATIVE_SUBMODULE_DIR, 'packages');
const rnForkPath = path.join(REACT_NATIVE_SUBMODULE_DIR, '..');
let content = await fs.readFile(reaUtilsPath, 'utf-8');
content = content.replace(
'react_native_node_modules_dir = ',
Expand Down
12 changes: 6 additions & 6 deletions tools/src/versioning/android/android-build-aar.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,21 @@ fi

pushd $EXPO_ROOT_DIR/android

export REACT_NATIVE_OVERRIDE_HERMES_DIR="$EXPO_ROOT_DIR/android/versioned-react-native/sdks/hermes"
export REACT_NATIVE_OVERRIDE_HERMES_DIR="$EXPO_ROOT_DIR/android/versioned-react-native/packages/react-native/sdks/hermes"

# Clean aar
rm -rf expoview/libs/ReactAndroid-temp

# Build aar
pushd versioned-react-native
set -e
./gradlew :ReactAndroid:assembleRelease
./gradlew :ReactAndroid:hermes-engine:assembleRelease
./gradlew :packages:react-native:ReactAndroid:assembleRelease
./gradlew :packages:react-native:ReactAndroid:hermes-engine:assembleRelease
popd

mkdir -p expoview/libs
# Grab the aar and unzip it
cp versioned-react-native/ReactAndroid/build/outputs/aar/ReactAndroid-release.aar expoview/libs/ReactAndroid-temp.aar
cp versioned-react-native/packages/react-native/ReactAndroid/build/outputs/aar/ReactAndroid-release.aar expoview/libs/ReactAndroid-temp.aar
rm -rf expoview/libs/ReactAndroid-temp
unzip expoview/libs/ReactAndroid-temp.aar -d expoview/libs/ReactAndroid-temp

Expand Down Expand Up @@ -60,7 +60,7 @@ do
done < $TOOLS_DIR/android-packages-to-rename.txt

# Rename packages in jars
java -jar $TOOLS_DIR/jarjar-1.4.1.jar process jarjar-rules.txt expoview/libs/ReactAndroid-temp/classes.jar expoview/libs/ReactAndroid-temp/classes.jar
java -jar $TOOLS_DIR/jarjar-e11d5636.jar process jarjar-rules.txt expoview/libs/ReactAndroid-temp/classes.jar expoview/libs/ReactAndroid-temp/classes.jar

# fix annotations
unzip expoview/libs/ReactAndroid-temp/annotations.zip -d expoview/libs/ReactAndroid-temp/annotations
Expand Down Expand Up @@ -88,7 +88,7 @@ do
echo "rule temporarydontversion.$PACKAGE.** $PACKAGE.@1" >> jarjar-rules.txt
done < $TOOLS_DIR/android-packages-to-keep.txt

java -jar $TOOLS_DIR/jarjar-1.4.1.jar process jarjar-rules.txt expoview/libs/ReactAndroid-temp/classes.jar expoview/libs/ReactAndroid-temp/classes.jar
java -jar $TOOLS_DIR/jarjar-e11d5636.jar process jarjar-rules.txt expoview/libs/ReactAndroid-temp/classes.jar expoview/libs/ReactAndroid-temp/classes.jar


pushd expoview/libs/ReactAndroid-temp
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf

# These are Windows script files and should use crlf
*.bat text eol=crlf

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle

# Ignore Gradle build output directory
build
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
plugins {
application
}

repositories {
google()
mavenCentral()
}

dependencies {
implementation("com.android.tools.build:manifest-merger:31.0.2")
}

application {
mainClass.set("com.android.manifmerger.Merger")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 71ea603

Please sign in to comment.