larryaasen / upgrader

A Flutter package for prompting users to upgrade when there is a newer version of the app in the store.
MIT License
526 stars 260 forks source link

feature: add support for appcast ABI filtering #347

Open vladchuk opened 8 months ago

vladchuk commented 8 months ago

This adds ABI filters in elements. Only Android is supported at the time. Original functionality is preserved: if abi is not specified, old behavior is in effect.

Justification Filtering only based on the OS/version is too limiting for Android devices. It is generally recommended to build artifacts per ABI, but there is currently no way to thus filter appcast items, forcing one to use a "fat" apk which is a few times bigger than necessary.

Implementation Although only Android is currently supported for this filtering, other OS can be easily added, if needed. The filter is on the \<enclosure> level, along with the binary (url). Since "sparkle" domain does not support "abi" (at least as far as I know - I could not find the complete appcast.xml schema anywhere), it is in the default (no prefix) domain, for simplicity.

Testing Basic unit testing was added. Also, limited testing conducted in production.

Please come back with questions/comments, if any. Hoping to using this in a official release soon!

larryaasen commented 7 months ago

@vladchuk To help better explain the problem and solution, please provide a complete example Appcast file showing the current usage with the issue, and also another example showing the solution.

vladchuk commented 7 months ago

Currently, only the following is possible:

<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
    <channel>
        <title>My App</title>
        <item>
            <enclosure sparkle:version="2.3.0" url="https://downloads/application-install-2.3.0.exe"
                sparkle:os="windows" />
        </item>
        <item>
            <enclosure sparkle:version="2.3.0" url="https://downloads/application-2.3.0.apk"
                sparkle:os="android" />
        </item>
    </channel>
</rss>

This allows one to distribute either a single Android binaries (ABI) or a fat apk, containing multiple ABI and thus forcing the client to needlessly download and use the file a few times bigger than necessary. This works OK for a single target ABI.

But what if one needs to support more than one? It is generally recommended to build specific APKs which contain a single ABI, targeting a specific device and sparing the client "the dead weight" of the ones it can't use. The following affords such precise and efficient targeting, since now the APKs contains only what necessary for each client:

<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
    <channel>
        <title>My App</title>
        <item>
            <enclosure sparkle:version="2.3.0" url="https://downloads/application-install-2.3.0.exe"
                sparkle:os="windows" />
        </item>
        <item>
            <enclosure sparkle:version="2.3.0" url="https://downloads/application-v7a-2.3.0.apk"
                sparkle:os="android" abi="armeabi-v7a" />
        </item>
        <item>
            <enclosure sparkle:version="2.3.0" url="https://downloads/application-v8a-2.3.0.apk"
                sparkle:os="android" abi="arm64-v8a" />
        </item>
    </channel>
</rss>

Android is given an example, but the situation is applicable to other platforms, for example Windows 32 vs 64 bit, etc. In fact, it's even worse, since it's impossible to combine different binaries in a single file, like for Android.

I hope this makes it clear what problem this addition would solve.

larryaasen commented 7 months ago

@vladchuk I like this idea and thanks for submitting. However, abi is an Android only concept that cannot be properly used on other OSes like Windows. How about a name that would work across all OSes and platforms?

vladchuk commented 7 months ago

I probably misled you by providing a lopsided (Android) example. ABI (Application Binary Interface) is actually a descriptive, universal and widely used concept. Here is an excerpt from an AI (Bard) inquiry:

"Application binary interfaces (ABIs) are applicable to a wide variety of platforms, including:

Operating systems: ABIs are used to define the interaction between applications and the operating system. For example, the Linux ABI defines how applications can interact with the Linux kernel.
Programing languages: ABIs can also be used to define the interaction between programs written in different programming languages. For example, the C++ ABI defines how C++ programs can interact with programs written in C.
Hardware architectures: ABIs can also be used to define the interaction between software and hardware. For example, the ARM ABI defines how software can interact with ARM processors.

Here are some specific examples of platforms where ABIs are used:

Windows: The Windows API is an ABI that defines how applications can interact with the Windows operating system.
macOS: The macOS API is an ABI that defines how applications can interact with the macOS operating system.
Android: The Android NDK (Native Development Kit) provides an ABI that defines how applications can interact with the Android operating system.
iOS: The Apple Developer Documentation provides an ABI that defines how applications can interact with the iOS operating system.
Linux: The Linux Standard Base (LSB) provides an ABI that defines how applications can interact with the Linux kernel.

In general, ABIs are used whenever there is a need for software from different sources to communicate with each other. This includes applications written in different programming languages, applications running on different operating systems, and applications running on different hardware architectures."

You can easily expand on this research if you like (with Bard, ChatGPT or simply Googling).

Ultimately, I think that calling it anything other than ABI would be quite confusing, while using it as is conveys the meaning very accurately and succinctly.