the thing is i have spent many day on this. all the solutions lead me to modify properties of existing activities and couldn’t figure out a way to write a new activity tag with its own properties on prebuild.
i already know how to place them on manifest on app eject, but really want to keep things wrapped in managed workflow.
i would really appreciate anyone’s help on this.
Managed workflow projects run on Expo Go client. The Expo Go client is restricted on what native code it can run or not. You can create a custom development build of your managed workflow, which is like creating a custom Expo Go client that includes any modified native code that you put into it: Create development builds - Expo Documentation. This way, you stay in the managed workflow and don’t have to eject. Also, with development builds, “eject” is deprecated since a development build allows adding custom native code or using pre-existing solutions such as config plugins.
Developing a config plugin allows you to use it with Development builds or running the command to build native build locally. Running the native build locally will create an android directory and you can manually check if the AndroidManifest.xml file is being updated with the values you provided in the config plugin.
you can manually check if the AndroidManifest.xml file is being updated with the values you provided in the config plugin.
this is the part exactly i am struggling with as i couldnt figur out how i can update the AndroidManifest.xml with this piece of code by using a plugin.
Your config plugin will receive a JavaScript object which represents the AndroidManifest.xml and you will have to find the “application” and insert a new “activity” into it. Then withAndroidManifest will convert the JavaScript object to XML and write it to AndroidManifest.xml.
So off the top of my head, maybe something like this (untested) will work:
const { withAndroidManifest } = require('@expo/config-plugins');
const customActivity = {
activity: {
$: {
'android:name': 'com.myapp.CustomActivity',
'android:showWhenLocked': 'true',
'android:turnScreenOn': 'true',
'android:launchMode': 'singleTop',
'android:showOnLockScreen': 'true',
},
},
};
function addCustomActivityToMainApplication(androidManifest, attributes) {
const { manifest } = androidManifest;
// Check if there are any application tags
if (!Array.isArray(manifest['application'])) {
console.warn('withAndroidMainActivityAttributes: No application array in manifest?');
return androidManifest;
}
// Find the "application" called ".MainApplication"
const application = manifest['application'].find(
(item) => item.$['android:name'] === '.MainApplication'
);
if (!application) {
console.warn('addCustomActivityToMainApplication: No .MainApplication?');
return androidManifest;
}
// Check if there are any activity tags
let activities = application["activity"];
if (!Array.isArray(activities)) {
console.warn('addCustomActivityToMainApplication: No activity array in .MainApplication?');
return androidManifest;
}
// If we don't find the custom activity, add it
// If we do find it, assume it's correct
if (
!activities.find(
(item) =>
item.$["android:name"] === "com.myapp.CustomActivity"
)
) {
activities.push(customActivity);
}
return androidManifest;
}
module.exports = function withAndroidCustomActivity(config, attributes) {
return withAndroidManifest(config, (config) => {
config.modResults = addCustomActivityToMainApplication(config.modResults, attributes);
return config;
});
};
Of course you could make that more general and take parameters like the name and other attributes from the plugins section of app.json.
I have never tried adding another activity to one of my apps before, so no idea what you need to do other than updating AndroidManifest.xml.