Basic Xamarin Print Example
Hi Everyone,
We've gotten several requests for some basic sample code for the Link-OS Multiplatform SDK showing it's use with Xamarin.
First, you need to install the SDK, either by downloading it from Zebra.com and following the install instructions, or getting it directly from Nuget. Full API documentation is on Link-OS SDK - Zebra Technologies Techdocs .
The sample code creates an app with a text box for entering a printer address and a print button. When you press the print button, the words "Hello World" print on your Zebra Printer. The address can be an IP address or a Bluetooth MAC address for your printer.
This sample code is for Android, but you can copy the printing portions into an iOS or Forms app without changes. I gave permissions for BLUETOOTH and BLUETOOTH_ADMIN in the manifest. As a note, this code will set your printer to ZPL mode, so if you want to your app to print in line mode, you will need to change it back or modify the code. If you just want to test this code over Bluetooth, you can speed up time to print by changing the connection builder string to
connection = ConnectionBuilder.Current.Build("BT:" + address);
Happy Coding!
MainActivity.cs
/***********************************************
CONFIDENTIAL AND PROPRIETARY
The source code and other information contained herein is the confidential and the exclusive property of
ZIH Corp. and is subject to the terms and conditions in your end user license agreement.
Copyright ZIH Corp. 2016
ALL RIGHTS RESERVED
***********************************************/
using System;
using Android.App;
using Android.Widget;
using Android.OS;
using System.Threading.Tasks;
using LinkOS.Plugin.Abstractions;
using LinkOS.Plugin;
using Android.Util;
using System.Text;
namespace BasicPrint
{
[Activity(Label = "BasicPrint", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
Button button;
EditText addressTxt;
const string tag = "BasicPrintApp";
IConnection connection;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
button = FindViewById
addressTxt = FindViewById
(Resource.Id.address); connection = null;
button.Click += delegate {
Start_Print();
};
}
private void Start_Print()
{
button.Enabled = false;
string address = addressTxt.Text;
// Bluetooth communications must be handled on a separate thread and it's
// best practice to handle network coms on it as well
new Task(() =>
{
Print(address);
}).Start();
}
private void Print(string address)
{
string zpl = "^XA^LL200^FO30,20^A0N,30,30^FDHello World^FS^XZ";
try
{
if ((connection == null) || (!connection.IsConnected))
{
connection = ConnectionBuilder.Current.Build(address);
connection.Open();
}
if ((SetPrintLanguage(connection)) && (CheckPrinterStatus(connection)))
{
connection.Write(Encoding.ASCII.GetBytes(zpl));
}
}
catch (Exception e)
{
//if the device is unable to connect, an exception is thrown
Log.Debug(tag, e.ToString());
}
finally
{
this.RunOnUiThread(() =>
{
button.Enabled = true;
});
}
}
private bool SetPrintLanguage(IConnection connection)
{
string setLanguage = "! U1 setvar \"device.languages\" \"zpl\"\r\n\r\n! U1 getvar \"device.languages\"\r\n\r\n";
byte[] response = connection.SendAndWaitForResponse(Encoding.ASCII.GetBytes(setLanguage), 500, 500);
string s = Encoding.ASCII.GetString(response);
if (!s.Contains("zpl"))
{
Log.Debug(tag, "Not a ZPL printer.");
return false;
}
return true;
}
private bool CheckPrinterStatus(IConnection connection)
{
IZebraPrinter printer = ZebraPrinterFactory.Current.GetInstance(PrinterLanguage.ZPL, connection);
IPrinterStatus status = printer.CurrentStatus;
if (! status.IsReadyToPrint)
{
Log.Debug(tag, "Printer in Error: " + status.ToString());
}
return true;
}
protected override void OnPause()
{
base.OnPause();
Log.Debug(tag, "Closing connection on inactive app");
if ((connection != null) && (connection.IsConnected))
{
connection.Close();
}
}
}
}
Main.axml
http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/address"
android:hint="@string/Address" />
android:id="@+id/MyButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/Hello" />
Robin West
Solution Architect
Zebra Technologies
Anonymous (not verified)
61 Replies
Hi, the aapt.exe is the s the Android Asset Packaging Tool (aapt). It is not part of the SDK. Please take a look at some of the Stackoverflow issues with it. <a href="https://stackoverflow.com/questions/30830285/what-is-the-function-of-aa… - What is the function of aapt.exe in android? - Stack Overflow</a>
Hello Robin,
Although I do all the operations, I still get the same error. I can only work in Xamarin when I create an android project. But when I create Xamarin Forms, I get out of memory error. The error is as follows
Severity Code Description Project File Line Suppression State
Error java.lang.OutOfMemoryError. Consider increasing the value of $(JavaMaximumHeapSize). Java ran out of memory while executing 'java.exe -Xmx1G -jar "C:\Program Files (x86)\Android\android-sdk\build-tools\23.0.3\\lib\dx.jar" --no-strict --dex --output=obj\Debug\android\bin obj\Debug\android\bin\classes "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid\v7.1\mono.android.jar" obj\Debug\__library_projects__\FormsViewGroup\library_project_imports\formsviewgroup.jar obj\Debug\__library_projects__\Xamarin.Android.Support.Animated.Vector.Drawable\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.Compat\library_project_imports\bin\classes.jar "obj\Debug\__library_projects__\Xamarin.Android.Support.Core.UI\library_project_imports\bin\classes.jar" obj\Debug\__library_projects__\Xamarin.Android.Support.Core.Utils\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.Design\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.Fragment\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.Media.Compat\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.Transition\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.v4\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.v7.AppCompat\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.v7.CardView\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.v7.MediaRouter\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.v7.Palette\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.v7.RecyclerView\library_project_imports\bin\classes.jar obj\Debug\__library_projects__\Xamarin.Android.Support.Vector.Drawable\library_project_imports\bin\classes.jar "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\ZSDK_ANDROID_API.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__commons-io-2.2.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__commons-lang3-3.4.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__commons-net-3.1.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__commons-validator-1.4.0.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__core-1.53.0.0.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__httpcore-4.3.1.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__httpmime-4.3.2.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__jackson-annotations-2.2.3.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__jackson-core-2.2.3.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__jackson-databind-2.2.3.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__opencsv-2.2.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__pkix-1.53.0.0.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__prov-1.53.0.0.jar" "obj\Debug\__library_projects__\ZSDK_ANDROIDX\library_project_imports\__reference__snmp6_1.jar"' zebraCrossPlatform.Android
I solved the problem. I marked the Android -> Properties -> Enable Multi-Dex box.
I created the android-sdk directory virtually in C directory.
Later I changed vstudio -> tools> Options Xamarin -> Android Settings -> Android SDK Location to C: \ android-sdk.
When I built it again, the program worked.
Yes, and I tried many time just to be sure. Were you able to do it with Xamarin Forms on iOS ? For me, that same code works fine on Android.
Can you check whether you passed the MAC address or the Serial Number of the printer to the connection builder below?
if ((connection == null) || (!connection.IsConnected))
{
connection = ConnectionBuilder.Current.Build(address);
connection.Open();
}
It looks like passing MAC address to the connection builder doesn't work for iOS. If you can manage to pass the Serial Number to the connection builder, then it should work for iOS. The Serial Number of the printer can be found on the back or bottom of the printer. Hope this helps.
Here is the copy from the connection builder API doc
connectionString
The format of the input string is: [prefix:] address [: port_number(s)]Prefix is either TCP_MULTI, TCP, TCP_STATUS, BT_MULTI, BT, or BT_STATUSThe format of address depends on the prefix and OS: BT : Android - address is the printer's BT MAC address. <strong><em>iOS - address is the printer's serial number.</em></strong> TCP : Android - address is either a DNS name or an IPv4 address. iOS - address is an IPv4 address.port_number(s) is optional, and only applicable for TCP connections.<strong>iOS Considerations:</strong>TCP_MULTI, BT_MULTI, and BT_STATUS are not availible. TCP IPv4 address only, DNS name not supported.
Hi Robin,
I am working on an Android App for the TC51. I am using VS 2015 with Xamarin. I need to be able to print to the QLn220 via Bluetooth. I saw your Blog posting and I added the Link-OS SDK to my project, set the BlueTooth and BlueTooth Admin permissions in the manifest and set the Java Max Heap Size to 1G. I cleaned my solution and then did a rebuild. Sadly I go the following message;
error MSB6006: "java.exe" exited with code 2
I did not alter any of the code, just added the SDK? Any ideas?
I also have another question, Is there an easy way to connect the TC51 to any printer on WiFi and have it print?
thank you
al
Hi Robin,
What happened to this thread? I was getting back to looking at the code and wanted to check how to add the mpsdk to my visual studio project it was gone?
Thank you
al
Hello Robin,
I have bought ZQ310
my question is: can i use a label generated from Zebra designer with linkos?
thanks
Hi Robin West, Thanks for your code, I used and works excellent.
I Try to add more lines, but I only can print 4 3 more lines, after that stop printing. We are using and iMZ320
Can You help us?
Thanks
Hi
I have a problem with the connection by wifi when making the conection.open I generated the following error could help me
{Zebra.Sdk.Comm.ConnectionException: Could not open connection
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in :0
at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniMethodInfo method) [0x00068] in <3cb12bce834a498199b2be6cd3e00922>:0
at Android.Runtime.JNIEnv.CallVoidMethod (System.IntPtr jobject, System.IntPtr jmethod) [0x0000e] in :0
at Zebra.Sdk.Comm.MultichannelConnection.Open () [0x00044] in C:\Users\jvanhuis\source\repos\xamarin-sdk\Binding Libraries\ZSDK_ANDROIDX\ZSDK_ANDROIDX\obj\Debug\generated\src\Zebra.Sdk.Comm.MultichannelConnection.cs:569
at LinkOS.Plugin.ConnectionImplementation.Open () [0x00001] in C:\Users\jvanhuis\source\repos\xamarin-sdk\Link_OS_SDK_for_Xamarin_Portable\LinkOS\LinkOS.Plugin.Android\ConnectionImplementation.cs:106
at LabelBunch.ViewModels.VariViewModels.PrintLineMode () [0x00010] in G:\proyectos\Labelbunch\LabelBunch\LabelBunch\LabelBunch\ViewModels\VariViewModels.cs:166
--- End of managed Zebra.Sdk.Comm.ConnectionException stack trace ---
com.zebra.sdk.comm.ConnectionException: Could not open connection
at com.zebra.sdk.comm.MultichannelConnection.open(Unknown Source)
at md5270abb39e60627f0f200893b490a1ade.ButtonRenderer_ButtonClickListener.n_onClick(Native Method)
at md5270abb39e60627f0f200893b490a1ade.ButtonRenderer_ButtonClickListener.onClick(ButtonRenderer_ButtonClickListener.java:30)
at android.view.View.performClick(View.java:5273)
at android.view.View$PerformClick.run(View.java:21315)
at android.os.Handler.handleCallback(Handler.java:743)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5665)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:822)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712)
}
Hello Robin,
I need your kind help.
I'm using your example with LinkOS_Xamarin_SDK 1.2; sometimes I receive communication error or broken pipe error while printing on bluetooth ZPL printer.
For this reason I wanna try new Zebra.Printer.SDK 2.15, but unfortunately your example doesn't work anymore.
For example, there isn't any "IConnection" interface.
(IConnection connection; )
Could you tell me where can I found a example (old xamarin android, not forms!) ?
Regards,
Mauro