I would like a new entry to be added under "Header Search Paths" once my Cordova plugin is added to an Xcode project.
How can I config it in my Cordova plugin.xml file?
Thanks.
As far as I know, there's no way to do this on a project-wide basis.
However, there is a way to add to the search path for each of your source files, which accomplishes the same thing. The source-file element in plugin.xml supports a compiler-flags attribute. To this attribute, you may add any flags that the compiler (in this case the clang command) supports. The compiler flag to add to the header search path is -I<path>. Note that if you include a space (eg -I <path>), Cordova will produce a misformatted .xcodeproj folder, and you will not be able to open the project in Xcode, nor build the Cordova project from the command line. Note also that <path> in this case is relative to your .xcodeproj folder that Cordova generates.
So, for example, if you have these files in your plugin folder (let's call it ~/com.MyPlugin/):
myAngleHeader.h
mySource.m
mySource.h
where mySource.h contains the line #include <myAngleHeader.h>
and mySource.m contains the line #include "mySource.h"
You would then want to put into your plugin.xml (~/com.MyPlugin/plugin.xml):
<source-file src="myAngleHeader.h" />
<source-file src="mySource.h" />
<source-file src="mySource.m" compiler-flags="-ImyApp/Plugins/com.MyPlugin/" />
where "myApp" is the name of your Cordova project. Note again that there must be no space after the -I flag.
This method unfortunately requires that the developer control both the plugin and the Cordova project. It won't be very useful if you want to publish a plugin for all to use. There is probably a better way to do this; I'd love to hear other solutions.
Hope that helps!
#JohnWalthour
I needed to do this for a cordova plugin I am creating and with the "after plugin install" hook it is possible. I realized I could run a node.js script after install and modify the HEADER_SEARCH_PATHS in ${project}/platforms/ios/cordova/build.xcconfig.
It required getting dirty but it works great. One crucial part of this working is that the Bundle name is assigned to ${PRODUCT_NAME} in the info.plist so you can use ${PRODUCT_NAME} in your build.xcconfig and it will interpolate with your project/app name. Cordova already has the ${PRODUCT_NAME} variable set for you.
Here is the relevant code -
plugin.xml (shortened for brevity and the important stuff)
<platform name="ios">
.....
<hook type="after_plugin_install" src="hooks/AfterPluginInstall.js" />
<hook type="before_plugin_uninstall" src="hooks/BeforePluginUninstall.js" />
.....
</platform>
AfterPluginInstall.js
#!/usr/bin/env node
'use strict';
let cwd = process.cwd();
let fs = require('fs');
let path = require('path');
console.log('InstagramAssetsPicker AfterPluginInstall.js, attempting to modify build.xcconfig');
let xcConfigBuildFilePath = path.join(cwd, 'platforms', 'ios', 'cordova', 'build.xcconfig');
console.log('xcConfigBuildFilePath: ', xcConfigBuildFilePath);
let lines = fs.readFileSync(xcConfigBuildFilePath, 'utf8').split('\n');
let headerSearchPathLineNumber;
lines.forEach((l, i) => {
if (l.indexOf('HEADER_SEARCH_PATHS') > -1) {
headerSearchPathLineNumber = i;
}
});
if (lines[headerSearchPathLineNumber].indexOf('InstagramAssetsPicker') > -1) {
console.log('build.xcconfig already setup for InstagramAssetsPicker');
return;
}
lines[headerSearchPathLineNumber] += ' "$(SRCROOT)/$(PRODUCT_NAME)/cordova-plugin-InstagramAssetsPicker/GPUImageHeaders"';
let newConfig = lines.join('\n');
fs.writeFile(xcConfigBuildFilePath, newConfig, function (err) {
if (err) {
console.log('error updating build.xcconfig, err: ', err);
return;
}
console.log('successfully updated HEADER_SEARCH_PATHS in build.xcconfig');
});
BeforePluginUninstall.js
#!/usr/bin/env node
'use strict';
let cwd = process.cwd();
let fs = require('fs');
let path = require('path');
console.log('InstagramAssetsPicker BeforePluginInstall.js, attempting to modify build.xcconfig');
let xcConfigBuildFilePath = path.join(cwd, 'platforms', 'ios', 'cordova', 'build.xcconfig');
console.log('xcConfigBuildFilePath: ', xcConfigBuildFilePath);
let lines = fs.readFileSync(xcConfigBuildFilePath, 'utf8').split('\n');
let headerSearchPathLineNumber;
lines.forEach((l, i) => {
if (l.indexOf('HEADER_SEARCH_PATHS') > -1) {
headerSearchPathLineNumber = i;
}
});
if (lines[headerSearchPathLineNumber].indexOf('InstagramAssetsPicker') === -1) {
console.log('build.xcconfig does not have header path for InstagramAssetsPicker.');
return;
}
let line = lines[headerSearchPathLineNumber];
lines[headerSearchPathLineNumber] = line.replace(/\ "\$\(SRCROOT\)\/\$\(PRODUCT_NAME\)\/cordova-plugin-InstagramAssetsPicker\/GPUImageHeaders\"/i, '');
let newConfig = lines.join('\n');
fs.writeFile(xcConfigBuildFilePath, newConfig, function (err) {
if (err) {
console.log('error updating build.xcconfig, err: ', err);
return;
}
console.log('successfully updated HEADER_SEARCH_PATHS in build.xcconfig');
});
I wanted to update my header search paths via the config as it was always a manual task setting it on build day. I have since added this plugin:
Cordova-Custom-Plugin
I was then able to add these to my config and didn't have to worry about it again.
<platform name="ios">
<!-- Set orientation on iPhone -->
<config-file platform="ios" target="*-Info.plist" parent="UISupportedInterfaceOrientations">
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
</config-file>
<!-- Set orientation on iPad -->
<config-file platform="ios" target="*-Info.plist" parent="UISupportedInterfaceOrientations~ipad">
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</config-file>
<!-- Set Header Search Paths-->
<preference name="ios-XCBuildConfiguration-HEADER\_SEARCH\_PATHS" value="'$(TARGET_BUILD_DIR)/usr/local/lib/include' '$(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include' '$(BUILT_PRODUCTS_DIR)'" buildType="release" xcconfigEnforce="true" />
Related
Is it possible to build the windows desktop app at fullscreen? 'Cause initially when I run my app, the size is at 1200x900.
In my config.xml I have this <preference name="Fullscreen" value="true" />
I also have this code based on my research from cordova-plugin-statusbar :
this.platform.ready().then(() => {
StatusBar.hide();
});
But I have no luck in running the app at fullscreen for Windows. I have found a solution but only for android:
if (this.platform.is("android")) {
this.androidFullScreen.isImmersiveModeSupported().then(
() => this.androidFullScreen.immersiveMode()
).catch((error: any) => console.log(error));
}
you can try below code , add in page.ts file
ionViewWillEnter() {
this.statusBar.overlaysWebView(true);
}// where you want full screen
ionViewWillEnter() {
this.statusBar.overlaysWebView(true);
}// where you want normal screen
When I create two new apps with tns, one is the regular js version and one is with typescript. I get a strange error in the typescript version when I try to access a native library.
When I create a loaded function with a console.log(pow(x,y)), it works fine with the js version but the typescript version crashes with this error.
error TS2304: Cannot find name 'pow'.
Why?
TS:
import { EventData } from "data/observable";
import { Page } from "ui/page";
import { HelloWorldModel } from "./main-view-model";
// Event handler for Page "navigatingTo" event attached in main-page.xml
export function navigatingTo(args: EventData) {
// Get the event sender
var page = <Page>args.object;
page.bindingContext = new HelloWorldModel();
}
export function loaded() {
console.log('Hello World')
console.log('pow(2.5, 3) = ', pow(2.5, 3));
}
JS:
var createViewModel = require("./main-view-model").createViewModel;
function onNavigatingTo(args) {
var page = args.object;
page.bindingContext = createViewModel();
}
function loaded() {
console.log('hello world')
console.log('pow(2.5, 3) = ', pow(2.5, 3));
}
exports.onNavigatingTo = onNavigatingTo;
exports.loaded = loaded;
TypeScript is strongly typed language and needs an explicit type definition for each variable (e.g. like pow). Instead of casting to any, you could provide definition files pre-generated by NativeScript that will give you typing and IntelliSense for the native Android and iOS APIs.
The latest release of NativeScript by default is creating the app without the platform declaration files (android17.d.ts for Android and ios.d.ts for iOS) and without those files, your TypeScript simply does not know about the native APIs references.
The reason not to include the definition files - those are enormously big and are needed only when the developers are going to use TypeScript (or Angular) + access to native APIs.
The solution:
1.) Install the definition files as a developer dependency
npm i tns-platform-declarations --save-dev
This will install your platform declaraion files in node_modules/tns-platform-declarations
2.) Create references.d.ts in your main app directory and add the following
// SEE the updated paths below
Now you are good to go!
UPDATE (as of October 2017 - with installing tns-core-modules 3.x.x (or above) and tns-platform-declarations 3.x.x (or above)):
The npm plugin now has a different structure so these are the proper paths (create references.d.ts file in the root directory and place the one below)
/// <reference path="./node_modules/tns-platform-declarations/ios/ios.d.ts" />
/// <reference path="./node_modules/tns-platform-declarations/android/android.d.ts" />
Important: Your tsconfig.json should look like this:
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"experimentalDecorators": true,
"lib": [
"es6",
"dom"
]
}
}
I have used following commands in my browser.xul to set a shortcut for my addon.
<keyset id="mainKeyset">
<key id="key_convert"
modifiers="accel"
keycode="VK_F12"
oncommand="myfunction()" />"
</keyset>
It used to work for previous versions of Firefox, but not anymore for newer versions.
has anything changed in the syntax?
Thanks
That code example looks correct, I suspect that there is some code within myfunction() that is failing, so we need more information probably. Try to replace myfunction() with alert("test"), that should work.
Some notes:
You must add it to a keyset, as the key listeners are attached when keyset is added
source: http://forums.mozillazine.org/viewtopic.php?f=19&t=2711165&p=12885299&hilit=mainKeyset#p12885299
You must set an oncommand attribute
source: How to set an XUL key dynamically and securely?
Can copy paste this to scratchpad:
var keyset = document.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul', 'keyset'); //http://forums.mozillazine.org/viewtopic.php?f=19&t=2711165&p=12885299&hilit=mainKeyset#p12885299
//cant use mainKeyset see topic above
var key = document.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul', 'key');
var props = {
id: 'key_convert',
modifiers: 'accel',
keycode: 'VK_F12',
oncommand: 'alert("tirggered")'
};
for (var p in props) {
key.setAttribute(p, props[p]);
}
keyset.appendChild(key);
Services.wm.getMostRecentWindow('navigator:browser').document.documentElement.appendChild(keyset);
I used following function for the windows mobile app(phonegap) to handle the backbutton navigation function.
function onBackKeyDown() {
var currentPageId = $.mobile.activePage.attr('id');
if(currentPageId == 'contact-us' || currentPageId == 'about-us' || currentPageId == 'location-map' || currentPageId == 'services'){
$.mobile.changePage("index.html", {
transition : "slide",
reverse : true,
changeHash : false
});
}else{
navigator.app.exitApp();
}
}
I wanted to come to the index if the current page is not index. Otherwise exit the app.
It seems like navigator.app.exitApp() doesn't work in windows phone 7. Is there any solution for overcome this issue.
This plugin came in handy for me.
http://shinymetilda.github.io/Cordova_Exit_Plugin/
Add the .cs file to your plugin directory.
Add the following code to config.xml
<feature name="AppTerminate">
<param name="wp-package" value="AppTerminate" />
</feature>
write this code instead of navigator.app.exitApp()
cordova.exec(null, null, "AppTerminate", "execute", []);
I want to inject a css file located on the skin folder in a browser page.
It is located on chrome://orkutmanager/skin/om.css, accessing manually show the file contents correctly.
I've tried this, but it's not working... What am I missing, or is it impossible?
You can also use the nsIStyleSheetService:
loadCSS: function() {
var sss = Components.classes["#mozilla.org/content/style-sheet-service;1"]
.getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var uri = ios.newURI("chrome://addon/skin/style.css", null, null);
if(!sss.sheetRegistered(uri, sss.USER_SHEET))
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
}
If you use USER_SHEET, the website's own CSS rules have higher priority than yours. Using AGENT_SHEET, your CSS should have higher priority.
In any way I needed to enforce some rules by using hte !important keyword.
I found this workaround. Read the file then inject it's contents...
function Read(file)
{
var ioService=Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var scriptableStream=Components
.classes["#mozilla.org/scriptableinputstream;1"]
.getService(Components.interfaces.nsIScriptableInputStream);
var channel=ioService.newChannel(file,null,null);
var input=channel.open();
scriptableStream.init(input);
var str=scriptableStream.read(input.available());
scriptableStream.close();
input.close();
return str;
}
var style = $("<style type='text/css' />");
style.html(Read("chrome://orkutmanager/skin/om.css"));
$("head").append(style);
I found that the link you referred to works if you reference the page document. In my case, using gBrowser.contentDocument worked.
var fileref = gBrowser.contentDocument.createElement("link");
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", "resource://extensionid/content/skin/style.css");
gBrowser.contentDocument.getElementsByTagName("head")[0].appendChild(fileref);
Obviously make sure that you can access your css via the resource:// protocol.