I’ve got several iOS apps and I need them to be aware of each other. More precisely, I need to know whether there’s already one of my apps installed.
I thought about registering a custom URL scheme (something like my-app-present://), so that I could check whether the custom scheme is supported and if yes, I would know there’s already one of my apps on the device. But that doesn’t work, because the schemes are registered through Info.plist and the app registers the scheme before it has a chance to check for its existence. In other words, the check always succeeds.
Then I thought about creating a file in the temporary directory, but NSTemporaryDirectory() returns a folder inside the application sandbox, so that wouldn’t work either. I also thought about keychain, but again it looks like each application has strictly separate keychain on iOS.
I don’t want to go through the list of running apps and I don’t want to use networking. Do you know some other tricks?
The custom URL scheme method sounds fine, as long as you have a different scheme for every app, for example my-app-1:// and my-app-2://. Then (I assume this is what you already knew) you can use canOpenURL: to check if the URL can be handled (i.e., your app is installed).
If by "talk to each other" you meant you just want to detect whether other app has been installed or not then iHasApp is an open source iOS framework could come in handy. I haven't used it yet. but from the description it appears to be a good choice.
http://www.ihasapp.com/documentation/Classes/iHasApp.html
Related
My understanding is that because of sandboxing, it isn't possible to view any text file (ie config file) associated with an iOS app using another app. Something quite simple with Android. Am I mistaken?
I am trying to implement a text config file with a Unity iOS app that gets loaded and parsed once when the application boots.
This config file would also be able to be edited and saved manually on that actual iOS device.
(addendum)
In Unity there is PersistentDataPath which resolves to /var/mobile/Container/Data/Application/foo/Documents
Is there an iOS supported file explorer app that will allow me view and edit files in this location (without jailbreaking)?
Use can check iOS App Groups. It allows multiple apps access to shared containers and allow interprocess communication. There is no so much documentation about this, but maybe that's what you're looking for. At least you can share NSUserDefaults between the apps.
NSUserDefaults it's a most simple way to save any (not big) configurations for your app. For manual editing: if your app on the device signed with developer certificate, you can connect through any iOS supported file explorer app and edit it. But after release, from App Store, your app installed in restricted/private path, so it's not possible, if only you don't have a jailbreak.
Initial configuration you can put into your app bundle, and at the first run just copy them to NSUserDefaults.
Short answer: There are utilities such as iExplorer - https://macroplant.com - that allow "file manager" type access. However...
Long answer: If your app requires users to buy (or get) other software to modify configuration files, the chances of Apple approving it are slim to none.
The appropriate thing to do is to provide a User Interface in your own app which allows the user to modify / update the settings.
Until iOS 9, we were able to use canOpenURL method to check if there are apps who can handle specific URL schemes, thus it was widely used to check if a specific app was installed by user.
Now, since iOS 9, we have to declare upfront the URL Schemes that can be checked by the app. This is cool in general, but it means that for every release of a new app, we would have to update previous apps to be able to check if the new one is installed or not.
Is there any sane way to do it now?
I guess most of the ads and cross promotion services out there relies on this and had to adapt somehow, anyone knows how?
Thanks
Krystian
Ok, so to recap.
Currently, the only way to handle my scenario, is to assign a specific scheme per app in an orderly fashion, for example:
my.domain.app01
my.domain.app02
...
If you have apps already released, just update them to add a new, additional scheme.
Now in Info.plist file, you will have to add all of your existing and future schemes to LSApplicationQueriesSchemes list in Info.plist.
The idea is: even though you have 10 apps released, you add entries for let's say 40. This way, you will not have to update your app to add schemes for future apps, they will already be there and you will be able to detect them.
This of course covers my scenario, where I want to be able to detect my own apps and make use of them.
Remember, that your app can handle more than one scheme, so you can assign the internal scheme + use something better named to allow external access to your app.
We have a need to support 100+ domains in our entitlements file for Universal Links.
Example:
applinks:test.myapp.com
applinks:blah.myapp.com
applinks:foo.bar.com
etc...
I know that *.myapp.com will be supported in iOS 9.3, but is there a way to do this elegantly for customers using iOS 9.0 to 9.2 without having to manually add 100+ entries to the entitlements file? Is there a way to do this without having to rebuild and re-release our app every time we need to add a domain to the list?
Thanks!
The new wildcard support in iOS 9.3 is designed for exactly the situation you're describing, so there isn't really a solid alternative in earlier OS versions.
If you don't want to worry about continually updating the list of subdomain applinks entries (or even if you do, but need to wait for App Store review), the best workaround is probably hosting fallback pages on each subdomain with a call-to-action the user can use to continue into the app. That would work as follows:
Assume that you have applinks:mydomain.com configured.
User opens a link to new.mydomain.com/exciting-page (which is NOT covered by the entitlement above).
User sees a custom interstitial, functionally similar to something like this. On this interstitial is a link pointing to mydomain.com/new/exciting-page
User opens the link and the app launches.
The only thing I am not sure about is whether mydomain.com and new.mydomain.com count as 'different domains' for the purpose of Universal Links, since Universal Linking functionality is disabled in Safari for links within the same domain (source). If this turns out not to work, you could easily use something like applinks:mydomain.io and a link to mydomain.io/new/exciting-page in step 3 instead.
This question could also be a general "How to change info.plist contents at compile-time" but I know it's a complex issue that is handled differently on iOS and MacOSX. The thing is that specifically when working with the Facebook SDK, it feels kind of wrong supplying my FB app-id twice - once in the "URL types" dictionary under "URL schemes" in the app's info.plist and once in my code. I want to be able to change the app-id dynamically from within my code without touching the info.plist file. I looked into Apple's launch services and found a potentially helpful "LSSetDefaultHandlerForURLScheme" method, only to find out that I was looking at the MAC developer library. I saw some other SO questions about this issue but the general opinion seems to be that this is not doable. Any ideas that don't involve pulling information out of the plist at compile time? (I want to be able to support several app-ids that are defined in a specific header file in my code).
Thanks!
Does iOS offer a way for an app to query the device for information about what other apps are installed/running?
All ios apps are sandboxed so this wouldn't be possible on a non-jailbroken device
There are a few options.
First, you can lookup for the specific process name of the app, but this may be prone to error as unrelated apps may be running using the same process name, for example, I've seen both the Batman and Dark Meadow game share a similar process name: UDKGame.
Secondly, using the URL scheme. This method is useful if you know what apps you are looking for and you know that this particular app implements the URL scheme. You can do a simple canOpenURL and find out if that app is installed.
I use the second method a lot to collect the URL schemes for use in my app, AppSwitch.