I have an app built with react native and I need to enable MultiDex
support. My problem is that I can't import the MultiDexApplication
class to extend it because at compile time I get symbol not found error
for both the import statement and the class name when extending it in MainApplication.java
build.gradle
dependencies {
classpath('com.android.tools.build:gradle:3.5.3')
classpath 'com.google.gms:google-services:4.2.0'
classpath "androidx.multidex:multidex:2.0.1"
}
If I try to add the dependency as implementation, I get the following error when starting the app:
Could not find method implementation() for arguments [androidx.multidex:multidex:2.0.1] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
In all online resources I saw that the dependecy was added as implementation so I guess that can be my problem.
MainApplication.java
package com.classmanager;
import android.app.Application;
import androidx.multidex.MultiDexApplication;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.oblador.vectoricons.VectorIconsPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class MainApplication extends MultiDexApplication implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this); // Remove this line if you don't want Flipper enabled
}
//@Override
//protected void attachBaseContext(Context base) {
//super.attachBaseContext(base);
//MultiDex.install(this);
//}
/**
* Loads Flipper in React Native templates.
*
* @param context
*/
private static void initializeFlipper(Context context) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper");
aClass.getMethod("initializeFlipper", Context.class).invoke(null, context);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
It's the default MainApplication from react-native init
, except that I imported the MultiDexApplication
class and extended it instead of Application
. But when I run the app, I get the following error:
import androidx.multidex.MultiDexApplication;
^
symbol: class MultiDexApplication
location: package androidx.multidex
C:\Users\meadi\WebstormProjects\ClassManager\android\app\src\main\java\com\classmanager\MainApplication.java:16: error: cannot find symbol
public class MainApplication extends MultiDexApplication implements ReactApplication {
^
symbol: class MultiDexApplication
C:\Users\meadi\WebstormProjects\ClassManager\android\app\src\main\java\com\classmanager\MainApplication.java:18: error: incompatible types: MainApplication cannot be converted to Application
new ReactNativeHost(this) {
^
Any idea why MultiDexApplication couldn't be resolved?
update: I tried adding the multidex dependecy as implementation to the app level build.gradle
. It seems now that the class is resolved, but i get this error:
D8: Cannot fit requested classes in a single dex file (# methods: 100718 > 65536)
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives:
The number of method references in a .dex file cannot exceed 64K.
So MultiDex is still not enabled
Update: Here is the project level build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
buildToolsVersion = "28.0.3"
minSdkVersion = 16
compileSdkVersion = 28
targetSdkVersion = 28
multiDexEnabled = true
}
repositories {
google()
jcenter()
}
dependencies {
classpath('com.android.tools.build:gradle:3.5.3')
classpath 'com.google.gms:google-services:4.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
google()
jcenter()
maven { url 'https://jitpack.io' }
}
}
And here is the app level build.gradle
apply plugin: "com.android.application"
import com.android.build.OutputFile
project.ext.react = [
entryFile : "index.js",
enableHermes: false, // clean and rebuild if changing
]
apply from: "../../node_modules/react-native/react.gradle"
/**
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
/**
* The preferred build flavor of JavaScriptCore.
*
* For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
* give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
/**
* Whether to enable the Hermes VM.
*
* This should be set on project.ext.react and mirrored here. If it is not set
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
* and the benefits of using Hermes will therefore be sharply reduced.
*/
def enableHermes = project.ext.react.get("enableHermes", false);
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.classmanager"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
dependencies {
implementation project (':react-native-vector-icons')
implementation 'com.google.firebase:firebase-analytics:17.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.multidex:multidex:2.0.1'
implementation "com.facebook.react:react-native:+" // From node_modules
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply plugin: 'com.google.gms.google-services'
classpath "androidx.multidex:multidex:2.0.1". It should beimplementation 'androidx.multidex:multidex:2.0.1'
.
build.gradle (Module)
-> This defines the module-specific build configurations.
build.gradle (Project)
-> This defines your build configuration that apply to all modules. This file is integral to the project, so you should maintain them in revision control with all other source code.
You should add below Module Level build.gradle
(android/app/build.gradle)
section.
dependencies {
implementation 'androidx.multidex:multidex:2.0.1'
}
FYI
Please remove multiDexEnabled = true
from project level build.gradle
section
Modify the module-level build.gradle file to enable multidex and add the multidex library as a dependency, as shown here:
android {
defaultConfig {
applicationId "com.classmanager"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
multiDexEnabled true
}
}