Shreevatsa Acharya
Shreevatsa Acharya

Reputation: 133

React Native v0.59.2 android signed apk stuck at splash screen

I recently upgraded react native to 0.59.2 from 0.55.4. I was using react native navigation by wix v1.1.486. As some functions from the library were throwing errors I decided to move to v2. I am able to run the app on ios flawlessly and android in debug mode.

But when I tried to generate a signed apk I was facing the "Unable to load script from assets 'index.android.bundle" issue and was able to fix it (reference)

Now I am stuck at the splash screen. The app does not move further.

verified it works in debug mode. tried using empty Main Activity so no issues from there. The project uses redux and I see the initial redux logs in the android studio. Tried running on both emulator and device. Also react-native run-android --variant=release works.

android/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 = 21
        compileSdkVersion = 21
        targetSdkVersion = 27
        supportLibVersion = "28.0.0"
        googlePlayServicesVersion = "15.0.1"
        androidMapsUtilsVersion = "0.5+"
    }
    repositories {
        jcenter()
        mavenLocal()
        mavenCentral()
        google()
    }
    dependencies {
         classpath 'com.android.tools.build:gradle:3.3.2'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        mavenLocal()
        jcenter()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        maven { url "https://jitpack.io" }
    }
}

subprojects {
        afterEvaluate {project ->
                if (project.hasProperty("android")) {
                        android {
                                compileSdkVersion 28
                                buildToolsVersion '28.0.3'
                            }
                    }
            }
    }

    subprojects { subproject ->
    afterEvaluate {
        if ((subproject.plugins.hasPlugin('android') || subproject.plugins.hasPlugin('android-library'))) {
            android {
                variantFilter { variant ->
                    def names = variant.flavors*.name
                    if (names.contains("reactNative51") || names.contains("reactNative55")|| names.contains("reactNative56")|| names.contains("reactNative57")) {
                        setIgnore(true)
                    }
                }
            }
        }
    }
}

app/build.gradle

apply plugin: "com.android.application"

import com.android.build.OutputFile

project.ext.react = [
        entryFile: "index.js",
        bundleAssetName: "index.android.bundle",
        bundleInDebug: false,
        bundleInStaging: true,
        bundleInRelease: true,
        jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
        resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
        jsBundleDirStaging: "$buildDir/intermediates/assets/staging",
        resourcesDirStaging:
                "$buildDir/intermediates/res/merged/staging",
        jsBundleDirRelease: "$buildDir/intermediates/assets/release",
        resourcesDirRelease:
                "$buildDir/intermediates/res/merged/release",
        devDisabledInDebug: false,
        devDisabledInStaging: true,
        devDisabledInRelease: true,
        inputExcludes: ["ios/**", "__tests__/**", "bundle_out/**"]
];

apply from: "../../node_modules/react-native/react.gradle"

project.ext.vectoricons = [
        iconFontNames: [ 'MaterialIcons.ttf', 'EvilIcons.ttf' ] // Name of the font files you want to copy
]

apply from: "../../node_modules/react-native-vector-icons/fonts.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

buildscript {
    repositories {
        maven { url 'https://maven.fabric.io/public' }
    }

    dependencies {
        classpath 'io.fabric.tools:gradle:1.+'
    }
}

apply plugin: 'io.fabric'

repositories {
    maven { url 'https://maven.fabric.io/public' }
}


android {
    compileSdkVersion rootProject.ext.compileSdkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    defaultConfig {
        applicationId "com.example"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode 76
        versionName "1.0.76"
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
        multiDexEnabled true
    }

    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                storeFile file(MYAPP_RELEASE_STORE_FILE)
                storePassword MYAPP_RELEASE_STORE_PASSWORD
                keyAlias MYAPP_RELEASE_KEY_ALIAS
                keyPassword MYAPP_RELEASE_KEY_PASSWORD
            }
        }
    }

    splits {
        abi {
            reset()
            enable enableSeparateBuildPerCPUArchitecture
            universalApk false  // If true, also generate a universal APK
            include "armeabi-v7a", "x86"
        }
    }
    buildTypes {
        release {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            signingConfig signingConfigs.release

        }
    }
    // 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:
            // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
            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
            }
        }
    }
}

configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details ->
        def requested = details.requested
        if (requested.group == 'com.android.support' && requested.name != 'multidex') {
            details.useVersion "${rootProject.ext.supportLibVersion}"
        }
    }
}

dependencies {
    implementation project(':react-native-vector-icons')
    implementation project(':react-native-navigation')
    implementation "com.android.support:design:28.0.0"
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    implementation "com.facebook.react:react-native:+"  // From node_modules
}

// 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'
}

MainActivity.java

package com.example;

import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;

import android.view.Window;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.crashlytics.android.Crashlytics;
import com.facebook.common.logging.FLog;

import io.fabric.sdk.android.Fabric;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import com.reactnativenavigation.NavigationActivity;


public class MainActivity extends NavigationActivity {
   private String VersionName;
   private String VersionCode;

   @Override
   public void addDefaultSplashLayout() {

       Fabric.with(this, new Crashlytics());
       FLog.setLoggingDelegate(ReactNativeFabricLogger.getInstance());

       Context context = getApplicationContext();
       try
       {
           VersionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;

           /*I find usefull to convert vervion code into String, so it's ready for TextViev/server side checks*/

           VersionCode = Integer.toString(context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode);
       } catch (PackageManager.NameNotFoundException e)
       {
           e.printStackTrace();
       }

       ImageView imageView = new ImageView(this);
       TextView textView = new TextView(this);

       RelativeLayout rl = new RelativeLayout(getApplicationContext());
       // Create LayoutParams for RelativeLayout
       LayoutParams lp = new RelativeLayout.LayoutParams(
               LayoutParams.MATCH_PARENT,
               LayoutParams.MATCH_PARENT
       );

       // Set RelativeLayout LayoutParams
       rl.setLayoutParams(lp);
       // Set a background color for RelativeLayout
       rl.setBackgroundColor(Color.parseColor("#ecf0f1"));

       // Create a LayoutParams for TextView widget
       LayoutParams lp_tv = new RelativeLayout.LayoutParams(
               LayoutParams.WRAP_CONTENT,
               LayoutParams.WRAP_CONTENT
       );

       lp_tv.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
       lp_tv.addRule(RelativeLayout.CENTER_HORIZONTAL);
       textView.setLayoutParams(lp_tv);

       LayoutParams lp_iv = new RelativeLayout.LayoutParams(
               LayoutParams.WRAP_CONTENT,
               LayoutParams.WRAP_CONTENT
       );
       lp_iv.addRule(RelativeLayout.CENTER_IN_PARENT);
       imageView.setLayoutParams(lp_iv);

       imageView.setImageResource(R.drawable.logo);
       textView.setText("V " + VersionName);
       textView.setPadding(0,0,0,8);

       rl.addView(imageView);
       rl.addView(textView);

       // inside your activity (if you did not enable transitions in your theme)
       getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

       setContentView(rl);

   }


}

MainApplication.java

package com.example;

import com.facebook.react.ReactApplication;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;

import com.reactnativenavigation.NavigationApplication;
import com.reactnativenavigation.react.NavigationReactNativeHost;
import com.reactnativenavigation.react.ReactGateway;

import java.util.Arrays;
import java.util.List;

import com.oblador.vectoricons.VectorIconsPackage;


public class MainApplication extends NavigationApplication {

    @Override
    protected ReactGateway createReactGateway() {
        ReactNativeHost host = new NavigationReactNativeHost(this, isDebug(), createAdditionalReactPackages()) {
            @Override
            protected String getJSMainModuleName() {
                return "index";
            }
        };
        return new ReactGateway(this, isDebug(), host);
    }

    @Override
    public boolean isDebug() {
        // Make sure you are using BuildConfig from your own application
       return BuildConfig.DEBUG;
        // return  true;
    }


    protected List<ReactPackage> getPackages() {
        // Add additional packages you require here
        // No need to add RnnPackage and MainReactPackage
        return Arrays.<ReactPackage>asList(
                new VectorIconsPackage(),
        );
    }

    @Override
    public List<ReactPackage> createAdditionalReactPackages() {
        return getPackages();
    }

}

Generated signed apk from ./gradlew assembleRelease gets stuck on launchscreen/splashscreen.

Upvotes: 3

Views: 1750

Answers (1)

Alon Bar David
Alon Bar David

Reputation: 1727

if your app is stuck at the splash screen, there is probably some error that is hidden, usually in the js bundle. Use adb logcat *:E to see android's error log and you'll probably get a better handle on what went wrong

Upvotes: 1

Related Questions