Skip to content
This repository has been archived by the owner on Oct 1, 2018. It is now read-only.

Refactored plugin hooks for newer XCode cli builds and codova >7 #129

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ is the same as:
</universal-links>
```

#### ios-team-id
#### ios-team-release

As described in `Step 2` of [Configure apple-app-site-association file for website](#configure-apple-app-site-association-file-for-website) section: when application is build from the CLI - plugin generates `apple-app-site-association` files for each host, defined in `config.xml`. In them there's an `appID` property that holds your iOS Team ID and Bundle ID:

Expand All @@ -261,11 +261,11 @@ As described in `Step 2` of [Configure apple-app-site-association file for websi
<widget id="com.example.ul" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
```

- `<TEAM_ID_FROM_MEMBER_CENTER>` - that property is defined in the member center of your iOS account. So, you can either put it in the generated `apple-app-site-association` file manually, or use `<ios-team-id>` preference in `config.xml` like so:
- `<TEAM_ID_FROM_MEMBER_CENTER>` - that property is defined in the member center of your iOS account. So, you can either put it in the generated `apple-app-site-association` file manually, or use `<ios-team-release>` preference in `config.xml` like so:

```xml
<universal-links>
<ios-team-id value="<TEAM_ID_FROM_MEMBER_CENTER>" />
<ios-team-release value="<TEAM_ID_FROM_MEMBER_CENTER>" />
</universal-links>
```

Expand All @@ -276,7 +276,7 @@ For example, following `config.xml`
<!-- some other cordova preferences -->

<universal-links>
<ios-team-id value="1Q2WER3TY" />
<ios-team-release value="1Q2WER3TY" />
<host name="mysite.com" >
<path url="/some/path/*" />
</host>
Expand All @@ -303,6 +303,8 @@ will result into

This is iOS-only preference, Android doesn't need it.

**Note:** If you want a different debug team, you can configure it using the `<ios-team-debug>` tag. Also projects that already have a `debug.json` present will be used in advance of this configuration.

#### Prevent Android from creating multiple app instances

When clicking on a universal link from another App (typically from an email client), Android will likely create a new instance of your app, even if it is already loaded in memory. It may even create a new instance with each click, resulting in many instances of your app in the task switcher. See details in [issue #37](https://github.com/nordnet/cordova-universal-links-plugin/issues/37).
Expand Down
86 changes: 0 additions & 86 deletions hooks/afterPrepareHook.js

This file was deleted.

184 changes: 184 additions & 0 deletions hooks/android/updateAndroidManifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
(function () {
// properties
'use strict';
var path = require('path');
var xmlHelper = require('../lib/xmlHelper.js');

// entry
module.exports = {
writePreferences: writePreferences
};

// injects config.xml preferences into AndroidManifest.xml file.
function writePreferences (context, preferences) {
var pathToManifest = path.join(context.opts.projectRoot, 'platforms', 'android', 'AndroidManifest.xml');
var manifest = xmlHelper.readXmlAsJson(pathToManifest);
var mainActivityIndex = getMainLaunchActivityIndex(manifest['manifest']['application'][0]['activity']);

// update manifest
manifest = updateLaunchOptionToSingleTask(manifest, mainActivityIndex);
manifest = updateUniversalLinksAppLinks(manifest, mainActivityIndex, preferences);

// save new version of the AndroidManifest
xmlHelper.writeJsonAsXml(pathToManifest, manifest);
}

// adds to main <activity>:
// android:launchMode="singleTask"
function updateLaunchOptionToSingleTask (manifest, mainActivityIndex) {
manifest['manifest']['application'][0]['activity'][mainActivityIndex]['$']['android:launchMode'] = 'singleTask';
return manifest;
}

// adds to main <activity> for App Links (optional)
// <intent-filter android:name="<bundle-id>.UniversalLinks" 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:scheme="https" android:host="ethan.app.link" />
// <data android:scheme="https" android:host="ethan-alternate.app.link" />
// </intent-filter>
function updateUniversalLinksAppLinks (manifest, mainActivityIndex, preferences) {
var intentFilters = manifest['manifest']['application'][0]['activity'][mainActivityIndex]['intent-filter'] || [];
var data = getAppLinkIntentFilterData(preferences);
var androidName = preferences.androidBundleId + '.UniversalLinks';

// remove
intentFilters = removeBasedOnAndroidName(intentFilters, androidName);

// add new
manifest['manifest']['application'][0]['activity'][mainActivityIndex]['intent-filter'] = intentFilters.concat([{
'$': {
'android:name': androidName,
'android:autoVerify': 'true'
},
'action': [{
'$': {
'android:name': 'android.intent.action.VIEW'
}
}],
'category': [{
'$': {
'android:name': 'android.intent.category.DEFAULT'
}
}, {
'$': {
'android:name': 'android.intent.category.BROWSABLE'
}
}],
'data': data
}]);

return manifest;
}

// determine the Universal Links domain <data> to append to the App Link intent filter
function getAppLinkIntentFilterData (preferences) {
var intentFilterData = [];
var hosts = preferences.hosts;

hosts.forEach(function(host) {
host.paths.forEach(function(path) {
// app.link link domains need -alternate associated domains as well (for Deep Views)
if (host.name.indexOf('app.link') !== -1) {
var first = host.name.split('.')[0];
var rest = host.name.split('.').slice(1).join('.');
var alternate = first + '-alternate' + '.' + rest;

intentFilterData.push(getAppLinkIntentFilterDictionary(host.name, host.scheme, path));
intentFilterData.push(getAppLinkIntentFilterDictionary(alternate, host.scheme, path));
} else {
// bnc.lt and custom domains
intentFilterData.push(getAppLinkIntentFilterDictionary(host.name, host.scheme, path));
}
});
});

return intentFilterData;
}

// generate the array dictionary for <data> component for the App Link intent filter
function getAppLinkIntentFilterDictionary (host, scheme, path) {
var output = {
'$': {
'android:host': host,
'android:scheme': scheme
}
};

if (path && path !== '*') {
var key = 'android:path';
if (~path.indexOf('*')) {
key = 'android:pathPattern';
path = path.replace(/\*/g, '.*');
}

if (path.indexOf('/') !== 0) {
path = '/' + path;
}

output['$'][key] = path;
}

return output;
}

// remove previous Branch related <meta-data> and <receiver> based on android:name
function removeBasedOnAndroidName (items, androidName) {
var without = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (item.hasOwnProperty('$') && item['$'].hasOwnProperty('android:name')) {
var key = item['$']['android:name'];
if (key === androidName) {
continue;
}
without.push(item);
} else {
without.push(item);
}
}
return without
}

// get the main <activity> because Branch Intent Filters must be in the main Launch Activity
function getMainLaunchActivityIndex (activities) {
var launchActivityIndex = -1;

for (var i = 0; i < activities.length; i++) {
var activity = activities[i];
if (isLaunchActivity(activity)) {
launchActivityIndex = i;
break
}
}

return launchActivityIndex;
}

// determine if <activity> is the main activity
function isLaunchActivity (activity) {
var intentFilters = activity['intent-filter'];
var isLauncher = false;

if (intentFilters == null || intentFilters.length === 0) {
return false;
}

isLauncher = intentFilters.some(function (intentFilter) {
var action = intentFilter['action'];
var category = intentFilter['category'];

if (action == null || action.length !== 1 || category == null || category.length !== 1) {
return false;
}

var isMainAction = action[0]['$']['android:name'] === 'android.intent.action.MAIN';
var isLauncherCategory = category[0]['$']['android:name'] === 'android.intent.category.LAUNCHER';

return isMainAction && isLauncherCategory;
});

return isLauncher;
}
})();
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ https://developer.android.com/training/app-indexing/enabling-app-indexing.html
var fs = require('fs');
var path = require('path');
var mkpath = require('mkpath');
var ConfigXmlHelper = require('../configXmlHelper.js');
var WEB_HOOK_FILE_PATH = path.join('ul_web_hooks', 'android', 'android_web_hook.html');
var WEB_HOOK_TPL_FILE_PATH = path.join('plugins', 'cordova-universal-links-plugin', 'ul_web_hooks', 'android_web_hook_tpl.html');
var LINK_PLACEHOLDER = '[__LINKS__]';
Expand All @@ -30,8 +29,7 @@ module.exports = {
*/
function generateWebHook(cordovaContext, pluginPreferences) {
var projectRoot = cordovaContext.opts.projectRoot;
var configXmlHelper = new ConfigXmlHelper(cordovaContext);
var packageName = configXmlHelper.getPackageName('android');
var packageName = pluginPreferences.androidBundleId;
var template = readTemplate(projectRoot);

// if template was not found - exit
Expand Down Expand Up @@ -159,4 +157,4 @@ function createDirectoryIfNeeded(dir) {
}
}

// endregion
// endregion
55 changes: 0 additions & 55 deletions hooks/beforePluginInstallHook.js

This file was deleted.

Loading