Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android library #4

Closed
wants to merge 7 commits into from
Closed

Android library #4

wants to merge 7 commits into from

Conversation

budo385
Copy link

@budo385 budo385 commented Jan 25, 2024

Android library and an update of android app. Android library is configured to be published on maven - check https://jitpack.io/#budo385/gs1-syntax-engine

@budo385
Copy link
Author

budo385 commented Jan 25, 2024

Adding "how to use" for android library, in Readme, would be nice if you accept the pr.

@terryburton
Copy link
Member

Thank you for this PR and apologies for the length of time taken to respond.

The good news is that GS1 has notionally decided to publish and maintain packaged libraries in common platform repositories for the various language bindings provided for the Syntax Engine, provided that the additional maintenance effort can be justified.

To start with, there has just been a release of an npm package. See issue #5 for details.

Concerning this PR, there's some minor issues:

  • The PR lacks a description of what problem is being solved and reasons for the design choices. Some of this may seem obvious to developers that are familiar with mobile app development workflows.
  • The PR itself is a series of disjoint commits (rather than each commit accomplishes one thing) that lack any justification.
  • It duplicates content into new directories, which isn't a maintainable development strategy approach going forward. There should be a better way to accomplish the library packaging, but I can't say what this is until we have decided on the ultimate for of the library.

However the above are not so important at this time, because there are broader issues that require further consideration...

The Android app in the source code repository is intended to be a simple demo of how the Java binding for the Syntax Engine native library might be used within an Android app. The functionality and results are not well tested. As such, there is code in the demo app that does not obviously belong in an Android/Java library, and if it were "blessed as such" then it should really be cleaned up and maintained as an API extension to the C native library (so that all bindings can benefit).

Specifically:

  • GS1 data format auto-detection: i.e. the code that processes the user input to determine whether the input is plain, AI element string, GS1 DL URI, etc. The issue here is that in future GS1 may introduce new formats that make auto-discrimination ambiguous and need to rely on heuristics. Hence there is no implementation of such a routine in the C library at this time. (When driving the Syntax Engine API directly you call the relevant input routine for your data of a certain format.)

  • Scan data post processing: The ML Kit Vision component's barcode scanning leaves a lot to be desired in terms of quality and unfortunately returns data strings that are inconsistent from one barcode symbology to another, and are sometimes ambiguous such that you cannot discriminate between AI data (FNC1 in first position) and plain data. There is variability in the output between different versions of the Vision component. Some versions even omit AI separator characters entirely or truncate the data! Therefore the onus on the user to translate the output and test for correctness.

The major decision to be made is whether to publish a Java and/or Android library, and where to. My intent so far has been to release a Java library package consisting of a single multi-architecture JAR published on Maven Central. The reasoning is that this benefits all Java developers and if there is no Android app specific helper code in the library then there is little point in also creating and maintaining an Android library — but I'm happy to be educated if this analysis is lacking.

(Because the library is based on native C code, it must be compiled for each of the common target architectures, e.g. x64, x86, arm, arm64. Creating multi-architecture Java library packages is challenging, but there are projects that appear to do this successfully, e.g. https://github.com/OddSource/ifaddrs4u/tree/main/ifaddrs4j)

@budo385 I would be interested to understand the typical Android app development life cycle and Android-specific issues with using native code in a lot more detail than I do at the moment, so we can work out if and how the Syntax Engine can best support Android app development. Would you be prepared to have a call with me to discuss this?

Once the final form of the Java/Android packages is decided we can work on either cleaning up or abandoning this PR.

@terryburton terryburton added the library repos Generation of packaged libraries for language specific repositories, e.g. Maven Central, npmjs.com label Apr 9, 2024
@vinaygopinath
Copy link

@terryburton Not the author, but thanks for the detailed response.

Scanning through the changes in this PR, it looks like it implements using the device camera to scan barcodes and GS1 codes using Google ML Kit in addition to using the Java wrapper in this repo to extract the components of the GS1 code. That seems like opinionated scope creep for an Android library, and I'm on board with your proposal of publishing a JAR accessible from Maven Central purely to parse the scanned string, leaving the task of scanning codes to the application developer.

@terryburton
Copy link
Member

@vinaygopinath The scanning code is taken from the example Android app that is already in the repository. So the patch is essentially a cp -a to a new directory that includes some minor changes and new configuration necessary to package assets for repo hosting — but to what aim? The PR does not make this clear, and I'm not an app developer so the purpose it isn't clear to me.

Thank you for taking the time to consider the approach that I outlined concerning the multi-architecture JAR. I conducted some brief testing, but I have had to set things aside for now because of the amount of effort involved. It may be prioritised in the future as a result of community feedback such as what you have provided.

Building the multi-architecture JAR:

  • There is a project that provides cross-compiler toolchains in the form of Docker images that might be usable to create the Syntax Engine shared library and JNI for a variety of platforms: https://github.com/multiarch/crossbuild — hopefully all relevant platforms (for servers and mobile / embedded) are supported.
  • To automate the generation of assets it would be necessary to create a CI workflow based on this which can assemble the final multi-architecture JAR file.

How the JAR would work:

  • The Java library (in the JAR file) can include a custom class loader routine that can probe the OS and architecture at runtime in order to attempt to System.load the correct JNI library for the platform — hopefully all relevant platforms can be detected reliably so that a single JAR is all that is necessary.
  • In order to System.load the native code it is necessary for the custom class loader to first copy it out of the JAR to temporary storage. This seems to work well for regular Java platforms, at least on Linux which I have tested.

Considerations for Android:

  • The above approach does not appear to work for Android since the native library .so files are stripped out of the APK during the build, i.e. the JAR doesn't appear to be manifested in the same way once the app is assembled. I haven't looked at how and why this occurs.
  • Assuming that you can avoid the above issue then there is still the issue that recent versions of Android introduce "W^X" enforcement, i.e. that they do not allow code to be loaded and executed from writable parts of the app storage, i.e. you cannot System.load what the application has written at runtime.
  • So a "supplementary" approach might be required for Android: Project may include a separate Gradle task in the app build process that performs the native library from JAR this extraction immediately prior to assembling the APK, effectively placing the native code in the typical project lib/ location (e.g. lib/arm64) so that it gets built into the APK in that same way that a "vendored-in" shared library (or output of an NDK build step) would be, such that it is accessible to the app at runtime. The custom class loader would need to be programmed to not attempt library extraction when running on Android and when the library can be loaded from the default native library location for the current platform.
  • So to use the packaged library for Android development, in addition to declaring an implementation dependency you would also need to add a task to the gradle.build, which sounds like it may be preferable to vendoring in the Syntax Engine code in the way shown by the current example Android app.

That's a lot of steps to put in order and there is still some risk of something critical not working out as intended, so the idea is shelved for now...

Of course if anyone would like to have a go at the above then this will be welcome.

@terryburton
Copy link
Member

Summary of discussion related to distributing a multi-architecture JAR via Maven Central captured in issue #7.

No response from original author regarding this PR. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
library repos Generation of packaged libraries for language specific repositories, e.g. Maven Central, npmjs.com
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants