Garbage Collector
Tales from an old nibble
Disabling MC40 Home Button with a custom intent
Note: #
[I’ve published another post that explain how to disable the Home Button on all the Zebra’s Android devices that are supported by Mx v4.3+.]({{ relref . “post/mx_home_button.md” }})
Intro #
Zebra Technologies’ devices are purpose built to be single use devices. Having an OS like Android nowadays provides a lot of flexibility… sometimes a bit too much.
With this idea in mind, the Android version used on these devices sometimes provide some nice surprise, like an Intent to disable the omnipresent Android’s Home button.
The basic idea #
MC40 support an Android intent to disable the normal Home button behavior: You can disable it and there’s no way to exit from the foreground application 1.
You can find a blog by Pavel Machala briefly describing the idea on Launchpad.
Here I want to present a simple sample that show how to use this intent, covering the only issue that is: handling re-branded devices
Project setup #
We start creating a new Android application in Android Studio (I’m using Android Studio v1.5.1 with Build tools 23.0.1, you’re mileage can vary if you’re using a different setup).
Note: is not required to build this application using Zebra Technologies’ EMDK. A normal Android application can use this intent.
Once we’ve the app framework setup by Android Studio, we can simplify the interface down to a Status message and a button.
First step: remove content_main.xml
and menu_main
then replace the content of activity_main.xml
with:
<?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:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tvwHomeBtnStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="24dp"
android:text="@string/home_btn_status_on"/>
<Button
android:id="@+id/btnToggleStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/toggle"/>
</LinearLayout>
This layout requires the following string.xml
inside the res/values
folder:
<resources>
<string name="app_name">MC40HomeButton</string>
<string name="home_btn_status_on">Home Button Enabled</string>
<string name="home_btn_status_off">Home Button Disabled</string>
<string name="toggle">Toggle current device setting</string>
</resources>
We can now remove a lot of the generated template code in MainActivity.java
trimming down the code to:
package com.pietromaggi.sample.mc40homebutton;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
If we run the application at this moment, it’s not doing a lot :-)
You can find the app at this stage on the github repository under the tag1
tag.
Next step would be to check that we’re really running on a Zebra Technologies’ MC40, and then adding some logic to the app.
Dealing with multiple OS versions and re-branding #
First we check that we’re running on a Zebra’s MC40 using a couple of Android constant:
android.os.Build.MANUFACTURER
android.os.Build.MODEL
The catch is that MC40, running Jelly Bean, report “Motorola Solution” as MANUFACTURER
, we need to address this difference and, as reported in Pavel’s notes, the broadcast intent action is different for Motorola Solution or Zebra’s MC40.
Once we’ve seen if the device the app is running on is supported, we can send a first Intent, to disable the home button, and configure the toggle button, so that is really toggle the Home Button status from disable to enabled and vice versa.
package com.pietromaggi.sample.mc40homebutton;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private static final String MANUFACTURER_ZEBRA = "Zebra Technologies";
private static final String MANUFACTURER_MSI = "Motorola Solutions";
private static final String MODEL_MC40 = "MC40N0";
private static final String INTENT_ZEBRA = "com.symbol.intent.action.HOMEKEY_MODE";
private static final String INTENT_MSI = "com.motorolasolutions.intent.action.HOMEKEY_MODE";
private static final String INTENT_EXTRA = "state";
private String mStrIntent;
private TextView mTvwStatus;
private int mStatus;
@Override
protected void onCreate(Bundle savedInstanceState) {
String StrManufacturer = Build.MANUFACTURER;
String strModel = Build.MODEL;
boolean bSupported = true;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTvwStatus = (TextView) findViewById(R.id.tvwHomeBtnStatus);
if (strModel.equalsIgnoreCase(MODEL_MC40)) {
// We're running on an MC40
if (StrManufacturer.equalsIgnoreCase(MANUFACTURER_ZEBRA)) {
// This is a Zebra Device
mStrIntent = INTENT_ZEBRA;
} else if (StrManufacturer.equalsIgnoreCase(MANUFACTURER_MSI)) {
// This is a Motorola Solution Device
// just double OS version, only Jelly Bean is supported
mStrIntent = INTENT_MSI;
if (Build.VERSION_CODES.JELLY_BEAN != Build.VERSION.SDK_INT) {
bSupported = false;
}
}
} else {
// This is something else, not supported
bSupported = false;
}
Button btnToggle = (Button)findViewById(R.id.btnToggleStatus);
if (bSupported) {
mTvwStatus.setText(R.string.home_btn_status_off);
mStatus = 0;
Intent i = new Intent(mStrIntent);
i.putExtra(INTENT_EXTRA, mStatus);
sendBroadcast(i);
btnToggle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Toggle Current Status
if (0 == mStatus) {
mStatus = 1;
mTvwStatus.setText(R.string.home_btn_status_on);
} else {
mStatus = 0;
mTvwStatus.setText(R.string.home_btn_status_off);
}
Intent i = new Intent(mStrIntent);
i.putExtra(INTENT_EXTRA, mStatus);
sendBroadcast(i);
}
});
} else {
mTvwStatus.setText(R.string.device_not_supported);
btnToggle.setEnabled(false);
}
}
}
If we run the application on a supported device, we get the expected behavior:
Managing state #
The application now works as expected, but with an issue linked to not managing the state. As an example, simply rotating the device, the Activity is destroyed to create a new one with the standard behavior to disable the Home Button, even if we just re-enabled it using the toggle
button.
An easy solution is to add some code to manage the Application status overriding the onSaveInstanceState(Bundle)
method:
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt(KEY_STATE, mState);
}
And update the onCreate
method to check the bundle to see if it’s defined and behave accordingly.
The final version of the application, managing the state, can be find on github associated to tag3.
Let me know if you’ve found this article useful.
Notes #
If your app locks down a few other things or you’re using something like Zebra’s Enterprise Home Screen. ↩︎