Sending data to thermal printer from Android device via usb
Asked Answered
T

4

7

I am working with sending data to a thermal printer from my application. I already have it working correctly over the network and my data prints correctly. There is now an additional requirement whereby we also have to be able to print via usb.

Here is what I've tried:

    private UsbManager mUsbManager;
    private UsbDevice mDevice;
    private UsbDeviceConnection mConnection;
    private UsbInterface mInterface;
    private UsbEndpoint mEndPoint;
    private PendingIntent mPermissionIntent;
    private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
    private static Boolean forceCLaim = true;

    HashMap<String, UsbDevice> mDeviceList;
    Iterator<UsbDevice> mDeviceIterator;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        mDeviceList = mUsbManager.getDeviceList();    
        mDeviceIterator = mDeviceList.values().iterator();

        Button print = (Button)findViewById(R.id.print);

        Toast.makeText(this, "Device List Size: " + String.valueOf(mDeviceList.size()), Toast.LENGTH_SHORT).show();
        TextView textView = (TextView) findViewById(R.id.usbDevice);
        String usbDevice = "";
        //This is just testing what devices are connected
        while (mDeviceIterator.hasNext()) {
            UsbDevice usbDevice1 = mDeviceIterator.next();
            usbDevice += "\n" +
                    "DeviceID: " + usbDevice1.getDeviceId() + "\n" +
                    "DeviceName: " + usbDevice1.getDeviceName() + "\n" +
                    "DeviceClass: " + usbDevice1.getDeviceClass() + " - " + translateDeviceClass(usbDevice1.getDeviceClass()) + "\n" +
                    "DeviceSubClass: " + usbDevice1.getDeviceSubclass() + "\n" +
                    "VendorID: " + usbDevice1.getVendorId() + "\n" +
                    "ProductID: " + usbDevice1.getProductId() + "\n";

            int interfaceCount = usbDevice1.getInterfaceCount();
            Toast.makeText(this, "INTERFACE COUNT: " + String.valueOf(interfaceCount), Toast.LENGTH_SHORT).show();

            mDevice = usbDevice1;

            if (mDevice == null) {
                Toast.makeText(this, "mDevice is null", Toast.LENGTH_SHORT).show();
            }else{
                Toast.makeText(this, "mDevice is not null", Toast.LENGTH_SHORT).show();
            }
            textView.setText(usbDevice);
        }

        if (mDevice == null) {
            Toast.makeText(this, "mDevice is null", Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this, "mDevice is not null", Toast.LENGTH_SHORT).show();
        }

        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        registerReceiver(mUsbReceiver, filter);
        mUsbManager.requestPermission(mDevice, mPermissionIntent);

  print.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //setup();
                print(mConnection, mInterface);
            }
        });
}

   private String translateDeviceClass(int deviceClass){
        switch(deviceClass){
            case UsbConstants.USB_CLASS_APP_SPEC:
                return "Application specific USB class";
            case UsbConstants.USB_CLASS_AUDIO:
                return "USB class for audio devices";
            case UsbConstants.USB_CLASS_CDC_DATA:
                return "USB class for CDC devices (communications device class)";
            case UsbConstants.USB_CLASS_COMM:
                return "USB class for communication devices";
            case UsbConstants.USB_CLASS_CONTENT_SEC:
                return "USB class for content security devices";
            case UsbConstants.USB_CLASS_CSCID:
                return "USB class for content smart card devices";
            case UsbConstants.USB_CLASS_HID:
                return "USB class for human interface devices (for example, mice and keyboards)";
            case UsbConstants.USB_CLASS_HUB:
                return "USB class for USB hubs";
            case UsbConstants.USB_CLASS_MASS_STORAGE:
                return "USB class for mass storage devices";
            case UsbConstants.USB_CLASS_MISC:
                return "USB class for wireless miscellaneous devices";
            case UsbConstants.USB_CLASS_PER_INTERFACE:
                return "USB class indicating that the class is determined on a per-interface basis";
            case UsbConstants.USB_CLASS_PHYSICA:
                return "USB class for physical devices";
            case UsbConstants.USB_CLASS_PRINTER:
                return "USB class for printers";
            case UsbConstants.USB_CLASS_STILL_IMAGE:
                return "USB class for still image devices (digital cameras)";
            case UsbConstants.USB_CLASS_VENDOR_SPEC:
                return "Vendor specific USB class";
            case UsbConstants.USB_CLASS_VIDEO:
                return "USB class for video devices";
            case UsbConstants.USB_CLASS_WIRELESS_CONTROLLER:
                return "USB class for wireless controller devices";
            default: return "Unknown USB class!";
        }
//Broadcast receiver to obtain permission from user for connection
 private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if(device != null){
                            //call method to set up device communication
                            mInterface = device.getInterface(0);
                            mEndPoint = mInterface.getEndpoint(0);
                            mConnection = mUsbManager.openDevice(device);

                            //setup();
                        }
                    }
                    else {
                        //Log.d("SUB", "permission denied for device " + device);
                        Toast.makeText(context, "PERMISSION DENIED FOR THIS DEVICE", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }
    };

 private void print(UsbDeviceConnection connection, UsbInterface intrface){

        String test = "THIS IS A PRINT TEST";
        byte [] testBytes = test.getBytes();

        if(intrface==null){
            Toast.makeText(this, "INTERFACE IS NULL", Toast.LENGTH_SHORT).show();
        }
        if(connection==null){
            Toast.makeText(this, "CONNECTION IS NULL", Toast.LENGTH_SHORT).show();
        }

        if(forceCLaim==null){
            Toast.makeText(this, "FORCE CLAIM IS NULL", Toast.LENGTH_SHORT).show();
        }   

        connection.claimInterface(intrface, forceCLaim);
        connection.bulkTransfer(mEndPoint, testBytes, testBytes.length, 0);

    }

So the device connects to the usb device, but when I try the bulktransfer nothing happens, could anyone shed light on this? Usb connectivity is a new area for me so any tips are appreciated

EDIT

So it turns out there were issues with endpoints and no returns from the bulktransfer, however, now those issues are resolved and it returns that the bulk transfer is successful, however, it still doesn't print. Does anyone have any ideas on this please??

Threadgill answered 21/1, 2015 at 11:48 Comment(9)
problem is that you have to know printer's protocol ... sending just a text will not work ... get the printer's documentation and find out how to print ... for example (i made it up!) you have to send #move 10,10; #print "THIS IS A PRINT TEST" ... maybe your printer is using ZPLSystematism
wrong link ... should be ZPLSystematism
@Systematism When I print over the network I just open a socket and send the bytes down, there is no need for any extras in order to have it print. There are thermal printer commands for centring, cutting etc but there are no print commands. Would it be different for usb?Threadgill
Suffice to say it's probably a lot more complicated than just sending text. Try a software USB packet sniffer while printing a small text payload over USB from a desktop, and you may get an idea of what it is doing, though documentation would be more useful for implementation.Pernambuco
@ChrisStratton thank you for your help. I would've imagined that it would've been similar to printing over a network? Open the port and write the data to the stream?Threadgill
So it turns out that it wasn't any more complex than my initial thought, I have managed to get my test string printing from my Nexus 10. Happy days!!!Threadgill
@DJ-DOO, what were you missing?Grizzly
Try endpoint number 1. On my printer is endpoint 0 IN-direction. You need to use OUT direction endpoint.Guttle
@Threadgill -> you can answer your own question, that would help other people get straight to the answer instead reading all the comments hoping for a miracle :) Good job btw!Moffat
O
1

For someone who is looking to make the code in questions work.

Solution used by DJ-DOO is,

I changed this line :

byte [] testBytes = test.getBytes();

To:

testBytes = test.getBytes(Charset.forName("UTF-8"));

Link: https://www.dreamincode.net/forums/topic/368925-sending-data-to-thermal-printer-from-android-device-via-usb/

Oraorabel answered 2/10, 2021 at 9:58 Comment(0)
D
0
private void print(UsbDeviceConnection connection, UsbInterface intrface) {

     String test = "THIS IS A PRINT TEST";
     byte [] testBytes = test.getBytes();

     if(intrface == null) {
         Toast.makeText(this, "INTERFACE IS NULL", Toast.LENGTH_SHORT).show();
     }

     if(connection == null) {
         Toast.makeText(this, "CONNECTION IS NULL", Toast.LENGTH_SHORT).show();
     }

     if(forceCLaim == null) {
         Toast.makeText(this, "FORCE CLAIM IS NULL", Toast.LENGTH_SHORT).show();
     }   

     connection.claimInterface(intrface, forceCLaim);
     connection.bulkTransfer(mEndPoint, testBytes, testBytes.length, 0);
     //Just Add 
     connection.close();    
 }
Darb answered 26/3, 2015 at 23:49 Comment(0)
S
0

@DJ-DOO, i have tried the same approach, but i did it this way:

instead of String test = "THIS IS A PRINT TEST";

use this: String test = "THIS IS A PRINT TEST\r\n";

For more check: What is the difference between \r and \n?

and your last code line "connection.bulkTransfer(mEndPoint, testBytes, testBytes.length, 0);" should be in another thread.

For example:

Thread thread = new Thread(new Runnable() {
   @Override
   public void run() {
   connection.bulkTransfer(mEndPoint, testBytes, testBytes.length, 0);
   }
});
thread.run(); //or thread.start(); -as you wish

Bonus: for paper cutting use: byte[] cut_paper = {0x1D, 0x56, 0x41, 0x10}; Before this byte array i recommend to send a string with above mentioned \n. It is enough to put the same line with cut_paper byte array after the first one:

Thread thread = new Thread(new Runnable() {
   @Override
   public void run() {
      connection.bulkTransfer(mEndPoint, testBytes, testBytes.length, 0);
      connection.bulkTransfer(mEndPoint, cut_paper, cut_paper.length, 0);
   }
});
thread.run();

Also source for help: https://developer.android.com/guide/topics/connectivity/usb/host.html

Hope it helps :)

Setzer answered 27/9, 2015 at 20:25 Comment(1)
Thanks, the cut_paper arry worked for me on a Star printerHowlond
P
0

I changed function print() and it works.

This my code

private void print(final UsbDeviceConnection connection, final UsbInterface usbInterface) {
    final String test = ed_txt.getText().toString() + "\n\n";
    testBytes = test.getBytes();
    Log.e(TAG, "print Click........................ ");
    if (usbInterface == null) {
        Log.e(TAG, "INTERFACE IS NULL");
    } else if (connection == null) {
        Log.e(TAG, "CONNECTION IS NULL");
    } else if (forceCLaim == null) {
        Log.e(TAG, "FORCE CLAIM IS NULL");
    } else {
        Log.e(TAG, "Prepare print... ");
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Log.e(TAG, "Printing.. ");
                UsbInterface intf = mDevice.getInterface(0);
                UsbEndpoint endpoint = intf.getEndpoint(0);
                UsbDeviceConnection conn = mUsbManager.openDevice(mDevice);
                conn.claimInterface(intf, true);

                byte[] cut_paper = {0x1D, 0x56, 0x41, 0x10};
                conn.bulkTransfer(endpoint, testBytes, testBytes.length, 0);
                conn.bulkTransfer(endpoint, cut_paper, cut_paper.length, 0);
            }
        });
        thread.run();
    }
}
Psoas answered 6/5, 2020 at 8:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.