22 January 2020

Mixed Reality apps failing the WACK - revisited

Intro

Last September I wrote about various hoops you had to jump through to get a Mixed Reality app to appear in the store and not have it to fail  the Windows Application Certification Toolkit (WACK). It's time for a little update, since part of what I wrote is no longer necessary, and some things have changed subtly.

The good news

I wrote how you manually had to mess with Package.AppManifest.xml, particularly how you had to remove the DirectX 10 dependency to make it (still) downloadable for HoloLens 1 devices. Provided you have been diligently installing the service updates that are issued for this device, by now your HoloLens 1 should have been updated to no longer reject apps that have this requirement. So no need to take this step anymore.

The bad news

The trick I wrote how to make sure some unsupported DLLs were not included does not work anymore. We have to resort to more drastic measures.

The problem

To recap: if you generate a C++ solution from the recommended Unity version (2018.4.x, LTS branch) you get the following errors in the WACK

  • HolographicAppRemoting.dll has failed the AppContainerCheck check.
  • PerceptionDevice.dll has failed the AppContainerCheck check.
  • UnityRemotingWMR.dll has failed the AppContainerCheck check.
  • The Supported API test will list 10 errors concerning UnityRemotingWMR calling unsupported APIs
  • The Debug configuration test will tell youUnity RemotingWMR is only built in debug mode
  • And if you try to build for x86 or ARM, the Package sanity test will tell you HolographicAppRemoting.dll, PerceptionDevice.dll and UnityRemotingWMR.dll are only available for x64.

I suggested editing the “Unity Data.vcxitems” file that is inside your store projects and change the contents of the DeploymentContent-tags for these files to false. That worked swell. Until, somewhere between Unity and Visual Studio versions upgrade, some brilliant person thought it a good idea to recreate that file whenever you change the architecture. So when you change the architecture from "x86" to "ARM" - something that happens automatically while creating multi-platform packages - you are greeted with this:

M previous solution does not work anymore, as the three offending DLLs are automatically added back to the file, and thus the WACK fails again. Some more brute force is being required.

The solution

If you expand the Il2CppOutputProject, you can simply see the offending DLL's. The solution is as simple as selecting and deleting them.

And then you can generate your packages, run the WACK again... and may get another failure:

This depends on the version of the WACK you have. As as you can read here, the Store has been updated to ignore this error. In other words, if you are down to this error, you are good to go for submission and (successful) certification in the Windows Store.

Mind you - as soon as you regenerate the solution from Unity, the project file may or may not be overwritten and you will need to repeat this. So - always always run the WACK before you submit - but then again, that's what you should do anyway.

Conclusion

The ever changing constellations of Unity and Visual Studio keep us throwing curveballs, but fortunately there's always been a way around. So far. Happy submitting!

15 January 2020

Mixed Reality apps failing MS Store validation on "10.5.1 Personal information" - and how to fix it

Intro

After fellow MVP (and RD, although not fellow-) Philipp Bauknecht discovered a bug in my AMS HoloATC app while testing it on his HoloLens 2 (what lunatic runs HoloLenses with DE-DE settings anyway :P) I created a fix for that and submitted the fixed app to the Microsoft Store on Saturday January 12th. I assumed it would pass right though. It did not. Monday morning I got a failure message:

That was not what I hoped, and certainly not what I expected

Parsing the message

I will admit to being rather confused, because I have a privacy policy link. In the Store. But apparently something has changed. If you want all the details, you can find them in the new App Developer Agreement, but the text in the failure basically says it all:

"For in-product include the privacy policy URL under the settings section"

So I need to add a privacy policy in the app. Okay. But they are expecting it under the settings section. This is clearly written with a desktop app in mind. But I don't have a main screen, let alone I can put a hamburger menu somewhere and put a "Settings" entry in this.

Solution part 1

So I could clearly not obey the letter of the law, but I can try to act in spirit. So I ventured out to see if I could get a privacy policy in the app in a way that would be acceptable to the Store testers. All my apps have like a "help" function, that you can activate by saying "help" or "show help". I actually advertise that on start-up with a floating text that is shortly visible after starting up the app.

This help screen looked like this:

And now looks like this

I actually added a text and a quad behind it, just ahead of the quad that is the main backdrop.

And on that quad there a very simple and crude behavior

using Microsoft.MixedReality.Toolkit.Input;
using UnityEngine;
using UnityEngine.WSA;

public class BrowserActivator : MonoBehaviour, IMixedRealityPointerHandler
{
    [SerializeField]
    private string _urlToOpen;

    public void OnPointerDown(MixedRealityPointerEventData eventData)
    {
        Launcher.LaunchUri(_urlToOpen,false);
    }

    public void OnPointerDragged(MixedRealityPointerEventData eventData)
    {
    }

    public void OnPointerUp(MixedRealityPointerEventData eventData)
    {
    }

    public void OnPointerClicked(MixedRealityPointerEventData eventData)
    {
    }
}

that launches a browser window when you tap on the text. In the app it looks like this:

And if you tap the indicated text, the app will move to the background and you will see this:

Or whatever URL you put into _urlToOpen in the editor. I took the exact same URL as in the Store. I am pretty sure this won't win me any design awards - but that's not the goal here. Note: these images where created with a HoloLens 1, as I am still lacking a HoloLens 2 (if anyone from Microsoft reads this - yes, that's a hint ;) ).

Solution part 2

Since I have no settings section, I thought it prudent to tell the testers where they could find the link to the privacy policy. So under "Submission options" I explained the why, where and how like this:

"IMPORTANT NOTE: this app failed App Policies: 10.5.1 Personal Information. Specifically, it missed an in app privacy policy. I was suggested to add it under section "settings" but there is no sections "settings", in fact, there are not sections at all, since this is not running in a window.
I have added a privacy policy tappable text in the help screen. You can access that by saying "help" or "show help", after you have initially placed the airport. This opens a browser and shows the privacy policy.
"

Proof of the pudding

As you can see, following this procedure took me through Store validation successfully. In fact, it took me through it twice - as it's Atlanta twin app ATL HoloATC got certified within hours after submitting with this addition.

Conclusion

Resuming:

  • Have some way in your app to popup the privacy policy web page.
  • Explain in Submission options to the testers where they can find it.

We can discuss at length how useful things like this are, if and how this could be communicated better to developers, if there needs to be guidance first before this is implement for the nice market of Mixed Reality apps - that don't have a window nor a settings section - whatever, this works, and while there is no official guidance on how to deal with privacy policies in apps like this, this article show you a way forward. Presumably, for the testers it's also just simply a matter of being mandated to tick off a box required by the legal department. And this is apparently an acceptable way of getting the box ticked. Job done.

No code sample this time - I assume everyone making MR apps will be able to re-create the two lines of actual code in the behaviour. And possible come up with a more elegant solution. But that was not the point of this - the point was getting in the store without a legal blocker.