Shell App Deployment

MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭

At this point, we are well in to understanding Xamarin and Xamarin Forms. On its face, it seems as though these technologies are going to solve a large swathe of issues that we have for getting enterprise level apps to our customers. However, I am green when it comes to app stores and the rules etc. for dealing with app stores. The main issue that I have in my mind is how to manage the deployment of multiple configurations (custom DLLs) for the one application.

Ultimately, we'd like to have one app store app for each platform (Android, iOS, UWP). This would require that custom assemblies be served up over the web after installing the application. I.e. once the shell app has been installed on the device, the shell would download further content such as images, data and custom assemblies (custom assemblies being the most important). There doesn't seem to be a technical hurdle to achieving this on iOS and Android. In this thread, I provide sample code on how assemblies can be loaded at runtime on iOS, and Android: https://forums.xamarin.com/discussion/comment/252571/#Comment_252571 . Unfortunately, the same cannot be done on UWP because UWP doesn't allow for assemblies being loaded from outside the AppX package, and it seems that Microsoft doesn't have any plans for allowing this in future.

If you clone this repo, you can see how assemblies can be loaded dynamically at runtime:
https://[email protected]/ChristianFindlay/xamarin-forms-scratch.git

When I got this right, my first thought was that this is fantastic. If we can dynamically load assemblies at runtime, we do not have to have multiple app store instances, which means that we don't have to be subject to the whims of the various apps stores. We can just deploy shell apps in to each app store, and from that point forward, the shell app can dynamically down the content that is needed for each of our customers. This really seems like a necessity because maintaining multiple app store deployments would be a nightmare from a maintenance point of view - especially if we have to wait for changes to the apps to be accepted. But, after talking to a friend about this, I realised that this might actually be a problem.

Will iPhones, iPads, and Android devices allow for assemblies being loaded dynamically? Have I perhaps stumbled on a feature that is supported by side loaded apps, but not supported on Store deployed apps? Could Apple, or Google potentially disable this capability in future?

If there's any risk of the above, how are other people dealing with the issues I've mentioned? Do you have more than 10 customers with different custom assemblies? Are you manually managing each customer's deployment through separate app store apps? How are you finding this? Any tips on how to automate this? Do the various app stores take long to approve a change?

Answers

  • JohnHJohnH GBMember ✭✭✭✭✭

    This isn't possible on iOS and is against Apple's rules even if you did find a way to do it.

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭
    edited March 2017

    Is it really? Where are Apple's rules on the matter?

    There is a way to do it. I've proved that it's possible. The Xamarin technology allows for it.

    My thinking on this, and I could be wrong is that Apple and Google allow certain APIs to be ran. When you register your app with them, they will scan your app to ensure that you are not running an API that they don't like. If we deploy a simple shell app in to the store, we are just deploying the Xamarin framework. There are no APIs in the Xamarin framework that Apple, or Google dont't like. When a .NET Standard, or PCL library is loaded in to the AppDomain from an external source, that doesn't change. The APIs used are internal to the Xamarin framework - not to Apple or Google. The app doesn't magically get new capabilities or anything like that. To put it another way, loading external .NET assemblies at runtime doesn't allow the app to call extra iOS/Android APIs. So, I figure it's really not breaking any of Apple or Google's policies. But, please correct me if I am wrong.

    Has anyone in the Xamarin team got any thoughts on this? Xamarin technology allows for assemblies to be loaded at runtime. Is this an intentional feature? Has there been any communication with Apple or Google about this in regards to whether or not their stores allow this?

  • JimBordenJimBorden USMember ✭✭

    I think that the element in question is 2.5.2 of the app store review guidelines:

    Apps should be self-contained in their bundles, and may not read or write data outside the designated container area, nor may they download, install, or execute code, including other iOS, watchOS, macOS, or tvOS apps.

    The meaning of "code" is subject to interpretation here. Many have determined that it means "compiled code" and not things like Javascript, etc (one of the features of the library I work on is to accept a Javascript function on a REST endpoint to calculate metrics about the data stored, and I have not heard anyone being rejected for it yet).

    In your case I think things are a bit more dangerous. The fact that it even works means that you must have AOT compiled it somehow, which means that it is literally machine code being downloaded and used that wasn't originally shipped with the application.

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭

    @JimBorden said:

    nor may they download, install, or execute code, including other iOS, watchOS, macOS, or tvOS apps.

    Hmm....

    The wording is pretty strong here, but as you say, it depends on the interpretation of code...

    In the iOS context, code would probably mean machine code as IL code doesn't exist in the iOS world.

    The meaning of "code" is subject to interpretation here. Many have determined that it means "compiled code" and not things like Javascript, etc (one of the features of the library I work on is to accept a Javascript function on a REST endpoint to calculate metrics about the data stored, and I have not heard anyone being rejected for it yet).

    I don't really see your JavaScript example is different from IL code. IL code is not human readable like JavaScript, but it's more or less the same thing in the sense that it gets interpreted at runtime.

    The fact that it even works means that you must have AOT compiled it somehow

    No. It's just a PCL library. You can try it out yourself with the sample app I have provided.

  • JimBordenJimBorden USMember ✭✭

    When I run your sample app on my device, it crashes when I press the Load Dynamic DLL... button

    2017-03-02 08:32:35.370 TestXamarinForms.iOS[2103:982998] error: Failed to load AOT module '/Users/builder/data/lanes/3985/35d1ccd0/source/xamarin-macios/builds/install/target64/lib/mono/aot-cache/arm64/data-0x122bf5800.so' in aot-only mode.

    Have you tried it on device? The simulator will probably work because the simulator is not an entirely accurate representation (It is still running on OS X, a platform which has JIT capability).

    I don't really see your JavaScript example is different from IL code.

    The human readability and limited scope of execution are probably the key factors here. You aren't wrong though. It depends on what Apple defines it as. Someone should ask them maybe. I think IL code has the potential to exercise a potentially nefarious path that exists somewhere while Javascript doesn't have that danger as much (though I realize the irony that most exploits are Javascript based...but only when running in the browser). It's a toss up I guess.

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭

    Also, it's looking more and more like what we need is to deploy our app through a process separate to the App Store. Apple has a program for this:

    https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/DistributingEnterpriseProgramApps/DistributingEnterpriseProgramApps.html#//apple_ref/doc/uid/TP40012582-CH33-SW1

    So, basically, the app store guidelines simply don't apply.

    I think this is where UWP's framework shortcomings really come in to play. In UWP, you cannot load an Assembly externally. Microsoft has confused App Store Policy with limitations on the development platform. Sure, app store apps may not allow for dynamically loading APIs. But, in UWP you are cut off at the knees because even if you side load the app, you still can't load external assemblies.

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭
    edited March 2017

    @JimBorden said:
    When I run your sample app on my device, it crashes when I press the Load Dynamic DLL... button

    2017-03-02 08:32:35.370 TestXamarinForms.iOS[2103:982998] error: Failed to load AOT module '/Users/builder/data/lanes/3985/35d1ccd0/source/xamarin-macios/builds/install/target64/lib/mono/aot-cache/arm64/data-0x122bf5800.so' in aot-only mode.

    Have you tried it on device? The simulator will probably work because the simulator is not an entirely accurate representation (It is still running on OS X, a platform which has JIT capability).

    Ouch. No I have not. So you are saying that the simulator is not a real representation of an iOS device?

    I did however test this on my Android device and it does work fine.

  • JamesLaveryJamesLavery GBBeta, University ✭✭✭✭✭
    When you compile a Xamarin app for IOS it is AOT compiled into a native IOS app. If you then download an assembly or load an assembly which was bundled as a resource in the app, this assembly needs to be compiled into native code. To do this you need JIT compilation which is not allowed by Apple. I think this just won't work on iOS I'm afraid.
  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭
    edited March 2017

    @JamesLavery said:
    When you compile a Xamarin app for IOS it is AOT compiled into a native IOS app. If you then download an assembly or load an assembly which was bundled as a resource in the app, this assembly needs to be compiled into native code. To do this you need JIT compilation which is not allowed by Apple. I think this just won't work on iOS I'm afraid.

    That sounds about right. So, basically the simulator has been lying to me.

    I must admit, I was very surprised when it worked. It didn't click, that actually, it shouldn't work.

  • JamesLaveryJamesLavery GBBeta, University ✭✭✭✭✭
    @MelbourneDeveloper Regarding the Enterprise Distribution program - this can only be used to distribute apps to people in your own organisation. Is this what you intend to do? If you want to distribute outside a single organisation, I think the only option is the public app store.
  • JimBordenJimBorden USMember ✭✭

    So you are saying that the simulator is not a real representation of an iOS device?

    Emphatically, yes I am saying this. The simulator is just an OS X application with some special candy for using iOS APIs. This is the main reason it is so much faster than Android's emulators, which are actually emulators and will be true to the behavior on device because they are actually running the Android OS (also, it is the reason it is called a "simulator" rather than an "emulator").

    I did however test this on my Android device and it does work fine.

    Android is a JIT enabled platform, so it will JIT compile that assembly when you load it. iOS is not a JIT enabled platform so it will search for the precompiled version when you load it. To get this approach to work (technically, if not allowable by Apple) you would have to bundle both the DLL and its corresponding compiled version and put those in the correct places (which I am not sure of)

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭

    @JamesLavery said:
    @MelbourneDeveloper Regarding the Enterprise Distribution program - this can only be used to distribute apps to people in your own organisation. Is this what you intend to do? If you want to distribute outside a single organisation, I think the only option is the public app store.

    That's how it appears. But, from speaking to other people, one option is for a given enterprise to set up their own account, and then give us access to administer it. Of course, this would be a headache because every one of our customers would have to get set up with an account.

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭

    @JimBorden said:

    So you are saying that the simulator is not a real representation of an iOS device?

    Emphatically, yes I am saying this. The simulator is just an OS X application with some special candy for using iOS APIs. This is the main reason it is so much faster than Android's emulators, which are actually emulators and will be true to the behavior on device because they are actually running the Android OS (also, it is the reason it is called a "simulator" rather than an "emulator").

    I did however test this on my Android device and it does work fine.

    Android is a JIT enabled platform, so it will JIT compile that assembly when you load it. iOS is not a JIT enabled platform so it will search for the precompiled version when you load it. To get this approach to work (technically, if not allowable by Apple) you would have to bundle both the DLL and its corresponding compiled version and put those in the correct places (which I am not sure of)

    Well, this explains a lot. Are there any decent iOS emulators out there?

    So, I guess my own question has been answered. UWP, and iOS won't allow for assemblies to be loaded dynamically, but Android will allow it. Whether or not Google will support it in to future is another question though...

  • JimBordenJimBorden USMember ✭✭

    That's how it appears. But, from speaking to other people, one option is for a given enterprise to set up their own account, and then give us access to administer it.

    This is exactly the process that was used at my former company.

  • MelbourneDeveloperMelbourneDeveloper AUMember ✭✭✭

    I'll leave this thread open for a few more days. After that, I'll write a summary and close the thread. It seems like writing a shell app system is simply not possible unless we are only intending on deploying on Android.

Sign In or Register to comment.