Xamarin.Droid Firebase with Facebook Authentication - c#

After hours of research on this, I have been trying to get this done. I have made further and some necessary improvement and this is what i have. I am able to successfully login but what i want to do next is to let Firebase display the logged users. That is what i have been struggling with for some hours now.
When i take out this line out of my code firebaseAuth.SignInWithCredential(credential).AddOnCompleteListener(this, new IOnCompleteListener<IAuthResult>());, I am able to login successfully but user doesn't show on Firebase.
But when i include the line firebaseAuth.SignInWithCredential(credential).AddOnCompleteListener(this, new IOnCompleteListener<IAuthResult>());, i get System.NullReferenceException has been thrown and i actually don't know where the error is coming from. Please help.
Thank you.
public class LoginActivity : BaseActivity, IFacebookCallback, IAuthStateListener, IOnCompleteListener
{
private ICallbackManager mCallbackManager;
private Firebase.Auth.FirebaseAuth firebaseAuth;
private IOnCompleteListener listener;
public static FirebaseApp app;
private Firebase.Auth.FirebaseAuth.IAuthStateListener firebaseAuthListener;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
FacebookSdk.SdkInitialize(this.ApplicationContext);
LoginButton button = FindViewById<LoginButton>(Resource.Id.login_button);
button.SetReadPermissions("email","public_profile");
mCallbackManager = CallbackManagerFactory.Create();
button.RegisterCallback(mCallbackManager, this);
}
public void handleFacebookAccessToken(AccessToken accessToken)
{
AuthCredential credential = FacebookAuthProvider.GetCredential(accessToken.Token);
firebaseAuth.SignInWithCredential(credential).AddOnCompleteListener(this, new IOnCompleteListener<IAuthResult>());
}
public void OnAuthStateChanged(Firebase.Auth.FirebaseAuth auth)
{
FirebaseUser user = firebaseAuth.CurrentUser;
if (user != null)
{
Console.WriteLine("The current user is " + firebaseAuth.CurrentUser);
}
Console.WriteLine("The current user is " + firebaseAuth.CurrentUser);
}
public void OnCancel()
{
throw new NotImplementedException();
}
public void OnError(FacebookException p0)
{
throw new NotImplementedException();
}
public void OnSuccess(Java.Lang.Object result)
{
LoginResult loginResult = result as LoginResult;
handleFacebookAccessToken(loginResult.AccessToken);
Console.WriteLine("My token is" + loginResult.AccessToken);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
mCallbackManager.OnActivityResult(requestCode, (int)resultCode, data );
}
protected override void OnStart(){
base.OnStart();
// firebaseAuth.AddAuthStateListener(firebaseAuthListener);
}
protected override void OnStop(){
base.OnStop();
// firebaseAuth.RemoveAuthStateListener(firebaseAuthListener);
}
private class IOnCompleteListener<T> : IOnCompleteListener
{
public IntPtr Handle => throw new NotImplementedException();
public void Dispose()
{
throw new NotImplementedException();
}
public void OnComplete(Android.Gms.Tasks.Task task)
{
if (!task.IsSuccessful)
{
}
else
{
}
}
}
}
}

I saw that you've tried to implement IOnCompleteListener for your LoginActivity, but I didn't find public void OnComplete(Task task) in your code, please make sure that you've implemented the Android.Gms.Tasks.IOnCompleteListener, and if you do this, you can simply change your code firebaseAuth.SignInWithCredential(credential).AddOnCompleteListener(this, new IOnCompleteListener<IAuthResult>()); to firebaseAuth.SignInWithCredential(credential).AddOnCompleteListener(this, this);.
Following is my demo, it works by my side:
[Activity(Label = "Activity3", Exported = true)]
[IntentFilter(new[] { Intent.ActionView },
DataScheme = "#string/fb_login_protocol_scheme"),]
public class Activity3 : Activity, IFacebookCallback, IOnCompleteListener
{
private ICallbackManager mCallbackManager;
private FirebaseAuth mAuth;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
FacebookSdk.SdkInitialize(this.ApplicationContext);
// Create your application here
SetContentView(Resource.Layout.layout3);
FirebaseApp.InitializeApp(this);
mAuth = FirebaseAuth.Instance;
LoginButton fblogin = FindViewById<LoginButton>(Resource.Id.fblogin);
fblogin.SetReadPermissions("email", "public_profile");
mCallbackManager = CallbackManagerFactory.Create();
fblogin.RegisterCallback(mCallbackManager, this);
}
private void handleFacebookAccessToken(AccessToken accessToken)
{
AuthCredential credential = FacebookAuthProvider.GetCredential(accessToken.Token);
mAuth.SignInWithCredential(credential).AddOnCompleteListener(this, this);
}
//facebook IFacebookCallback implementation
public void OnSuccess(Java.Lang.Object p0)
{
LoginResult loginResult = p0 as LoginResult;
handleFacebookAccessToken(loginResult.AccessToken);
}
public void OnCancel()
{
}
public void OnError(FacebookException p0)
{
}
//firebase IOnCompleteListener implementation
public void OnComplete(Task task)
{
if (task.IsSuccessful)
{
FirebaseUser user = mAuth.CurrentUser;
}
else
{
Toast.MakeText(this, "Authentication failed.", ToastLength.Short).Show();
}
}
// acitivity lifecycle
protected override void OnStart()
{
base.OnStart();
FirebaseUser currentUser = mAuth.CurrentUser;
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
var resultCodeNum = 0;
switch (resultCode)
{
case Result.Ok:
resultCodeNum = -1;
break;
case Result.Canceled:
resultCodeNum = 0;
break;
case Result.FirstUser:
resultCodeNum = 1;
break;
}
mCallbackManager.OnActivityResult(requestCode, resultCodeNum, data);
}
}

Related

xamarin android webview file upload download does not work . please i am comfortable with c#

i have created a mobile app for my website .the webview does not handle upload and download .so i followed the link Uploading files using a webview in Xamarin Android App and included the code from this link but does not handle upload and download. please guide. the storeactivity.cs code here.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.Net;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Webkit;
using Android.Widget;
namespace smartapp
{
[Activity(Label = "StoreActivity")]
public class StoreActivity : Activity
{
static ProgressBar progressBar;
WebView webview;
IValueCallback mUploadMessage;
private static int FILECHOOSER_RESULTCODE = 1;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.StoresView);
webview = FindViewById<WebView>(Resource.Id.StoreView);
// show progress bar
progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar);
// chrome client to upload files from webview
var chrome = new FileChooserWebChromeClient((uploadMsg, acceptType, capture) => {
mUploadMessage = uploadMsg;
var i = new Intent(Intent.ActionGetContent);
i.AddCategory(Intent.CategoryOpenable);
i.SetType("image/*");
StartActivityForResult(Intent.CreateChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
});
webview.LoadUrl("https://smartbook.pk/Stores/index");
webview.SetWebViewClient(new WebViewListener());
// download files from webview
webview.SetDownloadListener(new MyDownloadListerner(this));
webview.SetWebChromeClient(chrome);
webview.Settings.JavaScriptEnabled = true;
}
//
class MyDownloadListerner : Java.Lang.Object, IDownloadListener
{
Context cont;
public MyDownloadListerner(Context context)
{
cont = context;
}
public void OnDownloadStart(string url, string userAgent, string contentDisposition, string mimetype, long contentLength)
{
Android.Net.Uri uri = Android.Net.Uri.Parse(url);
Intent intent = new Intent(Intent.ActionView, uri);
cont.StartActivity(intent);
}
}
//
//
protected override void OnActivityResult(int requestCode, Result resultCode, Intent intent)
{
if (requestCode == FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage)
return;
Java.Lang.Object result = intent == null || resultCode != Result.Ok
? null
: intent.Data;
mUploadMessage.OnReceiveValue(result);
mUploadMessage = null;
}
}
// file chooser code
partial class FileChooserWebChromeClient : WebChromeClient
{
Action<IValueCallback, Java.Lang.String, Java.Lang.String> callback;
public FileChooserWebChromeClient(Action<IValueCallback, Java.Lang.String, Java.Lang.String> callback)
{
this.callback = callback;
}
//For Android 4.1
[Java.Interop.Export]
public void openFileChooser(IValueCallback uploadMsg, Java.Lang.String acceptType, Java.Lang.String capture)
{
callback(uploadMsg, acceptType, capture);
}
}
// webview listener code here
public class WebViewListener : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return true;
}
public override void OnPageStarted(WebView view, string url, Android.Graphics.Bitmap favicon)
{
progressBar.Progress = view.Progress;
}
public override void OnLoadResource(WebView view, string url)
{
progressBar.Progress = view.Progress;
}
public override void OnPageFinished(WebView view, string url)
{
progressBar.Progress = 0;
}
}
public override bool OnKeyDown(Android.Views.Keycode keyCode, Android.Views.KeyEvent e)
{
if (keyCode == Keycode.Back && webview.CanGoBack())
{
webview.GoBack();
return true;
}
return base.OnKeyDown(keyCode, e);
}
}
}
This is the Working Code of File Upload Hope this will Help you
public class MyWb : Activity
{
int count = 1;
IValueCallback mUploadMessage;
private static int FILECHOOSER_RESULTCODE = 1;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button> (Resource.Id.myButton);
button.Click += delegate {
button.Text = string.Format ("{0} clicks!", count++);
};
var chrome = new FileChooserWebChromeClient ((uploadMsg, acceptType, capture) => {
mUploadMessage = uploadMsg;
var i = new Intent (Intent.ActionGetContent);
i.AddCategory (Intent.CategoryOpenable);
i.SetType ("image/*");
StartActivityForResult (Intent.CreateChooser (i, "File Chooser"), FILECHOOSER_RESULTCODE);
});
var webview = this.FindViewById<WebView> (Resource.Id.webView1);
webview.SetWebViewClient (new WebViewClient ());
webview.SetWebChromeClient (chrome);
webview.Settings.JavaScriptEnabled = true;
webview.LoadUrl ("http://www.script-tutorials.com/demos/199/index.html");
}
protected override void OnActivityResult (int requestCode, Result resultCode, Intent intent)
{
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage)
return;
Java.Lang.Object result = intent == null || resultCode != Result.Ok
? null
: intent.Data;
mUploadMessage.OnReceiveValue (result);
mUploadMessage = null;
}
}
}
partial class FileChooserWebChromeClient : WebChromeClient
{
Action<IValueCallback, Java.Lang.String, Java.Lang.String> callback;
public FileChooserWebChromeClient (Action<IValueCallback, Java.Lang.String, Java.Lang.String> callback)
{
this.callback = callback;
}
//For Android 4.1
[Java.Interop.Export]
public void openFileChooser (IValueCallback uploadMsg, Java.Lang.String acceptType, Java.Lang.String capture)
{
callback (uploadMsg, acceptType, capture);
}
}

WakefulBroadcastReceiver Xamarin Does not work

I wrote a program, for when sms received it will play ring. But it's work only when program is running and when program closed it's doesn't work.
What should I do?
public class MainActivity : Activity
{
SampleReceiver receiver;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
receiver = new SampleReceiver();
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
intentFilter.Priority = 1000;
RegisterReceiver(receiver, intentFilter);
// Code omitted for clarity
}
}
[BroadcastReceiver(Enabled = true, Exported = true)]
public class SampleReceiver : WakefulBroadcastReceiver
{
private const string IntentAction = "android.provider.Telephony.SMS_RECEIVED";
public override void OnReceive(Context context, Intent intent)
{
try
{
Android.Net.Uri uri = RingtoneManager.GetDefaultUri(RingtoneType.Ringtone);
Ringtone ringtone = RingtoneManager.GetRingtone(context, uri);
ringtone.Play();
if (intent.HasExtra("pdus"))
{
var smsArray = (Java.Lang.Object[])intent.Extras.Get("pdus");
foreach (var item in smsArray)
{
var sms = SmsMessage.CreateFromPdu((byte[])item);
string address = sms.OriginatingAddress;
string smsText = sms.MessageBody;
Toast.MakeText(context, "Massage from : " + address + " Says : " + smsText, ToastLength.Long).Show();
}
}
}
catch (System.Exception ex)
{
//Toast.MakeText(context, ex.Message, ToastLength.Long).Show();
}
}
}
Tnx

how to implement a different thread inside the service in XAMARIN

What I am trying to do is to run the activity while having a background process when a button is pressed. (Because my real problem is when I am having a very long process, my front-end is being stopped for a while)
What I tried to do is to make a service and bind to it (which I don't know if I made it right since I thought it will work independently). But still, when I am trying to access the method from the service, my foreground is still being stopped for a while.
HOW CAN I ACHIEVE TO MAKE MY FOREGROUND STILL RUNNING WHILE WAITING FOR THE RESPONSE OF WEB SERVICE IN THE BACKGROUND
(I ALREADY MADE IT WITH PROGRESS BAR TO MAKE THE USER AWARE IT IS STILL LOADING)
Here is my service, serviceConnection and binder code: // it is still useless, i'm just trying to test this
[Service]
public class MyService : Service
{
static readonly string TAG = "X:" + typeof(MyService).Name;
int i;
#region Override OnCreate()
public override void OnCreate()
{
base.OnCreate();
Toast.MakeText(this, "MyService started", ToastLength.Short).Show();
}
#endregion
#region Override OnDestroy
public override void OnDestroy()
{
base.OnDestroy();
StopSelf();
Log.Debug(TAG, "MyService destroyed at {0}.", DateTime.Now);
}
#endregion
#region Override OnBind
public override IBinder OnBind(Intent intent)
{
return new MyBinder(this);
}
#endregion
public string GetTimestamp(string value)
{
// this is just a testing
if (value == string.Empty)
{
for (i = 0; i < 9999999; i++)
{
if (i == 100000)
Log.Debug(TAG, "100000 zxc");
if (i == 500000)
Log.Debug(TAG, "500000 zxc");
}
return "empty";
}
else
return i.ToString() + " from service";
}
}
public class MyBinder : Binder
{
MyService service;
public MyBinder(MyService service)
{
Toast.MakeText(service.ApplicationContext, "my binder", ToastLength.Short).Show();
this.service = service;
}
public string GetFormattedTimestamp(string value)
{
return service?.GetTimestamp(value);
}
}
public class MyServiceConnection : Java.Lang.Object, IServiceConnection
{
static readonly string TAG = typeof(MyServiceConnection).FullName;
public bool IsConnected { get; private set; }
public MyBinder Binder { get; private set; }
public MyServiceConnection()
{
IsConnected = false;
Binder = null;
}
public void OnServiceConnected(ComponentName name, IBinder binder)
{
Binder = binder as MyBinder;
IsConnected = Binder != null;
Log.Debug(TAG, "OnServiceConnected zxc");
}
public void OnServiceDisconnected(ComponentName name)
{
Log.Debug(TAG, "OnServiceDisconnected zxc");
IsConnected = false;
Binder = null;
}
}

Collecting GPS co-Ordinates

I am building a native android app using xamarin. The issue is, that the application collects and displays the coordinates perfectly on the emulator but when I put it on a smartphone (tried 2 samsung phones) it comes up with can't determine the current address. Extra information data and locations are turned on so I am not sure where the issue is. Thanks for your help. here is the xammarin recipe encase that helps https://developer.xamarin.com/recipes/android/os_device_resources/gps/get_current_device_location/
[Activity(Label = "NewRoute")]
public class NewRouteActivity : Activity, ILocationListener
{
static readonly string TAG = "X:" + typeof(NewRouteActivity).Name;
TextView _addressText;
Location _currentLocation;
LocationManager _locationManager;
string _locationProvider;
TextView _locationText;
public async void OnLocationChanged(Location location) {
_currentLocation = location;
if (_currentLocation == null)
{
_locationText.Text = "Unable to determine your location. Try again in a short while.";
}
else
{
_locationText.Text = string.Format("{0:f6},{1:f6}", _currentLocation.Latitude, _currentLocation.Longitude);
Address address = await ReverseGeocodeCurrentLocation();
DisplayAddress(address);
}
}
public void OnProviderDisabled(string provider) { }
public void OnProviderEnabled(string provider) { }
public void OnStatusChanged(string provider, Availability status, Bundle extras) { }
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.CreatetRoute);
_addressText = FindViewById<TextView>(Resource.Id.address_text);
_locationText = FindViewById<TextView>(Resource.Id.location_text);
FindViewById<TextView>(Resource.Id.get_address_button).Click += AddressButton_OnClick;
InitializeLocationManager();
Button btnEndPoint = FindViewById<Button>(Resource.Id.btnEndPoint);
btnEndPoint.Click += new EventHandler(AfterPointsCollected);
}
//Location Stuff
void InitializeLocationManager()
{
_locationManager = (LocationManager)GetSystemService(LocationService);
Criteria criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Fine
};
IList<string> acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);
if (acceptableLocationProviders.Any())
{
_locationProvider = acceptableLocationProviders.First();
}
else
{
_locationProvider = string.Empty;
}
Log.Debug(TAG, "Using " + _locationProvider + ".");
}
//Override OnResume so that Activity1 will begin listening to the LocationManager when the activity comes into the foreground:
protected override void OnResume()
{
base.OnResume();
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
}
async void AddressButton_OnClick(object sender, EventArgs eventArgs)
{
if (_currentLocation == null)
{
_addressText.Text = "Can't determine the current address. Try again in a few minutes.";
return;
}
Address address = await ReverseGeocodeCurrentLocation();
DisplayAddress(address);
}
async Task<Address> ReverseGeocodeCurrentLocation()
{
Geocoder geocoder = new Geocoder(this);
IList<Address> addressList =
await geocoder.GetFromLocationAsync(_currentLocation.Latitude, _currentLocation.Longitude, 10);
Address address = addressList.FirstOrDefault();
return address;
}
void DisplayAddress(Address address)
{
if (address != null)
{
StringBuilder deviceAddress = new StringBuilder();
for (int i = 0; i < address.MaxAddressLineIndex; i++)
{
deviceAddress.AppendLine(address.GetAddressLine(i));
}
// Remove the last comma from the end of the address.
_addressText.Text = deviceAddress.ToString();
}
else
{
_addressText.Text = "Unable to determine the address. Try again in a few minutes.";
}
}
//Override OnPause and unsubscribe Activity1 from the LocationManager when the activity goes into the background:
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
}
//Changing Activity
void AfterPointsCollected(object sender, EventArgs e)
{
//context //activity
Intent intent = new Intent(this, typeof(AfterPointsCollectedActivity));
//starts the activity with the intent above
this.StartActivity(intent);
}
Your phones are probably running MarshMallow which now require that you request permission for location services.
You can read more about it here https://blog.xamarin.com/requesting-runtime-permissions-in-android-marshmallow/. You might want to use this Nuget package that handles all that for you. https://github.com/jamesmontemagno/Xamarin.Plugins/tree/master/Geolocator

MonoDroid C# Translate

I am translating a java class to C#, however, I am unsure that I have done it properly. In my code below, RewardRequestListener's OnFinishedEvent should be called, however, it never hits a breakpoint or logs anything.
Here is my Java:
private RequestListener<Resource> mRequestListener = new RequestListener<Resource>() {
#Override
public void onFinished(Kiip manager, Resource response) {
if (response != null) {
if (mRewardActionToggle.isChecked()) {
manager.showResource(response);
} else {
toast("Reward Queued");
mResources.add(response);
}
} else {
toast("No Reward");
}
}
#Override
public void onError(Kiip manager, KiipException error) {
toast("error (" + error.getCode() + ") " + error.getMessage());
}
};
Here is my C#:
private static readonly string TAG = "example";
private Button mUnlockAchievement, mSaveLeaderboard, mShowNotification, mShowFullscreen, mGetActivePromos, mNewActivity;
private EditText mAchievementId, mLeaderboardId;
private static ToggleButton mPositionToggle, mRewardActionToggle;
private List<ME.Kiip.Api.Resource> mResources = new List<ME.Kiip.Api.Resource>();
private RewardRequestListener mRewardsListener;
private ActivePromosRequestListener mActivePromosListener;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
mRewardsListener = new RewardRequestListener(this);
}
class RewardRequestListener : Kiip.IRequestListener
{
ExampleActivity example = new ExampleActivity();
public RewardRequestListener(ExampleActivity example)
{
this.example = example;
}
public void OnError(Kiip p0, KiipException p1)
{
example.toast("error (" + p1.Code + ") " + p1.Message);
}
public void OnFinished(Kiip p0, Java.Lang.Object p1)
{
ME.Kiip.Api.Resource response = p1 as ME.Kiip.Api.Resource;
if (response != null)
{
if (mRewardActionToggle.Checked)
{
p0.ShowResource(response);
}
else
{
example.mResources.Add(response);
}
}
else
{
example.toast("No Reward");
}
}
public IntPtr Handle { get; set; }
public void Dispose()
{
}
}
public void OnClick(View v)
{
Kiip manager = Kiip.Instance;
switch (v.Id)
{
case Resource.Id.unlockAchievement:
manager.UnlockAchievement(mAchievementId.Text, mRewardsListener);
break;
}
}

Categories