Creating a custom plist
Sometimes you will need to modify the plist file that is automatically created when you build an iOS standalone.
You might need to do this to
- Add a permission
- Set a message to used in the app when requesting permission to a service
- ...
Property list(plist) files are XML files so can be edited in a text editor or the plist editor in Xcode.
For more information on plist files see this Apple Developer guide.
In this example we will see how to modify a plist to add a key and change the message displayed when the app requests access to location services.
Setting up the Standalone
Once you have created your stack open the Standalone Application Settings, go to the iOS pane and ensure you have set all the requirements you need. In this case we want the app to access the location 'When in Use'.
Save the Standalone
Now choose "Save as Standalone Application" from the File Menu and open the folder containing the app bundle. Right click the app bundle and choose "Show Package Contents".
Open the Info.plist file
Open the Info.plist file in your preferred text editor ready to make some changes.
Modifying a key
Find the NSLocationWhenInUseUsageDescription
key in the file. This key is automatically created by the Standalone Builder because we selected the 'When in Use' option for location services.
The first thing we are going to do is to provide a more descriptive string for this key, Apple sometimes require non-default descriptions so this type of modification can be common.
Update the <string>
value for the NSLocationWhenInUseUsageDescription
key with something more descriptive and relevant for your app.
<key>NSLocationWhenInUseUsageDescription</key><string>This application requires access to Location Services when in use to find local restaurants</string>
Adding a key
In some cases you might also want to add keys to the plist file. For example in iOS 11+ Apple added a requirement to include an NSLocationAlwaysAndWhenInUseUsageDescription
key so we'll add that here.
Add the key and string to your plist file, remember to include a descriptive string.
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key><string>This application requires access to Location Services to find local restaurants</string>
The Standalone Builder will now add this key, we are just using it as an example here.
Save the modified plist
Now we have a modified plist we need to rebuild our standalone and include it at the building stage. Modifying the plist after building the app will cause the app to be rejected.
Save your modified plist somewhere outside the app bundle, but leave it named "Info.plist"
Include the modified plist in your app
Now you need to include the modified plist when building your standalone
- Open the Standalone Application Settings
- Include the Info.plist file in the Copy Files pane
- Save the standalone
Now check the plist file in your new standalone. You will see that the modified plist is included.
Including a custom plist will override any changes you make in the iOS standalone settings, including the version number etc, so if you make any changes to your settings remember to update your custom plist or repeat this process to create a new plist file with all the settings you need included.
Ludovic THEBAULT
Usefull but do not forget to change bundle version and bundle build number !
You could use these command to make the change automatically :
### in the info.plist file replace bundle version with this :
### CFBundleVersion
### %%bundlebuild%%
### CFBundleShortVersionString
### %%bundleversion%%
### and in the stack script :
on savingMobileStandalone
put URL("file:" & specialfolderpath("resources") & "/info.plist") into tinfos
rename specialfolderpath("resources") & "/info.plist" to specialfolderpath("resources") & "/info.plist2"
replace "%%bundleversion%%" with the cRevStandaloneSettings["iOS,Bundle version"] of this stack in tinfos
replace "%%bundlebuild%%" with the cRevStandaloneSettings["iOS,Bundle build"] of this stack in tinfos
put tinfos into URL("file:" & specialfolderpath("resources") & "/info.plist")
end savingMobileStandalone
on mobileStandaloneSaved
rename specialfolderpath("resources") & "/info.plist2" to specialfolderpath("resources") & "/info.plist"
end mobileStandaloneSaved
simon
Hi, I'm trying to share, via Whatsapp, an Image captured from a LC scrip. With a lot of input from helpful people from the forum (see https://forums.livecode.com/viewtopic.php?f=9&t=31897)
it seems that I have to modify the pList as instructed on the WhatsApp FAQ (https://faq.whatsapp.com/en/iphone/23559013) and reproduced below:
Custom URL Scheme
Opening whatsapp:// URL with one of the following parameters, will open our app and perform a custom action.
URL Parameters Opens
app - The WhatsApp Messenger application
send New chat composer
text If present, this text will be pre-filled into message text input field on a conversation screen.
The Objective-C call to open one of these URLs is as follows:
NSURL *whatsappURL = [NSURL URLWithString:@"whatsapp://send?text=Hello%2C%20World!"];
if ([[UIApplication sharedApplication] canOpenURL: whatsappURL]) {
[[UIApplication sharedApplication] openURL: whatsappURL];
}
Be sure to include WhatsApp URL scheme in your application's Info.plist under LSApplicationQueriesSchemes key if you want to query presence of WhatsApp on user's iPhone using -[UIApplication canOpenURL:].
This is my first time dealing with pList and I'm really lost as what should I do. I was able to open the info.plist file as described above but that was all. Can you please tell me:
What should I add?
Where should be added?
Many thanks in advance, regards
Elanor Buchanan
Hi Simon
From your forum posts I see you found the lesson on Using Custom URL schemes and managed to get it working without having to change the plist, is that correct?
Having looked at the Whatsapp Custom URL scheme information it only works with text and not images unfortunately.
Kind regards
Elanor
Simon Schvartzman
HI Elanor, many thanks for your answer. You are correct I was able to fix it without the need to change the plist (what a relief...)
Best!
Kim
FYI - Apple seems to currently be fussy about WHERE you put your custom plist. I got the following error message when I had my LC Stack on desktop and my customised info.plist in a sub_folder, even though copy files was pointing at the info.plist in the sub_folder.
Error message = ITMS-90535: Unexpected CFBundleExecutable Key - The bundle at '/Payload/my_app.app/sub_folder/Info.plist' does not contain a bundle executable.
I managed to solve this by moving the SAME info.plist file onto the desktop and re-pointing the copy files at it there.
Trevix
Since:
"Including a custom plist will override any changes you make in the iOS standalone settings, including the version number etc, so if you make any changes to your settings remember to update your custom plist or repeat this process to create a new plist file with all the settings you need included."
So when if I sign the standalone for development, make pList change and put it in the copy pane, when I want to upload the standalone to the Store (and I sign it for distribution) do I have to change again the pList?
Elanor Buchanan
Hi Trevix
I'm sorry, I am not quite sure what you mean. You won't be able to make any changes to the plist in the app bundle once it has been built or your app will be rejected.
I think you should be able to use the same plist file with your development and distribution certificates.
I'm sorry if I have not fully understood your question, please let me know if not.
Kind regards
Elanor
roberto
"...I think you should be able to use the same plist file with your development and distribution certificates..."
This is what I needed. My iOS App was rejected by Apple because :
"We noticed that your app requests the user’s consent to access their Bluetooth but does not clarify the use of the Bluetooth in the applicable purpose string.
Next Steps
Please revise the relevant purpose string in your app’s Info.plist file to specify why the app is requesting access to the user's Bluetooth. You can modify your app's Info.plist file using the property list editor in Xcode.
To help users understand why your app is requesting access to their personal data, all permission request alerts in your app should specify how your app will use the requested feature."
Funny is that, after modifying the standalone pList, on first opening, the dialog from the OS appears correctly asking permission for using bluetooth, but the text is in two part (the device language is Italian): The first is in Italian ("MyAppName" desidera utilizzare il bluetooth). The second part is in English, reporting the text that I added in the pList (This application requires access to Bluetooth always, to use external hardware devices).
I wouldn't know how to add the reasons of BT use in the Italian text. Is this handled by Apple or LC?
If we have to specify the reasons for using things like localisation, bluetooth, etc, shouldn't the be handled by the standlone settings of LC?
Elanor Buchanan
Hi Roberto
We do have a bug report about providing a method to add permission descriptions in the Standalone Application Settings.
https://quality.livecode.com/show_bug.cgi?id=19780
The first part of the dialog you mentioned is provided by the OS and the second part is the text you added to the plist file. If you need to localize these strings you add an InfoPlist.strings file in a .lproj folder for each of the languages you want to provide localizations for. We have a lesson on how to do this here
http://lessons.livecode.com/m/4069/l/988547-localizing-property-list-values
For the Bluetooth permission messages you would add the following strings to your InfoPlist.strings file
NSBluetoothAlwaysUsageDescription="";
I hope that helps.
Kind regards
Elanor
Trevix
I am writing a file in the download folder of a Android 11 hardware (actually is a TvBox, but this shouldn't make a difference).
It works fine using the path "/storage/emulated/0/Download/" but only after giving permission to the standalone (LC 9.6.9rc2) on the OS setting of the device.
I set the LC standalone settings to "Allow external storage", but I am still not asked on launch to authorise the write. I still have to manually do it in the OS.
How can/should I modify the pList in this sense?
Thanks
Panos Merakos
Hello Trevix,
This lesson applies to iOS only, since on Android there are no plist files. However, to answer your question, to force an authorization dialog for this use case, I _think_ you can call directly:
androidRequestPermission "android.permission.READ_EXTERNAL_STORAGE"
Note that you still have to check "Allow external storage" in the android settings.
Hope this helps,
Kind regards,
Panos
--