Open KeithBoynton opened 5 years ago
Thanks for your feedback, I'm currently working on the .net standard version. I think I can fix it.
Thanks for your response, it's strange because it's working just fine in the distributed iOS and Windows versions. Is there anything you can suggest as a workaround?
If I can help progress it in any way then I'd like to help. This has the next release of my app blocked as both the Mac Distribution and Mac App Store versions crash. If you could point me in a direction to look I will be more than happy to try and help out.
@KeithBoynton Hi, can you test it please? https://www.nuget.org/packages/ksemenenko.GoogleAnalytics/1.0.4-pre
Hi, been away for a few days.. just back.. will test asap
@KSemenenko Hi again, unfortunately 1.0.4-pre is still crashing for on the distributed xamarin.mac version.
It gives the following trace..
Crashed Thread: 0 tid_307 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [499]
VM Regions Near 0:
-->
__TEXT 0000000101bbb000-0000000101fc8000 [ 4148K] r-x/rwx SM=COW /Applications/xxxxxxxxxxx.app/Contents/MacOS/xxxxxxxxxxx
Thread 0 Crashed:: tid_307 Dispatch queue: com.apple.main-thread
0 com.xxxxx.xxxxxxxxxxx 0x0000000101edd05d eglib_log_adapter + 13 (mono-logger.c:404)
1 com.xxxxx.xxxxxxxxxxx 0x0000000101ef726e monoeg_g_logv_nofree + 190 (goutput.c:150)
2 com.xxxxx.xxxxxxxxxxx 0x0000000101ef73ef monoeg_assertion_message + 143 (goutput.c:184)
3 com.xxxxx.xxxxxxxxxxx 0x0000000101cd5a69 mono_jit_thread_attach + 169
4 com.xxxxx.xxxxxxxxxxx 0x0000000101bea5a0 xamarin_switch_gchandle + 144 (runtime.m:1853)
5 com.xxxxx.xxxxxxxxxxx 0x0000000101bed217 xamarin_release_trampoline + 103 (trampolines.m:474)
6 libobjc.A.dylib 0x000000010e1a111a (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 710
7 com.xxxxx.xxxxxxxxxxx 0x0000000101bf49c2 xamarin_main + 1234 (launcher.m:674)
8 com.xxxxx.xxxxxxxxxxx 0x0000000101bf5834 main + 36 (launcher.m:679)
9 libdyld.dylib 0x000000010ec363d5 start + 1
No code changes since last time and the app logs show me it crashing on the same line.
If there is anything I can do to help please do let me know... any ideas for something for me to investigate?
Hi @KSemenenko would it be possible for you to give me a steer on what to look at to get this Xamarin.Mac crashing resolved. I'd like to contribute to try and progress this issue as my release path is blocked at the moment because of it.
@KeithBoynton You can try to add the project source code to your project and see what went wrong in the debugger.
Maybe there are some problems with disk access?
Hi @KSemenenko. I'm working with Keith on this issue a bit. I ended up pulling down the repo and tracing through to see what was happening. In a nutshell the Mac implementation is trying to write directly into the app bundle contents. The read and write methods in the DeviceInfo implementation for Mac are here: https://github.com/KSemenenko/GoogleAnalyticsForXamarinForms/blob/master/Plugin.GoogleAnalytics/Plugin.GoogleAnalytics.Mac/DeviceInfo.cs#L117
For these methods, GoogleAnalyticsFolder = "ga-store" and path = "ga-anonymous-id.guid" therefore File.Exists(Path.Combine(GoogleAnalyticsFolder, path))
evaluates to "[AppBundleFolder]/AppPackage/Contents/Resources/ga-store/ga-anonymous-id.guid". While Debug builds can get away with this, Distributed builds cannot write back into the app package to create folders/files.
I modified the methods to do the following, adding a method that uses the SpecialFolders to construct a path to the user's Library folder where application data can be stored. This seemed to work, perhaps something like this could be done instead:
static string GetFullGaFolder()
{
var docsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var gaFolder = Path.Combine(docsPath, "Library", GoogleAnalyticsFolder);
return gaFolder;
}
public string ReadFile(string path)
{
var gaFolder = GetFullGaFolder();
if (!File.Exists(Path.Combine(gaFolder, path)))
{
return string.Empty;
}
return File.ReadAllText(Path.Combine(gaFolder, path));
}
public void WriteFile(string path, string content)
{
var gaFolder = GetFullGaFolder();
if (!Directory.Exists(gaFolder))
{
Directory.CreateDirectory(gaFolder);
}
File.WriteAllText(Path.Combine(gaFolder, path), content);
}
Hopefully that helps! I'm sure @KeithBoynton would be interested in a fix for this ASAP. :)
Just thinking about this a little more...you might consider another segment in that Library path so that multiple applications using the library don't end up writing to the same ga-store folder. Perhaps something with the application name/id in there like Path.Combine(docsPath, "Library", ApplicationNameOrId, GoogleAnalyticsFolder)
@DennisWelu I don't really understand macOS, but is this not an isolated storage?
I'm no Mac expert, but I believe writing back to the app bundle, which is just a zip file essentially, messes up the digital signature (https://stackoverflow.com/a/23803875/1735721) that is applied for any kind of distribution build.
There are various options for storing data depending on what type of data you are storing...user data vs app data, backed up to iCloud vs not, whether the app is sandboxed or not (https://apple.stackexchange.com/a/28930).
Sandboxed apps on Mac have a lot of rules and things to do to get them set up (https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW6).
In fact I just thought to check and the app in question here is actually writing other similarly cached and internal use files to ".../Library/Containers/[InternalAppId]/Data/Caches/[Subfolder]". So it would be really nice to be able to configure it to use that Caches folder and maybe the "ga-store" folder is created under there... Not sure the best way to make that happen with the library you have. I see there are various pieces of config that you can configure like the app name and id, so maybe something from the config could be substituted into that path construction to get the appropriate container folder location?
Thank you so much for your help @DennisWelu @KSemenenko I'm going to do some testing based on Dennis' findings then when I understand it a little more and am confident it's writing into a place that is going to be workable for the AppStore version I'll submit it to the Mac AppStore for review and let you know the outcome.
Did you have any thoughts on how you want to handle the location of where it writes it's internal files in the Mac version?
@KSemenenko I can confirm this is now working in both the Xamarin.Mac Distribution and AppStore versions.
@KSemenenko do you want the fix merging into your codebase or do you have things you'd like to change first?
@KeithBoynton I will be very grateful if you create PR. then I will release a new version with .net standard
Happy to do that, I had created a branch to make the change but can't push it remotely before making a PR, do I need some other permissions?
@KeithBoynton There are two ways, the first via github:
or just archive the project and attach the archive here
@KSemenenko It's a really simple change.. probably much easier to just attach the updated file here...
Plugin.GoogleAnalytics/Plugin.GoogleAnalytics.Mac/DeviceInfo.cs DeviceInfo.zip
Implemented very well into Windows, Xamarin.iOS and Xamarin.Mac and everything is working really well in Debug within Visual Studio.
However when I come to package up and distribute, it crashes on the distributed version with the following stack trace:
I understand you have listed Xamarin.Mac as "partial" support but I assumed as I've gotten everything running nicely within Visual Studio in Xamarin.Mac I wasn't touching any of the unsupported elements.
I've wrapped it in a static class...
And I call it from my app logic....
The Analytics.AppClient.Initialise(); line is where it crashes. The "Setting up analytics" logging gets written but not the "Done" line.
I'm guessing this isn't expected, is there anything special needed to distribute or does that crash indicate anything to you?