Skip navigation

Android Blogs

5 Posts authored by: Pietro Francesco Maggi

The latest versions

As I'm writing the latest Zebra's EMDK for Android is v6.6, supporting KitKat, Lollipop and Marshmallow devices. All the documentation is available on TechDocs, and from there you can find all the samples and their source code on GitHub, under the Zebra organization.

Here you can find the latest version of the samples:

The older sample

Sample for older version of Zebra's EMDK for Android are still available on github but under a different organization: Developer Zebra.

Here you can find:

Plus you can find the ADT version of the sample:

A note on the sample

All these sample repositories are build in the same way. The master branch contains only a README file and there's a branch for every sample, PLUS a branch with all the sample that is the one that I usually clone using the command:

git clone -b AllSamples <Repository to clone>

 

 

edit for layout and typos.

Working in Android Studio you can notice that every project contains a local.properties file with at least a couple of properties containing the path for Android SDK and Android NDK.

Android Studio populates this information when it creates the project based on the ANDROID_HOME environment variable. If this variable is not present in your system Android Studio will find the correct path in other ways, but having ANDROID_HOME setup correctly is a really good idea, see the note at the end of this short post.

Given that I usually have in my build.gradle file a reference to Zebra's EMDK, look like a good idea to use sdk.dir instead than hardcoding the path (like I've done for a too much long time) given that the EMDK resides in Android SDK's add-ons folder.

So, my gradle files now includes:

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def sdkDir = properties.getProperty('sdk.dir')

so that I can the use the sdkDir variable like:

provided fileTree(include: ['com.symbol.emdk.jar'], dir: sdkDir+'/add-ons/addon-symbol_emdk-symbol-23/libs/') 

Much cleaner and nice :-)

 

A note on ANDROID_HOME

Is usually not a good idea to include in your revision system the local.properties file because this contains information... "local"... to your machine.

Imagine that you're sharing a project with a colleague or with a remote CI build server. In this case everybody will have the Android SDK (and the Zebra's EMDK that resides in the SDK add-ons) in a different folder.

The best option in this case is to avoid to share the local.properties file and have the ANDROID_HOME environment variable correctly setup so that the build works correctly on every machine.

 

If local.properties is not available, Gradle will use ANDROID_HOME automatically.

If local.properties is available, Gradle will use this file having a wrong sdk.dir set and fail.

 

Update

I got some enquiry to provide a complete gradle file to understand where to do the pasting.

Here’s one sample file:

 

Screen Shot 2017-09-21 at 11.20.40.png

 

I've a better formatting on the original post on my website if you need it.

Note: Links in this post are now broken due to Launchpad change of domain from motorolasolutions.com to zebra.com. Refer to the original post on my website for up-to-date links.

There’s a recurring question coming to me and to Launchpad’s forums lately:

How can I compile my Android app, using Zebra’s EMDK, if I need the latest support library?

Some background

With the Android tools moving super-fast (Android studio v1.0 launched at the beginning of 2015, the latest stable release is v1.4.1, we already have v1.5RC and v2.0 has been announced…) keeping up to this pace is not easy for our EMDK team!

We discovered some integration issues when Android Studio v1.3 was released and we presented a workaround to use the EMDK as the building SDK. Limiting the project to API level 16 or 19. This should be good, right?

A downside of this approach surfaced when Google updated the templates for new projects, now based on the Android Support Library. I really like the approach to base new projects on the support library; the problem is that it does require to build the project with API level 21+.

Here we can have a problem

Using Zebra’s EMDK

So, talking just about Android Studio, that is the current up-to-date Android IDE, we currently document two ways to use the EMDK:

  1. The official one, selecting the EMDK in the «Compile SDK» drop-down when creating the project
  2. The Android Studio v1.3+ workaround way that suggest to manually set the EMDK as the «Compile SDK».

Both methods fails to compile a project using the latest Android Support Library.

A little gradle magic

Here’s a third, UNOFFICIAL, way to include the EMDK in an Android project and use the latest available SDK to build the project.

Copy the lib file in your project

First of all, create in your Android project a lib folder and copy into it the com.symbol.emdk.jar library that you got installing the EMDK on your PC/Mac:

This is probably easier to say than to do, because the default Android Studio project view doesn’t show these files.

Android_Project1.jpg

The easiest way, at least for me, is to copy the file from the setup position to a newly created libs folder in my project from Windows’ File Explorer or OSX’s Finder and then check that everything is OK switching the Android Studio project view from «Android» to «Project Files»:

Android_Project2.jpg

Modify the build.gradle file

OK, once the file is included in our project (and this means that you can check in this file in your SCM and checkout on a new PC and rebuilt it without the need to Zebra EMDK installed) we can explain to Android Studio how to use it. To do this we need to modify the build.gradle file included in the app folder. If you’ve switched back to the «Android Project view», this is the Module: App, gradle file. As shown below:

gradle_file.jpg

In this file you need to setup the dependencies so that the build process uses this lib as a reference without including it into the final APK (otherwise the application will exit with and exception when launched).

   dependencies { compile fileTree(dir: 'libs', include: ['*.jar'], exclude: ['com.symbol.emdk.jar']) compile 'com.android.support:appcompat-v7:23.0.1' provided fileTree(dir: 'libs', include: ['com.symbol.emdk.jar']) } 

With this changes you can build your project using the latest available SDK, just remember that you’re targeting Zebra devices with API level 16 or 19, so, setup your minimum SDK accordingly.

You can find a demo app built with this technique on my github account.

Happy coding
~Pietro

This post has been reposted from my personal website.

Edit

Enterprise Browser v1.3 introduced a change that requires to enable FunctionKeysCapturable to be able to use the KeyCapture API.

 

<FunctionKeysCapturable                 value="1"/>

 

Updating your config.xml with this option will enable the KeyCapture API.

 

 

Enterprise Browser

Enterprise Browser is Zebra Technologies' Industrial Browser built for our Rugged Devices, we support most of our Windows Mobile/Windows CE devices and Android devices.

This product is usually used with existing web application that cannot be updated/modified moving from one device to another. This help us winning some opportunities but sometimes present some unique challenges like, as an example, disabling the Android back button default behaviour.

 

Back Button on Android?

Given that this is a crossplatform product (built on top of our RhoMobile Suite) we don't have a custom settings to disable the back button in the Config.xml configuration file, however it is still possible to add a default Metatags in the configuration so that no changes in the existing pages are needed.

So, do we've an API to intercept the Back Button?

Of course! the KeyCapture API can be used to intercept and disable it.

 

EB.KeyCapture.captureKey(BOOLEAN dispatch, STRING keyValue)
   

 

Setting the dispatch value to false, We just need to get the correct KeyCode.

This can a bit tricky and can be different from device to device, the best solution I've is to ask directly to the device with a simple HTML page that display the keycode off all the keys that are pressed:

 

<!DOCTYPE html>
<html lan="en">
<META HTTP-Equiv="KeyCapture" Content="KeyValue:All; Dispatch:False; KeyEvent:url('JavaScript:alert('Key Pressed: %s');')">
  <head>
    <meta charset="utf-8">
  <title>Display KeyCode</title>
  </head>
  <body>
    <H1>Press a key to see it's KeyCode</H1>
  </body>
</html>
   

 

Once we've the correct KeyCode, we just need to call this API in every page that is loaded in the browser… Sometimes that is not easy to do sometimes, especially when the application cannot be modified.

We've a solution for this issue: having a DefaultMetaTags in Enterprise Browser's configuration.

 

What's a DefaultMetaTags

We can start from the documentation, what does it means?

A DefaultMetaTags is a way to call an Enterprise Browser API on top of every HTML page that is loaded in the browser. This can be used, as an example to enable on screen UI elements like the battery or WiFi icon.

So, putting the different things together, we can put this in the ''Config.xml':

 

<DefaultMetaTags>
    <MetaTag value="KeyCapture~KeyValue:0xA6;Dispatch:False"/>
</DefaultMetaTags>
   

 

BTW: 0xA6 is the correct value for the Back Button on a TC55 running Android v4.4 KitKat.

 

Closing comments

Enterprise Browser's DefaultMetaTags is a very flexible way to "patch" an existing Web application without touching its source code.

As a closing comment here's a sample configuration that zoom the current webpage pressing a button:

 

<MetaTag VALUE="KeyCapture~KeyValue:0x79;Dispatch:False;KeyEvent:url('JavaScript:eval('zoom.page=\'1.3\';');')"/>
   

 

This post has been reposted from my personal website.

The good old ways!

On Symbol/MSI Windows Mobile devices, we where providing some APIs in the EMDK to get additional informations. Looking into the Resource Coordinator is possible to find APIs like:

  • RCM_GetESN() - retrieves the device electronic serial number
  • RCM_GetUniqueUnitId() - retrieves the unique unit identification number
  • RCM_GetVersion() - retrieves version information
  • etc…

…and we don't have anything like this in the Android EMDK. WHY?

Simply because the functionality is already included in the standard Android SDK.

Let's see how to get this is data on an MSI device with the Android OS.

The fabulous new way!

You can find the completed project in this repository on my github account, I'm using Windows 7 and Eclipse+ADT, but you can follow these steps with Android Studio quite nicely.

Create a new Project

Create a new Android project, nothing fancy here, it's just a standard app with a single Blank Activity. You can follow these images as a guideline. Your interface may vary as Google updates the Android wizard quite often.

create_project_01.jpg

create_project_02.jpg

create_project_03.jpg

create_project_04.jpg

create_project_05.jpg

Then we can do some housekeeping deleting the unnecessary main.xml menu resource:

delete_menu.jpg

We can then start the two main changes: - Setting up the Activity Layout - Updating the Activity onCreate method to retrieve the device data

activity_layout.jpg

Here's the code:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
    >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/device_name"
        />
    <TextView
        android:id="@+id/device_type"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:textSize="18sp"
        style="?android:listSeparatorTextViewStyle"
        />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/electronic_serial_number"
        />
    <TextView
        android:id="@+id/device_esn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:textSize="18sp"
        style="?android:listSeparatorTextViewStyle"
        />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/build_number"
        />
    <TextView
        android:id="@+id/build_number"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:textSize="18sp"
        style="?android:listSeparatorTextViewStyle"
        />
</LinearLayout>


 

This together with the string.xml containing the referenced string:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Get Device Info</string>
    <string name="electronic_serial_number">Device ESN:</string>
    <string name="build_number">Build Number:</string>
    <string name="device_name">Device:</string>
</resources>


 

Then the simple Activity java code to collect the information is:

package com.pietromaggi.sample.getdeviceinfo;
import android.os.Build;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends ActionBarActivity {
    TextView DeviceNameTextView;
    TextView ESNTextView;
    TextView BuildNumberTextView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DeviceNameTextView = (TextView)findViewById(R.id.device_type);
        DeviceNameTextView.setText(Build.DEVICE);
        ESNTextView = (TextView)findViewById(R.id.device_esn);
        ESNTextView.setText(Build.SERIAL);
        BuildNumberTextView = (TextView)findViewById(R.id.build_number);
        BuildNumberTextView.setText(Build.ID);
    }
}


 

Where's the tricks?

There's really no trick, Android SDK provide this information, and more using these constants:

Obviously, it's the OEM building the device that put together the plumbing to link the correct information. Your mileage may vary on different devices.

Running this application on an ET1 with Jelly Bean you get:

screen_ET1.png

Running this application on an MC40 with Jelly Bean you get:

screen_MC40.png

While the TC55 is always a bit different :-)

screen_TC55JB.png

Hope you may find this useful. Send me an email if you'd like to see any particular topic on this blog.

 

Reprinted from my personal blog

Filter Blog

By date:
By tag: