I am displaying on the touch of a button inside my app, an app on the appstore. The app pops up in a SKStoreProductViewController with the content of the app store. Now, is there any method to detect if the user has pressed install on the shown app, or even better, be alerted if the user has pressed intall and the app has finished installing? Since the user in my app in this way is capable of buying the fill version, I want to quit the trial when the download is over.
I dont think you can detect if user has pressed install or an app is installed when using SKStoreProductViewController [docs]. Only API iOS exposes is loadProductWithParameters:completionBlock:.
But if you want to check if your app has installed or not there are other ways -
1) Using custom URL scheme. Define a custom URL scheme for your app and then check using UIApplication -canOpenURL: That will tell you only that an application able to open that url scheme is available, not necessarily which application that is. There's no publicly available mechanism to inspect what other apps a user has installed on their device. Custom URL scheme check can be done something like this -
BOOL fullApp = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:NSString* urlString = [NSString stringWithFormat:#"yourFULLAppURL://"]]];
if(!fullApp)
{
NSLog(#"INVALID URL"); //Or alert or anything you want to do here
}
2) If you control both apps you might also use a shared keychain or pasteboard to communicate between them in more detail.
Related
My app uses in different screens:
[[UIApplication sharedApplication] openURL:url];
in order to open URLs received from my web service.
Sometimes, those URLs are unrelated to my project, so opening them going to Safari is OK. Others, those URLs belong to my own, like a product detail. Those ones could be opened by my app using universal links and going to the proper screen, but that's not happening.
Reading apple docs I saw this:
It’s important to understand that if your app uses openURL: to open a universal link to your website, the link does not open in your app. In this scenario, iOS recognizes that the call originates from your app and therefore should not be handled as a universal link by your app.
https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html
That behaviour confuses me. How can I use openURL to try to process first that URL inside my app instead of going directly to Safari?
I found a fast/dirty workaround. Remove openURL and use this every time my app uses openURL:
NSUserActivity* userActivity = [[NSUserActivity alloc] initWithActivityType:NSUserActivityTypeBrowsingWeb];
userActivity.webpageURL = url;
[[UIApplication sharedApplication].delegate application:[UIApplication sharedApplication] continueUserActivity:userActivity restorationHandler:nil];
Note that my appdelegate application:continueUserActivity:restorationHandler: will forward to openURL any URL that does not have a specific screen in my app, so, it is working perfectly fine, but I feel this is a terrible solution.
Your solution seems reasonable. Why is that terrible?
Probably you can implement more nicely looking solution, like stand-alone class LinkHandler. The class can identify if link can be handled by your App (than it will use App's handling). Otherwise class will pass this link to iOS handling with [UIApplication openURL:].
A lot of Apps doing this, imagine how Google+ or Facebook iOS Apps would handle links, that posted in these social networks.
Here's swift 4.2 version of Ricardo's own solution
let userActivity = NSUserActivity(activityType: NSUserActivityTypeBrowsingWeb)
userActivity.webpageURL = url;
UIApplication.shared.delegate?.application?(UIApplication.shared, continue: userActivity, restorationHandler: { _ in })
I wondered if there are a way to be notified when a new application is installed in my device and trigger some treatment in my applications. Like PACKAGE_ADDED BroadcastReceiver in android
Thank's
Apple does not provide such information. Instead, you could add something like:
if([[NSUserDefaults standardUserDefaults] objectForKey:#"firstRun"] == nil)
{
//This is a first run
[[NSUserDefaults standardUserDefaults] setObject:#"NotFirstRun" forKey:#"firstRun"];
}
to applicationDidFinishLaunchingWithOptions:
update
If you instead want to detect the installation of another app the approach is different:
You can't detect when an app is installed, but for SOME apps you can detect if they are installed.
Doing your own app launch (or perhaps using a backgroundfetch process) you can see if an app is installed IF the app responds to a URL Scheme AND you know that scheme.
Take a look at
([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:customURL]])
If this methode returns YES for a given URL Scheme you know that app is installed. Here is a partial list of URL Schemes for some common apps or search http://handleopenurl.com/. You can of course also make your own URL Scheme if you want to detect your own app.
No. Apple doesn't give you this data.
What you can do, however, is maintain an user defaults data and manipulate in applicationDidFinishLaunchingWithOptions: delegate.
I've used a library called 'GBVersionTracking' for detect when is his first launch.
Importing this library you can send messages to the class 'GBVersionTracking' like:
[GBVersionTracking isFirstLaunchEver];
[GBVersionTracking isFirstLaunchForVersion];
[GBVersionTracking isFirstLaunchForBuild];
https://github.com/lmirosevic/GBVersionTracking
I am working on a way to update an enterprise app OTA. I am opening a url to a copy of my app from my own server inside the app when I detect a new version is available. This works well except I want to give the user the option of not updating the app if they don't want to. What I would like to know is if there is any sort of notification that is sent to the ios app if the user presses cancel in the dialog that pops up when the url is opened. In other words I want a way for the app to continue ONLY if the user cancels the update request.
Here is the code I am executing to update the app.
NSURL *url = [NSURL URLWithString:#"itms-services://?action=download-manifest&url=http://www.mywebsite.com/myapp.plist"];
if (![[UIApplication sharedApplication] openURL:url]) {
NSLog(#"%#%#",#"Failed to open url:",[url description]);
}
I wasn't able to find any information what-so-ever about the itms protocol in the apple developer docs. I was able to achieve the effect I wanted by presenting a custom UIAlertView asking the user if they wanted to update before opening the url, but this has the unfortunate side-effect of prompting the user twice if they want to update, and still doesn't really handle the case where they cancel the update after the first prompt.
Any help on the matter would be appreciated.
I already know how to launch an app from safari, but is it possible to check if the app is installed before launching? I'm thinking to launch the app store if the app isn't currently installed on the iPhone.
It's not possible to check if app is installed from a web page. You could do it inside an other app by checking if your url scheme can be opened using UIApplication's -canOpenURL: method, but there is no javascript equivalent to this.
However, you can use the following workaround:
<script language="javascript">
function open_appstore() {
window.location='http://itunes.com/';
}
function try_to_open_app() {
setTimeout('open_appstore()', 300);
}
</script>
<a onClick="javascript:try_to_open_app();" href="yourappurl:">App name</a>
This code will set a timeout on the link that will call the open_appstore function if this timeout ends. Since your link is pointed at the app's custom url, Safari will try to open that link and if it can, it will open the app and stop the timer, so AppStore link will not be opened.
If the app link can't be opened, when timer runs out it will display an error popup saying it can't open the page (can't get rid of that), but it will immediately go to AppStore and dismiss that error.
iOS 9 adds a really nice feature that lets your app open a http/s url: Universal Links
In iOS 10 there is a popup saying "Open in [App Name]" when you tap the link and the app is installed. If the user does not tap on "Open" in the given timeout, this solution will use the fallback.
As 300ms is too short to tap anything, this solution always fails on iOS 10.
This worked for me with a similar situation: wherein I wanted to open gmaps app if it was supported - otherwise go to gmap site directly.
function mapLink(addy) {
addy = encodeURIComponent(addy);
var fallback = 'http://maps.google.com/?q=' + addy
, link = 'comgooglemaps://?q=' + addy;
try {
document.location = link;
} catch(err) {
document.location = fallback;
}
}
Seems to work pretty well for my use case.
Update:
If you want to do a new window on fallback, this still allowed the ios error message to pop up. To get around it try this.
try {
document.location = link;
} catch(err) {
window.location.reload(true);
window.open(fallback, '_blank');
}
The Solution from Apple:
From Apple Documentation
https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html
If the app is already installed on a user's device, the banner intelligently changes its action, and tapping the banner will simply open the app. If the user doesn’t have your app on his device, tapping on the banner will take him to the app’s entry in the App Store. When he returns to your website, a progress bar appears in the banner, indicating how much longer the download will take to complete. When the app finishes downloading, the View button changes to an Open button, and tapping the banner will open the app while preserving the user’s context from your website.
Smart App Banners automatically determine whether the app is supported on the user’s device. If the device loading the banner does not support your app, or if your app is not available in the user's location, the banner will not display.
To add a Smart App Banner to our webpage, include the following meta tag in the head of each page where you’d like the banner to appear:
NOTE: We can also pass the app-argument: like myName,etc.,
Check that Providing Navigational Context to Your App Header in this Page
Updates:
1. Once you have closed the banner that showing up, then that will not be displayed again even though you had that meta tag in our html.
2. To reset that launch the settings App then navigate to General>Resent>Reset all settings
You can simply read the return value from the method -(BOOL)openURL:(NSURL)url*, if it's NO, it means that the target application isn't installed. Following code snipped gives an example using the navigon url scheme:
NSString *stringURL = #"navigon://coordinate/NaviCard/19.084443/47.573305";
NSURL *url = [NSURL URLWithString:stringURL];
if([[UIApplication sharedApplication] openURL:url]) {
NSLog(#"Well done!");
} else {
stringURL = #"https://itunes.apple.com/it/app/id320279293?mt=8";
url = [NSURL URLWithString:stringURL];
[[UIApplication sharedApplication] openURL:url];
}
Thanks to zszen for the correction.
How programmatically restart an iPhone app in iOS?
I find this way http://writeitstudios.com/david/?p=54
But may be something simple.
The only way I know to do this is not ideal, but it works.
First, your app has to opt out of background execution (multitasking) The app has to quit when exited, not run as a background task. This is done with the plist key UIApplicationExitsOnSuspend.
Second, your app needs to register a custom URL scheme that can be used to launch the app.
Third, you need a web page hosted somewhere that when loaded will redirect to your app's custom URL scheme.
Forth, the user needs an active Internet connection.
To exit and restart, call UIApplication openURL on your hosted redirecting web page. Your app will exit and safari will launch and load your page. The page will redirect Safari to your custom URL scheme, prompting Safari to internally call openURL, causing iOS to launch your app.
my post that you linked to is referring to a Cocoa Application, not the iOS. On the iOS, you can quit an application (but Apple doesn't like this) by using exit(0); but I don't recommend that. You cannot restart iPhone apps though.
Unless you're developing for jailbroken devices, Apple won't even allow you to programatically terminate your app. So restarting the device is out of the question.
Your AppDelegate instance has a method
(void)applicationDidBecomeActive:(UIApplication *)application
{
}
In here, you can put logic to figure out if the app should restart, or continue doing whatever it was doing. For example you can have a BOOL variable appMustRestart that is false at first but gets triggered as true whenever something happens in your app that you'd like the next time to be a fresh relaunch.
if (appMustRestart)
{
[self resetVars]; // call a method that resets all your vars to initial settings
// INSERT CODE HERE TO TRANSFER FOCUS TO INITIAL VIEWCONTROLLER
}