Recently, I was asked
to make a program for printing some data to a small or handheld Bluetooth
printer device. This can be used for printing receipts, simple tickets, or
customer notes. I like how it works because usually, we are getting our
program output on a computer screen, but this time we are getting our
output on a tangible paper!
I tried everything
for printing but my thermal printer was printing only blank paper. At the end I
got the issue that is my printer paper is set from the wrong side. Yes that
also may be one issue in your case because I went through it . so cheque your
paper side if you are getting blank output page.
Now I am going to
explain how I connect to
the Bluetooth printer, then make socket connection and then output
the string that you put into the edittext.
MainActivity.java - contains button listeners and functions for
bluetooth connection, sending data, etc.
package mmsl.BluetoothFilePrinter;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import mmsl.GetPrintableImage.GetPrintableImage;
import android.app.Activity;
import android.bluetooth.BluetoothSocket;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Toast;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
EditText mNameEditText;
EditText mAmountEditText;
Button mPrintButton;
byte FontStyleVal;
private static BluetoothSocket mbtSocket;
private static OutputStream mbtOutputStream;
private boolean PrintImage = false;
int mPrintType = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mNameEditText = (EditText) findViewById(R.id.nameEditText);
mAmountEditText = (EditText) findViewById(R.id.amountEditText);
mPrintButton = (Button) findViewById(R.id.printButton);
mPrintButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mPrintType = 0;
StartBluetoothConnection();
}
});
}
private int[] Readcsv() {
try {
InputStream in = getAssets().open("logo.txt");// openFileInput();
BufferedReader reader = new BufferedReader(
new InputStreamReader(in));
int[] mona = new int[14926];
int cnt = 0;
try {
String line;
while ((line = reader.readLine()) != null) {
String[] RowData = line.split(",");
for (int i = 0; i < RowData.length; i++) {
mona[cnt] = Integer.parseInt(
RowData[i].replace("0x", "").replace(" ", ""),
16);
cnt++;
}
// do something with "data" and "value"
}
} catch (Exception ex) {
ex.printStackTrace();
// handle exception
} finally {
try {
in.close();
} catch (IOException e) {
// handle exception
}
}
return mona;
} catch (Exception e) {
return null;
}
}
protected void StartBluetoothConnection() {
if (mbtSocket == null) {
Intent BTIntent = new Intent(getApplicationContext(),
BTWrapperActivity.class);
this.startActivityForResult(BTIntent,
BTWrapperActivity.REQUEST_CONNECT_BT);
} else {
// mbtSocket.connect();
OutputStream tmpOut = null;
try {
tmpOut = mbtSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
mbtOutputStream = tmpOut;
senddatatodevice();
}
}
private void senddatatodevice() {
try {
mbtOutputStream = mbtSocket.getOutputStream();
switch (mPrintType) {
case 0:
byte[] Command = { 0x1B, 0x21, FontStyleVal };
mbtOutputStream.write(Command);
String sendingmessage = "Name : "
+ mNameEditText.getText().toString();
byte[] send = sendingmessage.getBytes();
mbtOutputStream.write(send);
mbtOutputStream.write(0x0D);
sendingmessage = "Amount : "
+ mAmountEditText.getText().toString();
send = sendingmessage.getBytes();
mbtOutputStream.write(send);
mbtOutputStream.write(0x0D);
mbtOutputStream.write(0x0D);
mbtOutputStream.write(0x0D);
mbtOutputStream.write(0x0D);
mbtOutputStream.flush();
break;
default:
break;
}
// outstream.write(0);
// mbtOutputStream.close();
// mbtOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
try {
if (mbtSocket != null) {
mbtOutputStream.close();
mbtSocket.close();
mbtSocket = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case BTWrapperActivity.REQUEST_CONNECT_BT:
try {
mbtSocket = BTWrapperActivity.getSocket();
if (mbtSocket != null) {
if (PrintImage == false) {
Thread.sleep(100);
senddatatodevice();
}
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
BTWrapperActivity:- check the Bluetooth connection and list all the
available Bluetooth devices in the rage of you phone. Select the name of the Bluetooth
printer and it automatically create one socket connection with that device and
send the data byte by byte.
package com.trust.trust_bank;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.UUID;
import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
// =============== Basically is a state machine, and the communications will happen in a separate thread so as not to obstruct the main UI
public class BTWrapperActivity extends ListActivity{
static public final int REQUEST_CONNECT_BT = 0x2300;
static private final int REQUEST_ENABLE_BT = 0x1000;
static private BluetoothAdapter mBluetoothAdapter = null;
static private ArrayAdapter<String> mArrayAdapter = null;
//static private Set<BluetoothDevice> btDevices = null;
static private ArrayAdapter<BluetoothDevice> btDevices = null;//BluetoothDevice[] btDevices = null;
private BluetoothDevice btDevices1=null;
// Unique UUID for this application, Basically the SPP Profile
private static final UUID SPP_UUID =
// UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
static private BluetoothSocket mbtSocket = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Change the title of the activity
setTitle("Bluetooth Devices");
// Get the List of paired and available devices
try {
if(initDevicesList() != 0) {
this.finish();
return;
}
} catch(Exception ex) {
this.finish();
return;
}
// Register the Broadcast receiver for handling new BT device discovery
IntentFilter btIntentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mBTReceiver, btIntentFilter);
}
public static BluetoothSocket getSocket() {
return mbtSocket;
}
private void flushData() {
try {
if(mbtSocket != null) {
mbtSocket.close();
mbtSocket = null;
}
if(mBluetoothAdapter != null) {
mBluetoothAdapter.cancelDiscovery();
}
if(btDevices != null) {
btDevices.clear();
btDevices = null;
}
if(mArrayAdapter != null) {
mArrayAdapter.clear();
mArrayAdapter.notifyDataSetChanged();
mArrayAdapter.notifyDataSetInvalidated();
mArrayAdapter = null;
}
finalize();
} catch(Exception ex){}
catch (Throwable e) {}
}
// Do not forget to add the permission for Bluetooth to use this method
// Also this method is very tightly coupled with the above method, for getting the status of bt connection
private int initDevicesList() {
// Flush any Pending Data
flushData();
// Get the Bluetooth Adaptor of the device
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter == null) {
// Weird Condition ==== Implies that the device does not have a bluetooth module ?????
Toast.makeText(getApplicationContext(), "Bluetooth not supported!!", Toast.LENGTH_LONG).show();
return -1;
}
if(mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
mArrayAdapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1);
mArrayAdapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line);
setListAdapter(mArrayAdapter);
// get the list of devices already paired
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
try {
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
} catch(Exception ex){
//ex.getStackTrace();
return -2;
}
Toast.makeText(getApplicationContext(), "Getting all available Bluetooth Devices", Toast.LENGTH_SHORT).show();
return 0;
} // End getDeviceList
@Override
protected void onActivityResult(int reqCode, int resultCode, Intent intent) {
super.onActivityResult(reqCode, resultCode, intent);
switch(reqCode) {
case REQUEST_ENABLE_BT:
if(resultCode == RESULT_OK) {
// Start getting the paired devices list
Set<BluetoothDevice> btDeviceList = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
try {
if (btDeviceList.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : btDeviceList) {
if(btDeviceList.contains(device) == false) {
btDevices.add(device); // Add the device to the device list
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress() /*+ "\n" + "Status : Paired"*/);
//mArrayAdapter.notifyDataSetChanged();
mArrayAdapter.notifyDataSetInvalidated();
}
}
}
} catch(Exception ex){}
}
break;
}
// Also register for new devices which are discovered
mBluetoothAdapter.startDiscovery();
} // End onActivityResult
private final BroadcastReceiver mBTReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
try{
// No paired device found
if(btDevices == null )
{
btDevices = new ArrayAdapter<BluetoothDevice>(getApplicationContext(), android.R.id.text1);
}
// Ensure non repetability
if( btDevices.getPosition(device) < 0 ) {
btDevices.add(device);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress() +"\n" /*+ "Status : Unpaired"*/);
//mArrayAdapter.notifyDataSetChanged();
mArrayAdapter.notifyDataSetInvalidated();
}
} catch(Exception ex)
{
//ex.fillInStackTrace();
}
}
}
};
@Override
protected void onListItemClick(ListView l, View v, final int position, long id) {
super.onListItemClick(l, v, position, id);
// Dont proceed if the bluetooth adapter is not valid
if(mBluetoothAdapter == null) {
return;
}
// Cancel the dicovery if still going on
if(mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// Try to connect with the selected device,
Toast.makeText(getApplicationContext(), "Connecting to " + btDevices.getItem(position).getName() + "," + btDevices.getItem(position).getAddress(), Toast.LENGTH_SHORT).show();
// made the thread different as the connecting proceedure might break down the system
Thread connectThread = new Thread(new Runnable() {
@Override
public void run() {
try {
try {
Method m = btDevices.getItem(position).getClass().getMethod("createInsecureRfcommSocket",
new Class[] {int.class});
try {
//================================================================
String address=btDevices.getItem(position).toString();
mBluetoothAdapter.getRemoteDevice(address);
btDevices1=mBluetoothAdapter.getRemoteDevice(address);
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
mbtSocket = btDevices1.createRfcommSocketToServiceRecord(uuid);
mbtSocket.connect();
//=================================================================
//mbtSocket = (BluetoothSocket) m.invoke(btDevices.getItem(position), 1);
//m.invoke(receiver, args)
} catch (IllegalArgumentException e) {
e.printStackTrace();
} /*catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} */
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// mbtSocket = btDevices.getItem(position).createRfcommSocketToServiceRecord(SPP_UUID);
// mbtSocket.connect();
} catch(IOException ex) {
//Toast.makeText(getApplicationContext(), "Unable to connect to " + btDevices.getItem(position).getName(), Toast.LENGTH_LONG).show();
runOnUiThread(socketErrorRunnable);
//Handler myHandler = new Handler();
//myHandler.post(socketErrorRunnable);
try {
mbtSocket.close();
} catch (IOException e) {
//e.printStackTrace();
}
mbtSocket = null;
return;
} finally {
runOnUiThread(new Runnable() {
@Override
public void run() {
//flushData();
unregisterReceiver(mBTReceiver);
finish();
}
});
}
}
});
connectThread.start();
}
private Runnable socketErrorRunnable = new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "Cannot establish connection", Toast.LENGTH_SHORT).show();
mBluetoothAdapter.startDiscovery();
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// Add the menu options
menu.add(0, Menu.FIRST, Menu.NONE, "Refresh Scanning");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()) {
case Menu.FIRST:
initDevicesList();
break;
}
return true;
}
} // End of class definition
Main.xml:- contains the layout of the app.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TableRow
android:id="@+id/TableRow01"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/nameTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enter Name : " >
</TextView>
<EditText
android:id="@+id/nameEditText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:text="" >
</EditText>
</TableRow>
<TableRow
android:id="@+id/TableRow02"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/amountTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Enter Amount : " >
</TextView>
<EditText
android:id="@+id/amountEditText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:numeric="decimal"
android:singleLine="true"
android:text="" >
</EditText>
</TableRow>
<Button
android:id="@+id/printButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Print Form" >
</Button>
</LinearLayout>
</ScrollView>
Note :-Most
importantally you have to take the permission of Bluetooth access. Without taking permission you cannot access Bluetooth
of your phone. And app will crash automatically.
Add below code into
the manifest.xml:-
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
Hope this code will help someone...
Happy coding....
Nice Post.. Its very help full for me to become a good android programmar
ReplyDeleteThank You Vishal Sir.
DeleteThank You Sir
ReplyDeleteAre these constants that you set or are they vendor specific?
ReplyDeletestatic public final int REQUEST_CONNECT_BT = 0x2300;
static private final int REQUEST_ENABLE_BT = 0x1000;
No they are not vendor specific
Deletegood one.. works perfectly.. but the color of list view is white ..I cannot see the list view in some mobile unless i press on particular list item.. i could not find any ways to change the color ..can you tell me how to change the color of list view??
ReplyDeleteThank you Sushanth. I have updated the code for BTWrapperActivity class, now you can see the list with black background.
Deletehow to print receipt in different languge like tamil,hindi........etc
ReplyDeleteHi Murugan you have to use Typeface for it. My previous post help you to do that http://androidnutts.blogspot.in/2012/11/how-to-use-hindi-font-in-android.html
DeleteActuallly am using MPD2 model Printer this printer not support for tamil font and only printing chinese laguage ...i tried Typeface also ..but its not working...help me to get tamil font....thank u...
ReplyDeletehow can i format the text alignment and make it bold ? .. by the way thanks for this post ..
ReplyDeleteany idea on how to print with image sir? thanks!
ReplyDeletecan u print other language(other then english) values
ReplyDeleteInputStream in = getAssets().open("logo.txt");// openFileInput();
ReplyDeletecan u upload logo.txt to this post?
cause when i running , android is error and stop.
Hi, After sending data to the device senddatatodevice(), nothing happens. Printer does not print data. The apps works well, it connects to the printer but does not actually print.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThank you...
ReplyDeleteHi,How to print bill receipt like table format.Please help me i struggle lot
ReplyDeletehi. how to print receipt with barcode? thanks.
ReplyDeletehi,its really helpful,thank you Manish Burade sir.
ReplyDeletecan you please guide me what if i have to print listview data somthing like bill. thank you sir
ReplyDeletehow to print image from canvas encoded data Using Bluetooth with Android Phone
ReplyDeleteHave u any idea bro
DeleteError:(11, 30) error: package mmsl.GetPrintableImage does not exist
ReplyDeleteHow solve this..
Bluetooth devices not scanedd
ReplyDeleteblutetooth device scanning page doesnt shows any device list
ReplyDelete