Source: discourse.nativescript.org
Background
The Zebra EMDK (Enterprise Mobility Development Kit) ships its own Android SDK as a JAR rather than being available through Maven Central or the Google Maven repository. When writing a NativeScript Android plugin that wraps EMDK functionality, you must add this external JAR as a compile-time-only (provided) dependency so that the device’s on-device EMDK library is used at runtime, rather than bundling a duplicate copy into the APK.
The Problem: ‘provided’ JAR Classes Being Skipped
After placing com.symbol.emdk.jar inside the plugin’s libs/ directory and adding the following configuration to include.gradle:
dependencies {
provided files('libs/com.symbol.emdk.jar')
compile fileTree(exclude: ['libs/com.symbol.emdk.jar'], include: ['*.jar'], dir: 'libs')
}Code language: PHP (php)
Running tns run android triggers the :buildMetadata Gradle task, which processes all JAR files to generate TypeScript metadata for NativeScript. During this step, the EMDK classes are not skipped as expected—instead, they are included in metadata generation and produce a stream of NullPointerException errors:
:buildMetadata
Skip com.symbol.emdk.simulscan.SimulScanConfig
Error: java.lang.NullPointerException
Skip com.symbol.emdk.simulscan.SimulScanManager
Error: java.lang.NullPointerException
Skip com.symbol.emdk.simulscan.SimulScanMultiTemplate
Error: java.lang.NullPointerException
Skip com.symbol.emdk.simulscan.SimulScanReader
Error: java.lang.NullPointerException
Skip com.symbol.emdk.simulscan.SimulScanReaderInfo
Error: java.lang.NullPointerException
Because the metadata for these classes is incomplete or corrupted, the app crashes at runtime whenever any EMDK API is called.
Why This Happens
The NativeScript Android runtime uses a custom Gradle task (buildMetadata) to reflect over every JAR on the compile classpath and generate JavaScript-accessible metadata. The provided configuration in Gradle is intended to mark a dependency as available at compile time but absent from the final APK—similar to Maven’s provided scope or the compileOnly configuration introduced in later Gradle versions.
However, the NativeScript build toolchain may still enumerate JARs in the provided configuration when building metadata. If the JAR contains classes that reference other classes not present on the classpath (common with vendor SDKs like EMDK), the reflection step throws NullPointerException errors and silently skips those classes. The result is incomplete metadata and a broken runtime API surface.
Key Concepts: ‘provided’ vs ‘compileOnly’ vs ‘compile’
| Configuration | Available at compile time | Packaged in APK | Notes |
|---|---|---|---|
compile | Yes | Yes | Deprecated in Gradle 3.x+; replaced by implementation |
provided | Yes | No | Legacy; replaced by compileOnly in Gradle 2.12+ |
compileOnly | Yes | No | Preferred modern equivalent of provided |
implementation | Yes | Yes | Preferred modern equivalent of compile |
For Android system-level SDKs like Zebra EMDK—where the real implementation lives on the device and your app should not bundle its own copy—compileOnly (or the legacy provided) is the correct scope.
Recommended Approaches
1. Use compileOnly Instead of provided
If your NativeScript and Gradle versions support it, replace provided with compileOnly:
dependencies {
compileOnly files('libs/com.symbol.emdk.jar')
implementation fileTree(exclude: ['com.symbol.emdk.jar'], include: ['*.jar'], dir: 'libs')
}Code language: PHP (php)
2. Exclude the JAR from the buildMetadata Task
If the NativeScript build toolchain still picks up the EMDK JAR during metadata generation and produces errors, you may need to explicitly exclude it from that task. Check the NativeScript plugin documentation or the project’s Gradle build scripts for a supported exclusion mechanism, such as an exclusions list in include.gradle or a project-level configuration option.
3. Verify the JAR’s Classpath Dependencies
The NullPointerException errors during reflection often indicate that the EMDK JAR references classes from the Android platform SDK or from other Zebra libraries that are not on the metadata-generation classpath. Ensure that the full Android SDK is available during the build, and check whether Zebra provides additional companion JARs that should also be on the compileOnly classpath (without being packaged into the APK).
Summary
When integrating a vendor-provided Android SDK JAR—such as the Zebra EMDK—into a NativeScript plugin, use the compileOnly (or legacy provided) Gradle configuration to keep the JAR off the final APK. If the NativeScript :buildMetadata task still processes the JAR and throws NullPointerException errors for EMDK classes, the root cause is typically missing transitive dependencies on the metadata-generation classpath. Resolve this by ensuring all referenced platform and companion classes are available at build time, or by using a supported exclusion mechanism in the NativeScript plugin build configuration.