since iOS 8.3 update my share extension (which calls my main app using URL Schemes) stopped working. So I found out that the UIWebView approach I had to launch my app is not working anymore. I also tried the approach Apple recommends, using NSExtensionContext, and still no results. Any thoughts about this? My code follows:
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[self.view addSubview: webView];
NSString *urlString = "com.myappscheme://shareextension";
NSString * content = [NSString stringWithFormat : #"<head><meta http-equiv='refresh' content='0; URL=%#'></head>", urlString];
[webView loadHTMLString:content baseURL:nil];
and
[self.extensionContext openURL:[NSURL URLWithString:urlString] completionHandler:^(BOOL success)
{
NSLog(#"fun=%s after completion. success=%d", __func__, success);
}];
I try executing both blocks of code on the didSelectPost method from my SLComposeServiceViewController controller, which was where it worked fine previously, before updating my device to iOS 8.3
You can make a try with this code, this works but I don't know if would be accepted by Apple.
UIResponder* responder = self;
while ((responder = [responder nextResponder]) != nil) {
NSLog(#"responder = %#", responder);
if ([responder respondsToSelector:#selector(openURL:)] == YES) {
[responder performSelector:#selector(openURL:) withObject:[NSURL URLWithString:#""]];
}
}
extensionContext.openURL is meant only for Today extensions. Apple does not provide a public API to achieve this, and it seems in iOS 8.3, Apple has blocked some of the workarounds. This seems by design. If you believe this functionality is needed, please open an enhancement request / bug report.
Related
I tried to integrate Facebook/Google+ in my app. I can do that by the inbuilt Facebook framework, Google Plus framework, Google open source framework, in iOS app by getting the details from the account added in settings app of the device. I can also do it by opening the Safari browser and redirect to my app after login to Facebook and Goolge+. so, I need without redirect the Safari browser.
Using new Google+ SDK, user will not have to reenter the password in safari or any browser.
Take a look on this:
https://developers.google.com/+/mobile/ios/sign-in
If the user has the native Google or Google+ mobile app installed then user will not have to re-enter their Google credentials to authorize your app.
OR
Try with GTMOAuth2ViewControllerTouch
- (id)initWithScope:(NSString *)scope
clientID:(NSString *)clientID
clientSecret:(NSString *)clientSecret
keychainItemName:(NSString *)keychainItemName
completionHandler:(GTMOAuth2ViewControllerCompletionHandler)handler
Plenty of references available online.
Google Drive iOS SDK: Display Cancel Login Button
Don't use Google-Plus, use GoogleSignIn.
Google just posted this solution:
Comment #109 on issue 900 by fa...#google.com: iOS SDK SignIn don't
leave app [Apple appstore rejection]
https://code.google.com/p/google-plus-platform/issues/detail?id=900
Hello everyone,
I’m delighted to announce an update to this issue. Today, we launched
version 2.0 of Google Sign In, featuring full built-in support for
Sign In via WebView. We hope that this update will at last remedy the
problem of App Store rejections due to use of our SDK.
Full documentation is here:
https://developers.google.com/identity/sign-in/ios
We’ve written a migration guide from G+ Sign In here:
https://developers.google.com/identity/sign-in/ios/quick-migration-guide
You can use the below code to sign in via Google+ using Webview:
Initialize UIWebview:
NSString *url = [NSString stringWithFormat:#"https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=%#&redirect_uri=%#&scope=%#",client_id,callbakc,scope];
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[webView setDelegate:self];
[self.view addSubview:webView];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
Implementation of delegate methods:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
// [indicator startAnimating];
if ([[[request URL] host] isEqualToString:#"localhost"]) {
// Extract oauth_verifier from URL query
NSString* verifier = nil;
NSArray* urlParams = [[[request URL] query] componentsSeparatedByString:#"&"];
for (NSString* param in urlParams) {
NSArray* keyValue = [param componentsSeparatedByString:#"="];
NSString* key = [keyValue objectAtIndex:0];
if ([key isEqualToString:#"code"]) {
verifier = [keyValue objectAtIndex:1];
break;
}
}
if (verifier) {
NSString *authToken = [NSString stringWithFormat:#"code=%#&client_id=%#&client_secret=%#&redirect_uri=%#&grant_type=authorization_code", verifier,client_id,secret,callbakc];
//Use Token to Login
} else {
// ERROR!
}
[webView removeFromSuperview];
webView = nil;
return NO;
}
return YES;
}
Use Scocial.framework
https://developer.apple.com/library/ios/documentation/Social/Reference/Social_Framework/
__block ACAccount * facebookAccount;
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
NSDictionary *emailReadPermisson = #{
ACFacebookAppIdKey : #"YOUR_API_KEY",
ACFacebookPermissionsKey : #[#"email"],
ACFacebookAudienceKey : ACFacebookAudienceEveryone,
};
NSDictionary *publishWritePermisson = #{
ACFacebookAppIdKey : #"YOUR_API_KEY",
ACFacebookPermissionsKey : #[#"publish_actions"],
ACFacebookAudienceKey : ACFacebookAudienceEveryone
};
ACAccountType *facebookAccountType = [accountStore
accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
//Request for Read permission
[accountStore requestAccessToAccountsWithType:facebookAccountType options:emailReadPermisson completion:^(BOOL granted, NSError *error) {if(granted){ // Enter your code}];
I have this code that return success = NO
[self.extensionContext openURL:[NSURL URLWithString:#"URLApp://"] completionHandler:^(BOOL success) {
[self.extensionContext completeRequestReturningItems:nil completionHandler:nil];
}];
So and I can't open containing app from my share extension when I debug it.
I've configured main target of contained app like this:
I've tested open URLApp:// from safari and it works for me.
I also used some examples provided here to understand how to open containing app using url scheme.
EDIT: Ok, just a little correction here. I got it working with placing a button over the label just like suggested above and the following code:
NSURL *url = [NSURL URLWithString:#"floblog://"];
[self.extensionContext openURL:url completionHandler:nil];
I linked it to a "Touch Up Inside" event. However, this also causes the app to launch when the user scrolls the Today view.
=======================================
I ran into the same issue. However, it seems that there is no solution for now since the release notes for the first beta of iOS 8 mention:
Known Issues: openURL does not work from an extension.
So I guess we will at least have to wait until beta 2.
I found this answer here by Julio Bailon:
UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
NSString *urlString = #"URLApp://";
NSString * content = [NSString stringWithFormat : #"<head><meta http-equiv='refresh' content='0; URL=%#'></head>", urlString];
[webView loadHTMLString:content baseURL:nil];
[self.view addSubview:webView];
[webView performSelector:#selector(removeFromSuperview) withObject:nil afterDelay:2.0];
I want to make phone call using UIWebView. I tried below code which works fine in if I simply put a button and on button click execute below code. But currently on button click, I call an api and on response I execute below code.
// Make a call to given phone number
- (void)callPhoneNumber:(NSString *)phoneNumber
{
if (!self.webView)
{
webView = [[UIWebView alloc] init];
[self.view addSubview:self.webView];
self.webView.delegate = self;
}
// Remove non-digits from phone number
phoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:#""];
// Make a call
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:#"tel:%#", phoneNumber]];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
}
Its not even calling webview delegate methods.
What can be the reason?
Please note that I want to call using webview only, so please don't suggest to use native contact app. Using webview keeps flow within the app. When call is ended users is in app only. Using native app, if user wants to come back to my app user has to manually open the app.
To dial a phone number you have to call -[UIApplication openURL:]:
NSString *phoneNumber = #"+5512345678";
NSURL *phoneNumberURL = [NSURL URLWithString:[NSString stringWithFormat:#"tel://%#", phoneNumber]];
[[UIApplication sharedApplication] openURL:phoneNumberURL];
Why not use this?
NSString *phoneNumberURL = [#"telprompt://" stringByAppendingString: phoneNumber];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:phoneNumberURL]];
This takes the user back to the app automatically once the call is finished. I hope that is what you want to achieve using webview.
https://stackoverflow.com/a/12065542/569497
Are you sure self.webView has been initialized?
Change: webView = [[UIWebView alloc] init];
To: self.webView = [[UIWebView alloc] init];
and this: [NSString stringWithFormat:#"tel:phoneNumber"] don't work; try: [NSString stringWithFormat:#"tel:%#",phoneNumber]
Personally, however, I never tried to make a phone call in this way.
If you want to call via UIWebView then use this example:
+ (void)callWithString:(NSString *)phoneString
{
[self callWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"tel:%#",phoneString]]];
}
+ (void)callWithURL:(NSURL *)url
{
static UIWebView *webView = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
webView = [UIWebView new];
});
[webView loadRequest:[NSURLRequest requestWithURL:url]];
}
I'm an iOS newb (.NET professional), so this may be a simple issue but I couldn't find anything through the SO search or Google (and maybe not looking for the right terms).
I'm writing an app that displays information from a DD-WRT router through it's web interface. I have no problem displaying the initial page and navigating through any of the other pages, but if I make any change on a form (and it redirects to apply.cgi or applyuser.cgi), the UIWebView is blank - it's supposed to display the same page, with the form submission changes. The site works fine in Mobile Safari, which I find intriguing, but I guess UIWebView isn't totally the same.
I think the iOS code is pretty standard for display a webpage, but I'll list it below. I can't give you access to my router because, well, that's not a good idea :) Hopefully someone with a DD-WRT router can help (or know what my issue is anyway).
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *sURL = #"http://user:pass#XXX.XXX.X.X";
NSURL *url = [NSURL URLWithString:sURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
self.webView.delegate = self ;
}
And I'm doing a few things with Javascript in the webViewDidFinishLoad method, but I know that's not the culprit because it still happens when I comment it out.
Well I figured out the problem on my own. I think part of it was putting the username & password in the URL (which was just a temporary measure) because I found that method provided the same results in mobile Safari and desktop Chrome.
So I added MKNetworkKit to my project that provided a simple way to add authentication to my request, and found I had to make a specific request to POST the data, then reloaded the page the to see the changes.
In the (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType method, I check if ([request.HTTPMethod isEqualToString:#"POST"]) and do this:
NSString *sPostData = [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding];
NSArray *aPostData = [sPostData componentsSeparatedByString:#"&"];
NSMutableDictionary *dPostData = [[NSMutableDictionary alloc] init];
//i don't know if this is the best way to set a dictionary, but it works
for (id apd in aPostData)
{
NSString *key = [apd componentsSeparatedByString:#"="][0];
NSString *val = [apd componentsSeparatedByString:#"="][1];
[dPostData setValue:val forKey:key];
}
MKNetworkEngine *engine = [[MKNetworkEngine alloc] init];
MKNetworkOperation *op = [engine operationWithURLString:[request.URL description] params:dPostData httpMethod:#"POST"];
[op setUsername:#"myUserName" password:#"myPassword" basicAuth:YES];
self.postedRequest = TRUE; //a bool I set so, when it comes to webViewDidFinishLoad, I reload the current page
[op start]; //send POST operation
I having working on a timer application since last 3 to 4 months (when there was no sign of iOS 6) but due to some issues could not complete it. Now since the advent of iOS 6.. I am getting error in my code. I recently downloaded the xcode 4.5 and iOS 6 SDK (within it). Now when I run the app. It crashes on different occasions. Sometimes crashes right when it is started. Some times no crashes at all.
Sometimes give me SGBRT error. Sometimes Bad_exc error(memory error). I don't know how to handle this. I have downloaded the iOS 5.1 simulator and on that when i run the app. No crashes at all but when I run the app on iOS 6 simulator. Wham! it crashes right away.
I am in dire need of guidance. Anyone who has experienced the same error and got it troubleshoot please help me too.
Thanks in Advance
Fahad.
- P.S. I added breakpoints to detect the errors and I was able to catch only one but could not understand why I got this error. Here is the code:
-(void) playAppSound:(NSString *) fName withExt:(NSString *) ext{
NSString *path = [[NSBundle mainBundle] pathForResource : fName ofType :ext];
if ([[NSFileManager defaultManager] fileExistsAtPath : path])
{
NSURL *pathURL = [[NSBundle mainBundle] URLForResource:fName withExtension:ext];
// Instantiates the AVAudioPlayer object, initializing it with the sound
if(self.appSoundPlayer)
{
if([self.appSoundPlayer isPlaying])
{
[self.appSoundPlayer stop];
[self.appSoundPlayer release];
}
}
//Thread breaks down in the next line self. appSoundPlayer...
self.appSoundPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: pathURL error: nil] ;
//self.appSoundPlayer.numberOfLoops = 1;
[appSoundPlayer setDelegate:self];
[appSoundPlayer prepareToPlay];
//[appSoundPlayer setVolume:1.0];
[appSoundPlayer play];
}
else{
// NSLog(#"error, file not found: %#", path);
}
}
Check Framework versions (SDK 5 <- wrong, SDK6 <-right)