Akavache crashing android app - xamarin

I'm using Xamarin.Forms and have this method to fetch my user object
public static async Task<Object> GetCurrentUser()
{
try
{
return await BlobCache.UserAccount.GetObject<Object>("NewUser").FirstOrDefaultAsync();
}
catch (KeyNotFoundException)
{
return null;
}
}
The code works well on my iOS emulator but keeps crashing on the android with this error
System.Collections.Generic.KeyNotFoundException The given key 'NewUser'
was not present in the cache.
Please I need help

Related

Xamarin UWP : app in front/rear (method unexisting ?)

I have a app in xamarin that listen a folder and do some action when a file is created.
But the thing is that I need to be able to :
bring my app in front when a file is created
push my app in rear when acyion are finished
I have a beginning of response with
Window.Current.Activate();
but that only work if my app is not minimize (app not in first view)
I've already tried this :
IList<AppDiagnosticInfo> infos = await AppDiagnosticInfo.RequestInfoForAppAsync();
IList<AppResourceGroupInfo> resourceInfos = infos[0].GetResourceGroups();
await resourceInfos[0].StartSuspendAsync();
but visual studio tell me
AppResourceGroupInfo don't have a definition for StartSuspendAsync()
but documentation mention it AppResourceGroupInfo.StartSuspendAsync Method
someone have an idea ?
UPDATE [2020-04-29 16:48] :
This is a pcl project
the intention is to use dependency service to have diferent comportement in function of platform (already implemented just need the front/rear
interface in pcl
public interface IWindowManager
{
void Minimize();
void Maximize();
}
in uwp
class WindowManager : IWindowManager
{
public async void Maximize()
{
try
{
Window.Current.Activate();
}
catch(Exception ex)
{
DependencyService.Get<IErrorLogger>().LogError(ex);
}
}
public async void Minimize()
{
IList<AppDiagnosticInfo> infos = await AppDiagnosticInfo.RequestInfoForAppAsync();
IList<AppResourceGroupInfo> resourceInfos = infos[0].GetResourceGroups();
resourceInfos[0].StartSuspendAsync();
}
}
and as I say StartSuspendAsync() encounter some problem
AppResourceGroupInfo don't have a definition for StartSuspendAsync()
Derive from official document, StartSuspendAsync() available in the Windows 10 update 1803 (build 17134). So please edit the UWP project mini version to 17134.
but that only work if my app is not minimize (app not in first view)
For making the app foreground, you could use the following code.
IEnumerable<AppListEntry> appListEntries = await Package.Current.GetAppListEntriesAsync();
await appListEntries.First().LaunchAsync();
Update
If above does not work, please try use register a protocol for UWP app and launch it with Windows.System.Launcher.LaunchUriAsync method.
public async void Maximize()
{
try
{
await Windows.System.Launcher.LaunchUriAsync(new Uri("testapp:"));
}
catch (Exception ex)
{
Debug.Write(ex);
}
}

Rendering the Google Recaptcha in Android Studio 3

I am using Android Studio 3
I am following this article to learn how to use Google Recaptcha in Android Studio.
Installed the package using this: implementation 'com.google.android.gms:play-services-safetynet:12.0.1'
API keys are also registered.
I saw there is onClick event handler but where is it mentioned about rendering the recaptcha?
Update 1
When I wrote the button click code as mentioned in the link...I got a complication error: inconvertible types cannot cast anonymous android.view.view.onclicklistener to java.util.concurrent.executor
Code as asked in comment
btn_Login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
SafetyNet.getClient(this).verifyWithRecaptcha("")
.addOnSuccessListener((Executor) this,
new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
#Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
// Indicates communication with reCAPTCHA service was
// successful.
String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
// Validate the user response token using the
// reCAPTCHA siteverify API.
}
}
})
.addOnFailureListener((Executor) this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException) {
// An error occurred when communicating with the
// reCAPTCHA service. Refer to the status code to
// handle the error appropriately.
ApiException apiException = (ApiException) e;
int statusCode = apiException.getStatusCode();
} else {
}
}
});
}
});
I used below code and everything is work fine now.
Make sure to implement Executor in the activity
btn_Login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
SafetyNet.getClient(Activity.this).verifyWithRecaptcha("")
.addOnSuccessListener((Activity) MyActivity.this,
new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
#Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
// Indicates communication with reCAPTCHA service was
// successful.
String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
// Validate the user response token using the
// reCAPTCHA siteverify API.
}
}
})
.addOnFailureListener((Activity) MyActivity.this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException) {
// An error occurred when communicating with the
// reCAPTCHA service. Refer to the status code to
// handle the error appropriately.
ApiException apiException = (ApiException) e;
int statusCode = apiException.getStatusCode();
} else {
}
}
});
}
});
According to the article, in your button click handler you must call the method SafetyNet.getClient(this).verifyWithRecaptcha(...) to show reCAPTCHA and handle success or error. Passing this, you give the SDK handle to your current view which should be shown after solving reCAPTCHA. Most probably the rendering will be done by the SDK itself given that it’s a part of the OS. And most probably it will be full-screen in a separate top-level view blocking access to your app before solving the riddle.
You should try to implement it in your app as described in the article and see how it goes. Then you can ask a more specific question.
EDIT: You combined 2 techniques in your code: copy-pasting the code from Google and implementing anonymous class from it. So the problem you asked in the comment is that using (Executor) this in line 5 refers now not to your View (as it was there in the original tutorial) but to the instance of the anonymous interface implementation new View.OnClickListener() that you created. Ypu can refer to this answer to see how it can be implemented not interfering with already complex reCAPTCHA code.

A while after I deploy my code to iOS the phone hangs up

Is there some way I can track what's happening with Xamarin? I do a debug with a target of my phone and then later it hangs up. I can't do anything, can't shut it down with the button on the side and the only way I can get the phone to work again is by pressing the button on the side and the home button. Running on iPhone 6s Plus.
Here is some code that I suspect might be causing a problem. Would also like to know if anyone can see anything that might cause the problem with the code:
public partial class App : Application
{
public static DataManager db;
private static Stopwatch stopWatch = new Stopwatch();
private const int defaultTimespan = 1;
public App()
{
InitializeComponent();
}
public static DataManager DB
{
get
{
if (db == null)
{
db = new DataManager();
}
return db;
}
}
protected override void OnStart()
{
App.DB.InitData();
MainPage = new Japanese.MainPage();
if (!stopWatch.IsRunning)
stopWatch.Start();
Device.StartTimer(new TimeSpan(0, 0, 1), () =>
{
if (stopWatch.IsRunning && stopWatch.Elapsed.Minutes >= defaultTimespan)
{
Debug.WriteLine("Checking database");
PointChecker.CheckScore();
stopWatch.Restart();
}
return true;
});
}
protected override void OnSleep()
{
Debug.WriteLine("OnSleep");
stopWatch.Reset();
}
protected override void OnResume()
{
Debug.WriteLine("OnResume");
// deductPoints();
stopWatch.Start();
}
}
iOS requires that everything is setup, with 17 seconds, on the initial first load. This means that you must set the MainPage in your App constructor, you can't set it in OnStart.
Or, you can place MainPage = new ContentPage(); in your App constructor, then it will be replaced in OnStart. However, you must set the MainPage, when it's constructing the Application.
Android and UWP I think, give you some freedom, and you can set it in OnStart, but definitely not iOS.
My iPhones are hangs up when I have debugger connected to running app and that connection is interrupted. For example, if you unplug lightning cable while Visual Studio is debugging - the phone will hangs.
So try to start your application from phone(without debugger attached) and check your datacable.

Xamarin iOS Google Sign-in component : App crashes due to error uiDelegate must either be a |UIViewController| or implement

I'm trying to implement google sign in using this component for xamarin.ios: Google Sign-in for iOS
It works great on emulator but when it comes to actual device it's crashing once i tap signin button. (iOS 10.2 - emulator is also using same OS)
I have a custom button which calls SignInUser method on SignIn.SharedInstance
It's crashing with below error (only when the app is deployed on device)
Objective-C exception thrown. Name: NSInvalidArgumentException Reason: uiDelegate must either be a |UIViewController| or implement the |signIn:presentViewController:| and |signIn:dismissViewController:| methods from |GIDSignInUIDelegate|.
I'm calling function below to initialize GoogleSignIn on FinishedLaunching method of AppDelegate.cs
public void Configure()
{
NSError configureError;
Context.SharedInstance.Configure(out configureError);
if (configureError != null)
{
// If something went wrong, assign the clientID manually
Console.WriteLine("Error configuring the Google context: {0}", configureError);
SignIn.SharedInstance.ClientID = googleClientId;
}
SignIn.SharedInstance.Delegate = this;
SignIn.SharedInstance.UIDelegate = new GoogleSignInUIDelegate();
}
Here's my implementation of ISignInUIDelegate():
class GoogleSignInUIDelegate : SignInUIDelegate
{
public override void WillDispatch(SignIn signIn, NSError error)
{
}
public override void PresentViewController(SignIn signIn, UIViewController viewController)
{
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(viewController, true, null);
}
public override void DismissViewController(SignIn signIn, UIViewController viewController)
{
UIApplication.SharedApplication.KeyWindow.RootViewController.DismissViewController(true, null);
}
}
So the emulator seems to know the methods are implemented, but not the device. Any idea what i am doing wrong here?
After some debugging i found where the actual issue was.
Somehow, the UIDelegate i assigned during initialization was lost when i was calling my login method. So i moved the line below from my initialization step to login
SignIn.SharedInstance.UIDelegate = new GoogleSignInUIDelegate();
Here's how my login method looks like now:
public void Login()
{
SignIn.SharedInstance.UIDelegate = new GoogleSignInUIDelegate(); //moved this here from Configure
SignIn.SharedInstance.SignInUser();
}
This took care of the issue for me but i am still not sure why this is only an issue on the device and not the emulator. Any Ideas?
Add a PreserveAttribute to your GoogleSignInUIDelegate class to prevent the Linker from removing the methods that can not be determined via static analysis.
Add the following class to your project:
public sealed class PreserveAttribute : System.Attribute {
public bool AllMembers;
public bool Conditional;
}
Apply the class attribute:
[Preserve (AllMembers = true)]
class GoogleSignInUIDelegate : SignInUIDelegate
{
~~~~
}
Re: https://developer.xamarin.com/guides/ios/advanced_topics/linker/
Setting PresentingViewController helped me to resolve the issue.
SignIn.SharedInstance.PresentingViewController = this;
Have found such fix here:
https://github.com/googlesamples/google-signin-unity/issues/169#issuecomment-791305225

Requesting Android permissions in a class (Xamarin)

I'm trying to request a permission at runtime for my app. I use a service provider to talk between the portable class and Android.
I start by calling this code on button press in the PCL:
using (new Busy(this))
{
var locationHelper = scope.Resolve<ILocationHelper>();
locationHelper.GetLocation(this);
}
This calls my Android level service:
public class AndroidLocationHelper : ILocationHelper, ILocationListener
{
readonly string[] PermissionsLocation =
{
Manifest.Permission.AccessCoarseLocation
};
const int RequestLocationId = 0;
public void GetLocation(SearchViewModel viewModel)
{
try
{
const string permission = Manifest.Permission.AccessCoarseLocation;
if (((int)Build.VERSION.SdkInt < 23) || (CheckSelfPermission(permission) == Permission.Granted))
{
}
else
RequestPermissions(PermissionsLocation, RequestLocationId);
}
catch (Exception ex)
{
Debug.WriteLine("Error while getting Location service");
Debug.WriteLine(ex.Message);
Messaging.AlertUser("There was an error with determining your location");
}
}
However, I get two errors on CheckSelfPermission and RequestPermissions. These two methods are only available to activities. The code works fine in MainActivity; however, I want to ask for permissions when the user hits a button, not in OnCreate or OnResume, etc.
Thanks for any help.
In your Android project, You can use this and use the Dependency Service to call it in Xamarin.Forms PCL project later:
var thisActivity = Forms.Context as Activity;
ActivityCompat.RequestPermissions(thisActivity, new string[] {
Manifest.Permission.AccessFineLocation }, 1);
ActivityCompat.RequestPermissions(thisActivity,
new String[] { Manifest.Permission.AccessFineLocation },
1);
You can try with ContextCompat.CheckSelfPermission, passing the application context, like this:
ContextCompat.CheckSelfPermission(Android.App.Application.Context, permission)
Update
In case of ActivityCompat.RequestPermissions, which requires an activity reference, you can keep track of the current activity. There is a very handy lib for that, called "CurrentActivityPlugin". You can find at https://github.com/jamesmontemagno/CurrentActivityPlugin
Rafael came up with a solution but I found another option that is a lot less effort just using MessagingCenter. In the MainActivity's OnCreate add a receiver that runs all the location code, that way you have access to all of the activities methods (and there are a bunch of tutorials on doing location services in MainActivity). Then add the Send inside of your service (the class).
To expound Rafael Steil's answer, I tried the suggested CurrentActivityPlugin and it worked on me. In my case I am trying to execute a voice call which needs CALL_PHONE permission. Here is the code snippet in your case: I used the ContextCompat & ActivityCompat so that I don't need to check the VERSION.SdkInt
using Plugin.CurrentActivity;
public void GetLocation(SearchViewModel viewModel){
var context = CrossCurrentActivity.Current.AppContext;
var activity = CrossCurrentActivity.Current.Activity;
int YOUR_ASSIGNED_REQUEST_CODE = 9;
if (ContextCompat.CheckSelfPermission(context, Manifest.Permission.AccessCoarseLocation) == (int)Android.Content.PM.Permission.Granted)
{
//Permission is granted, execute stuff
}
else
{
ActivityCompat.RequestPermissions(activity, new string[] { Manifest.Permission.AccessCoarseLocation }, YOUR_ASSIGNED_REQUEST_CODE);
}
}
It's dead simple
public bool CheckPermission()
{
const string permission = Manifest.Permission.ReceiveSms;
return ContextCompat.CheckSelfPermission(Forms.Context, permission) == (int) Permission.Granted;
}

Resources