expo app crashing at the start (google play)

Please provide the following:

  1. SDK Version:42
  2. Platforms(Android/iOS/web/all):Android
  3. Add the appropriate “Tag” based on what Expo library you have a question on.

I have recently updated app at google play with the interstital ad.
After the update app has been crashing at start
It works fine during expo start and even on android emulator
but the google play bundle keeps on crashing.
Been trying to debug it but I am having trouble.
this is app,js source sample:

import * as React from 'react';
import { useEffect } from 'react';
import { WebView } from 'react-native-webview';
import { StatusBar,StyleSheet} from 'react-native';
import Constants from 'expo-constants';
import { AdMobInterstitial } from 'expo-ads-admob';
const adFunction = async() => {
  await AdMobInterstitial.setAdUnitID('ca-app-pub-3940256099942544/1033173712'); /*test ID*/
  await AdMobInterstitial.requestAdAsync({ servePersonalizedAds: true});
  await AdMobInterstitial.showAdAsync();
}
export default function App() {
   
  useEffect(() => {
    setInterval(adFunction,45000);
   },[ ]);
    
  return (
    
  <>  
   <StatusBar backgroundColor="white" hidden ={true} />
     <WebView 
       style={styles.container}
       
       source={{ uri: 'https://xxj89098a8sdhjihjosad.net/' }} 
      />
   </>  
 
  ); 
 
}

*If you notice any errors or problems or suggestions it would be very much appreciated

Hey @chaosbahun, please read these docs to help get to the bottom of this.

Cheers,
Adam

Thanks for the reply, I was advised elsewhere to add metadata of my app ID to the androidManifest.xml in app. However there seems to be several androidManifest.xml files within node-modules of expo-application, expo-admob, expo-constants, and etc. Is this on the right track or it is not advisable to edit those files without ejecting expo?

I’m running into the same issue right now. In my situation I’ve narrowed it down to the android adaptiveIcon configuration. If I use a path to a real png, the app crashes on bundle download. If I don’t include adaptiveIcon under android, the app crashes. The only way it won’t crash is to include adaptiveIcon linked to a file that doesn’t even exist. This logs an error that Expo can’t find the file, but the app will actually load. Extremely strange. Try adding this to your app.json file.

"android": {
  "adaptiveIcon": {
    "foregroundImage": "./assets/anImageThatDoesNotExist.png",
    "backgroundColor": "#FFFFFF"
   }
 },

Thank you for your advice. The build runs on expo start and shows with expo go fine with the adaptiveIcon change you have mentioned. However when I actually trying to make an android bundle through expo build:android the build stops because of error at the Json file from the nonexistent adaptiveIcon and cannot continue. Is there anyway to bypass the erros and go on with the build?

Hi @chaosbahun

This should definitely not be necessary in a managed Expo app, and is also not possible when using expo build:android. (You would need to use eas build or otherwise eject if you did want to do something like this, but don’t think about that now because I don’t believe that’s the solution.) As a matter of interest, what is the metadata you were advised to add exactly?

In a plain (non-Expo) React Native app you would have an android directory in your app’s top level directory (i.e. separate from any you might find under node_modules), and there would be an AndroidManifest.xml in there. One of the things that the Expo managed workflow does is it avoids you needing to worry about that native code stuff (which does result in some limitations, but those limitations are not relevant to your case.)

The stuff under node_modules should not be changed usually, unless there’s a bug in one of those dependencies that you want to fix before the authors release a new version. (Again, I don’t think this is relevant to your case, but if you encounter a situation like this in future, you should use patch-package to keep things neat and allow it to still work if you use EAS Build.)

To modify stuff under the top level android directory that does not exist in a managed Expo app you would indeed need to eject, or else use EAS Build along with a Config Plugin. (But this should not be needed in your case :slight_smile:)

Hi @lisa559

Apps can crash for any number of reasons, unfortunately, so I doubt that your crash is related to @chaosbahun’s crash.

Generally the strategy to get to the bottom of this sort of thing is to try to make a new app that is as simple as possible, but has just enough of the code from your real app to cause the crash. Then it is much easier to figure out what caused the problem.

Also, if the app works in Expo Go, but crashes when you build the standalone version, then the section on the page that @adamjnav linked to called “Production Errors” might help. So you could try running expo start --no-dev --minify and seeing if the Expo Go app crashes now. If it does, that’s great, because it should give you more info about what the problem is. Hopefully it’s enough info for you to fix it. If so, do that and follow up here with the solution. If you still can’t work it out, post the details here and we’ll try to help.

@lisa559 about the adaptive icon problem, you should also try the above, but also see what happens if you use the default adaptive icon that you get when you create a new app with expo init.

1 Like

Thank you for your great insight into this occurrence.
This is the meta-data entered into the

node_modules\expo-ads-admob\android\src\main\AndroidManifest.xml:

<manifest>
    <application>
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>
</manifest>

which ends up looking like this

<manifest package="expo.modules.ads.admob" xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.INTERNET" />
<application>
     <meta-data
        android:name="com.google.android.gms.ads.APPLICATION_ID"
        android:value="ca-app-pub-ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
</application>
  
</manifest>

I have also tried entering this data into other places that had such a file:

node_modules\expo-application\android\src\main\AndroidManifest.xml

node_modules\expo-constants\android\src\main\AndroidManifest.xml

and etc.

Also it works fine under “expo start --no-dev --minify” as well without any crash, but when it is bundled and released onto google play and downloaded to my device and to few other android devices at home it crashed at start up.

import * as React from 'react';
import { Component } from 'react';
import { WebView } from 'react-native-webview';
import { AdMobInterstitial } from 'expo-ads-admob';


const INTERSTITIAL_ID ="ca-app-pub-9888888883999-888888888"; 
const INTERSTITIAL_TEST_ID ="ca-app-pub-3940256099942544/1033173712";

class App extends Component {
    adFunction = async () =>  {
          AdMobInterstitial.setAdUnitID(INTERSTITIAL_TEST_ID);    
    await AdMobInterstitial.requestAdAsync({servePersonalizedAds: true});
    await AdMobInterstitial.showAdAsync();
  };

  componentDidMount(){
    setInterval(this.adFunction,35000);
  }

  render() {
    return (

        <WebView  source={{ uri: 'https://pasd8hha8yu8ya888ad.net/' }} />
    );
    }
}

This is code sample of my current App.js file which works only during testing.

You should not be adding anything into AndroidManifest.xml files under node_modules. And only if you have a plain React Native app or an ejected Expo app should you be adding anything to the AndroidManifest.xml under your-app/android

The way to set the APPLICATION_ID in a managed Expo app is shown here. i.e. you add it to app.json. When Expo’s build servers build your app they will arrange for the app ID to be put in the AndroidManifest.xml.

hmmm… When I suggested that I forgot that Expo Go would have Expo’s AdMob app ID built in rather than yours, because it’s a pre-built app and you can’t change the app ID at run time. So I suppose that might be why it works there even in production mode.

Comparing your code to the documentation I only notice one obvious difference.

You have:

          AdMobInterstitial.setAdUnitID(INTERSTITIAL_TEST_ID);    

where the docs have:

    await AdMobInterstitial.setAdUnitID(adUnitID);

(i.e. they’re using await AdMobInterstitial.setAdUnitID() where you’re not using await).

I don’t know whether that’s the cause of the crash, but see if it fixes the problem.

Another thing: You’re calling setInterval() when the component mounts, but you’re never clearing the interval again, so it looks like a resource leak, I think. I came up with the following, based on the docs and converted it to a function component and used Dan Abramov’s useInterval hook to handle the clearing of the interval when the component unmounts. I have not tested it, but maybe see if it works for you?

import React, { useEffect, useRef, useState } from 'react';
import { Platform } from 'react-native';
import { WebView } from 'react-native-webview';
import { AdMobInterstitial } from 'expo-ads-admob';
import Constants from 'expo-constants';

const INTERSTITIAL_ID = 'ca-app-pub-9888888883999-888888888';
const INTERSTITIAL_TEST_ID = Platform.select({
  ios: 'ca-app-pub-3940256099942544/4411468910',
  android: 'ca-app-pub-3940256099942544/1033173712',
});
const adUnitID = Constants.isDevice && !__DEV__ ? INTERSTITIAL_ID : INTERSTITIAL_TEST_ID;

import React, { useState, useEffect, useRef } from 'react';

// from https://overreacted.io/making-setinterval-declarative-with-react-hooks/
function useInterval(callback, delay) {
  const savedCallback = useRef();

  // Remember the latest callback.
  useEffect(() => {
    savedCallback.current = callback;
  }, [callback]);

  // Set up the interval.
  useEffect(() => {
    function tick() {
      savedCallback.current();
    }
    if (delay !== null) {
      let id = setInterval(tick, delay);
      return () => clearInterval(id);
    }
  }, [delay]);
}

export default function App() {
  const adFunction = async () => {
    await AdMobInterstitial.setAdUnitID(adUnitID);
    await AdMobInterstitial.requestAdAsync({ servePersonalizedAds: true });
    await AdMobInterstitial.showAdAsync();
  };

  useInterval(adFunction, 35000);

  return <WebView source={{ uri: 'https://example.com/' }} />;
}

-I have updated with your code set up and it works well in testing phase.
-My app.json file is in format with what you have shown me.
-I deleted manual addition of metadata in the node modules to set it back to default.
-But in actual google play bundle even with the update it again crashes at set up.
-admob docs
Here it saids “web” is not supported for admob expo.

-adamjnav the admin told me on another post that webview is part of web and must be
web-supported to work webview admob

So my guess is that webview for admob not being supported is auto crashing the app or it may still be something else

Expo supports running an app not only on Android and on iOS, but also on the Web. The above statement is about running the Web version of your app. It is not referring to running your app on Android and displaying a WebView as part of your app.

This can all get confusing :slight_smile:. It seems that Adam misunderstood what you were asking. You cannot somehow use Expo’s expo-admob-ads module inside of a <WebView>, but if you’re just displaying a normal web site inside of the <WebView> then there should be no problem.

But this would be easy to test. Just replace the <WebView> with <Text>Testing testing 1 2 3</Text> and build the app to see if it still crashes. I believe it will, since I don’t think the <WebView> had anything to do with the crash.

The strange thing is that your app is crashing immediately, right? Not after 35 seconds?

Maybe test what happens if you comment out the useInterval(adFunction, 35000); call and instead use a button to trigger the call to adFunction. Then it shouldn’t be running any AdMob code until you press the button. But given your current app crashes immediately I suspect this version would also crash immediately.

import { Alert, Button } from 'react-native';
[...]
  // useInterval(adFunction, 35000);

  return <Button title="Press me" onPress={adFunction} />;

If it crashes only when you press the button it seems like it must have something to do with AdMob.
If it crashes immediately then it might not have anything to do with AdMob.

After the above try commenting out/removing the adFunction function and the AdMobInterstitial import completely and replace the call to adFunction in the button’s onPress handler with an alert:

  return <Button title="Press me" onPress={() => Alert.alert('Button pressed')} />;

Rebuild the app. If it still crashes, uninstall/remove the expo-admob-ads module, rebuild and try it again.

At this point if it still crashes then the cause can’t be AdMob. So now you should go to the link that Adam posted above where it talks about accessing the native device logs. These logs have a lot of information in them that is unrelated to your app, but if you search for a “fatal exception” you should hopefully find something that gives you a hint about what’s wrong.

The other strategy you could try is this:

Create a new app with expo init and build it without making any changes and test if it crashes for you. If it does it would be very surprising. If it does not crash, you could compare all of the files in the root of the project with the corresponding files in your real app to see what differences there are. You should probably ignore the yarn.lock or package-lock.json file (depending on whether you use yarn or npm) when doing this. Then you could see if you can start making changes to the new app to make it more like your real app. For each change you make, see if it still works in dev mode but crashes after you build it. This should allow you to get to exactly the change that causes the crash.

Thank you for all great suggestions and methods.
So far
Yes the app always crashes at start and not at the setInterval time.

I’ ve commented out the adFunction like you mentioned and tried these like you mentioned:

return <Button title="Press me" onPress={adFunction} />;

return <Button title="Press me" onPress={() => Alert.alert('Button pressed')} />;

both worked during testing the ad is displayed accordingly without crash when the button was pressed.

So I have created a test build with button with onpress function for showing interstial ads
and bundled it for google play update.

However even with the new test build app continues to crash the same way upon update from google play.

the app worked fine before adding admob for expo without crash so that is why I am still seeing it as an admob issue.

But however to know for sure it seems likely I might have to start from scratch again like you said.

1 Like

I have had the same issue as you where the app always crashed on android devices but not on iOS. I fixed it by giving an adaptiveIcon path to an image that does not exist. It gives an error when loading the app, but at least it doesn’t crash, so that was a temporary workaround while developing the app.

I tried to run expo publish to share the app with other testers, but I could not do that with the wrongful parameter in app.json.
So I initialized a new project, and installed all packages and copied the code over piece by piece, all the time testing the app and checking when it started crashing on android.
It started crashing when I copied my app.json, and I narrowed it down to splash/image.
At some point I had overwritten the template that comes with expo init with an image that did not have the same dimensions and I believe that it was at this point the app started crashing on android devices.
I am now using the template splash.png until I make a new one from that template.

It might be something different but similar in your case. I hope that this can help you.

If this “fixes” the crash it probably means you had a problem with the adaptiveIcon you were using before you made that change.

The temporary “fix” was to point to a non-existing adaptive-icon file.
I also tried with the adaptive-icon.png from the project template but that made the app crash on android.
It was fixed (not “fixed”) by switching back to the template splash.png. After that I could point to the existing adaptive-icon.png so that I wouldn’t get any errors when running expo publish .
Currently using a custom splash image, although based on the template. The adaptive icon is still the template one.
Point is that it really had nothing to do with the adaptiveIcon setting. It seems to me that setting it incorrectly kind of bypassed the actual issue that was crashing the app.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.