1 /**
2 * Strip android.permission.INTERNET from release builds only.
3 *
4 * The main AndroidManifest keeps the permission so debug builds can talk
5 * to Metro (and any other dev-time HTTP endpoint). Android's manifest
6 * merger applies build-type overlays AFTER the main manifest, so dropping
7 * a `src/release/AndroidManifest.xml` with `tools:node="remove"` is exactly
8 * the right level of surgery — debug and release diverge cleanly with no
9 * conditional logic at app.json level.
10 *
11 * Wired into app.json via:
12 * "plugins": [ ..., "./plugins/with-release-no-internet" ]
13 */
14 const { withDangerousMod } = require('@expo/config-plugins');
15 const fs = require('fs');
16 const path = require('path');
17 18 const RELEASE_MANIFEST = `<?xml version="1.0" encoding="utf-8"?>
19 <manifest
20 xmlns:android="http://schemas.android.com/apk/res/android"
21 xmlns:tools="http://schemas.android.com/tools">
22 <!-- The app is a pure URL router. Release builds make no network
23 calls themselves; debug builds keep INTERNET so Metro can reach them.
24 Written by plugins/with-release-no-internet.js — do not edit by hand;
25 this file is regenerated on every expo prebuild. -->
26 <uses-permission android:name="android.permission.INTERNET" tools:node="remove"/>
27 </manifest>
28 `;
29 30 module.exports = function withReleaseNoInternet(config) {
31 return withDangerousMod(config, [
32 'android',
33 async (config) => {
34 const dir = path.join(
35 config.modRequest.platformProjectRoot,
36 'app/src/release',
37 );
38 fs.mkdirSync(dir, { recursive: true });
39 fs.writeFileSync(path.join(dir, 'AndroidManifest.xml'), RELEASE_MANIFEST);
40 return config;
41 },
42 ]);
43 };
44