Ionic/Cordova:使用 config.xml 添加 intent-filter

Ionic/Cordova: Add intent-filter using config.xml

我正在使用 Ionic Framework(基于 Cordova)开发移动应用程序。

在 Android 中,我注册了我的应用程序以打开 *.txt 文件。 我这样做是在 platforms/android/AndroidManifest.xml 中添加 intent-filter 并且它有效。 但是平台文件夹在 .gitignore 中:我想使用 config.xml.

我尝试添加 config.xml:

     <platform name="android">
        <config-file target="AndroidManifest.xml" parent="/*/application/activity">
          <intent-filter><!-- ... --></intent-filter>
        </config-file>
        <!-- ... -->
     </platform>

我还尝试添加:

     <platform name="android">
        <config-file target="AndroidManifest.xml" parent="/manifest/application">
          <activity android:name="CordovaApp"> 
            <intent-filter><!-- ... --></intent-filter>
          </activity>
        </config-file>
        <!-- ... -->
     </platform>

然后我尝试更新AndroidManifest launching

ionic prepare

或者:

ionic remove platform android && ionic add platform android

但AndroidManifest.xml始终不变。 我做错了什么?

我正在使用 Ionic 1.3.2 和 Cordova 4.2.0。

编辑 这里是整个 config.xml:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <widget id="com.ionicframework.myapp551932" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
      <name>MyApp</name>
      <description>
            myApp
        </description>
      <author email="xxx@yyy.it" href="http://www.example.com/">
          A Team
        </author>
      <content src="index.html"/>
      <access origin="*"/>
      <preference name="webviewbounce" value="false"/>
      <preference name="UIWebViewBounce" value="false"/>
      <preference name="DisallowOverscroll" value="true"/>
      <preference name="BackupWebStorage" value="none"/>
      <preference name="SplashScreen" value="screen"/>
      <preference name="SplashScreenDelay" value="3000"/>
      <feature name="StatusBar">
        <param name="ios-package" value="CDVStatusBar" onload="true"/>
      </feature>
      <platform name="android">
        <config-file target="AndroidManifest.xml" parent="/manifest/application/activity">
          <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="file" />
            <data android:mimeType="*/*" />
            <data android:pathPattern=".*\.txt" />
            <data android:host="*" />
          </intent-filter>
          <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="content" />
            <data android:pathPattern=".*\.txt" />
            <data android:mimeType="*/*" />
          </intent-filter>
        </config-file>
        <icon src="resources/android/icon/drawable-ldpi-icon.png" density="ldpi"/>
        <icon src="resources/android/icon/drawable-mdpi-icon.png" density="mdpi"/>
        <icon src="resources/android/icon/drawable-hdpi-icon.png" density="hdpi"/>
        <icon src="resources/android/icon/drawable-xhdpi-icon.png" density="xhdpi"/>
        <icon src="resources/android/icon/drawable-xxhdpi-icon.png" density="xxhdpi"/>
        <icon src="resources/android/icon/drawable-xxxhdpi-icon.png" density="xxxhdpi"/>
        <splash src="resources/android/splash/drawable-land-ldpi-screen.png" density="land-ldpi"/>
        <splash src="resources/android/splash/drawable-land-mdpi-screen.png" density="land-mdpi"/>
        <splash src="resources/android/splash/drawable-land-hdpi-screen.png" density="land-hdpi"/>
        <splash src="resources/android/splash/drawable-land-xhdpi-screen.png" density="land-xhdpi"/>
        <splash src="resources/android/splash/drawable-land-xxhdpi-screen.png" density="land-xxhdpi"/>
        <splash src="resources/android/splash/drawable-land-xxxhdpi-screen.png" density="land-xxxhdpi"/>
        <splash src="resources/android/splash/drawable-port-ldpi-screen.png" density="port-ldpi"/>
        <splash src="resources/android/splash/drawable-port-mdpi-screen.png" density="port-mdpi"/>
        <splash src="resources/android/splash/drawable-port-hdpi-screen.png" density="port-hdpi"/>
        <splash src="resources/android/splash/drawable-port-xhdpi-screen.png" density="port-xhdpi"/>
        <splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" density="port-xxhdpi"/>
        <splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" density="port-xxxhdpi"/>
      </platform>
      <icon src="resources/android/icon/drawable-xhdpi-icon.png"/>
    </widget>

已解决!

我无法使用 Ionic 或 Cordova 来实现:这是 PhoneGap 的功能(请参阅此 Whosebug answer

我可以通过其他两种方式完成:

  1. 使用自定义 Cordova 插件
  2. 使用挂钩

我更喜欢第二种方式。我找到了一个 interesting hook 用于我的目的。 注意:记得安装一些包:

npm install lodash elementtree plist --save-dev

遗憾的是这个钩子合并了标签。 所以我写了这个钩子的一个小改动版本:see here。你可以把这个钩子放在 /hooks/after_platform_add.

现在我的 intent-filter 配置在 config.xml:

  <platform name="android">
    <config-file target="AndroidManifest.xml" parent="application/activity">
      <intent-filter><!-- ... --></intent-filter>
    </config-file>
    <!-- ... -->
  </platform>

我可以更新 AndroidManifest.xml 重新生成 android 平台:

ionic platform remove android && ionic platform add android

我遇到了同样的问题,但是安装(然后记住或记录依赖项)一堆 npm 依赖项然后使用一个大的通用挂钩的想法对于我需要的东西来说太重量级了。

挂钩可以是简单的 shell 脚本,这通常是一种更直接的修改文本文件的方法。在我的例子中,我只需要向 MainActivity activity 添加一个 intent-filter,这对于 sed 来说是一项微不足道的工作;我刚刚创建了文件 hooks/after_prepare/020_add_moozvine_intents.sh,内容为:

#!/usr/bin/env zsh

MANIFEST=${0:h}/../../platforms/android/AndroidManifest.xml
[[ -e $MANIFEST ]] || { print "Manifest not found at $MANIFEST." ; exit 1; }

grep -q HANDLE_MOOZVINE_NOTIFICATION $MANIFEST && { print "Manifest already modified. Nothing to do."; exit 0; }

AFTER_LINE='android:name="MainActivity"'
ADDITION='\
        <intent-filter>\
            <action android:name="HANDLE_MOOZVINE_NOTIFICATION" />\
            <category android:name="android.intent.category.DEFAULT" />\
        </intent-filter>
';

sed -i -e "/${AFTER_LINE}/a${ADDITION}" $MANIFEST

工作完成。您可以使用类似的方法对生成的文件进行任何简单的文本修改。

这是 Rich 用 JS 为未来的 Google 员工编写的上述解决方案,因为我在使用 shell 脚本时遇到了问题。

module.exports = function (context) {
    const fs = require('fs');
    const _ = require('lodash');

    const scheme = 'flowkey';
    const insertIntent = `
    <intent-filter>
                <action android:name="android.intent.action.VIEW"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <category android:name="android.intent.category.BROWSABLE"></category>
                <data android:scheme="${scheme}"></data>
    </intent-filter>
    `;
    const manifestPath = context.opts.projectRoot + '/platforms/android/AndroidManifest.xml';
    const androidManifest = fs.readFileSync(manifestPath).toString();
    if (!androidManifest.includes(`android:scheme="${scheme}"`)) {
        const manifestLines = androidManifest.split(/\r?\n/);
        const lineNo = _.findIndex(manifestLines, (line) => line.includes('@string/activity_name'));
        manifestLines.splice(lineNo + 1, 0, insertIntent);
        fs.writeFileSync(manifestPath, manifestLines.join('\n'));
    }
};

将其用作准备后挂钩。

注意:这是在 ES6 中,您可以在这里找到 ES5 版本:https://gist.github.com/smowden/f863331034bf300b960beef1ae25bf82

Cordova 9 现在直接支持使用 <config-file> and <edit-config> 部分,就像在 plugin.xml 文件中一样。

无需使用任何插件或hook,您可以直接执行以下操作,例如将intent过滤器添加到AndroidManifest.xml:

<?xml version='1.0' encoding='utf-8'?>
<widget id="yourdomain.app" version="1.7.8"
  xmlns="http://www.w3.org/ns/widgets"
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:cdv="http://cordova.apache.org/ns/1.0">
  <!-- ... -->
  <platform name="android">
    <!-- ... -->
    <config-file parent="application" target="AndroidManifest.xml">
      <activity android:label="webIntentFilter" android:name="yourdomain.app">
        <intent-filter android:autoVerify="true">
          <action android:name="android.intent.action.VIEW" />
          <category android:name="android.intent.category.DEFAULT" />
          <category android:name="android.intent.category.BROWSABLE" />
          <data android:host="yourdomain.com" android:scheme="https" />
        </intent-filter>
      </activity>
    </config-file>
  </platform>
  <!-- ... -->
</widget>

不要忘记将属性 xmlns:android="http://schemas.android.com/apk/res/android" 添加到您的 <widget> 标记中以避免构建时出现 unbound prefix 错误。