Ionic/Cordova: добавьте фильтр намерений с помощью config.xml
Я разрабатываю мобильное приложение с использованием Ionic Framework (на основе Кордовы).
В Android я зарегистрирую свое приложение, чтобы открыть *.txt файлы.
Я делаю это, добавляя фильтр намерений в platform/android/AndroidManifest.xml, и он работает.
Но папка платформы находится в .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
ionic prepare
Или также:
ionic remove platform android && ionic add platform android
Но AndroidManifest.xml всегда неизменен.
Что я делаю неправильно?
Я использую Ionic 1.3.2 и Cordova 4.2.0.
Edit
Здесь весь 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="[email protected]" href="#" onclick="location.href='http://www.example.com/'; return false;">
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>
Ответы
Ответ 1
Cordova 9 теперь напрямую поддерживает использование разделов <config-file>
и <edit-config>
, как в файлах plugin.xml.
Без использования какого-либо плагина или перехватчика вы можете напрямую сделать следующее, например, чтобы добавить фильтр намерений в 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
при сборке.
Ответ 2
Решено!
Я не могу сделать это с помощью Ionic или Cordova: это функция PhoneGap (см. этот fooobar.com/questions/451124/...)
Я могу сделать это двумя другими способами:
- Использование собственного плагина Cordova
- Использование крючка
Я предпочел второй путь. Я нашел интересный крючок для своих целей.
Примечание. Не забудьте установить некоторые пакеты:
npm install lodash elementtree plist --save-dev
К сожалению, этот крючок объединяет теги.
Поэтому я написал немного измененную версию этого хука: смотрите здесь. Вы можете поместить этот хук в /hooks/after_platform_add.
Теперь у меня есть конфигурация фильтра намерений в 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
Ответ 3
У меня была та же проблема, но идея установить (а затем запомнить или задокументировать зависимость) кучу зависимостей нпм, а затем использовать большой универсальный крючок была слишком тяжелой для того, что мне было нужно.
Крюками могут быть простые сценарии оболочки, которые часто являются гораздо более простым способом изменения текстовых файлов. В моем случае мне нужно было добавить фильтр-намерение в действие MainActivity
, которое является тривиальным заданием для 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
Работа выполнена. Вы можете использовать аналогичный подход для любых простых текстовых модификаций сгенерированных файлов.
Ответ 4
Вот приведенное выше решение Rich написано в JS для будущих Googlers, поскольку у меня были проблемы с оболочкой script.
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