how to create a plugin that writes a new activity in Manifes.xml

i would like to write a new activity in application section Manifest file like below

<activity
        android:name="com.myapp.CustomActivity"
        android:showWhenLocked="true"
        android:turnScreenOn="true"
        android:launchMode="singleTop"
        android:showOnLockScreen="true"
      />

how can i achieve this with a plugin.

Hi @emuter,

For the properties you mentioned, I’d also suggest taking a look at the solution described in this post forum: How to Edit android manifest was build - #4 by wodin

You can also learn more about creating a custom config plugin in Config plugins documentation to modify AndroidManifest.xml file.

thanks for replying on this.
i have seen this How to Edit android manifest was build - #4 by wodin link before.

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.

Yes. I’m already using a development build.

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.

 <activity
         android:name="com.myapp.CustomActivity"
         android:showWhenLocked="true"
         android:turnScreenOn="true"
         android:launchMode="singleTop"
         android:showOnLockScreen="true"
       />

Hi @emuter

You can build any XML you need. Under the hood Expo uses xml2js to manipulate the XML that ultimately ends up in AndroidManifest.xml.

See the docs here:

XML builder usage

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.

2 Likes

frankly, that’s quite simple. yet i have been banging my head assuming it should be more complicated than that.

though, there should be a minor correction here with removal of additional brackets.

const customActivity = {
    $: {
      'android:name': 'com.myapp.CustomActivity',
      'android:showWhenLocked': 'true',
      'android:turnScreenOn': 'true',
      'android:launchMode': 'singleTop',
      'android:showOnLockScreen': 'true',
    },
};

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 .

i need that to launch an intent screen as a new activity past the lock screen.

anyway, thank you so much for helping out.
Tc

1 Like

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