As I’ve continued working on the Xamarin.Forms application I’ve been building, I’ve learned a lot. One of the issues I ran into was an error in the iOS version of my application and as I didn’t find an easy to understand solution, I thought I would document it here. I’ll list the error first then explain the scenario and how to fix it.

AX Exchange error: Error Domain=Accessibility Code=0 “Remote service does not respond to _accessibilityMachPort” UserInfo={NSLocalizedDescription=Remote service does not respond to _accessibilityMachPort}

Part of the application revolves around uploading files. For Android this isn’t very difficult and it even makes sense as Android has a file system you can access and external storage in the form of SD cards. With iOS you can store files for your own app but not others (for the most part). However, you can access a user’s iCloud if they grant you permission. To this end, I started looking at the FilePicker Plugin for Xamarin and Windows.

In theory what this plugin would do is with one call open up a file picker connected to iCloud on iOS and to the disk on Android (and who knows on Windows). This plugin works great for Android. However, for iOS calling the PickFile method results in this error:

This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.

At the time of writing, it appears the author knows about the issue but hasn’t yet pushed a fix out to NuGet. So instead, I took that code and baked it into my app for Android and iOS and it worked for both. However, when the picker pops up to let you pick a file from iCloud, it comes along with the error being printed out to Application Output over and over and over again:

AX Exchange error: Error Domain=Accessibility Code=0 “Remote service does not respond to _accessibilityMachPort” UserInfo={NSLocalizedDescription=Remote service does not respond to _accessibilityMachPort}

I did a bit of searching and didn’t find anything DIRECTLY related to the FilePicker but I did find something about custom keyboards and external testing frameworks.
Xamarin.iOS apps are wired to use Calabash for testing with Xamarin Test Cloud and you will find this in the AppDelegate:

#if ENABLE_TEST_CLOUD
			Xamarin.Calabash.Start();
#endif

Commenting that out led to the error no longer occurring. I’m not 100% sure what the is causing this issue but at least there is a quick fix.

I’ve recently been working on a Xamarin.Forms project for Android and iOS and recently came across an issue that took some experimenting to get fixed so I thought I would share it for anyone else that might run into it.

Realm is a database designed for mobile applications and offers a safe, easy, non-ORM replacement for SQLite. The intent is that you can, for the most part, mark your data model objects as RealmObjects and Realm will handle all of the persistence for you. As with anything, it gets more complicated than that but so far it’s still much better for what I’m doing than SQLite. If I needed the ability to do offline synchronization with an online data source, I’d be looking at Azure Mobile Apps , but as I don’t I’m fine with what Realm will do for me.

Adding Realm to your Xamarin.Forms application just requires adding the Realm NuGet package to your projects. From there, you should be able to compile your projects without any issues.

However, if you have Continuous Integration set up to auto-build your projects and run tests with every build, it’s possible to run into an issue. I use Visual Studio Team Services to build all of my mobile projects and then deliver them to HockeyApp for beta testing. I’ll have to post more about setting up the Build Definition (the steps for building and uploading my compiled applications) but want to focus on the issue that having Realm in your projects has with the build process.

When you add Realm to your projects, it adds a Target as part of the package.
That step, called CopyRealmWeaver which copies RealmWeaver.Fody.dll as part of the build process. I won’t get into what Fody is but it’s a necessary part of using Realm. The XML found in the Realm.targets has the following inside of it:

<Target Name="CopyRealmWeaver" BeforeTargets="FodyTarget">
  <Message Text="CopyRealmWeaver" />
  <Error 
    Text="Solution directory was not set. If you are building via xbuild, specify by adding a /p:SolutionDir=/path/to/solution/folder argument. See github.com/realm/realm-dotnet/issues/656"
    Condition="'$(SolutionDir)' == ''" />
  <Copy SourceFiles="$(MSBuildThisFileDirectory)../tools/RealmWeaver.Fody.dll" DestinationFolder="$(SolutionDir)/Tools" />
</Target>

What this does is check to make sure $(SolutionDir) has been specified as part of the call to xbuild, or in the case of VSTS, msbuild. Provided that value has been specified, it then copies the RealmWeaver.Fody.dll from a tools directory in the packages folder into the Solution directory.

What’s wrong here

The problem here is that when compiling with VSTS, there is some step that changes the SolutionDir value to *undefined*. When I ran into this, it was especially weird as I couldn’t seem to find a reference to VSTS, build, and *undefined* anywhere. I did find a Stack Overflow post about Visual Studio replacing $(SolutionDir) with *undefined* which wasn’t the solution to my problem exactly but did get me on the right path. From there, I took a look at the call to MSBuild to see what was showing up:

2016-12-13T19:23:38.1392477Z ##[command]"C:\Program Files (x86)\MSBuild\14.0\bin\msbuild.exe" "C:\a\1\s\src\Droid\MyApp.Android.csproj" /nologo /nr:false /dl:CentralLogger,"C:\a\_tasks\XamarinAndroid_27edd013-36fd-43aa-96a3-7d73e1e35285\1.1.1\ps_modules\MSBuildHelpers\Microsoft.TeamFoundation.DistributedTask.MSBuild.Logger.dll";"RootDetailId=39592de0-fb1c-4156-a73e-b2e8ee77129e|SolutionDir=C:\a\1\s\src\Droid"*ForwardingLogger,"C:\a\_tasks\XamarinAndroid_27edd013-36fd-43aa-96a3-7d73e1e35285\1.1.1\ps_modules\MSBuildHelpers\Microsoft.TeamFoundation.DistributedTask.MSBuild.Logger.dll"  /p:configuration="Release" /p:_MSDeployUserAgent="VSTS_db204fe6-401b-4488-b9c9-02229bdeafd2_build_25_317" /t:PackageForAndroid /p:OutputPath="C:\a\1\b/Release" /p:JavaSdkDirectory=" C:\Program Files (x86)\Java\jdk1.8.0_102"

What I want to highlight from that call to msbuild is SolutionDir=C:\a\1\s\src\Droid. It seems like we’re specifying a Solution Directory, but the error shows us that somehow, that is being overwritten. So we need to override that overwrite and ensure a value is in fact being passed in.

Build Xamarin Additional Arguments

Thankfully, the Build Xamarin project build step has a spot for Additional Arguments at the bottom. In this case, I set the solution directory to the directory of my overall solution file and where the tools directory containing the RealmWeaver.Fody.dll is at. The format of the argument is important so this is what you should be using (adjusting the path for your) tools folder location of course:

/p:SolutionDir=”src”

With that done, I was able to run builds without any issue. This seem to be an Android only issue so you shouldn’t need to change anything on your iOS build.

Update 2-16-2017: A new error

After a recent update (to my code base), I found that my workaround was no longer working. The new error I was seeing was:

FodyTarget:
  Fody: Fody (version 1.29.4.0) Executing
  Fody: ProjectDirectory: 'D:\a\1\s\src\MyApp\MyApp.PCL\'.
  Fody: AssemblyPath: 'D:\a\1\s\src\MyApp\MyApp.PCL\obj\Release\MyApp.PCL.dll'
  Fody: Found path to weavers file 'D:\a\1\s\src\MyApp\MyApp.PCL\FodyWeavers.xml'.
##[error]Fody: SolutionDir "D:\a\1\s\src\MyApp\MyApp.PCL\src" does not exist.

What this appears to be doing is adding the SolutionDir that I specified above to the end of the PCL’s path. I was able to fix this once again by changing my Additional Arguments to:

/p:SolutionDir=”/”

I suspect this was due to a change in the Realm.targets XML file for the newer version of Realm that I updated to when I updated NuGets.