xamarin.auth stuck on success when isUsingNativeUI true - xamarin

Im using xamarin.auth for facebook, google and twitter login. Its not closing browser after get success, if i close browser manually IsAuthenticated returning false. If i use isUsingNativeUI false it works fine but very ugly new page with uncontrolled color and title. Is where a way to change color and title on there? I can use these 2 ways too but need to fix.
var authenticator = new OAuth2Authenticator(
clientId,
Constants.FacebookScope,
new Uri(Constants.FacebookAuthorizeUrl),
new Uri(Constants.FacebookAccessTokenUrl),
null, isUsingNativeUI: true);
authenticator.Completed += OnAuthCompleted;
authenticator.Error += OnAuthError;
AuthenticationState.Authenticator = authenticator;
var presenter = new Xamarin.Auth.Presenters.OAuthLoginPresenter();
presenter.Login(authenticator);
Ugly navigation bar and title

I just solved my issue with correct redirect url. 111111 means your client Id, add fb on start, ://authorize to the end of it.
public static string FacebookiOSRedirectUrl = "fb1111111111111://authorize";
public static string FacebookAndroidRedirectUrl = "fb1111111111111://authorize";
On ios it say unknown or wrong redirect url, you can fix it with add this on your plist.
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Xamarin.Auth facebook PAuth</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fb111111111111</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>

Related

Xamarin forms: IOS won't load webview

I have a webview on a page that opens with data from a previous page. It works on Android and with IOS the screen remains white. I have already searched a bit and found out that it can be due to the events. I use the events : OnAppearing, Navigating and Navigated.
<WebView x:Name="webview"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Navigating="webOnNavigating"
Navigated="webOnEndNavigating"
IsVisible="False"/>
public WebviewPage(String link, String username, String password)
{
InitializeComponent();
colorLogOutButton(link);
linkForApi = link;
compLink = link + "/Login1.aspx" + "?ID=" + GUID + "&Username=" + username + "&Password=" + password;
webview.Source = compLink;
}
You have to add an exception to the Apple Transport Security (ATS) in order to display HTTP content in your application. You can do that modifying your .plist and adding the NSAllowsArbitraryLoadsInWebContent key. Something like that:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>

Facebook login issue -canOpenURL: failed for URL: "fbauth2:///" - error: "(null)"

I have looked at every single thread on here, I have the latest Parse SDK(1.8.5), I have the latest Facebook SDK(4.6). I'm using Xcode Version 7.0.1 with iOS9 and swift 2.0. I have read the Facebook API docs page over and over to make sure I am not missing anything as well as the parse API docs. Here is my view controller
import ParseFacebookUtilsV4
import Parse
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let permissions = ["public_profile"]
PFFacebookUtils.logInInBackgroundWithReadPermissions(permissions) {
(user: PFUser?, error: NSError?) -> Void in
if let user = user {
if user.isNew {
print("User signed up and logged in through Facebook!")
} else {
print("User logged in through Facebook!")
}
} else {
print("Uh oh. The user cancelled the Facebook login.")
}
}
}
Here is the AppDelegate:
import UIKit
import CoreData
import Parse
import Bolts
import FBSDKCoreKit
import ParseFacebookUtilsV4
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
Parse.enableLocalDatastore()
// Initialize Parse.
Parse.setApplicationId("removed",
clientKey: "removed")
PFFacebookUtils.initializeFacebookWithApplicationLaunchOptions(launchOptions)
return true
}
func application(application: UIApplication,
openURL url: NSURL,
sourceApplication: String?,
annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application,
openURL: url,
sourceApplication: sourceApplication,
annotation: annotation)
}
Here is the info.plist:
<plist version="1.0">
<dict>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fbapi</string>
<string>fb-messenger-api</string>
<string>fbauth2</string>
<string>fbshareextension</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>facebook.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>fbcdn.net</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
<key>akamaihd.net</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>removed</string>
</array>
</dict>
</array>
<key>FacebookAppID</key>
<string>removed</string>
<key>FacebookDisplayName</key>
<string>removed</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
No compiler issues but when I run it I get the
canOpenURL: failed for URL: "fbauth2:///" - error: "(null)"
-canOpenURL: failed for URL: "fbauth2:///" - error: "(null)"
and when the simulator starts up just a blank screen, it does not route the Facebook login on the simulator.
Can anyone please help!
This is an error introduced by Xcode 7 and iOS9.
According to Facebook's Doc:
https://developers.facebook.com/docs/ios/ios9
Why do I see console messages like 'canOpenURL: failed for URL: "fb...://' or ?
This is an Xcode warning indicating the the canOpenURL: call returned false. As long as you have configured the LSApplicationQueriesSchemes entry in your plist as described above, you can ignore this warning
As long as FB login is working, and this is your only error message, you can ignore it. We get it on our production app too, hopefully Facebook will fix it in their next SDK update.
you can see this link:
http://myxcode.net/2015/10/28/plist-requriments-for-facebook-integration-ios-9/
its just another addiction to array:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fb</string>
</array>

Drag messages from Mail onto Dock using Swift

I am trying to get my application to accept a mail message that was dropped onto my application's dock icon directly from Mail.
I have followed this link Dropping Files onto Dock Icon in Cocoa and tried to convert in into Swift and the latest version of Xcode but with no joy.
This is my AppDelegate.Swift file:
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate
{
func application(sender: NSApplication, openFile filename: String) -> Bool
{
println(filename)
return true
}
func application(sender: NSApplication, openFiles filenames: [String])
{
println(filenames)
}
}
I have set the document types for my project:
When I drag the mail document from Mail into the dock, then the dock highlights as if it wants to accept it but nothing triggers the openFiles method.
Incidentally if I drag the mail file out of Mail and into the Finder, and then drag it onto the dock icon it works fine.
And Mail drop only seems to work in El Capitan. I can see that mail can now be dropped into TextWrangler; this did not work under Yosemite.
As a bonus I'm offering an additional 50 bounty to anyone who can help me sort this out.
You can extract the mail item's URL by registering your app as a service by adding the following to your app's info.plist:
<key>NSServices</key>
<array>
<dict>
<key>NSMessage</key>
<string>itemsDroppedOnDock</string>
<key>NSSendTypes</key>
<array>
<string>public.data</string>
</array>
<key>NSMenuItem</key>
<dict>
<key>default</key>
<string>Open Mail</string>
</dict>
</dict>
</array>
Then your Swift app delegate would look like this:
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(aNotification: NSNotification) {
NSApp.servicesProvider = self
}
#objc func itemsDroppedOnDock(pboard: NSPasteboard, userData: NSString, error: UnsafeMutablePointer<NSString>) {
// help from https://stackoverflow.com/questions/14765063/get-dropped-mail-message-from-apple-mail-in-cocoa
print("dropped types: \(pboard.types)")
if let types = pboard.types {
for type in types {
print(" - type: \(type) string: \(pboard.stringForType(type))")
}
}
}
}
When you drop a mail message on your app's dock, the output will be something like:
dropped types: Optional(["public.url", "CorePasteboardFlavorType 0x75726C20", "dyn.ah62d4rv4gu8yc6durvwwaznwmuuha2pxsvw0e55bsmwca7d3sbwu", "Apple URL pasteboard type"])
- type: public.url string: Optional("message:%3C2004768713.4671#tracking.epriority.com%3E")
- type: CorePasteboardFlavorType 0x75726C20 string: Optional("message:%3C2004768713.4671#tracking.epriority.com%3E")
- type: dyn.ah62d4rv4gu8yc6durvwwaznwmuuha2pxsvw0e55bsmwca7d3sbwu string: Optional("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<array>\n\t<string>message:%3C2004768713.4671#tracking.epriority.com%3E</string>\n\t<string></string>\n</array>\n</plist>\n")
- type: Apple URL pasteboard type string: Optional("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<array>\n\t<string>message:%3C2004768713.4671#tracking.epriority.com%3E</string>\n\t<string></string>\n</array>\n</plist>\n")
Unfortunately, you probably need to figure out how to convert the mail URL "message:%3C2004768713.4671#tracking.epriority.com%3E" into the actual underlying mail file, but it's a start.
Alternatively, if you are willing to accept a drop in your app's window rather than on the dock, you should be able to just use NSDraggingInfo.namesOfPromisedFilesDroppedAtDestination, which is how I expect the Finder is able to copy the mail message when you drop one on a Finder window (note that the Finder does not respond to mail messages being dropped in its dock icon, only when they are dropped on a window).
Edit:
See Dropping promised files on to application icon in Dock on how to get promised file.

Not Sure How to Update Bool Values in Plist from UISwitch in UITableViewCell

I have a table with four rows, each having a title and switch as an accessory. I would like for the plist Boolean value to be updated when the corresponding switch is tapped.
Plist:
<array>
<dict>
<key>Bools</key>
<array>
<false/>
<false/>
<false/>
<false/>
</array>
<key>Strings</key>
<array>
<string>String0</string>
<string>String1</string>
<string>String2</string>
<string>String3</string>
</array>
</dict>
</array>
Here are the data source methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; {
return [allergens count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; {
return [[[allergens objectAtIndex: section] objectForKey: #"Strings"] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; {
return #"Header";
}
Here is my switch, with selector: switchToggled
UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchView;
[switchView addTarget:self action:#selector(switchToggled:) forControlEvents: UIControlEventTouchUpInside];
Below is the IBAction method. I can successfully get the switch tapped to appear in the log, so I know everything works. I am just not sure how to get the correct Boolean value to be updated.
- (IBAction)switchToggled:(id)sender {
NSLog(#"switch tapped");
}
Any help is appreciated! Thanks.
I was so new to programming when I posted this I was not aware that I could not programmatically edit a plist in the main bundle at runtime. I now understand that to achieve the effect I want I should save the starting plist to the app documents directory and work from that. I used this article to help format the process of saving and loading data to and from the documents directory.

How to handle with a default URL scheme

I want to build URI (or URL scheme) support in my app.
I do a LSSetDefaultHandlerForURLScheme() in my + (void)initialize and I setted the specific URL schemes also in my info.plist. So I have URL schemes without Apple Script or Apple Events.
When I call myScheme: in my favorite browser the system activates my app.
The problem is, how to handle the schemes when they are called. Or better said: How can I define what my app should do, when myScheme: is called.
Is there a special method that I have to implement or do I have to register one somewhere?
As you are mentioning AppleScript, I suppose you are working on Mac OS X.
A simple way to register and use a custom URL scheme is to define the scheme in your .plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>URLHandlerTestApp</string>
<key>CFBundleURLSchemes</key>
<array>
<string>urlHandlerTestApp</string>
</array>
</dict>
</array>
To register the scheme, put this in your AppDelegate's initialization:
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self
andSelector:#selector(handleURLEvent:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
Whenever your application gets activated via URL scheme, the defined selector gets called.
A stub for the event-handling method, that shows how to get the URL string:
- (void)handleURLEvent:(NSAppleEventDescriptor*)event
withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]
stringValue];
NSLog(#"%#", url);
}
Apple's documentation: Installing a Get URL Handler
Update
I just noticed a problem for sandboxed apps that install the event handler in applicationDidFinishLaunching:. With enabled sandboxing, the handler method doesn't get called when the app is launched by clicking a URL that uses the custom scheme.
By installing the handler a bit earlier, in applicationWillFinishLaunching:, the method gets called as expected:
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification
{
[[NSAppleEventManager sharedAppleEventManager]
setEventHandler:self
andSelector:#selector(handleURLEvent:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
}
- (void)handleURLEvent:(NSAppleEventDescriptor*)event
withReplyEvent:(NSAppleEventDescriptor*)replyEvent
{
NSString* url = [[event paramDescriptorForKeyword:keyDirectObject]
stringValue];
NSLog(#"%#", url);
}
On the iPhone, the easiest way to handle URL-scheme activation is, to implement UIApplicationDelegate's application:handleOpenURL: - Documentation
All credits should go to weichsel and kch
I'm just adding swift(2.2/3.0) code for your convenience
func applicationWillFinishLaunching(_ notification: Notification) {
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleGetURL(event:reply:)), forEventClass: UInt32(kInternetEventClass), andEventID: UInt32(kAEGetURL) )
}
#objc func handleGetURL(event: NSAppleEventDescriptor, reply:NSAppleEventDescriptor) {
if let urlString = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue {
print("got urlString \(urlString)")
}
}
The problem is, how to handle the schemes when they are called.
That's where the Apple Events come in. When Launch Services wants your app to open a URL, it sends your app a kInternetEventClass/kAEGetURL event.
The Cocoa Scripting Guide uses this very task as an example of installing an event handler.
I'm just adding slightly different Swift 4/5 version of the code:
func applicationWillFinishLaunching(_ notification: Notification) {
NSAppleEventManager
.shared()
.setEventHandler(
self,
andSelector: #selector(handleURL(event:reply:)),
forEventClass: AEEventClass(kInternetEventClass),
andEventID: AEEventID(kAEGetURL)
)
}
#objc func handleURL(event: NSAppleEventDescriptor, reply: NSAppleEventDescriptor) {
if let path = event.paramDescriptor(forKeyword: keyDirectObject)?.stringValue?.removingPercentEncoding {
NSLog("Opened URL: \(path)")
}
}
You can define the “get URL” command in a scripting terminology SDEF and implement the corresponding method. For example, Terminal’s SDEF contains the following command definition for handling URLs
<command name="get URL" code="GURLGURL" description="Open a command an ssh, telnet, or x-man-page URL." hidden="yes">
<direct-parameter type="text" description="The URL to open." />
</command>
and declares that the application responds to it:
<class name="application" code="capp" description="The application's top-level scripting object.">
<cocoa class="TTApplication"/>
<responds-to command="get URL">
<cocoa method="handleGetURLScriptCommand:" />
</responds-to>
</class>
The TTApplication class (a subclass of NSApplication) defines the method:
- (void)handleGetURLScriptCommand:(NSScriptCommand *)command { … }

Resources