Audience

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

Submitted by saim hasanusta on May 04, 2019 Permalink

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

Submitted by saim hasanusta on May 04, 2019 Permalink

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.

Submitted by Alexandre Coupal on May 04, 2019 Permalink

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.

Submitted by Anonymous (not verified) on May 04, 2019 Permalink

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.

Submitted by Allen Lukowitz on May 04, 2019 Permalink

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

Submitted by Allen Lukowitz on May 04, 2019 Permalink

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

Submitted by Jose Espinoza on May 04, 2019 Permalink

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

Submitted by Giovanni Pantano on May 04, 2019 Permalink

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 &lt;3cb12bce834a498199b2be6cd3e00922&gt;: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)
}

Submitted by Mauro Carta on May 14, 2019 Permalink

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