Morning Lads/ladies,
Shortest background I can write: In-house application for managing inventory, developer made redundant, no iOS Developers in the company, in comes me. I have no iOS developing experience, limited HTML/Javascript programming background.
App runs on iOS v6.1.6, had to fish out Macbook from '08, now running El Capitan v10.11.6, and xCode v 6.4 (6E35b). I don't know what software/OS versions were used to develop the app/maintain it. Xcode is set to make the Project Format: Xcode 3.2-compatible.
Painfully, I have managed to locate prev. developers xcodeproj file, change to my developer profile for code signing, clean/build/archive/export a .ipa. This installs and the app runs on the intended devices.
Error is: Update Available, An updated application is available and will install now.
Only occurs when the user chooses his user profile (no password, just press User > Userprofile), a store (which section of the warehouse the items are), navigates around the app for a few seconds, presses the Home button and then reopens the application.
Currently, you have to uninstall (regular iOS uninstall)/reinstall via webserver to fix the issue. I have tried removing the files from the webserver after reinstall. The update is still prompted. The update will install the application successfully. If you open the app after this 'update' it will instantly prompt to update again.
My question is, if this isn't too vague, where could I look first to find the cause of this supposed 'loop' of updating?
EDIT1: *****Workflow:******
I've pulled the project file from the depths of the messy Stocktake folder(8 different distributions/versions scattered) using the last modified dates.
After loading the project into Xcode, the first item that demands attention is 'Validate Project Settings'. These including (under the sub-heading, bolded, Build Settings) Target 'StockTake' - Automatically Select Architectures, Project 'StockTake' - Automatically Select Architectures, Project 'StockTake' - Enable build active architecture only when debugging. I perform the changes and enable the subsequent popup asking to create a snapshot.
From the top, Stocktake Info, Deployment target, iOS Deployment Target [6 . 1]
Switch to Identity: Bundle Identifier is correct (has been changed from previous owner, I hack-jobbed this using notepad++ and navigating through the project files looking for anything related to him)
Version: [1.0] (i'll leave it as this this time round)
Build: [1.0]
I also make sure that the correct Team is selected.
BUILD SETTINGS
Architectures: Base SDK [Latest iOS (iOS 8.4)]
Code signing: All either iOS Developer, or automatic.
Everything else is left as it is when I bring up the project file.
Clean, Clean Succeeded
Build, Build Stocktake: Succeeded
Then, Product, Destination, iOS Device
Archive
(Can see Stocktake, creation date, Version is what is listed above [1.0])
Validate, Choose correct team, Provisioning profile is what XC has created
iTunes Store operation failed (No suitable app records were found, check bundle identifier)
I leave this as is because I can use the export function in the organizer successfully anyway.
Export, Save Ad Hoc Dep., Choose correct team, Export with XC-created prov. profile, Export
.ipa is created successfully.
I can go more in-depth, but I don't want to make a MASSIVE wall of text. I can upload a PDF of my in-depth findings somewhere if need be.
-(void) promptForUpdate
{
CCAlertView *alert = [[CCAlertView alloc] initWithTitle:#"Update Available" message:#"An updated application is available and will install now."];
[alert addButtonWithTitle:#"Ok" block:^{
// open update URL in Web Browser
if (![[UIApplication sharedApplication] openURL:kUpdaterURL]) {
ALog(#"Failed to open app updater URL: %#", kUpdaterURL);
}
}];
[alert show];
}
I managed to solve this particular issue, we will see if any more issues pop up. There must have been a version mismatch between the appname.plist, and two web.config files related to an Oracle database this app connects to. We run two Maximo environments here, production and test.
To fix this problem:
I opened appname.plist(Stocktake.plist in my case) and found the following coding:
<key>bundle-version</key>
<string>1.0</string>
I editted this to:
<key>bundle-version</key>
<string>1.16</string>
This was to match the two webconfig files, which looked like this:
<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="true" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="MaximoConnection" value="provider=OraOLEDB.Oracle; data source=maximo75test; user id=; password=;" />
<add key="BatchSize" value="200" />
<add key="Version" value="1.16" />
I didn't touch the bundle-version string, because throughout each previous distribution I found, it had been 1.0. I had played around with the web.config Version file before, but was matching it to the App version I was creating in Xcode (I think the last version I tried creating was 1.6). I'm unsure why this worked, I haven't entered 1.16 into any of the .ipas I created, it was 1.16 when I initially started my troubleshooting,but it could have something to do with Maximo (perhaps Maximo is version 1.16?).
If anyone has trouble with this 'Update Available' loop, i'd suggest trying to find the last iteration of whatever application you're working with, and the latest version of the software you're integrating with, and set the version AND build to the same number before you export. It isn't best practice, but at least if you can get it working, you can slowly replace versions/builds until you find the problem.
This post (linked below) helped me come to the conclusion of changing the versions:
Version vs build in XCode
According to this bug report, custom iOS Frameworks are added automatically to Xcode's 'Embed Binaries' section.
The 'offending' code linked to from that bug report (the code I actually need) is also present in the version of Cordova I'm using (version 6.0.0, via Meteor), but the framework is still added is a non-embedded binary, making my app fail on startup.
So I'm wondering how I can ensure my custom frameworks get embedded?
The code in question looks like this (in my plugin.xml):
<platform name="ios">
<framework src="build/MyFramework.framework" custom="true" />
</platform>
Try to use the new 'embed' option that is mentioned in the jira ticket to see if they are available in your cordova version.
<platform name="ios">
<framework src="build/MyFramework.framework" custom="true" embed="true"/>
</platform>
Maybe the default value for embed is false.
i have a small project using the plugin plugin.google.maps (https://github.com/wf9a5m75/phonegap-googlemaps-plugin) .
Also, i use phonegap buid service, not CLI.
In config.xml file i have the code
<gap:plugin name="plugin.google.maps" source="plugins.cordova.io" version="~1.2.4">
<param name="API_KEY_FOR_ANDROID" value="xxx" />
<param name="API_KEY_FOR_IOS" value="xxx" />
</gap:plugin>
Android apk's works like a charm, but on ios device i get the message
"Api key is not setted.
Please replace 'API_KEY_FOR_IOS' in the platforms/ios/.../...Info.plist with your API key."
Does anyone have a clue how i can solve this using the phonegap build service?
Despite the fact that this was supposed to work
(https://github.com/wf9a5m75/phonegap-googlemaps-plugin/issues/411#issuecomment-75452290)
after a couple of days in a nutshell i figured that i had to override the instructions for ios property list for the plist key "Google Maps API Key".
So, in config.xml i inserted the code:
<gap:config-file platform="ios" parent="Google Maps API Key" mode="replace">
<string>xxx</string>
</gap:config-file>
where xxx is the Google Maps API Key for iOS
http://docs.build.phonegap.com/en_US/configuring_config_file_element.md.html
I'm using Phonegap Build to compile a game I made using Construct 2.
Now when I install the game on my iphone a geolocation permission alerts pops up, although my game doesn't use geolocation.
I think phonegap somehow inserts geolocation code into the .ipa file
I thought this wasn't gonna be a problem, but I submitted the game to the appstore and the reviewer is asking me what features of my game use geolocation. My game status in itunes connect right now is 'metadata rejected' because of this.
Is there a way to remove this geolocation thing?
I already googled the problem but I can't find a solution.
Here's my config.xml file:
> <preference name="permissions" value="none"/> <preference
> name="android-targetSdkVersion" value="21" /> <feature
> name="http://api.phonegap.com/1.0/network"/> <gap:config-file
> platform="ios" parent="UIStatusBarHidden"><true/></gap:config-file>
> <gap:config-file platform="ios"
> parent="UIViewControllerBasedStatusBarAppearance"><false/></gap:config-file> </widget>
#gleegum, when you install the plugin via config.xml, it will initiate the Geolocation permission sequence. Did you perhaps accidentally insert the geolocation plugin into your config.xml? -Jesse
I am new to the Cordova CLI.
I need to perform the following steps programmatically via Cordova.
In the project .plist add a new row
Enter the following values in the new row:
Key: GDLibraryMode Type:String (default) Value:GDEnterpriseSimulation
I think I need to do this in the config.xml file in my project's root (or maybe the one in the "platforms" folder).
Can someone explain to me how to add the entry via the config.xml so that the above entry is added at compile-time?
I am using Cordova 3.3.1-0.42 (I know it is not the latest). I have already made my project and all is fine, I just need to add this entry added to the pList.
EDIT: 2/8/21
As per a comment on this question:
For anyone coming late to this, setting values in the project plist is now supported by Cordova CLI 7 and above
I don't think you can do this via straight config.xml modification. At least, I didn't see any mention of this in the docs: http://cordova.apache.org/docs/en/3.3.0/config_ref_index.md.html
I think you have to create a plugin, because they can insert plist entries: http://docs.phonegap.com/en/3.3.0/plugin_ref_spec.md.html#Plugin%20Specification
See the 'config-file element' section. Here's a guess as to what the relevant section of the plugin.xml will look like:
<platform name="ios">
<config-file target="*-Info.plist" parent="CFBundleURLTypes">
<array>
<dict>
<key>GDLibraryMode</key>
<string>GDEnterpriseSimulation</string>
</dict>
</array>
</config-file>
</platform>
Then you can install the plugin: cordova plugin add <your plugin name or file location>
I really like #james's solution using a Cordova hook. However, there are two issues. The docs state:
"we highly recommend writing your hooks using Node.js"
"/hooks directory is considered deprecated in favor of the hook elements in config.xml"
Here's a Node.js implementation using the plist NPM package:
var fs = require('fs'); // nodejs.org/api/fs.html
var plist = require('plist'); // www.npmjs.com/package/plist
var FILEPATH = 'platforms/ios/.../...-Info.plist';
module.exports = function (context) {
var xml = fs.readFileSync(FILEPATH, 'utf8');
var obj = plist.parse(xml);
obj.GDLibraryMode = 'GDEnterpriseSimulation';
xml = plist.build(obj);
fs.writeFileSync(FILEPATH, xml, { encoding: 'utf8' });
};
Of all the hook types provided by Cordova, the relevant ones for your situation are:
after_prepare
before_compile
Choose a hook type, and then add the hook to your config.xml file:
<platform name="ios">
<hook type="after_prepare" src="scripts/my-hook.js" />
</platform>
You can use the PlistBuddy utility inside a Cordova hook script to modify the *-Info.plist file.
For example, I have the following script under <project-root>/hooks/after_prepare/010_modify_plist.sh which adds a dictionary property and adds an entry within that dictionary:
#!/bin/bash
PLIST=platforms/ios/*/*-Info.plist
cat << EOF |
Add :NSAppTransportSecurity dict
Add :NSAppTransportSecurity:NSAllowsArbitraryLoads bool YES
EOF
while read line
do
/usr/libexec/PlistBuddy -c "$line" $PLIST
done
true
Be sure to make the script executable (chmod +x).
The true at the end of the script is because PlistBuddy returns with an error exit code if the key being added already exists, and doesn't provide a way to detect if the key already exists. Cordova will report a build error if the hook script exits with an error status. Better error handling is possible but a pain to implement.
These are the steps I ended up doing to enable my application to share files through itunes between devices.
1.In your application navigate to your config.xml. Type this piece into your config under the platform tag <platform name="ios">.
<config-file platform="ios" target="*-Info.plist" parent="UIFileSharingEnabled">
<true/>
</config-file>
2. Then go to your command line tool and type: cordova prepare
Uninstall and reinstall your application on your device, and you will see your app appear in itunes for you to share any files between your devices.
A few things, make sure cordova is up to date, and that you added the platform for ios.
npm install -g cordova
This command installs cordova.
cordova platform add ios
This command adds the platform for ios.
What is happening is when you run the cordova prepare command you are using Apple's Xcode SDK that is generated in the platform/ios folder. There you can see the plist file that is generated for your application, which is labeled as "yourApp-info.plist". There you can see the new key and string produced in the xml layout which looks like this:
<key>UIFileSharingEnabled</key>
<true/>
Also word of warning, my company dropped this ionic framework application into my lap a couple weeks ago (with a really short deadline). Everything I am telling you is based on couple weeks of learning. So this may not be the best practice, but I hope it helps someone out.
Edit
Link to the docs
This does seem to be possible now using the config.xml: at least some core plugin authors say so. For instance, in the docs for the Cordova Camera Plugin, they discuss the new requirement in iOS 10 that you provide a permission message string in the plist. To accomplish it, they suggest executing the plugin add command with arguments, thus:
cordova plugin add cordova-plugin-camera --variable CAMERA_USAGE_DESCRIPTION="My App would like to access your camera, to take photos of your documents."
This has the result that you not only get a new <plugin> added to config.xml, but it has a <variable> child:
<plugin name="cordova-plugin-camera" spec="~2.3.0">
<variable name="CAMERA_USAGE_DESCRIPTION" value="My App would like to access your camera, to take photos of your documents." />
</plugin>
Which then seems to correlate to the new keys in my info.plist, perhaps somehow passing the values at runtime?
<key>NSCameraUsageDescription</key>
<string/>
<key>NSPhotoLibraryUsageDescription</key>
<string/>
I'd be lying if I said that I know exactly how it works, but it seems to point the way.
UPDATE: for people want to use camera with iOS >= 10.
This mean, by normal you can config in plugin as:
<!-- ios -->
<platform name="ios">
<config-file target="*-Info.plist" parent="NSLocationWhenInUseUsageDescription">
<string></string>
</config-file>
<config-file target="*-Info.plist" parent="NSCameraUsageDescription">
<string></string>
</config-file>
<config-file target="*-Info.plist" parent="NSPhotoLibraryUsageDescription">
<string></string>
</config-file>
</platform>
But for now, you can't config NSCameraUsageDescription and NSPhotoLibraryUsageDescription in plugin. You need to config them in platform -> iOS project by Xcode or in *-Info.plist file.
Since iOS 10 it's mandatory to add a NSCameraUsageDescription and
NSPhotoLibraryUsageDescription in the info.plist.
Learn more: https://www.npmjs.com/package/cordova-plugin-camera
I'm using the following in the ionic 3 without any additional plugin or imports and I think this could be helpful for others:
<platform name="ios">
<edit-config file="*-Info.plist" mode="merge" target="NSLocationWhenInUseUsageDescription">
<string>Location is required so we can show you your nearby projects to support.</string>
</edit-config>
<edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
<string>Camera accesss required in order to let you select profile picture from camera.</string>
</edit-config>
<edit-config file="*-Info.plist" mode="merge" target="NSPhotoLibraryUsageDescription">
<string>Photo library accesss required in order to let you select profile picture from gallery / library.</string>
</edit-config>
</platform>
You can set the display name in app's plist by directly editing the ios.json in the plugins directory.
Adding the following to the config_munge.files section of the ios.json file will do the trick and it will be maintained even when using the CLI.
"*-Info.plist": {
"parents": {
"CFBundleDisplayName": [
{
"xml": "<string>RevMob Ads Cordova Plugin Demo</string>",
"count": 1
}
]
}
}
Here's a complete example
Yes, it is possible!
I am using Cordova 9.0.0 (cordova-lib#9.0.1).
For example this is the configuration file that I used to insert new string value into Info.plist :
<platform name="ios">
<edit-config file="*-Info.plist" mode="merge" target="NSMicrophoneUsageDescription">
<string>My awesome app wish to hear your awesome voice through Microphone. Not for fancy stuff, just want to hear you.</string>
</edit-config>
<edit-config file="*-Info.plist" mode="merge" target="---Key configuration---">
<string>---string value---</string>
</edit-config>
</platform>
After that, don't forget to rebuild your staging file by running this two command in your terminal :
cordova platform rm ios
cordova platform add ios
To confirm the change, you can check the newly generated .plist file by opening them with xCode.
-Info.plist file located at :
./platform/ios/[your app name]/[your app name]-Info.plist
#TachyonVortex solution seems to be the best option but was crashing down in my case. The issue was caused by an empty NSMainNibFile field that is not right converted by the plist NPM package. In the .plist file
<key>NSMainNibFile</key>
<string></string>
<key>NSMainNibFile~ipad</key>
<string></string>
is converted to:
<key>NSMainNibFile</key>
<string>NSMainNibFile~ipad</string>
I fixed it with by adding to the script:
obj.NSMainNibFile = '';
obj['NSMainNibFile~ipad'] = '';
The script finally looks like (scripts/my-hook.js):
var fs = require('fs'); // nodejs.org/api/fs.html
var plist = require('plist'); // www.npmjs.com/package/plist
var FILEPATH = 'platforms/ios/***/***-Info.plist';
module.exports = function (context) {
var xml = fs.readFileSync(FILEPATH, 'utf8');
var obj = plist.parse(xml);
obj.GDLibraryMode = 'GDEnterpriseSimulation';
obj.NSMainNibFile = '';
obj['NSMainNibFile~ipad'] = '';
xml = plist.build(obj);
fs.writeFileSync(FILEPATH, xml, { encoding: 'utf8' });
};
and config.xml:
<platform name="ios">
<hook type="before_build" src="scripts/my-hook.js" />
</platform>
I have used this plugin to solve the problem, maybe it can help you :
https://www.npmjs.com/package/cordova-plugin-queries-schemes
If you are trying to modify a .plist in a native iOS plugin with a <config-file> tag in your plugin.xml, here is what you need to do:
Make sure your .plist is xml, not binary! You can use plutil to convert a binary .plist into xml, and commit it to version control.
plutil -convert xml1 Info.plist
The instructions for <config-file> indicate that target= is relative to the generated xcode project at platforms/ios/<project>/, but I found that I needed to prepend a wildcard character to my path to get it to work:
target="*/Resources/MyResources.bundle/Info.plist"
If you want to add a key at the top level of the .plist, you need to set parent equal to the key name, and then nest a <string> tag with the value. Using an <array> or <dict> as any examples show will cause these keys to be nested under parent.
Here is a complete example that works for me for adding multiple top level properties:
<platform name="ios">
<config-file target="*/Resources/MyResources.bundle/Info.plist" parent="MyDistribution">
<string>Cordova</string>
</config-file>
<config-file target="*/Resources/MyResources.bundle/Info.plist" parent="MyVersion">
<string>3.2.0</string>
</config-file>
</platform>
I prefer the after_prepare hook for bigger projects or if you have multiple plugins using the same permissions. But you can always go the simple way:
simply:
- remove the plugin that requires the desired permission
- add it again with --save
- in config.xml, the plugin now has a new variable with a blank description that you can fill in
- now build ios with -- release and they will be set.
you just need following steps
1.
Go to Project navigator
Select the target
Click on info from tab option other option are build setting build phase
you will see key type value
When you point on any key name you will find + and - sign
click on the + sign
write Key: GDLibraryMode in key section
Type:Stringin tyoe section
Value:GDEnterpriseSimulation in value section