I am developing a restaurant app which print receipts after customer purchases foods. I have added a config screen in app which the manager uses to configure printers. A manager can print a test page to test whether he has entered right ip and port. Here is my code which prints test page:
private class PrintTask extends AsyncTask<Printer, Boolean, String> {
#Override
protected String doInBackground(Printer... params) {
try {
publishProgress(true);
Socket sock = new Socket(params[0].getIp(), Integer.parseInt(params[0].getPort()));
PrintWriter oStream = new PrintWriter(sock.getOutputStream());
oStream.printf("--------------------------------\r\n");
oStream.printf("*** TEST PRINT ***\r\n");
oStream.printf("You have configured your \n\r");
oStream.printf(params[0].getName());
oStream.printf("\r\nprinter successfully\n\r");
oStream.printf("| Thanks |\r\n");
oStream.printf("--------------------------------\r\n");
oStream.close();
sock.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
publishProgress(false);
return "";
}
#Override
protected void onProgressUpdate(Boolean... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
if(!values[0]) {
waitView.setVisibility(View.GONE);
}
else {
waitView.setVisibility(View.VISIBLE);
}
}
}
The problem is if I print on a network printer (a stand alone printer without attaching to any PC) it prints text properly. Here I am using the ip and default port 9100. But when I print to a shared printer attached to a PC, it fails to print. Any idea, where I am doing wrong...???
From what your describe it looks like that standalone printer is running some kind of "text printing service" on your given port. So looks like everything you send to this port will be printed as text.
Whereas when you have "Shared" printer on your Windows machine, it's implemented using Windows Printer service or smth like that. It's not just simple socket/port anymore where you can write ASCII text.
Related
I am trying to print a turn number from my android kiosk/tablet. User just presses on an image button and the turn should be printed.
The kiosk connects to a USB Epson TM-T20 printer.
I downloaded the sample EPOS2_Printer app that epson provides, and I built it's APK, it works fine on the kiosk, so I am trying to use its code and integrate it into what I am trying to do. The problem is I am unable to get the printer to be discovered and selected without user interaction.
The sample EPSON provides has a DiscoveryActivity, where the app searches for connected devices, you select the one you want from search results and that takes you back to main activity with the target field pre-filled.
I am trying to stay in the same activity, and onClick, do the discovery and get target (only 1 printer) and print to it.
Reading this: Epson printer connect fails status ERR_CONN the comment below says to use Discover.start to get the target, but how can you integrate that with Printer.connect?
I can share code, just wanted to be as short as possible here.
Any help is appreciated!
Share your code, please
Did you try something like this?
printer = new Print(getApplicationContext());
try {
// Open
printer.openPrinter(
connectionType,
openDeviceName,
Print.FALSE,
Print.PARAM_DEFAULT,
Print.PARAM_DEFAULT);
}
catch (EposException e) {
result.setEposException(e);
return;
}
try {
// Print data if printer is printable
printer.getStatus(printerStatus, batteryStatus);
result.setPrinterStatus(printerStatus[0]);
result.setBatteryStatus(batteryStatus[0]);
if (isPrintable(result)) {
printerStatus[0] = 0;
batteryStatus[0] = 0;
printer.beginTransaction();
isBeginTransaction = true;
printer.sendData(builder, sendTimeout, printerStatus, batteryStatus);
result.setPrinterStatus(printerStatus[0]);
result.setBatteryStatus(batteryStatus[0]);
}
}
catch (EposException e) {
result.setEposException(e);
}
finally {
if (isBeginTransaction) {
try {
printer.endTransaction();
}
catch (EposException e) {
// Do nothing
}
}
}
try {
printer.closePrinter();
}
I am following the Zebra Android Link_OS SDK sample code for printing a test label on a ZQ510 over Bluetooth, but it won't print in ZPL format.
Here is the code I'm running to print the label:
private void sendZplOverBluetooth(final String theBtMacAddress) {
new Thread(new Runnable() {
public void run() {
try {
// Instantiate connection for given Bluetooth® MAC Address.
Connection thePrinterConn = new BluetoothConnection(theBtMacAddress);
// Initialize
Looper.prepare();
// Open the connection - physical connection is established here.
thePrinterConn.open();
// This example prints "This is a ZPL test." near the top of the label.
String zplData = "^XA^FO20,20^A0N,25,25^FDThis is a ZPL test.^FS^XZ";
// Send the data to printer as a byte array.
thePrinterConn.write(zplData.getBytes());
// Make sure the data got to the printer before closing the connection
Thread.sleep(500);
// Close the connection to release resources.
thePrinterConn.close();
Looper.myLooper().quit();
} catch (Exception e) {
// Handle communications error here.
e.printStackTrace();
}
}
}).start();
}
And here is the result of the print. (I ran it twice, that's why there are two test prints).
Then I read about how it might be in a different mode because for some reason Zebra can't detect their own proprietary language. So I tried to get the settings and see through the Android app. Again using the given Link-OS SDK example code:
private static void displaySettings(Connection c) throws ConnectionException, ZebraPrinterLanguageUnknownException, SettingsException, ZebraIllegalArgumentException {
ZebraPrinter genericPrinter = ZebraPrinterFactory.getInstance(c);
ZebraPrinterLinkOs linkOsPrinter = ZebraPrinterFactory.createLinkOsPrinter(genericPrinter);
if (linkOsPrinter != null) {
System.out.println("Available Settings for myDevice");
Set<String> availableSettings = linkOsPrinter.getAvailableSettings();
for (String setting : availableSettings) {
System.out.println(setting + ": Range = (" + linkOsPrinter.getSettingRange(setting) + ")");
}
System.out.println("\nCurrent Setting Values for myDevice");
Map<String, String> allSettingValues = linkOsPrinter.getAllSettingValues();
for (String settingName : allSettingValues.keySet()) {
System.out.println(settingName + ":" + allSettingValues.get(settingName));
}
String darknessSettingId = "print.tone";
String newDarknessValue = "10.0";
if (availableSettings.contains(darknessSettingId) &&
linkOsPrinter.isSettingValid(darknessSettingId, newDarknessValue) &&
linkOsPrinter.isSettingReadOnly(darknessSettingId) == false) {
linkOsPrinter.setSetting(darknessSettingId, newDarknessValue);
}
System.out.println("\nNew " + darknessSettingId + " Value = " + linkOsPrinter.getSettingValue(darknessSettingId));
}
}
This time, I get a SettingsException with the description of Operation cannot be performed on raw channel with a printer set to line print mode
How am I able to print ZPL text using a Mac and developing Android correctly? I read about using some Zebra Utility app for changing the mode, but it's only available for Windows, and their Android app doesn't work.
Regardless, if someone was to use the app with a printer in the incorrect mode, they would have to go through all this unnecessary setup that wouldn't be intuitive for just anybody.
Thanks for the help and appreciate any feedback.
You can programmatically set the print mode to ZPL, it's currently in line-mode.
To do so:
BluetoothConnection printerIns= new BluetoothConnection(theBtMacAddress);
ZebraPrinter zPrinterIns = ZebraPrinterFactory.getInstance(printerIns);
//Set printer to ZPL mode
zPrinterIns.sendCommand("! U1 setvar \"device.languages\" \"zpl\"\r\n");
//Feed and calibrate to the media
zPrinterIns.sendCommand("~jc^xa^jus^xz");
In your example code, You are establishing a Bluetooth connection and attempting to send raw data, make use of the ZebraPrinterand BluetoothConnection classes provided by Zebra instead from the com.zebra.sdk.printer namespace.
I corrected your code, it should work now.
new Thread(new Runnable() {
public void run() {
try {
// Instantiate connection for given Bluetooth® MAC Address.
BluetoothConnection thePrinterConn = new BluetoothConnection(theBtMacAddress);
// Initialize
Looper.prepare();
// Open the connection - physical connection is established here.
ZebraPrinter zPrinterIns = ZebraPrinterFactory.getInstance(thePrinterConn);
zPrinterIns.sendCommand("! U1 setvar \"device.languages\" \"zpl\"\r\n");
zPrinterIns.sendCommand("~jc^xa^jus^xz");
Thread.sleep(500);
// Send the data to printer as a byte array.
zPrinterIns.sendCommand("^XA^FO20,20^A0N,25,25^FDThis is a ZPL test.^FS^XZ");
// Make sure the data got to the printer before closing the connection
Thread.sleep(500);
// Close the connection to release resources.
thePrinterConn.close();
Looper.myLooper().quit();
} catch (Exception e) {
// Handle communications error here.
e.printStackTrace();
}
}
}).start();
If you don't want to perform this step programmatically like in the Dayan answer and you have acces to a Windows machine (or emulating one), install the Zebra Setup Utilities. Then following the instructions here https://km.zebra.com/kb/index?page=content&id=SO7296 to switch the print mode to ZPL with the command
! U1 setvar "device.languages" "zpl"
I am currently developing an Android application (in JAVA) for NFC smartphones. I am trying to communicate to an Nfca tag but keep getting a TagLostException no matter the command I send via transceive(byte[]). The tag is well connected to the device.
Here is the important piece of code:
public void onNewIntent(Intent intent) {
setIntent(intent);
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // get the tag object for the discovered tag
nfca = NfcA.get(tag); // try and get the instance for this tag
if(nfca == null) {
Alert("tag","the tag is not NfcA");
} else {
new Thread(new Runnable() {
#Override
public void run() {
handler.sendEmptyMessage(1); //this will call handleMessage function and handle all error
}
}).start();
}
}
final Handler handler = new Handler() {
//handles the connection with the tag
#Override
public void handleMessage(final Message msgs) {
// try to connect to the NfcA tag
try {
nfca.connect();
} catch(IOException e) {
Alert("nfca.connect","cannot open connection ><");
}
Toast.makeText(NfcaActivity.this, "tag connected", Toast.LENGTH_LONG).show();
}
};
try {
//nfca.setTimeout(3000);
pageBuffer = nfca.transceive(command);
} catch(IOException e) {
Alert("pageBuffer","cannot perform transceive "+ e.toString());
} catch(Exception e) {
Alert("exception!", e.toString());
}
I am trying with the following command : {00 CA 42 08 00} or {00 A4 00 00 02 3F00} but have the same results.
Those commands are working when I am using a smart card reader and a software on my PC. The smart card is non-empty.
I expect that the card has the IsoDep technology available, too? If that is the case, you should connect using that. One of the commands you list looks like an ISO 7816-4 APDU to select the Master File. This is supposed to be used with ISO 14443-4 cards, which is exactly what the IsoDep technology represents.
I am developing shopping cart application in Android 2.1 . I want to print the order details ( customer details , cart details, order total) , when user submit the order . I want to use some WIFI printer for printing the data. Please help me with suitable examples ...
I assume you want to print on receipt-sized paper. If so, Star Micronics has an Android SDK with support for Wifi connections as well as USB and Bluetooth. Download it here: http://starmicronics.com/support/sdkdocumentation.aspx
If you're looking for a regular size printer, check out Google Cloud Print: https://developers.google.com/cloud-print/?hl=en
Create a Socket connection from ip address and port number.
String ip = "your printer ip address";
int port = port number;
private class printTCP extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
if (!ip.equals("")) {
if ((pref.getString(Const.PORT_CASH) != null) && (!pref.getString(Const.PORT_CASH).equals(""))) {
port = Integer.parseInt(pref.getString(Const.PORT_CASH));
try {
client = new Socket(ip, port);// ip address and port number of ur hardware device
String text = "Test Print";
byte[] bytes = text.getBytes(); //create a byte array
outputStream = client.getOutputStream();
outputStream.write(bytes, 0, bytes.length); //write file to the output stream byte by byte
outputStream.flush();
outputStream.close();
client.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
}
}
I would like to implement an application to receive a file from a Bluetooth device.
Before receiving, a notification will be raised to accept an incoming file request.
From there, i would like to activate "accept" and download the file automatically without raising an accept dialog when the user receive a second file from another Bluetooth paired device, without notification disturbance when the user launchs an application.
I developed an app that include this kind of task, and you can use BluetoothChat example.
You must set the secure flag to false:
`
boolean secure = false;
try {
if (secure) {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
MY_UUID_SECURE);
} else {
tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE, MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
mmServerSocket = tmp;
}`
And then read the buffer from the InputStream that you can find in ConnectedThread:
while (true) {
try {
bytes = mmInStream.read(buffer);
/*write bytes in a file*/
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
BluetoothChatService.this.start();
break;
}
}
You can try using the Bluetooth socket connection to set a client server TCP like connection.
ON ROOTED DEVICES, You can just install only two apps on your phone to achieve your goal.
XPosed Installer
Auto-Accept
This way you hook System service.
import android.util.*;
import de.robv.android.xposed.*;
import de.robv.android.xposed.callbacks.XC_LoadPackage.*;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class Tutorial implements IXposedHookLoadPackage
{
private String TAG="TUTORIAL";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.bluetooth"))
{
Log.i(TAG,"Not: "+lpparam.packageName);
return;
}
Log.i(TAG,"Yes "+lpparam.packageName);
findAndHookMethod("com.android.bluetooth.opp.BluetoothOppManager", lpparam.classLoader, "isWhitelisted", String.class,new XC_MethodHook() {
#Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.v(TAG,"HOOK DONE");
param.setResult(true); /* you can compare the sender address(String) with your computer and determine if you return true or just allow the original method to be called after this returns.*/
}
});
}
}
For more information, please visit my answer in SO.
I'll post some direct links here.
Links
Dropbox link of the auto accepting app
Dropbox link of the project files (zip)
Xposed apk site
Towelroot site to root your phone
Auto-Accept github repository