0

I'm trying to use a Xamarin.AccountStore to retain a user's login credentials so that they don't have to type them out every time they use the app.

Saving credentials looks something like this:

Account account = new Account(...);
AccountStore store = AccountStore.Create();
store.Save(account, appName);

When emulating the app from VS, this works exactly as I expected. When running on an actual phone through Xamarin Live, the Save method throws an exception for what looks to be a missing method in the Android library.

Exception Message:

Constructor on type 'Java.Security.KeyStore+SecretKeyEntry' not found.

Stack Trace:

at System.RuntimeType.CreateInstanceImpl (System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes, System.Threading.StackCrawlMark& stackMark) [0x00213] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
at System.Activator.CreateInstance (System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Object[] args, System.Globalization.CultureInfo culture, System.Object[] activationAttributes) [0x000ba] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
at System.Activator.CreateInstance (System.Type type, System.Object[] args) [0x00000] in <896ad1d315ca4ba7b117efb8dacaedcf>:0 
at NInterpret.Interpreter.newobj (System.Collections.Generic.Dictionary`2[TKey,TValue] gargs, Mono.Cecil.MethodReference m, System.Object[] createInstanceArgs) [0x00305] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.interpretBlock (System.Object[] args, System.Object[] locals, Mono.Cecil.Cil.Instruction initialInstruction, Microsoft.FSharp.Collections.FSharpSet`1[T] inTries, Microsoft.FSharp.Core.FSharpOption`1[T] lastException) [0x03d5b] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.interpret (System.Object[] args) [0x00099] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.callAMethod (NInterpret.AMethod m, NInterpret.AType[] ptypes, NInterpret.AType[] genericMethodArgs, System.Collections.Generic.Dictionary`2[TKey,TValue] genericArgsIndex, System.Object[] args, System.Collections.Generic.List`1[T] byRefArgs, Microsoft.FSharp.Core.FSharpOption`1[T] byRefTarget, System.Object target, System.Boolean virtualCall) [0x00184] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.callMethodReference (System.Collections.Generic.Dictionary`2[TKey,TValue] gargs, Mono.Cecil.MethodReference ms, System.Boolean virtualCall) [0x00384] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.interpretBlock (System.Object[] args, System.Object[] locals, Mono.Cecil.Cil.Instruction initialInstruction, Microsoft.FSharp.Collections.FSharpSet`1[T] inTries, Microsoft.FSharp.Core.FSharpOption`1[T] lastException) [0x03c6e] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.interpret (System.Object[] args) [0x00099] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.callAMethod (NInterpret.AMethod m, NInterpret.AType[] ptypes, NInterpret.AType[] genericMethodArgs, System.Collections.Generic.Dictionary`2[TKey,TValue] genericArgsIndex, System.Object[] args, System.Collections.Generic.List`1[T] byRefArgs, Microsoft.FSharp.Core.FSharpOption`1[T] byRefTarget, System.Object target, System.Boolean virtualCall) [0x00184] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.callMethodReference (System.Collections.Generic.Dictionary`2[TKey,TValue] gargs, Mono.Cecil.MethodReference ms, System.Boolean virtualCall) [0x00384] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.interpretBlock (System.Object[] args, System.Object[] locals, Mono.Cecil.Cil.Instruction initialInstruction, Microsoft.FSharp.Collections.FSharpSet`1[T] inTries, Microsoft.FSharp.Core.FSharpOption`1[T] lastException) [0x03c6e] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0 
at NInterpret.Interpreter.interpretBlock (System.Object[] args, System.Object[] locals, Mono.Cecil.Cil.Instruction initialInstruction, Microsoft.FSharp.Collections.FSharpSet`1[T] inTries, Microsoft.FSharp.Core.FSharpOption`1[T] lastException) [0x0013c] in <5a7d38ec7eef0f2aa7450383ec387d5a>:0

I've tested this on several Android devices, all with the same results. The emulator is running Android 7.1, and the phones run 6.* and 7.1, so it doesn't seem like this is an Android version issue.

I've also tried clearing out my bin and obj folders, reinstalling the related Nuget packages, restarting VS and my PC, etc., none of which have helped.

What's causing these behavioral differences between emulated and real devices?

Potentially Unrelated:

At one point, I wrapped the Save expression in a try/catch and returned a bool to indicate whether the save had succeeded. In the emulator, this returns true after a successful save. On a "real" device, the catch statement is tripped (and should return false), but after returning to the calling code, the returned value is not false, but rather (null). This is frustrating for lots of reasons (How did a non-nullable bool get assigned a value other than true/false? How can I do anything with confidence if I can't trust the return types of my functions? etc.). I have no idea whether or not this behavior is related to the question at hand, but I include it here for completeness' sake.

  • Do not try to test that with Xamarin Live, deploy/debug directly on a device without using Live – SushiHangover Apr 30 '18 at 19:47
  • @SushiHangover, this resolved the issue. I didn't realize the Xamarin Live player was significantly different from a direct deploy. We'll avoid using it going forward. Make this comment an answer, and I'm happy to accept it! – bpatterson May 01 '18 at 15:55
  • Live works fine for its design intent, "previewing XAML", once your app's complexly increases, full debug sessions are the only alternative currently. – SushiHangover May 01 '18 at 16:26

1 Answers1

0

Per SushiHangover's note above, it turns out that Xamarin Live is not suited to actually running an app, and should only be used for tasks like viewing layouts.

The lack of various logical components when using Xamarin Live is likely the root cause of the other odd behaviors mentioned above as well.

Using an emulator or a USB connection to a physical phone both seem to work as expected.