yavsc/ZicMoove/ZicMoove.Droid/MainActivity.cs

556 lines
20 KiB
C#

using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Gms.Common;
using Android.OS;
using Android.Speech.Tts;
using Android.Util;
using Android.Widget;
using Newtonsoft.Json.Linq;
using Plugin.DeviceInfo;
using SQLite.Net;
using SQLite.Net.Platform.XamarinAndroid;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Xamarin.Auth;
using XLabs;
using XLabs.Caching;
using XLabs.Caching.SQLite;
using XLabs.Enums;
using XLabs.Forms;
using XLabs.Forms.Services;
using XLabs.Ioc;
using XLabs.Platform.Device;
using XLabs.Platform.Mvvm;
using XLabs.Platform.Services;
using XLabs.Platform.Services.Email;
using XLabs.Platform.Services.Media;
using XLabs.Serialization;
using XLabs.Serialization.JsonNET;
namespace ZicMoove.Droid
{
using Android.Runtime;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using ZicMoove.Interfaces;
using Data;
using Droid.OAuth;
using Helpers;
using Interfaces;
using Model.Auth.Account;
using static Android.Manifest;
using Settings;
using Model.Auth;
using Com.Paypal.Android.Sdk.Payments;
using Java.Math;
using Org.Json;
using Xamarin.Forms;
[Activity(
Name = Constants.ApplicationName + ".MainActivity",
Label = Constants.ApplicationLabel,
Theme = "@style/MainTheme",
Icon = "@drawable/icon",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
[IntentFilter(new[] { Intent.ActionMain },
Categories = new[] { Intent.CategoryLauncher },
Icon = "@drawable/icon")]
public class MainActivity :
// global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,
XFormsCompatApplicationDroid,
IPlatform, IComponentContext
{
private PayPalConfiguration config = new PayPalConfiguration()
.Environment(PayPalConfiguration.EnvironmentSandbox)
.MerchantName("Yavsc")
.LanguageOrLocale("fr")
.RememberUser(true)
.AcceptCreditCards(true) // needs card.io
// TODO .MerchantPrivacyPolicyUri(new Uri("http://"))
// TODO .MerchantUserAgreementUri(new Uri("http://"))
.ClientId(Constants.PaypalClientId)
.SandboxUserPassword(Constants.PaypalClientSecret)
;
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
XamSvg.Setup.InitSvgLib();
// FIXME usefull?
SetPersistent(true);
// global::Xamarin.Forms.Forms.SetTitleBarVisibility(Xamarin.Forms.AndroidTitleBarVisibility.Never);
//var tb = FindViewById<Android.Support.V7.Widget.Toolbar>(ToolbarResource);
// FIXME tb is null
var stb = new Android.Support.V7.Widget.Toolbar(this);
SetSupportActionBar(stb);
var tb = new Toolbar(this);
SetActionBar(tb);
if (Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat)
{
Android.Webkit.WebView.SetWebContentsDebuggingEnabled(true);
}
IXFormsApp<XFormsCompatApplicationDroid> app = null;
if (!Resolver.IsSet)
{
var xfapp = new XFormsCompatAppDroid();
this.SetIoc(xfapp);
}
else
{
app = Resolver.Resolve<IXFormsApp>() as IXFormsApp<XFormsCompatApplicationDroid>;
if (app != null)
app.AppContext = this;
}
global::Xamarin.Forms.Forms.Init(this, bundle);
global::Xamarin.FormsMaps.Init(this, bundle);
Xamarin.Forms.Forms.ViewInitialized += (sender, e) =>
{
if (!string.IsNullOrWhiteSpace(e.View.StyleId))
{
e.NativeView.ContentDescription = e.View.StyleId;
}
};
var fapp = new ZicMoove.App(this);
LoadApplication(fapp);
var componentName = StartService(new Intent(this, typeof(YavscChooserTargetService)));
// TabLayoutResource = Resource.Layout.Tabbar;
// ToolbarResource = Resource.Layout.Toolbar;
/*
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
global::Xamarin.FormsMaps.Init(this, bundle);
LoadApplication(new App(this));
/* var x = typeof(Themes.DarkThemeResources);
x = typeof(Themes.LightThemeResources);
x = typeof(Themes.Android.UnderlineEffect); */
var intent = new Intent(this, typeof(PayPalService));
intent.PutExtra(PayPalService.ExtraPaypalConfiguration, config);
this.StartService(intent);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == Constants.AllowBeATarget)
{
if (grantResults.Length > 0)
{
if (grantResults[0] == Android.Content.PM.Permission.Granted)
{
// yay!
}
else
{
// Should we show an explanation?
if (ActivityCompat.ShouldShowRequestPermissionRationale(this,
Permission.BindChooserTargetService))
{
//Show permission explanation dialog...
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
throw new NotImplementedException();
}
else
{
//Never ask again selected, or device policy prohibits the app from having that permission.
//So, disable that feature, or fall back to another situation...
}
}
}
}
}
private SimpleContainer SetIoc(XFormsCompatAppDroid app)
{
var resolverContainer = new SimpleContainer();
app.Init(this);
var documents = app.AppDataDirectory;
var pathToDatabase = Path.Combine(documents, "xforms.db");
resolverContainer.Register<IDevice>(t => AndroidDevice.CurrentDevice)
.Register<IDisplay>(t => t.Resolve<IDevice>().Display)
.Register<IFontManager>(t => new FontManager(t.Resolve<IDisplay>()))
.Register<IEmailService, EmailService>()
.Register<IMediaPicker, MediaPicker>()
.Register<ITextToSpeechService, XLabs.Platform.Services.TextToSpeechService>()
.Register<IDependencyContainer>(resolverContainer)
.Register<IXFormsApp>(app)
.Register<ISecureStorage>(t => new KeyVaultStorage(t.Resolve<IDevice>().Id.ToCharArray()))
.Register<IJsonSerializer, JsonSerializer>()
.Register<ICacheProvider>(
t => new SQLiteSimpleCache(new SQLitePlatformAndroid(),
new SQLiteConnectionString(pathToDatabase, true), t.Resolve<IJsonSerializer>()));
Resolver.SetResolver(resolverContainer.GetResolver());
return resolverContainer;
}
public bool EnablePushNotifications(bool enable)
{
if (enable)
return StartNotifications();
else
return StopNotifications();
}
private string gCMStatusMessage = null;
public string GCMStatusMessage
{
get
{
return gCMStatusMessage;
}
}
public App AppContext
{
get; set;
}
bool StartNotifications()
{
if (IsPlayServicesAvailable(out gCMStatusMessage))
{
var intent = new Intent(this, typeof(GcmRegistrationIntentService));
StartService(intent);
return true;
}
return false;
}
bool StopNotifications()
{
return StopService(new Intent(this, typeof(GcmRegistrationIntentService)));
}
public void RevokeAccount(string userName)
{
var accStore = AccountStore.Create(this);
var accounts = accStore.FindAccountsForService(Constants.ApplicationLabel);
accStore.Delete(
accounts.Where(a => a.Username == userName).FirstOrDefault()
, Constants.ApplicationLabel);
Toast.MakeText(this,
Resource.String.yavscIdentRemoved
, ToastLength.Short);
}
public void OpenWeb(string Uri)
{
var u = global::Android.Net.Uri.Parse(Uri);
Intent i = new Intent(Intent.ActionView, u);
StartActivity(i);
}
protected override void OnStart()
{
base.OnStart();
if (MainSettings.PushNotifications)
StartNotifications();
long queryId = Intent.GetLongExtra("BookQueryId", 0);
if (queryId > 0)
{
Task.Run(async () =>
{
var query = DataManager.Instance.BookQueries.LocalGet(queryId);
App.ShowBookQuery(query);
});
}
}
public bool IsPlayServicesAvailable(out string msgText)
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.Success)
{
if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
msgText = GoogleApiAvailability.Instance.GetErrorString(resultCode);
else
{
msgText = "Sorry, this device is not supported";
Finish();
}
return false;
}
else
{
msgText = "Google Play Services is available.";
return true;
}
}
public async Task<IEnumerable<Account>> GetAndroidAccounts()
{
return await Task.Run(() =>
{
var manager = AccountStore.Create(this);
return manager.FindAccountsForService(Constants.ApplicationLabel);
});
}
public void AddAccount()
{
var auth = new YaOAuth2Authenticator(
clientId: Constants.APIKey,
clientSecret: Constants.APISecret,
scope: Constants.Scope,
authorizeUrl: new Uri(Constants.AuthorizeUrl),
redirectUrl: new Uri(Constants.RedirectUrl),
accessTokenUrl: new Uri(Constants.AccessTokenUrl));
Intent loginIntent = auth.GetUI(this);
var accStore = AccountStore.Create(this);
auth.Completed += (sender, eventArgs) =>
{
if (eventArgs.IsAuthenticated)
{
int expires_in = int.Parse(eventArgs.Account.Properties["expires_in"]);
var tokens = new Tokens
{
AccessToken = eventArgs.Account.Properties["access_token"],
RefreshToken = eventArgs.Account.Properties["refresh_token"],
ExpiresIn = expires_in,
TokenType = eventArgs.Account.Properties["token_type"]
};
RunOnUiThread(
async () =>
{
using (var client = new HttpClient())
{
// get me
using (var request = new HttpRequestMessage(HttpMethod.Get, Constants.UserInfoUrl))
{
request.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", tokens.AccessToken);
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
string userJson = await response.Content.ReadAsStringAsync();
JObject jactiveUser = JObject.Parse(userJson);
Account acc = eventArgs.Account;
var uid = jactiveUser["Id"].Value<string>();
var username = jactiveUser["UserName"].Value<string>();
var roles = jactiveUser["Roles"].Values<string>().ToList();
var emails = jactiveUser["EMails"].Values<string>().ToList();
var avatar = jactiveUser["Avatar"].Value<string>();
var address = jactiveUser["Avatar"].Value<string>();
var newuser = new User
{
UserName = username,
EMails = emails,
Roles = roles,
Id = uid,
YavscTokens = tokens,
Avatar = avatar,
Address = address
};
MainSettings.SaveUser(newuser);
accStore.Save(acc, Constants.ApplicationLabel);
}
}
}
});
}
};
auth.Error += Auth_Error;
StartActivity(loginIntent);
}
private void Auth_Error(object sender, AuthenticatorErrorEventArgs e)
{
// TODO handle
}
public T Resolve<T>()
{
return (T)Resolver.Resolve(typeof(T));
}
public object Resolve(Type t)
{
return Resolver.Resolve(t);
}
protected override void OnSaveInstanceState(Bundle outState)
{
// TODO Save instance
base.OnSaveInstanceState(outState);
}
public override void OnStateNotSaved()
{
base.OnStateNotSaved();
}
public override void OnRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState)
{
base.OnRestoreInstanceState(savedInstanceState, persistentState);
}
private void CheckSharing()
{
// .BIND_CHOOSER_TARGET_SERVICE
// Here, thisActivity is the current activity
if (ContextCompat.CheckSelfPermission(this,
Permission.BindChooserTargetService) != Android.Content.PM.Permission.Granted)
{
ActivityCompat.RequestPermissions(this,
new String[] { Permission.BindChooserTargetService },
Constants.AllowBeATarget);
// Constants.AllowReadContacts is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
public void Pay(double amount, PayMethod method, string name = null)
{
if (name == null) name = $"Votre commande {Constants.ApplicationLabel}";
var payment = new PayPalPayment(new BigDecimal(amount), "EUR", "the item",
PayPalPayment.PaymentIntentOrder);
var intent = new Intent(this, typeof(PaymentActivity));
intent.PutExtra(PayPalService.ExtraPaypalConfiguration, config);
intent.PutExtra(PaymentActivity.ExtraPayment, payment);
this.StartActivityForResult(intent, (int)RequestCode.PayImmediate);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (requestCode == (int)RequestCode.PayDelayed)
if (resultCode == Result.Ok)
{
var confirm = data.GetParcelableExtra(PaymentActivity.ExtraResultConfirmation);
if (confirm != null)
{
try
{
Log.Info("xam.paypal.test", confirm.ToString());
// TODO: send 'confirm' to your server for verification.
// see https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
// for more details.
}
catch (JSONException e)
{
Log.Error("xam.paypal.test", "something went really wrong here: ", e);
}
}
}
else if (resultCode == Result.Canceled)
{
Log.Info("xam.paypal.test", "Canceled.");
}
else if ((int)resultCode == PaymentActivity.ResultExtrasInvalid)
{
Log.Info("xam.paypal.test", "Invalid Payment or PayPalConfiguration.");
}
}
protected override void OnDestroy()
{
this.StopService(new Intent(this, typeof(PayPalService)));
base.OnDestroy();
}
enum RequestCode : int
{
PayImmediate = 1,
PayDelayed
}
private static string imagesFolder = null;
public static string ImagesFolder
{
get
{
if (imagesFolder != null) return imagesFolder;
var appData =
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
imagesFolder = System.IO.Path.Combine(appData, Constants.ImagePath);
DirectoryInfo di = new DirectoryInfo(imagesFolder);
if (!di.Exists) di.Create();
return imagesFolder;
}
}
public void UpdateAppImages()
{
var images = ImagesFolder;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Constants.YavscHomeUrl);
var targets = DataManager.Instance.Activities.Select(
a => new string[2] { a.Photo, a.Code }
).ToArray();
foreach (var photo in targets)
{
if (photo[0] != null)
{
var streamtask = client.GetStreamAsync(photo[0]);
streamtask.Wait();
if (streamtask.IsCompleted)
{
using (streamtask.Result)
{
FileInfo fi = new FileInfo(Path.Combine(images, $"{photo[1]}.svg"));
using (var ostr = fi.OpenWrite())
{
streamtask.Result.CopyTo(ostr);
}
}
}
}
}
foreach (var act in DataManager.Instance.Activities)
{ act.LocalPhoto = Path.Combine(images, $"{act.Code}.svg"); }
DataManager.Instance.Activities.SaveEntity();
}
}
}
}