How to Edit android manifest was build

Please provide the following:

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

hello. Please I need to edit my Android manifest. I am using eas , so not on the expo app. Can’t I do this? I am using the notifee library and need to add
<activity

android:showWhenLocked=“true”
android:turnScreenOn=“true”
/>
To my Android manifest. Please how do I do this. Thank you

Hi @alex261816, you can edit your Android manifest with Config Plugins. Please see the documentation here: Config Plugins - Expo Documentation on how to do it.

Hello @amanhimself please I do not understand how to do that even with the docs. The package doesn’t automatically require the permission. I have also asked in notifee forum and they told me that I have to do it myself and I should ask here.

Hi @alex261816

This should do it. Create a directory in the root of your project called plugins and put the following file into it:

plugins/withAndroidMainActivityAttributes.js:

const { withAndroidManifest } = require("@expo/config-plugins");

function addAttributesToMainActivity(androidManifest, attributes) {
  const { manifest } = androidManifest;

  if (!Array.isArray(manifest["application"])) {
    console.warn("withAndroidMainActivityAttributes: No application array in manifest?");
    return androidManifest;
  }

  const application = manifest["application"].find(
    (item) => item.$["android:name"] === ".MainApplication"
  );
  if (!application) {
    console.warn("withAndroidMainActivityAttributes: No .MainApplication?");
    return androidManifest;
  }

  if (!Array.isArray(application["activity"])) {
    console.warn("withAndroidMainActivityAttributes: No activity array in .MainApplication?");
    return androidManifest;
  }

  const activity = application["activity"].find(
    (item) => item.$["android:name"] === ".MainActivity"
  );
  if (!activity) {
    console.warn("withAndroidMainActivityAttributes: No .MainActivity?");
    return androidManifest;
  }

  activity.$ = { ...activity.$, ...attributes };

  return androidManifest;
}

module.exports = function withAndroidMainActivityAttributes(config, attributes) {
  return withAndroidManifest(config, (config) => {
    config.modResults = addAttributesToMainActivity(config.modResults, attributes);
    return config;
  });
};

Then add a plugins section to your app.json like this:

{
  "expo": {
[...]
    "plugins": [
      [
        "./plugins/withAndroidMainActivityAttributes",
        {
          "android:showWhenLocked": true,
          "android:turnScreenOn": true
        }
      ]
    ]
  }
}
2 Likes

I just tried that and rebuilt the app. It doesn’t work still.

Hi

How did you build the app?

Also, please explain what “doesn’t work” means exactly.

I used eas to build the app. Also by doesn’t work, I mean the expected behavior isn’t the same as the current behavior. It just shows as a normal notification. According to notifee in their behavior tab, it’s supposed to display as a full screen action, that is, like a call notification which stays on the screen till a user interacts with it or sth. But this one I only see the notification and get the vibration, just like a normal notification even after setting it up to display like a full screen notification.

Ah, well that’s a separate issue :slight_smile:

If I create a new app and add the config plugin and reference it in app.json as mentioned above, then when I run npx expo prebuild -p android I see the following in AndroidManifest.xml:

$ grep -3E 'showWhenLocked|turnScreenOn' android/app/src/main/AndroidManifest.xml 
    <meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
    <meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
    <meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://exp.host/@wodin/notifeeTest"/>
    <activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="portrait" android:showWhenLocked="true" android:turnScreenOn="true">
      <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>

As you can see, the showWhenLocked and turnScreenOn attributes have been added.

Note: You don’t need to run npx expo prebuild yourself for this to work. It is run on the build servers during the build process. If you use VS Code there is also an extension that should allow you to check this sort of stuff without running npx expo prebuild.

So if it’s not doing what you expect then either my config plugin is not adding the attributes correctly (let me know if you see a problem), or there’s an issue somewhere between your code and notifee. So at this point it might be best for you to ask notifee for further clarification.

Okay. Thank you for the androidManifest code. I just checked mine and I didn’t see mine. I added the plugin and copied the exact code you wrote and pasted. But it doesn’t still add

If you have an android directory in your app you are on the Bare workflow.

If you’re on the Bare workflow you can just edit AndroidManifest.xml with a text editor.
Alternatively, you can regenerate the native android and ios projects by running npx expo prebuild --clean. This will wipe out any manual changes you might have made to the native projects, but it will apply changes from app.json, including config plugins when generating the native projects.

But if you intend to use the Managed workflow then you will need to basically get rid of the ios and andrdoid directories and let the build servers run npx expo prebuild for you during the build process.

See expo.fyi/prebuild-cleanup for more details on reverting to the Managed workflow.

I’ve also explained this on the forums before, so if the above is not explained well enough, maybe this post will help :slight_smile:

I also didn’t use prebuild as I know that the prebuilding is done when I build the app.

This is how I add the plugin:

plugins: [
      [
        "./plugins/withAndroidMainActivityAttributes",
        {
          "android:showWhenLocked": true,
          "android:turnScreenOn": true
        }
      ],
]

And this is the code:

const { withAndroidManifest } = require("@expo/config-plugins");

function addAttributesToMainActivity(androidManifest, attributes) {
  const { manifest } = androidManifest;

  if (!Array.isArray(manifest["application"])) {
    console.warn("withAndroidMainActivityAttributes: No application array in manifest?");
    return androidManifest;
  }

  const application = manifest["application"].find(
    (item) => item.$["android:name"] === ".MainApplication"
  );
  if (!application) {
    console.warn("withAndroidMainActivityAttributes: No .MainApplication?");
    return androidManifest;
  }

  if (!Array.isArray(application["activity"])) {
    console.warn("withAndroidMainActivityAttributes: No activity array in .MainApplication?");
    return androidManifest;
  }

  const activity = application["activity"].find(
    (item) => item.$["android:name"] === ".MainActivity"
  );
  if (!activity) {
    console.warn("withAndroidMainActivityAttributes: No .MainActivity?");
    return androidManifest;
  }

  activity.$ = { ...activity.$, ...attributes };

  return androidManifest;
}

module.exports = function withAndroidMainActivityAttributes(config, attributes) {
  return withAndroidManifest(config, (config) => {
    config.modResults = addAttributesToMainActivity(config.modResults, attributes);
    return config;
  });
};

Is there anything I’m doing wrong?

That looks right, but I think you have previously run npx expo prebuild or npx expo run:android to generate the native project in the android directory. See my previous post for what you can do about it.

After editing it manually, Do I need to prebuild the app again? Or it would just work automatically?

If you decide to stick with the Bare workflow, then you basically have a plain React Native app. This means that e.g. if you want to change an app icon or the name of the app or the splash screen etc. you will need to do it in the native code directly. Also, if you want to upgrade to a later version of React Native later you will need to follow the React Native upgrade instructions (in addition to the normal Expo upgrade instructions.) So it will complicate upgrades in future.

But yes, if you have a Bare app and you manually edit AndroidManifest.xml, and you do not have the android directory in your .gitignore file, then eas build will not run npx expo prebuild, so your changes to AndroidManifest.xml will not be interfered with.

Personally, I would revert to the managed workflow and use the config plugin to make the necessary changes to AndroidManifest.xml. In this case, the build servers will run npx expo prebuild and the config plugin will add the attributes to the manifest.

If you are unsure that the AndroidManifest.xml changes are actually making their way into the compiled app you can dump the manifest from the “.aab” that you build with eas build -p android --profile production

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