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<Button>(Resource.Id.MyButton);

            addressTxt = FindViewById<EditText>(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

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    <EditText

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:id="@+id/address"

        android:hint="@string/Address" />

    <Button

        android:id="@+id/MyButton"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:text="@string/Hello" />

</LinearLayout>

Robin West

Solution Architect

Zebra Technologies

Comments


Thank you, Robin! A timely add to LaunchPad as I was just starting with Bluetooth printing to QLn320 using Xamarin.Android!


Hi Robin, Thank you very much for help and your quick answer, but I can not to connect to my printer P4T.tm and print. When I get to line 59 picture1. he jumps direct (catch (Exception e)). picture2.

Thank you again for your help

1.png

2.png

10-07 14:15:39.031 D/BasicPrintApp( 7184):at android.bluetooth.BluetoothAdapter.cancelDiscovery(BluetoothAdapter.java:705)
10-07 14:15:39.031 D/BasicPrintApp( 7184):at com.zebra.sdk.comm.BluetoothConnection.cancelBluetoothDiscovery(Unknown Source)
10-07 14:15:39.031 D/BasicPrintApp( 7184):at com.zebra.sdk.comm.BluetoothConnection.open(Unknown Source)
10-07 14:15:39.031 D/BasicPrintApp( 7184):at com.zebra.sdk.comm.MultichannelConnection.openPrintingChannel(Unknown Source)
10-07 14:15:39.031 D/BasicPrintApp( 7184):at com.zebra.sdk.comm.MultichannelBluetoothConnection.open(Unknown Source)
10-07 14:15:39.031 D/BasicPrintApp( 7184):at com.zebra.sdk.comm.internal.ConnectionBuilderInternal.determineConnectionToTry(Unknown Source)
10-07 14:15:39.031 D/BasicPrintApp( 7184):at com.zebra.sdk.comm.internal.ConnectionBuilderInternal.build(Unknown Source)
10-07 14:15:39.031 D/BasicPrintApp( 7184):at com.zebra.sdk.comm.ConnectionBuilder.build(Unknown Source)
10-07 14:15:39.031 D/BasicPrintApp( 7184):at dalvik.system.NativeStart.run(Native Method)

10-07 14:15:39.132 D/dalvikvm( 7184): GC_CONCURRENT freed 237K, 4% free 9292K/9607K, paused 5ms+5ms

Thread finished: <Thread Pool> #5

10-07 14:15:50.726 D/Mono    ( 7184): [0x98f830] worker finishing

Le thread 'Unknown' (0x5) s'est arrêté avec le code 0 (0x0).

Thread finished: <Thread Pool> #3

Le thread 'Unknown' (0x3) s'est arrêté avec le code 0 (0x0).


Hi Robin,

Thank you for your reply but I finally account not used your pluging. And I can print its no plubléme. but I have a problem with the ZPL code on a chain of caractaire when I made a space. you can see in the pictures. And when I have more space the printer does not respond.

Thank you again for your help

ERREUR3.png

IMG_4005.JPG

ERREUR2.png

IMG_4004.JPG

ERREUR1.png


Hi Robin, thanks for guide.

However, I encounter an issue when with Bluetooth connection. Even though I had called the IConnection.close() method, the device is still connected, and other phone cannot connect to the printer unless I manually turn off bluetooth connection on the phone.

This happens to both Android and iOS.

How should I close the connection properly?


Hello robin west ,

i'm a beginner with mobile dev and xamarin i've installed visual studio 2015 professionnel.

vs 2015 included xamarin => i can created project compile and deploy and a device => all works.

I work the a big society and i need to print on a zebra MZ 220.

I've follow your insturction :

- create new blank project android with vs 2015

- add nuget package LinkOS_Xamarin_SDK

- copy paste the code

- build solution

when i type the address mac or the name of the printer in the method Print as this

private void Print(string address)

        {

            //

            if (String.IsNullOrEmpty(address))

                address = "LUXXH134893625"; // "AC3FA413BCBD"; //

                .....

I have this error :

Zebra.Sdk.Comm.ConnectionException: Could not open connection string "LUXXH134893625"

  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3415/7db2aac3/source/mono/external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143

  at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00082] in /Users/builder/data/lanes/3415/7db2aac3/source/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.g.cs:12649

  at Android.Runtime.JNIEnv.CallStaticObjectMethod (IntPtr jclass, IntPtr jmethod, Android.Runtime.JValue* parms) [0x00000] in /Users/builder/data/lanes/3415/7db2aac3/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:562

  at Zebra.Sdk.Comm.ConnectionBuilder.Build (System.String p0) [0x00049] in C:\repos\xamarin-sdk\Binding Libraries\ZSDK_ANDROIDX\ZSDK_ANDROIDX\obj\Release\generated\src\Zebra.Sdk.Comm.ConnectionBuilder.cs:54

  at LinkOS.Plugin.ConnectionBuilderImplementation.Build (System.String connectionString) [0x00000] in C:\repos\xamarin-sdk\Link_OS_SDK_for_Xamarin_Portable\LinkOS\LinkOS.Plugin.Android\ConnectionBuilderImplementation.cs:19

  at FirstPrint.MainActivity.Print (System.String address) [0x00037] in C:\CHB_DEV\ANDROID XAMARIN\MY_PROJECT\DIVERS TUTO\ZEBRA_PRINT\FirstPrint\FirstPrint\MainActivity.cs:86

  --- End of managed exception stack trace ---

com.zebra.sdk.comm.ConnectionException: Could not open connection string "LUXXH134893625"

  at com.zebra.sdk.comm.internal.ConnectionBuilderInternal.build(Unknown Source)

  at com.zebra.sdk.comm.ConnectionBuilder.build(Unknown Source)

  at dalvik.system.NativeStart.run(Native Method)

}

Any idea ?

I've realize also a second project with this code (button click) and i can send some command to print and it's workkkkk fine here is it the code

With this sample i can see that my printer WORK fine ...i don't know what's happens with my first sample ...

if you can help me, it would be appreciate ..

private void Button_Click(object sender, EventArgs e)

        {

            //

            new System.Threading.Tasks.Task(() =>

            {

                try

                {

                    //mac address printer zebra

                    string address = "AC3FA413BCBD";

                    //start

                    Zebra.Sdk.Comm.BluetoothConnectionInsecure thePrinterConn = new Zebra.Sdk.Comm.BluetoothConnectionInsecure(address);

                    //open connection

                    thePrinterConn.Open();

                    //This example prints "This is a CPCL test." near the top of the label.

                    String cpclData = "! 0 200 200 210 1\r\n"

                            + "TEXT 4 0 30 10 This is a CPCL test.\r\n"

                            + "FORM\r\n"

                            + "PRINT\r\n";

                    // Send the data to printer as a byte array.

                    thePrinterConn.Write(System.Text.Encoding.ASCII.GetBytes(cpclData));

                    // Close the insecure connection to release resources.

                    thePrinterConn.Close();

                }

                catch (Exception exception)

                {

                    Android.Util.Log.Debug("printZebraSample", exception.ToString());

                }

            }).Start();

thanks for your time


Hello, I have a zebra P4T.m. and I tried your code but I get errors. Thank you in advance for your help (I apologize for my english)

**********************************************************************************************************************************

Erreurjava.lang.OutOfMemoryError. Consider increasing the value of $(JavaMaximumHeapSize). Java ran out of memory while executing 'java.exe -jar "C:\Program Files (x86)\Android\android-sdk\build-tools\24.0.2\\lib\dx.jar" --no-strict --dex --output=obj\Debug\android\bin obj\Debug\android\bin\classes "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v7.0\mono.android.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'AppTestBluetooth5

Hi Amine, Nearly any time you are creating a new Android app on Xamarin, one quirk is you have to set the Heap size.  Do this by going into the Android Project Properties.  In the Android Options tab, go to the Advanced tab.  Enter 1G in the "Java Max Heap Size:"


Hi Amine,

Can grab a little more of the log?  It' looks like you are missing some of the exception stacktrace.  I can't see what is wrong.


Hi Robin, thank you for your help because it is very important that I succeed my printing. with these capture screenshots I tried to show you all the steps of the code. I hope that you can see where there are errors. otherwise I suggest you take control of my PC with TeamViewer if you want. Thank you very much.

Best regards

B1.png

B2.png

B3.png

B4.png

B5.png

B7.png

{Zebra.Sdk.Comm.ConnectionException: Could not open connection string "AC:3F:A4:1F:2A:F5"

  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3511/f4db8a57/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143

  at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00082] in /Users/builder/data/lanes/3511/0e59c362/source/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.g.cs:12649

  at Android.Runtime.JNIEnv.CallStaticObjectMethod (System.IntPtr jclass, System.IntPtr jmethod, Android.Runtime.JValue* parms) [0x00000] in /Users/builder/data/lanes/3511/0e59c362/source/monodroid/src/Mono.Android/JNIEnv.g.cs:562

  at Zebra.Sdk.Comm.ConnectionBuilder.Build (System.String p0) [0x00049] in C:\repos\xamarin-sdk\Binding Libraries\ZSDK_ANDROIDX\ZSDK_ANDROIDX\obj\Release\generated\src\Zebra.Sdk.Comm.ConnectionBuilder.cs:54

  at LinkOS.Plugin.ConnectionBuilderImplementation.Build (System.String connectionString) [0x00000] in C:\repos\xamarin-sdk\Link_OS_SDK_for_Xamarin_Portable\LinkOS\LinkOS.Plugin.Android\ConnectionBuilderImplementation.cs:19

  at AppTestBluetooth5.MainActivity.Print (System.String address) [0x00026] in D:\TestAppli\AppTestBluetooth5\AppTestBluetooth5\MainActivity.cs:59

  --- End of managed Zebra.Sdk.Comm.ConnectionException stack trace ---

com.zebra.sdk.comm.ConnectionException: Could not open connection string "AC:3F:A4:1F:2A:F5"

  at com.zebra.sdk.comm.internal.ConnectionBuilderInternal.build(Unknown Source)

  at com.zebra.sdk.comm.ConnectionBuilder.build(Unknown Source)

  at dalvik.system.NativeStart.run(Native Method)

}

===============================================================================

Exit:

10-10 11:03:05.316 D/BasicPrintApp(18505): Zebra.Sdk.Comm.ConnectionException: Could not open connection string "AC:3F:A4:1F:2A:F5"

10-10 11:03:05.316 D/BasicPrintApp(18505):   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3511/f4db8a57/source/mono/mcs/class/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143

10-10 11:03:05.316 D/BasicPrintApp(18505):   at Java.Interop.JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00082] in /Users/builder/data/lanes/3511/0e59c362/source/Java.Interop/src/Java.Interop/Java.Interop/JniEnvironment.g.cs:12649

10-10 11:03:05.316 D/BasicPrintApp(18505):   at Android.Runtime.JNIEnv.CallStaticObjectMethod (System.IntPtr jclass, System.IntPtr jmethod, Android.Runtime.JValue* parms) [0x00000] in /Users/builder/data/lanes/3511/0e59c362/source/monodroid/src/Mono.Android/JNIEnv.g.cs:562

10-10 11:03:05.316 D/BasicPrintApp(18505):   at Zebra.Sdk.Comm.ConnectionBuilder.Build (System.String p0) [0x00049] in C:\repos\xamarin-sdk\Binding Libraries\ZSDK_ANDROIDX\ZSDK_ANDROIDX\obj\Release\generated\src\Zebra.Sdk.Comm.ConnectionBuilder.cs:54

10-10 11:03:05.316 D/BasicPrintApp(18505):   at LinkOS.Plugin.ConnectionBuilderImplementation.Build (System.String connectionString) [0x00000] in C:\repos\xamarin-sdk\Link_OS_SDK_for_Xamarin_Portable\LinkOS\LinkOS.Plugin.Android\ConnectionBuilderImplementation.cs:19

10-10 11:03:05.316 D/BasicPrintApp(18505):   at AppTestBluetooth5.MainActivity.Print (System.String address) [0x00026] in D:\TestAppli\AppTestBluetooth5\AppTestBluetooth5\MainActivity.cs:59

10-10 11:03:05.316 D/BasicPrintApp(18505):   --- End of managed Zebra.Sdk.Comm.ConnectionException stack trace ---

10-10 11:03:05.316 D/BasicPrintApp(18505): com.zebra.sdk.comm.ConnectionException: Could not open connection string "AC:3F:A4:1F:2A:F5"

10-10 11:03:05.316 D/BasicPrintApp(18505): at com.zebra.sdk.comm.internal.ConnectionBuilderInternal.build(Unknown Source)

10-10 11:03:05.316 D/BasicPrintApp(18505): at com.zebra.sdk.comm.ConnectionBuilder.build(Unknown Source)

10-10 11:03:05.316 D/BasicPrintApp(18505): at dalvik.system.NativeStart.run(Native Method)

Thread started: <Thread Pool> #7

Thread started: <Thread Pool> #8

10-10 11:03:05.371 D/Mono    (18505): [0x63ad00] worker starting

Thread finished: <Thread Pool> #3

10-10 11:03:36.160 D/Mono    (18505): [0x6284e8] worker finishing

Le thread 'Unknown' (0x3) s'est arrêté avec le code 0 (0x0).


Hi Amine,

I hate to ask the basic questions, but have you made sure Bluetooth is turned on on the Android device as well as the printer?  Are you sure the printer you have does have Bluetooth? Not all do.  Also verify the MAC address is for Bluetooth and not Wi-Fi. 

Robin


Hi Robin,

Great news about the Xamarin component. Unfortunately I'm not able to get your example to work. I can establish a Bluetooth connection to my QLn420, and the call to SetPrintLanguage confirms it is a ZPL printer, but the call to CheckPrinterStatus throws an exception on the line:

IPrinterStatus status = printer.CurrentStatus;

I get the following exception:

Malformed status response - unable to determine printer status

The documentation for the CurrentStatus property is a little confusing too:

/// <summary>

/// Get a new instance of PrinterStatus that can be used to determine the status of a printer.

/// On Zebralink Mobile Printers, this function only works if the printer is not currently printing or processing other data, otherwise returns a MalformedStatusResponse exception.

/// Link-OS and non-Mobile printers can be checked for status while prinintg.

/// </summary>

IPrinterStatus CurrentStatus { get; }

I don't really know the difference between a Zebralink Mobile Printer, a Link-OS printer and a non-Mobile printer... As far as I am aware the QLn420 is a Link-OS printer, correct? So this method should work??


Hi Christophe,

It looks like it can't find a printer at that MAC address.  Have you verified the Bluetooth MAC address of the printer?  In your first example you have one address and second example have another address.  I'm assuming you tried the first example with the same address/printer as your second sample.  Did you get the same exception?


Hello Robin,

great to have a reply so fast

yes in the first example it's was a mistake because this name LUXXH134893625 is the name of the printer found when i activitate the bluethbooth..

The mac address is AC3FA413BCBD => i've try also with AC:3F:A4:13:BC:BD but nothing work with this method ConnectionBuilder.Current.Build(address);

Same thing when i use ConnectionBuilder.Current.Build("BT:" + address);

Now, on the same printer same mac address of course if i use BluetoothConnectionInsecure(address)

that's works ...

Ok i think we use BluetoothConnectionInsecure for our dev ...

but if you have another idea or something i must to check ...

i use :

- vs 2015 professionnal

- nuguet package installed LinkOS_Xamarin_SDK

- sdk zebra installed

Just last question, is it better to use cpcl or zpl command ?

I repeat sorry i'm a beginner and my poor english can't help me, but i've notice i've send zpl i obtain some strange print ...

but if i send some cpcl all works ...

Thanks and have an happy coding day without problem


hi any reply on this?

here's my code:

private void PrintByZebraPrinter()
        {
            IConnection connection = null;
            Acr.UserDialogs.UserDialogs.Instance.ShowLoading("Connecting to printer...");

            Task task = new Task(new Action(() =>
            {
                try
                {
                    // BlueTooth
                    // Android - address is the printer's BT MAC address.
                    // iOS - address is the printer's serial number.
                    connection = ConnectionBuilder.Current.Build(String.Format("BT:{0}", Config.PrinterAddress));
                    connection.Open();

                    IPrinterStatus status;
                    if (!ZebraHelper.PreCheckPrinterStatus(connection, out status))
                    {
                        Device.BeginInvokeOnMainThread(() =>
                        {
                            DisplayAlert("", "Unable to print. Printer is " + status.Status, "OK");
                        });

                        return;
                    }

                    foreach (var cmd in downloadCommand)
                    {
                        connection.Write(Encoding.UTF8.GetBytes(cmd));
                    }
                    connection.Write(Encoding.UTF8.GetBytes(ConstructZPL()));

                    if (!ZebraHelper.PostPrintCheckStatus(connection, out status))
                    {
                        Device.BeginInvokeOnMainThread(() =>
                        {
                            DisplayAlert("", "Error durring print. Printer is " + status.Status, "OK");
                        });

                        return;
                    }
                }
                catch (Exception ex)
                {
                    string message = ex.Message;
                    message = string.Format("Please make sure printer and your phone's bluetooth are turned on.");
                    Device.BeginInvokeOnMainThread(() =>
                    {
                        DisplayAlert("Could not connect to printer", message, "OK");
                    });
                }
                finally
                {
                    Acr.UserDialogs.UserDialogs.Instance.HideLoading();
                    if (connection != null)
                    {
                        if (connection.IsConnected)
                            connection.Close();
                    }

                    DependencyService.Get<IInfoService>().DisconnectBluetoothDevice();
                }
            }));
            task.Start();
        }


Hi Pat,

The QLn420 is a Link-OS printer, so I'm not sure why this would be happening.  The only thing I can think of right now is to try modifying the timeouts.  It may not be getting the full status due to slow Bluetooth communication, so it's saying the status is malformed.  The timeouts to adjust are the MaxTimeoutForRead and TimeToWaitForMoreData. What device are you using for your app? 


Hi,

I'm getting the following error Screen Shot 2016-12-09 at 3.35.19 PM.png

and

Screen Shot 2016-12-09 at 3.28.26 PM.png

Thanks


Hi Robin,

Code is working now but it takes about 5 mins to come out of this method and print

connection = ConnectionBuilder.Current.Build("XXQLJ144902320");

5mins for the above above line.


connection.Open();

Above code is inside a function and called as

new Task(() =>
            {

                Print();
    }).Start();

Thanks


Hi Sandeep,

You have to make sure to import the nuget package on the top 'Solution' as opposed to the projects. 

Once this is open and you have the SDK selected, make sure all the projects are selected and installed on.


Hi Robin,

The following code is taking 5 mins to execute

connection =ConnectionBuilder.Current.Build("XXQLJ144902320");

5mins for the above above line.


connection.Open();

Above code is inside a function and called as

new Task(() =>
            {

                Print();
    }).Start();

Thanks


Hi Robin

I am new to Zebra printer control.

My final goal is encoding RFID tag via Zebra printer using android phone.

It would be nice to use Xamarin since other features of this existing app is already in Xamarin.  ( I believe ZPL already support RFID encoding via android phone.. please correct me if I am wrong.)

And I believe communicating via Bluetooth is already supported in Xamarin at this point, please correct me if I am wrong.

Thanks!


Hi Jun, You can encode RFID with Xamarin and/or Android.  Just add your tag encoding commands to the ZPL being sent.  Bluetooth communication is also supported.


Hi Robin,

I have a problem with LinkOS V1.1.75.

I am creating a Xamarin forms (v2.3.3.180) app for a TC51 using VS2015. I am using a network conected ZD420.

I have added the LinkOS SDK to both my portable and droid projects (that is currently all the projects in this solution).

When I try to build the droid project, I get the following error:

Error        java.lang.OutOfMemoryError. Consider increasing the value of $(JavaMaximumHeapSize). Java ran out of memory while executing 'java.exe -Xmx1G -jar "C:\Users\Pete%20Thomson\AppData\Local\Xamarin\MonoForAndroid\AndroidSDK\build-tools\23.0.2\\lib\dx.jar" --no-strict --dex --multi-dex --main-dex-list=obj\Debug\multidex.keep --output=obj\Debug\android\bin obj\Debug\android\bin\classes "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v7.0\mono.android.jar" "C:\Program Files (x86)\MSBuild\Xamarin\Android\android-support-multidex.jar"

I have enabled Multi-dex and the Java maximum heap size is 1G.

This project compiles and runs fine with LinkOS version 1.0.59.

Can you give me any suggestions how to deal with this? If you need the full debug output, can I e-mail it to you as it's quite big to post here?

Thanks,

Pete


Hi Peter, I haven't seen this past updating the Java maximum heap size to 1G.  It's really low by default.  It is an Android issue, so shouldn't matter if you are using Forms or not.  Doing a quick search, it looks like you can also edit the manifest: android:largeHeap="true"  c# - Getting OutOfMemoryException in Xamarin - Stack Overflow


Thanks Peter & Robin,

I think android:largeHeap="true" only has an effect when running the application, not on the build. However, I have already tried adding it to the manifest, which made no difference.

Any other suggestions greatly appreciated.

Thanks,

Pete


Hi Robin

    We have problems with release compilation of Xamarin_LinkOS_Developer_Demo:

2>C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1473,5): error MSB4018: The "LinkAssemblies" task failed unexpectedly.

2>C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1473,5): error MSB4018: Xamarin.Android.XamarinAndroidException: error XA2006: Reference to metadata item '!!0[] System.Array::Empty()' (defined in 'ZSDK_ANDROIDX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null') from 'ZSDK_ANDROIDX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' could not be resolved. ---> Mono.Cecil.ResolutionException: Failed to resolve !!0[] System.Array::Empty()

2>C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(1473,5): error MSB4018:    at Mono.Linker.Steps.MarkStep.MarkMethod(MethodReference reference)

.....

    We use VS.NET 2015 Prof.

Can you help us please ?

Angelo Bombardieri


Hi Pete

    Use Java maximum heap size to 2G with android:largeHeap="true".

Angelo Bombardieri


I also found this error in the Xamarin demo solution. I copied the implementation to my project and it worked - unfortunately not using Xamarin.Forms if that helps narrow things down.

Peter Douglas


Hi Angelo,

I believe that a heap size over 1G is ignored, but I'm not 100% certain, so I had already tried 2G anyway.

I concluded that as the Link OS SDK contains so much functionallity, it is very bloated and was overkill for my application, so I created my own functions to talk to the printer using TcpClient and used that instead.

Cheers,

Pete


Hi Robin!

I am replicating this code in Xamarin with VS 2015 .... create a portable project of shared code (PCL) ... and when starting my project this throws me the following error:
Error Invalid resource directory name: "res main.xml". Print.Android C: \ Users \ crisa \ Desktop \ Omni \ AHSE Systems \ Xamarin Programming \ Print \ Print \ Print.Android \ aapt.exe

Can you help me with this error?


Hi,

I am getting the following errors when I try to use this code.

http://i.imgur.com/5vBboWC.png (Link is to the screenshot, I cannot seem to add images to this post?)

I have added the code to the PCL of a new Xamarin project.

Also, when it tries to get the connection with the serial number I get this error. Bluetooth is enabled in the manifest and the printer is paired with the phone. - http://i.imgur.com/Z2gIkdq.png


Robin,

I am a Zebra SE trying to make a simple printing sample in Xamarin for Android only, TC51.  Assuming this sample works on a Xamarin.android project as well, how do I get the bluetooth MAC address of the terminal in code.  I will be connecting the printer via the android bluetooth manager outside the application.


Hi Kevin,

Many of our printers have the Bluetooth MAC as a barcode on the back of the printer.  Many also have an NFC chip with the MAC address encoded in it as well.  We have some sample code showing how to scan and pair or tap and pair here.  You can pair with a printer using the Android Bluetooth Manager, but you have to connect to the printer via your sample app, so the above code is still valid.  Hope that answers your question.  EDIT: The EMDK for Xamarin also has some scan and pair/Tap and Pair API's.


is there a myBTconnection.getconnectedMAC  or some other command,  Although they will primarily be using TC51, this needs to work on some non-zebra terminals also so was hoping some call existed to retrieve the MAC that did not involve scanning or NFC

Thanks for the really fast response


Hi Kevin, I'm afraid not.  If you are doing discovery, you can check the mac address with the method IDiscoveredPrinter.Address, then get the connection with IDiscoveredPrinter.Connection


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.  windows - What is the function of aapt.exe in android? - Stack Overflow 


Hi Colm, I realize you might have figured this out already, but the RunOnUIThread is an API off of the Android.App library.  The if the Encoding.ASCII is not available, and I've run into some versions and runtimes of Xamarin where it wasn't, use UTF8 as the encoding instead. 

It's hard to know what the issue is with the Bluetooth connection without knowing more about the situation.  It could be something as small as the printer being off or out of range, to any number of different issues.

Also, You should be able to use this library on the PCL level rather than just the Android and iOS levels if you wanted to save yourself the coding in both areas.


Hi Robin, with mobile zebra printer and Zebra API i can manage printing in Xamarin.Forms PCL project (on visual studio 2017)? My device for my app is an Ipad, but the technology chosen was xamarin.forms to be able to manage non-IOS devices in the future.


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.


We need to add the following to the Info.plist for iOS in Xamarin

<key>UIBackgroundModes</key>

<array>

    <string>external-accessory</string>

</array>

<key>UISupportedExternalAccessoryProtocols</key>

<array>

    <string>com.zebra.rawport</string>

</array>


Not sure if you have already paired the Bluetooth between your phone with the printer. We need to manually pair them through the phone's settings for iPhone.


Hi Robin,

I was able to run your sample for Xamarin forms but only for Android. When I'm using that same code in iOS, I get an error saying :
"Counld not connect to device on address AC:3F:A4:CC:62:87 ... at LinkOS.Plugin.ConnectionImplementation.Open() .."

Does iOS need something special in the plist or in the developer account ... ? Any suggestions ?

Yes, I paired the device before and the connection is well established. I also used the Zebra Utility app for iOS and it prints.

Thank you in advance for your help.


Hi Steven, thanks for the quick reply. So I added :

<key>UIBackgroundModes</key>

<array>

<string>external-accessory</string>

</array>

<key>UISupportedExternalAccessoryProtocols</key>

<array>

<string>com.zebra.rawport</string>

</array>

But I still can't connect. Am I missing something else ? The zebra documentation is saying :

  • Link your project to the ExternalAccessory framework

Is that something Im suppose to do ? My project builds fine, I don't see why I would need that framework.


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

connectionStringThe format of the input string is: [prefix:] address [: port_number(s)]
Prefix is either TCP_MULTI, TCP, TCP_STATUS, BT_MULTI, BT, or BT_STATUS
The format of address depends on the prefix and OS:
   BT : Android - address is the printer's BT MAC address. iOS - address is the printer's serial number.
   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.
iOS Considerations:TCP_MULTI, BT_MULTI, and BT_STATUS are not availible. TCP IPv4 address only, DNS name not supported.

We have some progress!! It now connects, but I have an exception when trying to SetPrintLanguage. The exception is "ConnectionException : Error writing to the connection".

My method SetPrintLanguage() is the same as suggested in this page. Thanks again for replying so quick.


Got it, I need BT: in front of the serial number. Its working fine now. Thanks a lot Steven. Hopefully this will helps others, since there is not a lot of info for iOS on the web.


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, Try adding Multidex


Thank you for your quick response, I did see that online as a possible solution but then I got this error:

1>CREATEMULTIDEXMAINDEXCLASSLIST : error : Can't read (Can't process class (Unsupported class version number (maximum 51.0, Java 1.7)))

al