-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Android error when building with Expo #182
Comments
I'm having the same issue here. |
@JoshRiser The missing reference should be present. Your error might be related to mismatched cached packages either on a legacy expo build, or a cloud eas build. (As far as I can tell, eas local builds don't cache anything.) @jpbast If you can provide the relevant logging (either local or cloud), that will help to diagnose. In both cases, since the eas build process is so different from the legacy expo build, and the local and cloud eas builds work differently, it's helpful to specify which type of build. It may also be relevant if the app was converted from expo to eas, and what versions of expo and eas-cli are used. Some general recommendations:
I have tested this first using the defaults created by package.json dependencies "dependencies": {
"expo": "~49.0.15",
"expo-splash-screen": "~0.20.5",
"expo-status-bar": "~1.6.0",
"react": "18.2.0",
"react-native": "0.72.6",
"rollbar": "^2.26.2",
"rollbar-react-native": "^1.0.0-beta.1"
}, This works for me, with no build or runtime errors, and I can send Rollbar messages from the Java app. Then I converted to an eas app This also worked with no issues. And lastly I did this using the cloud build with no errors. |
I was having a similar error. Without changing any native files, I could build the app on EAS, but the app was crashing every time I opened it. Then I built a development build, and the app was still crashing, but now I could see the error message. I managed to make it work by creating a config plugin // plugins/rollbar-config-plugin.js
const { withMainApplication, AndroidConfig } = require('@expo/config-plugins');
const withRollbarAndroid = (config, { rollbarPostToken, environment }) => {
return withRollbarMainApplication(config, { rollbarPostToken, environment });
};
const withRollbarMainApplication = (config, { rollbarPostToken, environment }) => {
return withMainApplication(config, async (config) => {
config.modResults.contents = modifyMainApplication({
contents: config.modResults.contents,
rollbarPostToken,
environment,
packageName: AndroidConfig.Package.getPackage(config),
});
return config;
});
};
const modifyMainApplication = ({ contents, rollbarPostToken, packageName, environment }) => {
if (!packageName) {
throw new Error('Android package not found');
}
const importLine = `import com.rollbar.RollbarReactNative;`;
if (!contents.includes(importLine)) {
const packageImport = `package ${packageName};`;
// Add the import line to the top of the file
// Replace the first line with the rollbar import
contents = contents.replace(`${packageImport}`, `${packageImport}\n${importLine}`);
}
const initLine = `RollbarReactNative.init(this, "${rollbarPostToken}", "${environment}");`;
if (!contents.includes(initLine)) {
const soLoaderLine = `SoLoader.init(this, /* native exopackage */ false);`;
// Replace the line SoLoader.init(this, /* native exopackage */ false); with regex
contents = contents.replace(`${soLoaderLine}`, `${soLoaderLine}\n\t\t${initLine}\n`);
}
return contents;
};
const withRollbar = (config, options) => {
config = withRollbarAndroid(config, options);
return config;
};
module.exports = withRollbar;
Then on your {
plugins: {
['./plugins/rollbar-config.plugin', {
environment: "production",
rollbarPostToken: "POST_CLIENT_ITEM_ACCESS_TOKEN"
}]
}
} This also enables Rollbar to log crashes in the native code (Android) |
@vitorfrs-dev It's good that this works for you. The doc suggests adding |
@waltjones if we're using expo we do not have direct access to MainApplication.java when building for release - without ejecting we can only get fingers in there via a plugin as far as I know. Did get it working using your plugin though @vitorfrs-dev, kudos 🙌 Maybe worth considering adding some version of this to the repo to support expo users? |
I'd also love to see an official Expo plugin for Rollbar. In our app, it's the only library we still have to support native configuration manually. Having it configured with Expo would be amazing! |
@vitorfrs-dev @waltjones From what I understand, aside from the plugin option mentioned above, there is no alternative for getting |
@camsjams, this plugin worked on See the Expo 50 breaking changes
You can try using the plugin with the Kolin syntax, but I only tested it with // plugins/rollbar-config-plugin/withRollbarAndroid.js
const { withMainApplication, AndroidConfig } = require('@expo/config-plugins');
const withRollbarAndroid = (config, { rollbarPostToken, environment }) => {
return withRollbarMainApplication(config, { rollbarPostToken, environment });
};
const withRollbarMainApplication = (_config, { rollbarPostToken, environment }) => {
return withMainApplication(_config, async (config) => {
config.modResults.contents = modifyMainApplication({
contents: config.modResults.contents,
rollbarPostToken,
environment,
packageName: AndroidConfig.Package.getPackage(config),
});
return config;
});
};
const modifyMainApplication = ({ contents, rollbarPostToken, packageName, environment }) => {
if (!packageName) {
throw new Error('Android package not found');
}
const importLine = `import com.rollbar.RollbarReactNative`;
if (!contents.includes(importLine)) {
const packageImport = `package ${packageName}`;
// Add the import line to the top of the file
// Replace the first line with the rollbar import
contents = contents.replace(`${packageImport}`, `${packageImport}\n${importLine}`);
}
const initLine = `RollbarReactNative.init(this, "${rollbarPostToken}", "${environment}")`;
if (!contents.includes(initLine)) {
const soLoaderLine = 'SoLoader.init(this, false)';
// Replace the line SoLoader.init(this, /* native exopackage */ false); with regex
contents = contents.replace(`${soLoaderLine}`, `${soLoaderLine}\n\t\t${initLine}\n`);
}
return contents;
};
module.exports = withRollbarAndroid; // plugins/rollbar-config-plugin/index.js
const withRollbarAndroid = require('./withRollbarAndroid');
const withRollbar = (config, options) => {
config = withRollbarAndroid(config, options);
return config;
};
module.exports = withRollbar; // app.config.ts
{
plugins: {
['./plugins/rollbar-config-plugin', {
environment: "production",
rollbarPostToken: process.env.POST_CLIENT_ITEM_ACCESS_TOKEN
}]
}
}
|
@vitorfrs-dev amazing! This last code snippet above does indeed work on Thank You |
The plugin above did not work with Expo 51. Going back to Bugsnag. Sorry. |
Not sure if you saw above, but it does work if you use the plugin route on Expo 51. It would be nice to have added into main package, I agree. But I'd much rather use Rollbar over Sentry or Bugsnag. Good luck! |
I ran out of time to debug it but the code didn't work and my compiled app in the internal test track still crashed upon start. I don't know enough about all the intricacies of how Android apps are built to resolve it, so I just posted as a warning to others. The code above was not the saving grace I thought it would be. I don't know why. If someone can post steps to perhaps help me debug and resolve, I'm keen to try again. |
After a few months, since I last checked this thread, it seems like the team has been away for the future of this SDK 🫠 Here is a complete version of @vitorfrs-dev plugin considering iOS. Note that I used a similar approach for Android Java, this should not work with Kotlin, but the implementation for that should not be too hard considering it's only a "find and replace" implementation. const {
withMainApplication,
withAppDelegate,
AndroidConfig,
IOSConfig,
} = require('@expo/config-plugins');
/**
* Options for the Rollbar plugin.
* @typedef {Object} PluginOptions
* @property {string} rollbarPostToken - The Rollbar post token for API access.
* @property {string} [environment] - The environment in which the app is running.
*/
const DEFAULT_APP_NAME = '<your-app-name>';
/**
* Configures Rollbar for Android by modifying the MainApplication.java file.
*
* @param {Object} config - The Expo configuration object.
* @param {PluginOptions} options - The options for the Rollbar plugin.
* @returns {Object} The modified Expo configuration object.
*/
const withRollbarAndroid = (config, {rollbarPostToken, environment}) => {
return withMainApplication(config, (props) => {
props.modResults.contents = modifyMainApplication({
contents: props.modResults.contents,
rollbarPostToken,
environment,
packageName: AndroidConfig.Package.getPackage(config) ?? DEFAULT_APP_NAME,
});
return props;
});
};
/**
* Modifies the MainApplication.java file to include Rollbar initialization for Android.
*
* @param {Object} options
* @param {string} options.contents - The contents of the MainApplication.java file.
* @param {string} options.rollbarPostToken - The Rollbar post access token.
* @param {string} options.packageName - The Android package name. Defaults to "<your-app-name>".
* @param {string} [options.environment] - The environment in which the app is running.
* @returns {string} The modified contents of the MainApplication.java file.
*/
const modifyMainApplication = ({contents, rollbarPostToken, packageName, environment}) => {
const importLine = `import com.rollbar.RollbarReactNative;`;
if (!contents.includes(importLine)) {
const packageImport = `package ${packageName};`;
contents = contents.replace(`${packageImport}`, `${packageImport}\n${importLine}`);
}
const initLine = `RollbarReactNative.init(this, "${rollbarPostToken}", "${environment}");`;
if (!contents.includes(initLine)) {
const soLoaderLine = `SoLoader.init(this, /* native exopackage */ false);`;
contents = contents.replace(`${soLoaderLine}`, `${soLoaderLine}\n\t\t${initLine}\n`);
}
return contents;
};
/**
* Configures Rollbar for iOS by modifying the AppDelegate.m file.
*
* @param {Object} config - The Expo configuration object.
* @param {PluginOptions} options - The options for the Rollbar plugin.
* @returns {Object} The modified Expo configuration object.
*/
const withRollbariOS = (config, {rollbarPostToken}) => {
return withAppDelegate(config, (props) => {
props.modResults.contents = modifyAppDelegate({
contents: props.modResults.contents,
rollbarPostToken,
bundleIdentifier: IOSConfig.BundleIdentifier.getBundleIdentifier(config) ?? DEFAULT_APP_NAME,
});
return props;
});
};
/**
* Modifies the AppDelegate.m file to include Rollbar initialization for iOS.
*
* @param {Object} options
* @param {string} options.contents - The contents of the MainApplication.java file.
* @param {string} options.rollbarPostToken - The Rollbar post access token.
* @param {string} options.bundleIdentifier - The iOS bundle identifier. Defaults to "<your-app-name>"..
* @returns {string} The modified contents of the AppDelegate.m file.
*/
const modifyAppDelegate = ({contents, rollbarPostToken, bundleIdentifier}) => {
const importLine = `#import <RollbarReactNative/RollbarReactNative.h>`;
if (!contents.includes(importLine)) {
const appDelegateImport = `#import "AppDelegate.h"`;
contents = contents.replace(`${appDelegateImport}`, `${appDelegateImport}\n${importLine}`);
}
const initLine = `NSDictionary *options = @{
@"accessToken": @"${rollbarPostToken}"
};
[RollbarReactNative initWithConfiguration:options];`;
if (!contents.includes(initLine)) {
const selfModuleLine = `self.moduleName = @"main";`;
contents = contents.replace(`${selfModuleLine}`, `${selfModuleLine}\n\t\t${initLine}\n`);
}
return contents;
};
/**
* Adds Rollbar support for both Android and iOS platforms via Expo plugin.
*
* @param {Object} config - The Expo configuration object from ../app.config.ts
* @param {PluginOptions} options - The options for the Rollbar plugin.
* @returns {Object} The modified Expo configuration object with Rollbar integrated.
*/
const withRollbar = (config, options) => {
if (!rollbarPostToken) {
console.warn('No Rollbar Post token given, skipping...');
return config;
}
config = withRollbarAndroid(config, options);
config = withRollbariOS(config, options);
return config;
};
module.exports = withRollbar; |
I couldn't expand this plugin considering Kotlin and Swift because I don't have enough expertise for that, it'd be one of the last parts before contributing with an official plugin for the project. |
When trying to build my Expo managed app on Android, I run into the following error:
(same as a closed issue here)
I also found this closed issue, where waltjones gave a solution, which I tried on version 1.0.0-beta.1, 0.9.0 (where there was a PR related to walt's solution,) and 0.9.1 (the version at the time of walt's solution.)
I tried these two configuration options:
and
And neither of them work.
I am also trying to use this configuration with the Provider and ErrorBoundary if that makes a difference.
It all works fine on iOS but Android doesn't want to work.
The text was updated successfully, but these errors were encountered: