React-native-push-notification: Crash on Android - FATAL EXCEPTION: main ... java.lang.ClassCastException: com.mybundle.MainApplication cannot be cast to com.facebook.react.ReactApplication

Created on 15 May 2017  路  20Comments  路  Source: zo0r/react-native-push-notification

The library works fine on iOS but it crashed on Android.

V/RNPushNotification: onMessageReceived: Bundle[{scheme=app.scheme, badge=1, notification=Bundle[{body=this is a push notification message., title=Push Notification Title}], collapse_key=com.mybundle}]

05-15 12:45:46.667 31469-31469/com.mybundle E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mybundle, PID: 31469
java.lang.ClassCastException: com.mybundle.MainApplication cannot be cast to com.facebook.react.ReactApplication
at com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService$1.run(RNPushNotificationListenerService.java:59)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5437)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)

Most helpful comment

I am using Expo detached and trying to implement the react-native-push-notification in both android and ios. I got the same issue on android which crashing my app once received remote notification from firebase with error:
java.lang.ClassCastException: com.myapp.MainApplication cannot be cast to com.facebook.react.ReactApplication
I am not an expert in Java, but I got it working by modifying the android java code in MainApplication, here is my code:

package host.exp.exponent;


import com.facebook.react.ReactPackage;

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

import expolib_v1.okhttp3.OkHttpClient;

// Needed for `react-native link`
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactApplication;
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
import com.dooboolab.RNIap.RNIapPackage;

public class MainApplication extends ExpoApplication implements ReactApplication{

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }


  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new ReactNativePushNotificationPackage(),
            new RNIapPackage()
    );
  }
  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
              new ReactNativePushNotificationPackage(),
              new RNIapPackage()
      );
    }
  };
  @Override
  public boolean isDebug() {
    return BuildConfig.DEBUG;
  }


  @Override
  public String gcmSenderId() {
    return getString(R.string.gcm_defaultSenderId);
  }

  @Override
  public boolean shouldUseInternetKernel() {
    return BuildVariantConstants.USE_INTERNET_KERNEL;
  }

  public static OkHttpClient.Builder okHttpClientBuilder(OkHttpClient.Builder builder) {
    // Customize/override OkHttp client here
    return builder;
  }
}

Now i can receive remote notification from firebase.

All 20 comments

I am having the same issue, i am not a very experienced android developer. Any help is appreciated.

You class com.mybundle.MainApplication isn't of the right type. Not sure how that's possible. Can you pass the code here?

I am using https://expo.io/ and Detaching to ExpoKit since I would need to use some native libraries for iOS and Android. It crashed at this line

ReactInstanceManager mReactInstanceManager = ((ReactApplication) getApplication()).getReactNativeHost().getReactInstanceManager();

in RNPushNotificationListenerService.java

Another issue that might be related: https://github.com/zo0r/react-native-push-notification/issues/260 mentioned the getReactInstanceManager()

I have been trying to fix the issue myself for at least 3 days (with trials and errors) before I posted the issue. I am not Android developer.

Hope that someone would be able to lead me to the right direction to fix the crash. Thanks.

This is my MainApplication.Java and it could be related to the crash that we faced.

package com.mybundle;

import android.support.multidex.MultiDexApplication;

import com.facebook.react.ReactPackage;
import com.react.rnspinkit.RNSpinkitPackage;
import com.horcrux.svg.RNSvgPackage;
import com.imagepicker.ImagePickerPackage;
import com.oblador.keychain.KeychainPackage;
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
import io.branch.rnbranch.*;
import io.branch.referral.Branch;
import com.kevinejohn.RNMixpanel.*;
import com.aakashns.reactnativedialogs.ReactNativeDialogsPackage;

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

// Needed for `react-native link`
// import com.facebook.react.ReactApplication;

public class MainApplication extends MultiDexApplication {

  // Needed for `react-native link`
  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        // Add your own packages here!
        // TODO: add cool native modules

        // Needed for `react-native link`
        // new MainReactPackage()
        new RNBranchPackage(),
        new RNSpinkitPackage(),
        new RNSvgPackage(),
        new ImagePickerPackage(),
        new KeychainPackage(),
        new ReactNativePushNotificationPackage(),
        new RNMixpanel(),
        new ReactNativeDialogsPackage()
    );
  }

  @Override
  public void onCreate() {
      super.onCreate();
      // initialize the Branch object
      Branch.getAutoInstance(this);
  }

}

This is the Project build.gradle.

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.2.3'
  }
}

allprojects {
  repositories {
    mavenLocal()
    jcenter()
    mavenCentral()
    maven {
      url "https://jitpack.io"
    }
    maven {
      url "$rootDir/../.expo-source/android/maven"
    }
  }
}

task clean(type: Delete) {
  delete rootProject.buildDir
}

This is the App build.gradle.

apply plugin: 'com.android.application'

android {

  compileSdkVersion 24
  buildToolsVersion '23.0.1'

  defaultConfig {
    applicationId "com.mybundle"
    minSdkVersion 19
    targetSdkVersion 24
    versionCode 1
    versionName "1.0"
    multiDexEnabled true
    ndk {
      abiFilters 'armeabi-v7a', 'x86'
    }
    manifestPlaceholders = [
      'appAuthRedirectScheme': 'com.mybundle'
    ]
  }
  buildTypes {
    debug {
        debuggable true
    }
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }

  dexOptions {
    javaMaxHeapSize "8g"
  }
}

task exponentPrebuildStep(type: Exec) {
  workingDir '../../'

  if (System.getProperty('os.name').toLowerCase().contains('windows')) {
    commandLine 'cmd', '/c', '.\\.expo-source\\android\\detach-scripts\\prepare-detached-build.bat'
  } else {
    commandLine './.expo-source/android/detach-scripts/prepare-detached-build.sh'
  }
}
preBuild.dependsOn exponentPrebuildStep

repositories{
  flatDir{
    dirs 'libs'
  }
  mavenLocal()
  maven { url 'https://maven.fabric.io/public' }
}

dependencies {
  compile (project(':react-native-svg')){ exclude module: 'react-native' }
  compile (project(':react-native-spinkit')){ exclude module: 'react-native' }
  compile (project(':react-native-image-picker')){ exclude module: 'react-native' }
  compile (project(':react-native-branch')){ exclude module: 'react-native' }
  compile (project(':react-native-keychain')){ exclude module: 'react-native' }
  compile (project(':react-native-push-notification')){ exclude module: 'react-native' }
  compile (project(':RNMixpanel')){ exclude module: 'react-native' }
  compile (project(':react-native-dialogs')){ exclude module: 'react-native' }

  compile ('com.google.android.gms:play-services-gcm:9.8.0') {
    force = true;
  }
  compile ("com.google.android.gms:play-services-base:9.8.0") {
    force = true;
  }
  compile ("com.google.android.gms:play-services-basement:9.8.0") {
    force = true;
  }
  compile ("com.google.android.gms:play-services-iid:9.8.0") {
    force = true;
  }
  compile ("com.google.android.gms:play-services-tasks:9.8.0") {
    force = true;
  }
  compile ("com.google.android.gms:play-services-auth:9.8.0") {
    force = true;
  }
  compile ("com.google.android.gms:play-services-maps:9.8.0") {
    force = true;
  }
  compile ("com.google.android.gms:play-services-analytics:9.8.0") {
    force = true;
  }
  compile ("com.google.android.gms:play-services-location:9.8.0") {
    force = true;
  }
  compile ("com.google.android.gms:play-services-ads:9.8.0") {
    force = true;
  }

  compile 'com.airbnb.android:lottie:2.0.0-beta4'

  compile fileTree(dir: 'libs', include: ['*.jar'])
  testCompile 'junit:junit:4.12'
  compile 'com.android.support:appcompat-v7:24.1.1'
  compile 'com.android.support:multidex:1.0.0'

  compile('host.exp.exponent:expoview:16.0.0@aar') {
    exclude group: 'com.facebook.android', module: 'facebook-android-sdk'
    exclude group: 'com.facebook.android', module: 'audience-network-sdk'
    exclude group: 'io.nlopez.smartlocation', module: 'library'
    transitive = true;
  }

  compile ('com.facebook.android:facebook-android-sdk:4.7.0') {
    exclude module: 'bolts-android'
  }
  compile('com.facebook.android:audience-network-sdk:4.19.0') {
    exclude module: 'play-services-ads'
  }
  compile('io.nlopez.smartlocation:library:3.2.11') {
    transitive = false
  }
}

You MainApplication is not correct. If you create a new react native project (with react-native init AwesomeProject) you'll see what it should look like. Basically you need to implement ReactApplication, the getPackages method need to be moved inside an anonymous inner ReactNativeHost:

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() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage(),
                    ... you dependencies go here
            );
        }
    };

Here is mine, it is already using ReactApplication, it still giving me the same issue

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    protected boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new RNSpinkitPackage(),
           new MainReactPackage(),
            new RNSharePackage(),
            new RNViewShotPackage(),
            new RNGeocoderPackage(),
            new LinearGradientPackage(),
            new ImagePickerPackage(),
            new PickerPackage(),
            new ReactNativePushNotificationPackage(),
            new RNDeviceInfo(),
            new ReactVideoPackage(),
            new VectorIconsPackage(),
            new RNSpinkitPackage(),
            new ReactNativeI18n(),
            new GoogleAnalyticsBridgePackage(),
            new RCTCameraPackage()
      );
    }
  };

  @Override
  public ReactNativeHost getReactNativeHost() {
      return mReactNativeHost;
  }
}

I honestly don't know if my implementation is correct or otherwise. I have tried the implementation like

public class MainApplication extends MultiDexApplication implements ReactApplication

with

new MainReactPackage(),

the android app couldn't even run.

At least with the implementation that I showed above, it could run. I can login using the app and do other stuff with the app. I could even receive the push notification via onMessageReceived but it crashed afterwards.

The above implementation I used is following:
https://github.com/expo/expo/blob/master/exponent-view-template/android/app/src/main/java/detach/app/template/pkg/name/MainApplication.java

for the detached expo app.

@r1cebank Are you using expo as well?

@r1cebank you cannot be getting the same error as @voyage11 - maybe submit a new issue with your won stack trace

@voyage11 I am not using expo, i used react-native init @npomfret i am currently check to see if the crashing is caused by other causes, if i find anything i will create a new issue. Thanks

I just posted an issue on the expo repository. Hope that someone knows something about this crash.

@voyage11 my crash is caused by something else. thanks for the help

For anyone who has the similar crash. Check out version 2.1.1 instead of the latest version. V 2.1.1 will not crash your app.

Personally, I forked the repo, checked out the commit related to V 2.1.1, created a branch and made a small change for my own project, you may see here: https://github.com/voyage11/react-native-push-notification/tree/fixAndroidCrash

I am using Expo detached and trying to implement the react-native-push-notification in both android and ios. I got the same issue on android which crashing my app once received remote notification from firebase with error:
java.lang.ClassCastException: com.myapp.MainApplication cannot be cast to com.facebook.react.ReactApplication
I am not an expert in Java, but I got it working by modifying the android java code in MainApplication, here is my code:

package host.exp.exponent;


import com.facebook.react.ReactPackage;

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

import expolib_v1.okhttp3.OkHttpClient;

// Needed for `react-native link`
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactApplication;
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
import com.dooboolab.RNIap.RNIapPackage;

public class MainApplication extends ExpoApplication implements ReactApplication{

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }


  public List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new ReactNativePushNotificationPackage(),
            new RNIapPackage()
    );
  }
  private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

    @Override
    public boolean getUseDeveloperSupport() {
      return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
              new ReactNativePushNotificationPackage(),
              new RNIapPackage()
      );
    }
  };
  @Override
  public boolean isDebug() {
    return BuildConfig.DEBUG;
  }


  @Override
  public String gcmSenderId() {
    return getString(R.string.gcm_defaultSenderId);
  }

  @Override
  public boolean shouldUseInternetKernel() {
    return BuildVariantConstants.USE_INTERNET_KERNEL;
  }

  public static OkHttpClient.Builder okHttpClientBuilder(OkHttpClient.Builder builder) {
    // Customize/override OkHttp client here
    return builder;
  }
}

Now i can receive remote notification from firebase.

I did the above and it fixed the crashes, however when I get a notification the app just goes to the main view instead of going through my handler.

This is wrong... It shouldn't rely on the Application class implementing ReactApplication interface...
In react native, you are not required to implement ReactApplication interface on the Application class. You can just create a ReactRootView and a ReactInstanceManager independently.
This assumption is wrong...

You need to look into how Expo is generating the application then. It has its own tool and syntax for detaching the project. I don't think React Native should be recommending using Expo anymore in all honesty.

I am not using Expo. I just have one activity that instantiates a ReactRootView. I solved it by forking this repo and adding a way to set the ReactInstanceManager used by the activity.

@gchenz47 I used your solution to fix my problem, and thank you sooo much! Only now I have another problem. When I build for release the app seems to want to load assets from index.android.bundle, which is not there when using Expo. This gives me the screen attached below. When you press reload the app works like normal but I think this could have to do with the nativeHost override?

@gchenz47, thank you for posting your solution, I was able to keep the app from crashing in the scenario where a cloud message push notification is received within the app while running.

@KthProg, I completely agree with you, ExpoKit is bug-prone and very brittle at this point. I am looking forward to when the OTA update module is separated from it, and a truly bare workflow can be used. I will be migrating off of it immediately when that happens.

Was this page helpful?
0 / 5 - 0 ratings