Facebook SDK for Xamarin.iOS login return issue - facebook

I'm trying to use the Facebook SDK for Xamarin.iOS(the one from Facebook, not from Octorcurve) to get the users Authed on my app.
I've followed the Sample that comes with the component from the store. The sample just works but I'm stuck after the login/permissions without firing the events to notify the viewController that we have a user logged in. I have set the plist file with the app name, id, and Url schema as requested by facebook SDK. So, the code is:
Note that I'm not creating the UI from code. I have a .xib IB file with the UI and yes, I added a view for the FBLoginView and set its custom class to FBLoginView.
AppDelegate.cs(omitted the rest of code for brevity):
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
window = new UIWindow (UIScreen.MainScreen.Bounds);
viewController = new LoginViewController ();
navController = new UINavigationController (viewController);
window.RootViewController = navController;
window.MakeKeyAndVisible ();
return true;
}
public override bool OpenUrl (UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return FBSession.ActiveSession.HandleOpenURL(url);
}
public override void OnActivated (UIApplication application)
{
FBSession.ActiveSession.HandleDidBecomeActive();
}
LoginViewController.cs(the controller for the NIB file):
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
loginView = btnLogin as FBLoginView;
loginView.ReadPermissions = new string[] { "email" };
loginView.PublishPermissions = new string[]{ "publish_actions", "publish_stream", "manage_pages" };
loginView.DefaultAudience = FBSessionDefaultAudience.Everyone;
loginView.ShowingLoggedInUser += (sender, e) =>
{
var a = e;
};
loginView.FetchedUserInfo += (sender, e) =>
{
user = e.User;
};
}
So, whis this code I have 2 issues:
Note that I'm casting btnLogin as FBLoginView since idk how to set the outlet on Interface Builder to use the right type of FBLoginView... It always say that it its type wasnt found when I'm adding the Outlet in the .h file. So I just created it as UIView and did the cast on the code. This cast is valid and still working, since the permissions that I'm passing are being asked for user authorisation at the consent FB screen.
The two events ShowingLoggedInUser and FetchedUserInfo never get called and the AppDelegate never call OpenUrl neither OnActivated.
Am I missing something? All I need is get the access_token that should be returned somewhere after the login. How do I get it?
I really appreciate any help.
Thanks!

Just to provide feedback for people...
Suddenly, after 2 days hitting my head agains the wall, I just cleaned the project, rebuild it and restarted Xamarin STUDIO... Now the events are fired... No single thing changed and things are working...
There are weird behaviours unexplained to me with Xamarin that just work or not, like sometime I start the app, and it just hangs on "Waiting for debugger to connect..." and nothing happens connecting to the device while in Simulator it works fine...
Thanks

Related

button back to my app in the background and when you resume it starts again

I am developing an app in Xamarin.Forms, before I was trying to make a master detail page to become my MainPage when I logged in to my app, this I have already achieved. Now I have the problem that when I use the button behind the phone my app is miimiza and goes to the background which is the behavior I hope, but when I return to my app does not continue showing my master detail page, but returns to my LginPage.
It is as if my app was running twice or at least there were two instances of LoginPage existing at the same time, this is because in my LoginPage I trigger some DisplayAlert according to some messages that my page is listening through the MessaginCenter and they are they shoot twice.
Can someone tell me how I can return the same to my app on the master detail page and not restart in the strange way described?
LoginView.xaml.cs:
public partial class LogonView : ContentPage
{
LogonViewModel contexto = new LogonViewModel();
public LogonView ()
{
InitializeComponent ();
BindingContext = contexto;
MessagingCenter.Subscribe<LogonViewModel>(this, "ErrorCredentials", async (sender) =>
{
await DisplayAlert("Error", "Email or password is incorrect.", "Ok");
}
);
}
protected override void OnDisappearing()
{
base.OnDisappearing();
MessagingCenter.Unsubscribe<LogonViewModel>(this, "ErrorCredentials");
}
}
Part of my ViewModel:
if (Loged)
{
App.token = token;
Application.Current.MainPage = new RootView();
}
else
{
MessagingCenter.Send(this, "ErrorCredentials");
}
Thanks.
I hope this is in Android. All you can do is, you can override the backbuttonpressed method in MainActivity for not closing on back button pressed of the entry page. like below, you can add some conditions as well.
public override void OnBackPressed()
{
Page currentPage = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault();
if (currentPage != null)
{
if (currentPage.GetType().Name == "HomePage" || currentPage.GetType().Name == "LoginPage")
{
return;
}
}
base.OnBackPressed();
}
When you press the Home button, the application is paused and the
current state is saved, and finally the application is frozen in
whatever state it is. After this, when you start the app, it is
resumed from the last point it was saved with.
However, when you use the Back button, you keep traversing back in
the activity stack, closing one activity after another. in the end,
when you close the first activity that you opened, your application
exits. This is why whenever you close your application like this, it
gets restarted when you open it again.
Answer taken from this answer. The original question asks about the native Android platform, but it still applies here.
It means you have to Use Setting Plugin or save data in Application properties.
You have to add below code in App.xaml.cs file:
if (SettingClass.UserName == null)
MainPage = new LoginPage();
else
MainPage = new MasterDetailPage();
For Setting Plugin you can refer this link.

Facebook api with Xamarin

I am creating an application by Xamarin (andoroid / iOS) and would log in using facebook, and I do so by sharing the same access code?
You can do it by following the code sample I've published here: https://github.com/IdoTene/XamarinFormsNativeFacebook
a guide of how to do so:
Steps to set up your project:
Installation:
1) For Android download from nuget/Components the Facebook Android SDK: http://components.xamarin.com/view/facebookandroid and place it in your droid project.
2) For iOS download from nuget/Components the Facebook iOS SDK: http://components.xamarin.com/view/facebookios and place it in your iOS project.
Set up components:
Shared code set up:
1) Add a FacebookLoginButton which inherits from Button, leave it without any implementation
2) Add that button to the login page
3)Add to App.cs the following property:
public static Action<string> PostSuccessFacebookAction { get; set; }
4) in the LoginPage.xaml.cs (or in the viewmodel class if you have one), add the navigation for this action:
App.PostSuccessFacebookAction = async token =>
{
//you can use this token to authenticate to the server here
//call your FacebookLoginService.LoginToServer(token)
//I'll just navigate to a screen that displays the token:
await Navigation.PushAsync(new DiplayTokenPage(token));
};
Android: 1) Add to strings.xml file (found at Resources/Valus) The following lines {Your App Id Here} {Your App Name}
2) Add to Manifest.xml the following code:
3) Create activity class for facebook (I called it FacebookActivity)
4) Create a custom rendrer for the facebook Login button (I called it FacebookLoginButtonRendererAndroid)
5) Add to mainActivity class The OnActionResult method to handle response from the FacebookActivity
iPhone:
1) In AppDelegate class, register in method FinishedLaunching the following:
FBSettings.DefaultAppID = FacebookAppId;
FBSettings.DefaultDisplayName = FacebookAppName;
2) Override the following methods:
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
base.OpenUrl(application, url, sourceApplication, annotation);
return FBSession.ActiveSession.HandleOpenURL(url);
}
public override void OnActivated(UIApplication application)
{
base.OnActivated(application);
// We need to properly handle activation of the application with regards to SSO
// (e.g., returning from iOS 6.0 authorization dialog or from fast app switching).
FBSession.ActiveSession.HandleDidBecomeActive();
}
3) Create a custom rendrer for the facebook Login button (I called it FacebookLoginButtonRendererIos)

WP: What callback to be used when page is loaded from app launching

Inside MainpPage.xaml.cs, what callback can be used so that I know it is coming from launching the App but not coming from other page? I know that there is Application_Launching in App.xaml.cs. But if I place below code there, exception is thrown somewhere. If I put in Loaded callback, I can't distinguish if it is called from App launching from navigated from other page.
if (MediaPlayer.State == MediaState.Playing)
{
MediaPlayer.Pause();
}
I would like to stop any existing playing music after entering my app.
Thanks
In you App.xaml:
public void TryStopAllMusic()
{
if (MediaPlayer!=null && MediaPlayer.GameHasControl)
{
MediaPlayer.Stop(); //stop to clear any existing music
}
}
In the constructor, under InitializeComponent() of your MainPage.xaml.cs:
public MainPage()
{
InitializeComponent();
(Application.Current as App).TryStopAllMusic();
}
That's all.

Facebook action script 3 API login/logout issue

I'm making mobile AIR app for Android using Flash builder 4.5, AIR 2.6, Facebook action script 3 API the latest version.
I have a problem with login/logout. I can login only one time - then my data caches somehow and Facebook automatically logs me in. When I call logout I receive response TRUE, but I don't really logout from system. Standard login dialog doesn't appear for me. I have already read a lot of articles on stackoverflow and open issues on official site, but none of them were helpfull. How can I solve this? Here is the code I use:
package
{
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.external.ExternalInterface;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.system.Capabilities;
import flash.system.Security;
import flash.display.Loader;
import com.facebook.graph.FacebookMobile;
public class TestProj extends Sprite
{
public function TestProj()
{
super();
//register to add to stage
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
// support autoOrients
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
}
private function onAddedToStage(event:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
FacebookMobile.init("195053007196177", initCallback);
}
private function initCallback(success:Object, fail:Object):void
{
var appPermissions:Array = new Array("read_stream", "offline_access", "publish_stream", "read_friendlists");
FacebookMobile.login(loginCallback, this.stage, appPermissions);
//FacebookMobile.logout(logoutCallback);
}
private function loginCallback(success:Object, fail:Object):void
{
//And here I always receive success with my UserID
//and login dialog don't appears to me before this
if (success)
{
trace("login ok");
}
else
trace("login failed");
}
private function logoutCallback(success:Object):void
{
//here I reseive "TRUE" always!!
trace(success);
}
}
}
You're only passing the 1st argument of logoutCallback to your logout method. If you add in the 2nd argument of your site url specified for your app, it should clear it out the html cookie for that window. Also, set FacebookMobile.manageSession = false;
FacebookMobile.logout(logoutCallback, "http://your_app_origin_url");
There is a potential, related bug that involves Desktop and Mobile not accessing or clearing the access token's the same way. For that, there's a hack that describes exposing the access token in FacebookMobile, then manually calling the "logout" method with the access token. The issue is described here, including a method called "reallyLogout". If what I've written above doesn't work, implement "reallyLogout".
When you log out, your app clears the local session but does not log you out of the system. This is clearly defined in the documentation for logout. Think about it, if you're logged into Facebook on your Smartphone, Web Browser, and now this Mobile Desktop App, and suddenly you log out... it shouldn't log you out EVERYWHERE, just within that browsers session. So pass that 2nd parameter.
I've had this exact problem, and after trying numerous fixes, this finally seems to work:
The default logout functionality seems to not be properly clearing cookies via the FacebookMobile actionscript API. The solution in comment #33 here worked for me, reproduced here. Make sure to sub in your own APP_ID:
function logout(e:MouseEvent):void {
FacebookMobile.logout(onLogout, "https://m.facebook.com/dialog/permissions.request?app_id=APP_ID&display=touch&next=http%3A%2F%2Fwww.facebook.com%2Fconnect%2Flogin_success.html&type=user_agent&perms=publish_stream&fbconnect=1");
}
function onLogout(result:Object):void
{
trace("Perfect Log Out!")
}
Have had this Android Facebook clean logout problem the whole day, manage to solve it. Hope it helps. Here is my FB mobile handlelogin code to ensure all fb cookies and sessions are being removed and user will need to relogin.
Sometimes FB server is very slow. Its best to put a timer before you call handleLoginClick() again
function handleLoginClick():void
{
trace("connecting to facebook");
if (FacebookMobile.getSession() == null)
{
FacebookMobile.init(APP_ID, onHandleInit, null);
FacebookMobile.manageSession = false
}
else
{
var webView:StageWebView = new StageWebView();
webView.viewPort = new Rectangle(0, 0, 1, 1);
webView.stage = this.stage;
webView.loadURL("https://m.facebook.com/logout.php?confirm=1&next=http://www.facebook.com&access_token=" + FacebookMobile.getSession().accessToken);
webView.addEventListener(Event.COMPLETE,webviewhandleLoad);
function webviewhandleLoad(e:Event)
{
FacebookMobile.logout(null, "http://apps.facebook.com/<appName>/");
FacebookMobile.logout(null, "http://www.facebook.com");
webView.dispose()
webView = null
setTimeout(handleLoginClick,3000)
}
}
}
look at the solution of this problem. Maby someone it helps:
var stage_ref:Stage = PlatformUtil.originalStage(); //my custom class to get stage
var webView:StageWebView = new StageWebView();
webView.viewPort = new Rectangle(0, 0, stage_ref.width, stage_ref.height);
FacebookMobile.login(loginCallback, stage_ref, appPermissions, webView);
http://code.google.com/p/facebook-actionscript-api/issues/detail?id=381
http://code.google.com/p/facebook-actionscript-api/issues/detail?id=382
http://code.google.com/p/facebook-actionscript-api/issues/detail?id=383

Redirect action to mobile view

public ActionResult Home()
{
return View();
}
This is what I have for my current site within the HomeController. How can I detect if the action is called from a mobile device, and if it is, re-direct to MobileHome.aspx instead of Home.aspx.
I don't need to know the details of the device, because I am implementing the view in JQuery Mobile, which should adjust itself correctly depending on the view it's rendered in.
You may find the following blog post useful.
The following is an override on the Controller class. I have not tested this, so consider it pseudo code:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (this.Request.Browser.IsMobileDevice && filterContext.Result is ViewResultBase)
{
var viewResult = filterContext.Result as ViewResultBase;
viewResult.ViewName = "Mobile" + viewResult.ViewName;
}
base.OnActionExecuted(filterContext);
}
You can use the Request.Browser.IsMobileDevice to determine if the device is mobile (obviously), and then check to see if the result it a view. However, changing the view name is not sufficient if you pass an actual view to the result of your action.