Since iOS6, I can't tell whether the application can launch Safari or not.
If Safari is restricted on the device (Settings>General>Restrictions), nothing happens when trying to open a URL, and there's no indication of what went wrong:
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
[[UIApplication sharedApplication] canOpenURL:url]; // Returns YES
[[UIApplication sharedApplication] openURL:url]; // Returns YES
However, Safari does not launch, and the user is left wondering why my buttons are "broken".
This seems like a bug to me so I filed a radar #12449905.
Is there another way to solve this problem?
If this is an Apple bug, then it looks like the thing for you to do is to program around it. Once the user clicks the button, you can always write something like this:
[self performSelector:#selector(notifyUserOfRestrictedAccess) withObject:self afterDelay:.5];
In the app delegate, you can set a property such as:
- (void)applicationWillResignActive:(UIApplication *)application {
self.openingExternalProgram = YES;
}
In your view controller, create the method like this:
-(void) notifyUserOfRestrictedAccess {
if (!appDelegate.openingExternalProgram) {
// Message the user via UIAlertView about restricted Safari access
}
appDelegate.openingExternalProgram = NO;
}
I'm sure there are better ways, but at least you don't have to wait on Apple.
Related
Alright I think I am close to a solution here. I think I must be missing something small. Hope you guy can help.'
I am trying to have another app open another custom app and run a method from that app that is being called through the URL scheme. I understand that in ios 9 they made it manitory to define in the info.plist the key
<key>LSApplicationQueriesSchemes</key>
<array>
<string>URLScheme0</string>
<string>URLScheme1</string>
<string>URLScheme2</string>
ect....
</array>
And I think I have done that properly. Though I want a confirm on this and other thing. Firstly, do I add this to the info.plist of the "calling" app, or the "receiving" app, or BOTH? As, I have it now it is with both. When I remove it from the calling apps plist I get the error.
"This app is not allowed to query for scheme xxx”
Keep in mind I have also included in the plist for the receiving app the URL types and URL schemes array with the same scheme names.
The the calling app I have a button mapped with this methods code:
- (IBAction)killMethod:(id)sender {
NSString *customURL = #"TurnOffRelay://";
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:customURL]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
} else {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"URL error" message:#"No custom URL defined for Kill Relay" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
}
}
and for the receiving app I have in the appDelegate.m :
- (BOOL)application:(UIApplication *)application OpenURL:(NSURL *)url sourceApplication:(NSString *) sourceApplication annotation:(id)annotation {
NSLog(#" Calling application: %#", sourceApplication);
NSLog(#"URL scheme: %#", [url scheme]);
if ([sourceApplication isEqualToString:#"net.ble.relay"]) {
if ([[url scheme] isEqualToString:#"TurnOffRelay://"]) {
ViewController *viewController = [[ViewController alloc] init];
[viewController killSwitch];
NSLog(#"Running killSwitch");
}
return YES;
}
else
return NO;
}
With what I have right now running I am able to actually press the button in the "calling" app and from there the "receiving" app opens, but alas, the method I want to run doesn't run inside of the if statements. I am wondering what I am doing wrong. I will gladly answer any questions about things I may have missed. This has been bothering me all day. Would like some sort of guidance. Thanks in advance.
pay attention to if ([[url scheme] isEqualToString:#"TurnOffRelay://"]) 。 url scheme is TurnOffRelay rather than TurnOffRelay://.
So, after changing the OpenURL to openURL and then noticing that the sourceApplication name was wrong. I am guessing that if I had typed in the correct application to use, as in, the actual name of the application that was "calling" the If block would have proceeded correctly. But I am sure, also, that if I had not changed the openURL I would have been stuck again.
Thanks for the help. Its now working as intended.
I tried to open facebook app using this
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"fb://"]];
when my app is running in foreground , it works fine but if my app is in background it didn't work .
help me out .
I'm very new in programming
You are think impossible task. Think and first ask your self what are you trying.
Your app in to background it means (minimized). then where to trigger for calling open Facebook Native app method.
If app in background then you can't have any event for handle your app event from iPhone screen.
That bellow code for open Fb native app from app. but from background it out of logic think. that not relevant at all.
you can open facebook app using this bellow :-
- (IBAction)OpenFB: (id) sender
{
NSURL* facebookURL = [NSURL URLWithString: #"fb://profile/157893597658332"];
UIApplication* app = [ UIApplication sharedApplication ];
if( [ app canOpenURL: facebookAppURL ] ) {
[ app openURL: facebookAppURL ];
} else {
// url wrong
}
}
Here it is very nice Article
http://www.plungeinteractive.com/blog/2012/12/31/open-facebook-and-twitter-native-apps-from-your-ios-appgame/
UPDATE:-
I dont think this is suitable for your requirement but using Custom URL Scheme. you can able to Open your app from from safari browser or other app. just setting URL type--> setting URL schemes like bellow
and then try like i did in bellow image that open your app from browser:-
You cannot launch another app from the background mode because that would be pre-empting the user's current task without user interaction. There is only one application that is permitted to pre-empt the user's current action and that is the phone in the case of an incoming call.
What you could do is display a local notification and if the user actions that notification to launch your app - placing it back into foreground - then you could launch Facebook.
UILocalNotification* localNotification = [[UILocalNotificationalloc] init];
localNotification.fireDate = nil;
localNotification.alertBody = #"I want to launch Facebook";
localNotification.timeZone = nil;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
then in your app delegate -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Handle launching from a notification
UILocalNotification *locationNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsLocalNotificationKey];
if (locationNotification) {
// Open Facebook
[application openURL:[NSURL URLWithString:#"fb://"];
}
return YES;
}
But if the user chooses not to action your notification there is nothing you can do.
currently I'm using UIWebView to make phone calls
NSURL *telURL = [NSURL URLWithString:[NSString stringWithFormat:#"tel://123456789"];
[self.callWebview loadRequest:[NSURLRequest requestWithURL:telURL]];
when I touch on a button to make call, an UIAlertView appears and ask for confirmation with title 123456789
How can I change its title and message ?
Thanks.
Don't use a UIWebView, just present a UIAlertView to the user asking if he/she want to call. Also there are no // in the tel: scheme, so tel:123456789 is correct.
Then just open open the tel: url via [[UIApplication sharedApplication] openURL:telURL].
Also do not forget the check whether the users device can make phone calls:
NSURL *telURL = [NSURL URLWithString:#"tel:123456789"];
if ([[UIApplication sharedApplication] canOpenURL:telURL]) {
// Present the user with the dialog to start the call
} else {
// inform the user that he/she can't call numbers from their device.
}
Our app relies on UIWebview to return to the app following a phone call initiated by the user. After consulting a number of developers, we did not make any changes for iOS6, expecting the app to work fine.
Now, the following has happened:
1) UIWebview IS still working - bringing the user back into the app when they end a call
2) However, the app is directing the user to the wrong screen - it is taking it to the screen FOLLOWING the one the user should see. The crucial screen where the user can log their phone call is not showing up.
3) The only exception seems to be when the user logs out and logs back in - in this case they can see the correct screen ONLY once, and then the next time they call they go to the wrong screen again.
I am not a coder but after looking through the code as it stands, it looks like this is one of three (nearly identical) snippets of code that should be calling the End Call screen at the end of a phone call but under iOS6 is not:
- (IBAction)onCall:(id)sender
{
DashCaller *caller = [[DashCaller alloc] init];
NSString *callNumber = _phone.number;
if (!callNumber)
{
callNumber = #"No Phone number";
}
else if (callNumber.length == 0)
{
callNumber = #"No Phone number";
}
else
{
callNumber = [callNumber stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
DashDelegate.calledPhone = _phone;
DashDelegate.callLogVC.delegate = _viewController;
DashDelegate.callStartDate = [NSDate date];
NSUserDefaults *setting = [NSUserDefaults standardUserDefaults];
NSNumber *blockNumber = [setting valueForKey:BLOCK_NUMBER];
NSURL *url = nil;
if (blockNumber.boolValue)
url = [NSURL URLWithString:[NSString stringWithFormat:#"tel://%#%#", kStringBlockNumber, callNumber]];
else {
url = [NSURL URLWithString:[NSString stringWithFormat:#"tel://%#", callNumber]];
}
[caller callTelURL:url];
}
Specifically, the line "DashDelegate.callLogVC.delegate = _viewController;" seems like it should be calling the CallLogVC view but instead it is going to the screen that should appear right after that view.
Anyone with thoughts on what to change (that could have been affected by iOS6)? The app is fully functional in iOS5. And, why might the app show this page only once after a log-out-log-in and then stop showing it?
To go back to original app you can use telprompt:// instead of tel:// - The tell prompt will prompt the user first, but when the call is finished it will go back to your app:
NSString *phoneNumber = [#"telprompt://" stringByAppendingString:mymobileNO.titleLabel.text];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:phoneNumber]];
You may also try these app delegate methods for restoring application after the call finishes.
- (void)applicationDidBecomeActive:(UIApplication *)application;
- (BOOL) application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
- (BOOL) application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
I have an issue with the activity indicator view continuing to animate after the page has finished loading. The problem only occurs on UIWebView pages that have already been visited.
I am also using MBProgressHUD and this stops animating after the ViewDidLoad as expected.
The page loads almost instantaniously and then the animation starts in the nav bar. It's almost as if the page is pulled from the device cache and then the application looks to go and load it.
The spinner only stops animating when you visit a different view controller.
Has anyone else faced issues similar to this?
EDIT
- (void)showNetworkActivity {
[self performSelector:#selector(showNetworkActivityWithDelay) withObject:nil afterDelay:0.5];
}
- (void)showNetworkActivityWithDelay {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
- (void)hideNetworkActivity {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
Works okay when I remove the delay.
I inherited the code, so I'm not sure whether the delay is needed. Is there any good reason to have a delay on showing the networkActivityIndicator?
Here the solution.
Try to call [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; directly.
performSelector:withObject:afterDelay: schedules a timer on the same
thread to call the selector after the passed delay.
I don't see reasons to use the delay in this examples. In fact, if you use it, the selector showNetworkActivityWithDelay is called after a delay and you could not see it immediately on the screen.
Obviously you can continue to wrap the activity indicator logic with the previous methods like the following (but it's not necessary):
- (void)showNetworkActivity {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
- (void)hideNetworkActivity {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
Sounds like you don't have UIWebViewDelegate set up. Set the delegate in the header/implementation, then start animating the indicator in UIWebViewDelegate webViewDidStartLoad, then stop animating in webViewDidFinishLoad and webViewDidFailLoadWithError.