I have a Xamarin Forms app that is deployed to a Zebra TC51 device. It works very well. TC51 is a very interesting rugged device. I use EMDK to work with integrated barcode reader. You can find a lot of information and code samples here.
Now I would like to use my app without a TC51 device. For example, I would like to test it with an Android Virtual Device. So, I open “AVD Manager” in Visual Studio for MAC and run Android Accelerated x86 AVD. It starts, everything is fine. I start a debug session and APK is deployed to AVD and… now start problems!
/Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.Debugging.targets(516,2): error : Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY]
This is the first error. It seems that I should have a device with EMDK installed to deploy my app. How can I solve this problem?
Modify AndroidManifest.xml
I have to modify AndoridManifest.xml and add the code in “bold“
<application android:label="fev_ventilazione_smartwatch" android:icon="@drawable/icon"> <uses-library android:name="com.symbol.emdk" android:required="false"/> </application>
What does it mean? Here all explanations you need.
android:required
Boolean value that indicates whether the application requires the feature specified in android:name
.
- When you declare
android:required="true"
for a feature, you are specifying that the application cannot function, or is not designed to function, when the specified feature is not present on the device. - When you declare
android:required="false"
for a feature, it means that the application prefers to use the feature if present on the device, but that it is designed to function without the specified feature, if necessary.
The default value for android:required
if not declared is "true"
.
Ok. A first problem is solved. I am very happy. Now I try to deploy again the app to my AVD. All seems to work fine and…
Another big problem. An exception appears:
Yes, my code needs EMDK! How can I solve this problem?
Remove EMDK code with preprocessor directives
Preprocessor directive are very powerful. To use these directives we have to create a new configuration for our solution. I add some pictures to explain better all the steps. I have VS4Mac in Italian… maybe a little different from English version.
Add a new configuration.
Double click to “(master)” solution and select “Configurations”, you should see something like this (I hope MFractor developer do not be angry for popup…;)):
Select “Release” configuration, press “Copy” and create a new “ReleaseNoEMDK” configuration. Obviously, you can do the same with “Debug” configuration if you need to debug your app without EMDK installed.
Now, when you try to change your configuration, you should have a situation like this:
Select “ReleaseNoEMDK” and double click PCL Solution. In “Project Option” popup, select “Compiler” and add “NO_EMDK” symbol.
Double click to Android Solution and add NO_EMDK symbol.
Now your projects have the right configuration to use preprocessor directives. You can add these directives to your Android project, when you use EMDK (all EMDK code is under Android project!). For example in MainActivity.cs:
#if !NO_EMDK public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, EMDKManager.IEMDKListener #else public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity #endif
or ScanReceiver.cs
#if !NO_EMDK [BroadcastReceiver] public class ScanReceiver : BroadcastReceiver { public static DateTime UltimaLetturaBarcode = DateTime.MinValue; // This intent string contains the source of the data as a string private static string SOURCE_TAG = "com.motorolasolutions.emdk.datawedge.source"; // This intent string contains the barcode symbology as a string private static string LABEL_TYPE_TAG = "com.motorolasolutions.emdk.datawedge.label_type"; // This intent string contains the captured data as a string // (in the case of MSR this data string contains a concatenation of the track data) private static string DATA_STRING_TAG = "com.motorolasolutions.emdk.datawedge.data_string"; // Intent Action for our operation public static string IntentAction = "barcodescanner.RECVR"; public static string IntentCategory = "android.intent.category.DEFAULT"; public event EventHandler<string> scanDataReceived; public override void OnReceive (Context context, Intent i) { // check the intent action is for us if (i.Action.Equals (IntentAction)) { // define a string that will hold our output String Out = ""; // get the source of the data String source = i.GetStringExtra (SOURCE_TAG); // save it to use later if (source == null) source = "scanner"; // get the data from the intent String data = i.GetStringExtra (DATA_STRING_TAG); // let's define a variable for the data length int data_len = 0; // and set it to the length of the data if (data != null) data_len = data.Length; string sLabelType = ""; // check if the data has come from the barcode scanner if (source.Equals ("scanner")) { // check if there is anything in the data if (data != null && data.Length > 0) { // we have some data, so let's get it's symbology sLabelType = i.GetStringExtra (LABEL_TYPE_TAG); // check if the string is empty if (sLabelType != null && sLabelType.Length > 0) { // format of the label type string is LABEL-TYPE-SYMBOLOGY // so let's skip the LABEL-TYPE- portion to get just the symbology sLabelType = sLabelType.Substring (11); } else { // the string was empty so let's set it to "Unknown" sLabelType = "Unknown"; } // let's construct the beginning of our output string Out = "Scanner " + "Symbology: " + sLabelType + ", Length: " + data_len.ToString () + ", Data: " + data.ToString () + "\r\n"; } } // check if the data has come from the MSR if (source.Equals ("msr")) { // construct the beginning of our output string Out = "Source: MSR, Length: " + data_len.ToString () + ", Data: " + data.ToString () + "\r\n"; } if (scanDataReceived != null) { // Prendo la data precedente if ((DateTime.Now - UltimaLetturaBarcode).TotalMilliseconds < 1000) return; UltimaLetturaBarcode = DateTime.Now; System.Diagnostics.Debug.WriteLine("scanDataReceived '" + data + "'"); //scanDataReceived (this, Out); scanDataReceived(this, data); } } } } #endif
Using these directives you can add or remove EMDK specific code from your source only selecting the correct project configuration.
Hope this can be useful. Let me know. Comments are well accepted! And happy Halloween…
Hello
I have something misunderstand, you said you need EMDK , but why you remove EMDK code with preprocessor directives?
I have NoClassDefFoundError too, i think it should be deploy some DLL or EMDK file to mobile computer.
"Mi piace""Mi piace"
Where are you deploying your app? If you are diployimg on a non zebra device, you have not your emdk installed so, your project build but your app crashes
"Mi piace""Mi piace"
I have a Zebra MC36, Android 4.4, and use Xamarin Live Play to debug.
"Mi piace""Mi piace"
https://www.zebra.com/us/en/support-downloads/software/developer-tools/emdk-for-android.html
I don’t see mc35 on device list. You should contact Zebra
"Mi piace""Mi piace"