expo / config-plugins

Out-of-tree Expo config plugins for packages that haven't adopted the config plugin system yet.
454 stars 98 forks source link

Enables to add a new item to "queries" in AndroidManifest.xml #123

Open ytakzk opened 1 year ago

ytakzk commented 1 year ago

Library

No

Summary

It would be nice if developers can add a new item to "queries" in AndroidManifest.xml for Package Visibility.

https://medium.com/androiddevelopers/package-visibility-in-android-11-cc857f221cd9

Any existing examples?

No

lennartschoch commented 1 year ago

For now, you can use your own types as a workaround:

export type ManifestIntent = {
  action: {
    $: {
      "android:name": string
    }
  }
  data: {
    $: {
      "android:scheme": string
    }
  }
}

export type ManifestWithQueries = AndroidManifest["manifest"] & {
  queries?: {
    intent?: ManifestIntent[]
  }
}

Then, just cast the manifest to your custom type in your plugin:

  config = withAndroidManifest(config, config => {
    const oldManifest = config.modResults.manifest as ManifestWithQueries

    if (!oldManifest.queries?.intent) {
      oldManifest.queries = { ...(oldManifest.queries ?? {}), intent: [] }
    }

    const manifest: ManifestWithQueries = {
      ...oldManifest,
      queries: {
        ...oldManifest.queries,
        intent: [
          ...(oldManifest.queries.intent ?? []),
          {
            action: {
              $: {
                "android:name": "android.intent.action.VIEW",
              },
            },
            data: {
              $: {
                "android:scheme": "uber",
              },
            },
          },
        ],
      },
    }
    config.modResults.manifest = manifest
    return config
  })
ansh commented 1 year ago

This would be dope!

yjose commented 1 year ago

Thank you @lennartschoch for the workaround here is a more complete example: ( i am using js)

// types.ts
export type ManifestQueries = {
  package: {
    $: {
      "android:name": string;
    };
  }[];
  intent: {
    action: {
      $: {
        "android:name": string;
      };
    };
    category: {
      $: {
        "android:name": string;
      };
    };
    data: {
      $: {
        "android:scheme": string;
      };
    };
  }[];
};
const {
  AndroidConfig,
  withAndroidManifest,
  createRunOncePlugin,
} = require("expo/config-plugins");

/**
 * @type {import('./types').ManifestQueries}
 * what we are trying to add:
 * <queries>
    <package android:name="com.apple.android.music"/>
    <package android:name="com.spotify.music"/>
    <intent></intent>
      <action android:name="android.intent.action.VIEW"/>
      <category android:name="android.intent.category.BROWSABLE"/>
      <data android:scheme="https"/>
    </intent>
  </queries>
 */

const queries = {
  package: [
    {
      $: {
        "android:name": "com.apple.android.music",
      },
    },
    {
      $: {
        "android:name": "com.spotify.music",
      },
    },
  ],
  intent: [
    {
      action: {
        $: {
          "android:name": "android.intent.action.VIEW",
        },
      },
      category: {
        $: {
          "android:name": "android.intent.category.BROWSABLE",
        },
      },
      data: {
        $: {
          "android:scheme": "https",
        },
      },
    },
  ],
};

/**
 * @param {import('@expo/config-plugins').ExportedConfig} config
 */
const withAndroidManifestService = (config) => {
  return withAndroidManifest(config, (config) => {
    config.modResults.manifest = {
      ...config.modResults.manifest,
      //@ts-ignore
      queries,
    };

    return config;
  });
};

module.exports = createRunOncePlugin(
  withAndroidManifestService,
  "withAndroidManifestService",
  "1.0.0"
);