Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cordova 5 build command is deleting iOS device orientation settings

With Cordova 5.1.1, when executing "cordova build ios", any device orientation settings previously selected in the XCode project are deleted leaving the orientation settings checkboxes unselected.

While the "orientation" config preference may provide a means of forcing orientation, I need to be able to set different orientation preferences for the iPad and iPhone.

All previous Cordova versions (below 5) respected those settings. Any ideas?

Using XCode 6.3.2.

like image 214
sdesapio Avatar asked Jun 15 '15 15:06

sdesapio


2 Answers

EDIT:

According to @Abhinav Gujjar the issue causing cordova prepare to overwrite manual changes made to orientation settings in the .plist has been fixed. However, AFAIK there's still no way to set different orientation preferences for iPad vs iPhone in the config.xml, so the answer below stands.

UPDATE:

I created the plugin cordova-custom-config, which wraps up the hook below and means platform-specific custom config blocks (such as these orientation settings) can be defined in config.xml. So you can use the plugin rather than need to manually create the hook below.


This was introduced in the Cordova 5.0.0 CLI - see here.

In the meantime, I've been using an after_prepare hook as a workaround. Just place the following in <your_project>/hooks/after_prepare/some_file.js and change the orientation settings as appropriate:

#!/usr/bin/env node

// Set support for all orienations in iOS .plist - workaround for this cordova bug: https://issues.apache.org/jira/browse/CB-8953
var platforms = process.env.CORDOVA_PLATFORMS.split(',');
platforms.forEach(function(p) {
    if (p == "ios") {
        var fs = require('fs'),
            plist = require('plist'),
            xmlParser = new require('xml2js').Parser(),
            plistPath = '',
            configPath = 'config.xml';
        // Construct plist path.
        if (fs.existsSync(configPath)) {
            var configContent = fs.readFileSync(configPath);
            // Callback is synchronous.
            xmlParser.parseString(configContent, function (err, result) {
                var name = result.widget.name;
                plistPath = 'platforms/ios/' + name + '/' + name + '-Info.plist';
            });
        }
        // Change plist and write.
        if (fs.existsSync(plistPath)) {
            var pl = plist.parseFileSync(plistPath);
            configure(pl);
            fs.writeFileSync(plistPath, plist.build(pl).toString());
        }
        process.exit();
    }
});
function configure(plist) {
    var iPhoneOrientations = [
        'UIInterfaceOrientationLandscapeLeft',
        'UIInterfaceOrientationLandscapeRight',
        'UIInterfaceOrientationPortrait',
        'UIInterfaceOrientationPortraitUpsideDown'
    ];
    var iPadOrientations = [
            'UIInterfaceOrientationLandscapeLeft',
            'UIInterfaceOrientationLandscapeRight',
            'UIInterfaceOrientationPortrait',
            'UIInterfaceOrientationPortraitUpsideDown'
    ];
    plist["UISupportedInterfaceOrientations"] = iPhoneOrientations;
    plist["UISupportedInterfaceOrientations~ipad"] = iPadOrientations;
}

Note: you'll need to install the plist and xml2js node modules if you don't already have them.

like image 192
DaveAlden Avatar answered Nov 15 '22 08:11

DaveAlden


IF you want to, you can to it programmatically on the JS side.

For iOS, orientation can be programmatically controlled by defining a javascript callback on window

/** 
// @param {Number} degree - UIInterfaceOrientationPortrait: 0,
// UIInterfaceOrientationLandscapeRight: 90, 
// UIInterfaceOrientationLandscapeLeft: -90,     
// UIInterfaceOrientationPortraitUpsideDown: 180
* @returns {Boolean} Indicating if rotation should be allowed.
*/
function shouldRotateToOrientation(degrees) {
     return true;
}

Set allowed orientations in your config.xml file

<platform name="ios">
    <preference name="Orientation" value="all" />
</platform>

And add the shouldRotateToOrientation(degrees)

onDeviceReady: function() {
    app.receivedEvent('deviceready');
    window.shouldRotateToOrientation = function(degrees) {
        //if device an iPad ?
        if ( navigator.userAgent.match(/iPad/i) ) {
            return true;
        } 
        //else if device an iPhone ?
        else if (navigator.userAgent.match(/iPhone/i)) {
            if (degrees == 0) { //orientation is portrait
              return true;
            }
            return false; //refuse all other orientations for iPhone
        }
        return true;
    };
}
like image 39
Niko Avatar answered Nov 15 '22 08:11

Niko