26

I have to develop an App for Android tablets that demands printing files to a Bluetooth printer. Printing over Bluetooth is one of the most important features of my app. Unfortunately, there's not a lot of information about this subject so I'd like to ask for advice.

As far as I know it's not possible to print over Bluetooth on Android (using native calls), as Android's BT Stack doesn't implement BPP (Basic Printing Profile). Doing a little research I've found the following alternatives:

SDKs/Libraries

  • Sybase-iAnywhere-Blue-SDK-for-Android : Commercial SDK that supports a lot of BT profiles. Developed by a large company (good support I guess). I have not found a lot of information about this one. Is there some documentation,API or examples on how to use this SDK? Does anybody know how to download the demo version? (link seems to be broken last time I tried)
  • iPrint SDK: Commercial SDK. Some examples on their website but nothing else.
  • Zebralink: Only for Zebra printers (naturally). Other manufacturers probably have APIs for their printers too.

Google Play Apps

  • PrinterShare: Commercial (Premium key)
  • Bluetooth Smart Printing: Free and lightweight. Claims to print to Bluetooth printers.

Ideally I wouldn't want to be tied to a specific brand or printer model. Now the questions:

  • What do you think it would be the best choice?
  • Do you know any other alternative that I've missed?
  • Can I easily print files from my App using an external App?
  • What format should I use for my files to be able to print them over Bluetooth? (pdf,images,etc.)
  • Any advices on printer manufacturer and models?
  • Have you had any real experience printing over Bluetooth on Android?
  • Is there any plans in the immediate future to implement Bluetooth printing on Android?

Thanks in advance for your help ;)

Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
Mikel
  • 321
  • 1
  • 3
  • 7
  • I can vouch for the **PrinterShare** app - https://play.google.com/store/apps/details?id=com.dynamixsoftware.printershare - it works on my devices for my HP Officejet 100 mobile printer. I couldn't find the **Bluetooth Smart Printing** app in Google Play, though. Do you have a link? – ban-geoengineering Mar 29 '17 at 20:14

6 Answers6

12

Star Micronics has an SDK for Android printing via Bluetooth (as well as ethernet and USB). You can download it here: http://www.starmicronics.com/support/SDKDocumentation.aspx.

As you mentioned, you can't print natively at this point in time so the alternate solutions you found are your options today.

In my experience, it's best to use an API and not an external application. The biggest reason is you get total control over printer behavior. It's easy too if the API is built intelligently. Using an external app is limiting because you can't customize your print outs the way you want to.

The Star SDK I linked you to has a really nice sample app that lets you test and customize a lot of printer functions to see them in action. Each function is documented in the source code. The commands and their parameters are also available in the app itself as a quick on screen reference which is convenient. On top of all that, it's well documented.

Star's a great company to work with because you can get a free demo printer of your choice to use for your development.

If you choose this way, you can send plain text to the printer along with commands. The API handles converting the data into what the printer can understand.

LtH
  • 692
  • 7
  • 18
1

The possibility of printing to BlueTooth printer depends highly on the model of printer you are trying to use.

For instance, I use CITIZEN CMP-10BT printer which can be controled by sending specific sequences of bytes which can easily be done using Android API. I even built a framework on top of that.

The problem lies only in the fact you can not tell for sure which printer models will be used by end-users so some ultimate SDK will definitely be of great need.

Nikhil
  • 16,194
  • 20
  • 64
  • 81
Alex Semeniuk
  • 1,865
  • 19
  • 28
  • Thanks for your answer, Alex. Out of curiosity, is the "framework" you mention open source. And, if so, where might one find it? Thanks. – Joshua Pinter Jul 10 '14 at 21:42
  • @ Josh Pinter: Unfortunately, no. It is a part of commercial project so there is no place it can be "found". If you are still interested, you can write me an email (see address in profile) and I may provide some of the code parts necessary for printing. – Alex Semeniuk Jul 17 '14 at 10:09
  • Thanks, Alex. Couldn't find your email address but I think I've got what I'm looking for, for now. I appreciate your offer to help, though. – Joshua Pinter Jul 17 '14 at 16:14
  • @AlexSemeniuk can you help me? I want to print using CITIZEN CMP-10BT but I can't do it without a SDK or some code to guide me. I'm trying to connect over BluetoothSocket, but it's returning always `read failed.`. Can you help me? I'm sending an email for you requesting it. – Felipe Bonezi Feb 16 '17 at 17:55
1

You can download this component: https://components.xamarin.com/view/ocpp-thermal-printer-usb it Works like a charm in most usb and bluetooth generic printers. I créate a class to send most usual esc commands. Usage: outerInstance.mService.Write(modes.pordefecto());

public class modes
{
    public static byte[] condensado()
    {
        byte[] cmd = new byte[3];
        cmd[0] = 0x1b;
        cmd[1] = 0x21;
        cmd[2] |= 0x01;

        return cmd;
    }

    public static byte[] pordefecto()
    {
        byte[] cmd = new byte[3];
        cmd[0] = 0x1b;
        cmd[1] = 0x21;
        cmd[2] |= 0x00;
        return cmd;
    }

    public static byte[] negrita()
    {
        byte[] cmd = new byte[3];
        cmd[0] = 0x1b;
        cmd[1] = 0x21;
        cmd[2] |= 0x08;
        return cmd;
    }

    public static byte[] lineamenor()
    {
        byte[] cmd = new byte[3];
        cmd[0] = 0x1b;
        cmd[1] = 0x33;
        cmd[2] |= 0x14;
        return cmd;
    }

    public static byte[] cancelalinea()
    {
        byte[] cmd = new byte[2];
        cmd[0] = 0x1b;
        cmd[1] = 0x32;
        return cmd;
    }

    public static byte[] centra()
    {
        byte[] cmd = new byte[3];
        cmd[0] = 0x1b;
        cmd[1] = 0x61;
        cmd[2] |= 0x01;
        return cmd;
    }

    public static byte[] quitacentro()
    {
        byte[] cmd = new byte[3];
        cmd[0] = 0x1b;
        cmd[1] = 0x61;
        cmd[2] |= 0x00;
        return cmd;
    }

    public static byte[] codepage()
    {
        byte[] cmd = new byte[5];
        cmd[0] = 0x1f;
        cmd[1] = 0x1b;
        cmd[2] = 0x1f;
        cmd[3] |= 0xfe;
        cmd[4] |= 0x01;
        return cmd;
    }

    public static byte[] latino()
    {
        byte[] cmd = new byte[5];
        cmd[0] = 0x1f;
        cmd[1] = 0x1b;
        cmd[2] = 0x1f;
        cmd[3] |= 0xff;
        cmd[4] |= 0x12;
        return cmd;
    }
    public static byte[] logo()
    {
        byte[] cmd = new byte[4];
        cmd[0] = 0x1c;
        cmd[1] = 0x70;
        cmd[2] = 0x01;
        cmd[3] |= 0x00;

        return cmd;
    }
}
0

Use Printooth library for any kind of printers, With zero configurations, simple usage and well documentation

https://github.com/mazenrashed/Printooth

Here is a sample code to print a simple line :

var printables = ArrayList<Printable>()
var printable = Printable.PrintableBuilder()  
    .setImage(image) 
    .setNewLinesAfter(1) // To provide n lines after sentence
    .build()
printables.add(printable)
BluetoothPrinter.printer().print(printables)

You can continue reading here : https://github.com/mazenrashed/Printooth/blob/master/README.md

Mazen Rashed
  • 139
  • 1
  • 3
0

Any printer which uses ZPL can print simply by writing the instructions to the printer via the bluetooth interface (tested and works)

My problem is I'm not sure how to detect whether or not a BT device is a printer

write(zplString, btSocket)

fun write(bytes: String, socket: BluetoothSocket) {
        val mmOutStream = socket.outputStream
        /* Send data to BT device */
        try {
            mmOutStream?.write(bytes.toByteArray(Charset.forName("UTF-8")))
        } catch (e : Exception){
            Log.v("BT", "Unable to send message")
            if (socket.isConnected){
              socket.close()
            }
            attemptConnection()
            try {
                for (mSocket in sockets) {
                    val fbOutStream = mSocket.outputStream
                    fbOutStream?.write(bytes.toByteArray(Charset.forName("UTF-8")))
                }
            } catch (e : Exception){
                /* Fallback write failed */
                Log.v("BT", "Unable to send message second attempt")
            }
        }
    }

private fun attemptConnection(){
   for (socket in sockets){
       try{
           if (socket.isConnected){
              socket.close()
           }
        } catch (e: Exception){
         /* Do nothing, we just want to try to close it */
        }
     }
     sockets.clear()
     for (device in btConnectList) {
        var tempSocket: BluetoothSocket? = null
            try {
                tempSocket = device.createInsecureRfcommSocketToServiceRecord(myUUID)
            } catch (e: Exception) {
                Log.v("BT", "Could not connect to socket")
            }
            if (tempSocket != null) {
                try {
                    tempSocket.connect()
                } catch (e: IOException) {
                    Log.v("BT", "Connection falied attempting fallback")
                    try {
                        val clazz = tempSocket.remoteDevice.javaClass
                        val paramTypes = arrayOf<Class<*>>(Int::class.java)
                        val m = clazz.getMethod("createRfcommSocket", *paramTypes)
                        val fallbackSocket =
                            m.invoke(tempSocket.remoteDevice, 2) as BluetoothSocket
                        fallbackSocket.connect()
                    } catch (e: Exception) {
                        Log.v("BT", "Fallback failed")
                    }
                }
                sockets.add(tempSocket)
            } else {
                /* Try fallback */
                try {
                    tempSocket = device.bluetoothClass.javaClass.getMethod(
                        "createRfcommSocket", Int::class.java
                    ).invoke(device, 1) as BluetoothSocket
                    tempSocket.connect()
                    sockets.add(tempSocket)
                } catch (e: Exception) {
                    Log.v("BT", "Fallback failed")
                }
            }
        }
    }
Rowan Berry
  • 171
  • 7
0

from android 4.4 you can print with Android framework Library like mentioned here: https://developer.android.com/training/printing

for example, to print an image you would do something like this:

private fun doPhotoPrint() {
    activity?.also { context ->
        PrintHelper(context).apply {
            scaleMode = PrintHelper.SCALE_MODE_FIT
        }.also { printHelper ->
            val bitmap = BitmapFactory.decodeResource(resources, R.drawable.droids)
            printHelper.printBitmap("droids.jpg - test print", bitmap)
        }
    }
}
Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38