Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ react {
/**
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
*/
def enableProguardInReleaseBuilds = false
def enableProguardInReleaseBuilds = true

/**
* The preferred build flavor of JavaScriptCore (JSC)
Expand Down Expand Up @@ -111,27 +111,50 @@ android {
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
shrinkResources enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}

sourceSets {
main { assets.srcDirs = ['src/main/assets', '../../html'] }
}

packaging {
jniLibs {
useLegacyPackaging = false
}
}
}

dependencies {
// If your app supports Android versions before Ice Cream Sandwich (API level 14)
implementation 'com.facebook.fresco:animated-base-support:1.3.0'
/**
* Strip DevModeWeb.bundle from release builds to reduce install size.
* DevModeWeb.bundle is only used when Dev Mode is enabled in the app settings.
* The WebRunnerHandler already selects 'Web.bundle' for non-dev builds.
*/
android.applicationVariants.all { variant ->
if (variant.buildType.name == 'release') {
variant.mergeAssetsProvider.configure {
doLast {
def devModeBundle = new File(outputDir.get().asFile, 'DevModeWeb.bundle')
if (devModeBundle.exists()) {
delete(devModeBundle)
println "[SubWallet] Stripped DevModeWeb.bundle from release assets"
}
}
}
}
}

dependencies {
implementation "androidx.biometric:biometric:1.1.0"

// For animated GIF support
implementation 'com.facebook.fresco:animated-gif:2.5.0'
implementation 'com.facebook.fresco:animated-gif:3.6.0'

// For WebP support, including animated WebP
implementation 'com.facebook.fresco:animated-webp:2.5.0'
implementation 'com.facebook.fresco:webpsupport:2.5.0'
implementation 'com.facebook.fresco:animated-webp:3.6.0'
implementation 'com.facebook.fresco:webpsupport:3.6.0'

// Fix duplicate Kotlin JDK 7 & JDK 8
implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
Expand Down
104 changes: 94 additions & 10 deletions android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,10 +1,94 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:
# ProGuard rules for SubWallet Mobile (React Native)
# ============================================================

# ---------------------------------------------------------------------------
# React Native core
# ---------------------------------------------------------------------------
-keep class com.facebook.react.** { *; }
-keep class com.facebook.hermes.** { *; }
-keep class com.facebook.jni.** { *; }

# Keep ReactMethod-annotated methods (native modules)
-keep @com.facebook.react.bridge.ReactModule class * { *; }
-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
-keep class * extends com.facebook.react.bridge.NativeModule { *; }
-keepclassmembers class * extends com.facebook.react.bridge.NativeModule {
@com.facebook.react.bridge.ReactMethod <methods>;
@com.facebook.react.bridge.ReactSyncHook <methods>;
}

# Keep ReactPackage implementations
-keep class * implements com.facebook.react.ReactPackage { *; }

# ---------------------------------------------------------------------------
# Hermes JS engine
# ---------------------------------------------------------------------------
-keep class com.facebook.hermes.unicode.** { *; }
-keep class com.facebook.hermes.intl.** { *; }

# ---------------------------------------------------------------------------
# Kotlin
# ---------------------------------------------------------------------------
-keep class kotlin.Metadata { *; }
-dontwarn kotlin.**
-dontwarn kotlinx.**

# ---------------------------------------------------------------------------
# AndroidX
# ---------------------------------------------------------------------------
-keep class androidx.biometric.** { *; }
-dontwarn androidx.**

# ---------------------------------------------------------------------------
# Fresco (animated GIF / WebP support)
# ---------------------------------------------------------------------------
-keep class com.facebook.imagepipeline.** { *; }
-keep class com.facebook.fresco.** { *; }
-keep class com.facebook.drawee.** { *; }
-keep class com.facebook.datasource.** { *; }
-dontwarn com.facebook.fresco.**

# ---------------------------------------------------------------------------
# JavaScript Interface (WebView bridge)
# ---------------------------------------------------------------------------
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}

# ---------------------------------------------------------------------------
# Enums (prevent stripping)
# ---------------------------------------------------------------------------
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}

# ---------------------------------------------------------------------------
# Serializable / Parcelable
# ---------------------------------------------------------------------------
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

# ---------------------------------------------------------------------------
# Suppress warnings for known missing optional deps
# ---------------------------------------------------------------------------
-dontwarn com.google.android.gms.**
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
-dontwarn org.conscrypt.**

# ---------------------------------------------------------------------------
# Crash reporting: keep source file names & line numbers
# ---------------------------------------------------------------------------
-keepattributes SourceFile,LineNumberTable
-renamesourcefileattribute SourceFile
4 changes: 2 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@
<application
android:name=".MainApplication"
android:label="@string/app_name"
android:largeHeap="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
android:enableOnBackInvokedCallback="false"
android:extractNativeLibs="false"
android:supportsRtl="true">
<activity
android:name=".MainActivity"
android:theme="@style/BootTheme"
android:label="@string/app_name"
android:extractNativeLibs="true"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize"
android:exported="true">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app.subwallet.mobile

import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import com.zoontek.rnbootsplash.RNBootSplash
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
Expand All @@ -10,6 +11,7 @@ import com.swmansion.rnscreens.fragment.restoration.RNScreensFragmentFactory

class MainActivity : ReactActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
supportFragmentManager.fragmentFactory = RNScreensFragmentFactory()
setTheme(R.style.AppTheme)
RNBootSplash.init(this, R.style.BootTheme)
Expand Down
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ buildscript {
minSdkVersion = 24
compileSdkVersion = 36
targetSdkVersion = 36
ndkVersion = "27.1.12297006"
ndkVersion = "29.0.14206865"
kotlinVersion = "2.1.20"
}
subprojects { subproject ->
Expand Down
113 changes: 113 additions & 0 deletions android/check_elf_alignment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/bin/bash
progname="${0##*/}"
progname="${progname%.sh}"

# usage: check_elf_alignment.sh [path to *.so files|path to *.apk]

cleanup_trap() {
if [ -n "${tmp}" -a -d "${tmp}" ]; then
rm -rf ${tmp}
fi
exit $1
}

usage() {
echo "Host side script to check the ELF alignment of shared libraries."
echo "Shared libraries are reported ALIGNED when their ELF regions are"
echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED."
echo
echo "Usage: ${progname} [input-path|input-APK|input-APEX]"
}

if [ ${#} -ne 1 ]; then
usage
exit
fi

case ${1} in
--help | -h | -\?)
usage
exit
;;

*)
dir="${1}"
;;
esac

if ! [ -f "${dir}" -o -d "${dir}" ]; then
echo "Invalid file: ${dir}" >&2
exit 1
fi

if [[ "${dir}" == *.apk ]]; then
trap 'cleanup_trap' EXIT

echo
echo "Recursively analyzing $dir"
echo

if { zipalign --help 2>&1 | grep -q "\-P <pagesize_kb>"; }; then
echo "=== APK zip-alignment ==="
zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification'
echo "========================="
else
echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher."
echo " You can install the latest build-tools by running the below command"
echo " and updating your \$PATH:"
echo
echo " sdkmanager \"build-tools;35.0.0-rc3\""
fi

dir_filename=$(basename "${dir}")
tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX")
unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1
dir="${tmp}"
fi

if [[ "${dir}" == *.apex ]]; then
trap 'cleanup_trap' EXIT

echo
echo "Recursively analyzing $dir"
echo

dir_filename=$(basename "${dir}")
tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX")
deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; }
dir="${tmp}"
fi

RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"

unaligned_libs=()

echo
echo "=== ELF alignment ==="

matches="$(find "${dir}" -type f)"
IFS=$'\n'
for match in $matches; do
# We could recursively call this script or rewrite it to though.
[[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}"
[[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}"

[[ $(file "${match}") == *"ELF"* ]] || continue

res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)"
if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then
echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)"
else
echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)"
unaligned_libs+=("${match}")
fi
done

if [ ${#unaligned_libs[@]} -gt 0 ]; then
echo -e "${RED}Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}"
elif [ -n "${dir_filename}" ]; then
echo -e "ELF Verification Successful"
fi
echo "====================="
15 changes: 14 additions & 1 deletion html/DevModeWeb.bundle/site/index.html
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>SubWallet</title><script inline inline-asset="fallback.js$" inline-asset-delete></script><script inline inline-asset="web-runner.js$" inline-asset-delete></script><script defer="defer" src="fallback-a4bb9c5dd9b5093ca29f.js"></script><script defer="defer" src="web-runner-83b9a4421c622678f2fa.js"></script></head><body><div id="root">SubWallet</div></body></html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>SubWallet</title>
<script inline inline-asset="fallback.js$" inline-asset-delete></script>
<script inline inline-asset="web-runner.js$" inline-asset-delete></script>
<script defer="defer" src="fallback-a4bb9c5dd9b5093ca29f.js"></script>
<script defer="defer" src="web-runner-5713fe34bb32affbb1a1.js"></script>
</head>
<body>
<div id="root">SubWallet</div>
</body>
</html>

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion html/Web.bundle/site/index.html
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>SubWallet</title><script inline inline-asset="fallback.js$" inline-asset-delete></script><script inline inline-asset="web-runner.js$" inline-asset-delete></script><script defer="defer" src="fallback-a4bb9c5dd9b5093ca29f.js"></script><script defer="defer" src="web-runner-9a36ff79350ca65502dc.js"></script></head><body><div id="root">SubWallet</div></body></html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>SubWallet</title>
<script inline inline-asset="fallback.js$" inline-asset-delete></script>
<script inline inline-asset="web-runner.js$" inline-asset-delete></script>
<script defer="defer" src="fallback-a4bb9c5dd9b5093ca29f.js"></script>
<script defer="defer" src="web-runner-a745d18765d663ba95d0.js"></script>
</head>
<body>
<div id="root">SubWallet</div>
</body>
</html>

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3651,7 +3651,6 @@ DEPENDENCIES:
- "RNFastImage (from `../node_modules/@d11/react-native-fast-image`)"
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNInAppBrowser (from `../node_modules/react-native-inappbrowser-reborn`)
- RNKeychain (from `../node_modules/react-native-keychain`)
- RNLocalize (from `../node_modules/react-native-localize`)
- RNPermissions (from `../node_modules/react-native-permissions`)
- RNQrGenerator (from `../node_modules/rn-qr-generator`)
Expand Down Expand Up @@ -3889,8 +3888,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-gesture-handler"
RNInAppBrowser:
:path: "../node_modules/react-native-inappbrowser-reborn"
RNKeychain:
:path: "../node_modules/react-native-keychain"
RNLocalize:
:path: "../node_modules/react-native-localize"
RNPermissions:
Expand Down
Loading