In my cross-platform app I save application properties in the following way:
Application.Current.Properties["myValue"] = "Test";
await Application.Current.SavePropertiesAsync();
I then retrieve them later like this:
string myVal = Application.Current.Properties["myValue"];
This works perfectly when using the Android emulator. I can close the emulator down, and when I restart it again, my app data is preserved.
However, when I deploy this app to a physical Android device, data preservation works as expected until I close the app and open it again. At this point I retrieve an empty value. It's as though the data is only saved to memory (and not to file).
Furthermore, the iOS version of the exact same app works faultlessly. When I open the app up, all previous values have been saved and I can retrieve them.
What am I doing wrong on the Android version? Is there an Android setting, permission, or option which I need to enable to have the values saved between app sessions when actually deployed to a phone?
I had a similar problem where only the debug version saved Properties. I think we're still waiting for the bug fix, and this is the workaround on Xamarin Forms bugzilla.
In short: go to .Droid project settings -> Android Options -> Linker
and enter/add "System.Runtime.Serialization" to Skip linking assemblies.
Wow! After lots of research, I have getting solution for same issue in mine. Problem is that, when i store List or DataTable in Application.Current.Properties then all properties are removed after reopen app but if i store List or DataTable as serialize, it working fine.
In VS you need to enable the option:
Preserve application data/cache on device between deploys
You can find this at Tools > Options > Xamarin > Android Settings.
I don't know if this has stopped in the latest updates of Xamarin Forms, the data is available until the application is running similar to session but persistent storage does not work.
The best api I think available for this is Akavache https://github.com/akavache/Akavache.
You can read this blog https://codemilltech.com/akavache-is-aka-awesome/.
Update
There is a bug filed in bugzilla:
https://bugzilla.xamarin.com/show_bug.cgi?id=26444
I don't remember exactly which part of this solved the issue, but when I followed the instructions to prepare the Android application for release from start to finish, the issue went away. The problem occurred when debug builds were used on an Android device.
https://developer.xamarin.com/guides/android/deployment,_testing,_and_metrics/publishing_an_application/part_1_-_preparing_an_application_for_release/
The link details the suggested settings for the Android project when releasing to device. Following these instructions should solve the issue.
Related
I have a vendor provided .framework file that I created an iOS binding project for using Objective Sharpie. I can call into the library, get callbacks, pull data, mostly everything works except the library being able to access the current location. The public headers for that project are here StripeTerminal
In my C# code, I used the Xamarin.Essentials to pull the current location.
var location = await Geolocation.GetLastKnownLocationAsync();
This returns with my location both in the simulator and on a real iPhone. I can see the access is granted to my app in the Privacy-> Location Services menu.
I have the below in my info.plist file, which I have tried targeting 9.0 SDK and 12.0 SDK.
<key>NSLocationWhenInUseUsageDescription</key>
<string>Location required for accepting payments.</string>
In an example XCode project provided by the vendor, that is able to pull the location by inspecting their verbose logs. In the Xamarin app, their logs get stuck on a requestLocation and never continue past it. I even tried setting the Link option to Don't Link and the result is the same.
What is wrong with my binding project that would prevent a native framework library from being able to access the location?
The issue was a mix of how Xamarin works and iOS. I created a CLLocationManager object in my C# code and setup a listener for location changes, except it never worked. So I tried the Xamarin.Essentials package to get the current location using GetLastKnownLocationAsync and that worked every time, so it wasn't a permission issue or a simulator issue. Digging into the Xamarin.Essentials code I found the below.
NSRunLoop.Main.InvokeOnMainThread(() => manager = new CLLocationManager());
Reading more documentation, I found that the CLLocationManager can only be successfully created from an active run loop. Wrapping calls into the Stripe Terminal iOS SDK in the NSRunLoop.Main.InvokeOnMainThread allowed things to work as they were creating a CLLocationManager expecting the call to be in an active run loop without checking first, or documenting that behavior. Stripe's internal code waited on a callback, which never happened, thus hanging the SDK in a weird state.
I specifically need help getting the app build into my apps. I am so new to the MAC ecosystem. I need to get my app build from my windows 10 box (parallels) running VS2017/Xamarin Forms project uploaded to My Apps. What i have found is helpful if you are using xcode on the mac.
I have read tons of pages and help files and with all of that what I have includes:
created an app in VS2017/Xamarin that runs happily on the emulator from the MAC (MacBook Pro)
purchased the app dev subcription from apple
created a Production certificate (I don't need this yet but I was in there so...)
created a Development certificate
created a key pair from the Dev cert (that show up in the keychain)
created an App Group
created my app's placeholder under My Apps on App Store Connect
added my iPhone to devices via connecting to the Mac getting the UDID from iTunes
created a development provisioning profile for my iPhone (Not sure how this helps my testflight plight)
Assumptions
You must submit for review the same way for both TestFlight and Prod release to the actual store.
You don't need to open the app in xcode outside Xamarin
There is a tool or concept I am missing out on.
For development outside of Xcode, you will want to use Apple's Application Loader App to upload your app to App Store Connect.
As I said in comment to Matt below his correct answer to my actual question above, I needed to get the project right to get to that point.
Here are the more intimate details for the lurkers. I hope this helps some of you.
I was getting, or trying, to get all of this in place manually instead of letting VS do it's work getting this stuff together while I got to coding. FastLane FTW
Open the account management window, go to Tools > Options > Xamarin > Apple Accounts
Add your AppleID
Click on your appleID
Click the add button
Select your id in the lower text area
then add your distro cert. As is proper you deploy to TestFlight as a prod release.
Then get over to to your iOS project properties:
Make sure that your project is outputting an IPA. (Not Beer ;) )
These are my settings that worked. There could be other configurations that work as well.
I never get the automatic provisioning to work. And while this bundle signing settings look like it will not work, it does. I have received my apple approval for beta and users are in testflight.
Also, make sure you update the version of the app in the plist for subsequent releases. This change is not carried through from the AssemblyInfo.cs as one might expect. viola.
If you see this during debug make sure your debug version has Developer (Automatic) set for your debug settings.
FWIW - My VS2017:
While this does not perfectly match the info # https://learn.microsoft.com/en-us/xamarin/cross-platform/macios/apple-account-management?tabs=windows it worked for me. That page was key to the solution and deserves citing. Your mileage may vary.
If I missed something please reach out and I will update this.
I currently use App.Current.Properties dictionary to save some basic data needed for the app to connect to a database.
Unfortunately, when building and reinstalling the app on the Android simulator (didn't tried on the iOS one), app data seems to be wiped, so every time I test the app I've to re-enter connection info.
How can I avoid that?
Does it work if you start the app without redeploying it? If you just click the app icon on the emulator. If it does not you have propbarly forgot to call the save method.
Application.Current.SavePropertiesAsync();
When I build share extension from Xcode for the real device, Xcode arbitrarily stop debug. But when I launch for simulator, the problem does not occur.
Environment
Xcode 7.1.1
iOS 9.1
Details
When I build share extension, Xcode shows "Finished running MobileSafari.app on iPhone", but Safari does not run. And, The square stop button is arbitrarily gray. So, I launch Safari by myself and choose my extension and post. The debug section does not show anything. Also, URL request is not sent Rails server.
This is the picture when I build the share extension for the real device.
I do not know why the real device can not launch share extension at Xcode.
If anyone know the answer about this problem, please tell me.
Typically you can debug a share extension by going to Debug -> Attach to process or PID and entering the name of your share extension. From there you can open the share extension on your device or simulator and Xcode's debugger should attach and hit breakpoints correctly. However, I've noticed that log messages do not show up when doing this, nor do values populate for variables in the debugger view.
Here's how I got the debugging to work correctly. Run the share extension scheme. When it asks you what app to run, chose 'Photos' (because that's the app your extension will operate in). The Photos app will then launch on your device and you may proceed to use your extension. The debugger in Xcode should then work as expected.
I encountered this issue as well, though unfortunately I don't know the exact solution, maybe I can offer some information that might be helpful.
I (like you, judging by your screenshot) was using Cocoapods, and Cocoapods was copying resources from the pods into the bundle of the app extension after it was code signed. If memory serves, this was interfering with the code signing in some way, and therefore preventing the app from running under the debugger.
I believe that one of the symptoms of this was that logs appeared in the mac's console (or the device's console, can't remember which) saying something about "blasting onto the device using the old skool[sic] method."
You could confirm that this is the case by removing Cocoapods from your project, or any pods that require resources to be copied after compilation. I believe that the solution was to add some kind of special build phase to the extension project to copy the bundle resources, and disabling whatever Cocoapods uses by default.
As a temporary solution, I believe that deleting your app from the device should allow you to attach the debugger once, on the run where the app is installed for the first time. You might also try deleting derived data for your project.
I'm discovering Xamarin Android with Visual Studio and I'm working with the keystore.
All my code is based on Xamarin's https://github.com/xamarin/Xamarin.Auth
When I deploy and use the keystore, everything is working fine. Data are persisted and I can save, delete and retrieve them without a problem.
I can turn off the emulator or kill the application, the keystore is still here with the data in it.
But if I modify the code and redeploy the application without stopping the emulator, my keystore is lost.
Any idea on where I should start digging to troubleshoot this problem. I don't have any exception.
Looks like you need to set the setting to Preserve application data/cache on device between deploys.
Check this answer for details:
SharedPreferences not saving values properly