LAMW - (SOLVED) simple esc/POS printing bridge?
lazarus / 43-Android
----------------------------------------------------------------------
Mongkey · 2023-05-28 00:46
Library:
https://github.com/DantSu/ESCPOS-ThermalPrinter-Android
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
EscPosPrinter printer = new
EscPosPrinter(BluetoothPrintersConnections.selectFirstPaired(), 203,
48f, 32);printer .printFormattedText( "[C]
" +
PrinterTextParserImg.bitmapToHexadecimalString(printer, this.getApplic
ationContext().getResources().getDrawableForDensity(R.drawable.logo,
DisplayMetrics.DENSITY_MEDIUM))+"\n" + "[L]\n" +
"[C]ORDER N°045\n" + "[L]\n" +
"[C]================================\n" + "[L]\n" +
"[L]BEAUTIFUL SHIRT[R]9.99e\n" + "[L] + Size : S\n" +
"[L]\n" + "[L]AWESOME HAT[R]24.99e\n" + "[L]
+ Size : 57/58\n" + "[L]\n" +
"[C]--------------------------------\n" + "[R]TOTAL PRICE
:[R]34.98e\n" + "[R]TAX :[R]4.23e\n" + "[L]\n" +
"[C]================================\n" + "[L]\n" +
"[L]Customer :\n" + "[L]Raymond
DUPONT\n" + "[L]5 rue des girafes\n" + "[L]31547
PERPETES\n" + "[L]Tel : +33801201456\n" + "[L]\n" +
"[C]831254784551\n" +
"[C]https://dantsu.com/" );
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i package
com.dantsu.thermalprinter; import androidx.annotation.NonNull;import
androidx.appcompat.app.AppCompatActivity;import
androidx.core.app.ActivityCompat;import
androidx.core.content.ContextCompat; import android.Manifest;import
android.annotation.SuppressLint;import android.app.AlertDialog;import
android.app.PendingIntent;import
android.content.BroadcastReceiver;import
android.content.Context;import android.content.Intent;import
android.content.IntentFilter;import
android.content.pm.PackageManager;import
android.hardware.usb.UsbDevice;import
android.hardware.usb.UsbManager;import android.os.Bundle;import
android.util.DisplayMetrics;import android.util.Log;import
android.widget.Button;import android.widget.EditText; import
com.dantsu.escposprinter.connection.DeviceConnection;import com.dantsu
.escposprinter.connection.bluetooth.BluetoothConnection;import com.dan
tsu.escposprinter.connection.bluetooth.BluetoothPrintersConnections;im
port com.dantsu.escposprinter.connection.tcp.TcpConnection;import
com.dantsu.escposprinter.connection.usb.UsbConnection;import
com.dantsu.escposprinter.connection.usb.UsbPrintersConnections;import
com.dantsu.escposprinter.textparser.PrinterTextParserImg;import
com.dantsu.thermalprinter.async.AsyncBluetoothEscPosPrint;import
com.dantsu.thermalprinter.async.AsyncEscPosPrint;import
com.dantsu.thermalprinter.async.AsyncEscPosPrinter;import
com.dantsu.thermalprinter.async.AsyncTcpEscPosPrint;import
com.dantsu.thermalprinter.async.AsyncUsbEscPosPrint; import
java.text.SimpleDateFormat;import java.util.Date; public class
MainActivity extends AppCompatActivity { @Override protected
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Button button =
(Button) this.findViewById(R.id.button_bluetooth_browse);
button.setOnClickListener(view -> browseBluetoothDevice());
button = (Button) findViewById(R.id.button_bluetooth);
button.setOnClickListener(view -> printBluetooth()); button =
(Button) this.findViewById(R.id.button_usb);
button.setOnClickListener(view -> printUsb()); button =
(Button) this.findViewById(R.id.button_tcp);
button.setOnClickListener(view -> printTcp()); } /*==========
======================================================================
============== ======================================BLUETOOTH
PART============================================ ==================
======================================================================
======*/ public interface OnBluetoothPermissionsGranted {
void onPermissionsGranted(); } public static final int
PERMISSION_BLUETOOTH = 1; public static final int
PERMISSION_BLUETOOTH_ADMIN = 2; public static final int
PERMISSION_BLUETOOTH_CONNECT = 3; public static final int
PERMISSION_BLUETOOTH_SCAN = 4; public
OnBluetoothPermissionsGranted onBluetoothPermissionsGranted;
@Override public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions,
grantResults); if (grantResults.length > 0 && grantResults[0]
== PackageManager.PERMISSION_GRANTED) { switch
(requestCode) { case
MainActivity.PERMISSION_BLUETOOTH: case
MainActivity.PERMISSION_BLUETOOTH_ADMIN: case
MainActivity.PERMISSION_BLUETOOTH_CONNECT: case
MainActivity.PERMISSION_BLUETOOTH_SCAN:
this.checkBluetoothPermissions(this.onBluetoothPermissionsGranted);
break; } } } public void
checkBluetoothPermissions(OnBluetoothPermissionsGranted
onBluetoothPermissionsGranted) {
this.onBluetoothPermissionsGranted = onBluetoothPermissionsGranted;
if (android.os.Build.VERSION.SDK_INT <
android.os.Build.VERSION_CODES.S &&
ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new
String[]{Manifest.permission.BLUETOOTH},
MainActivity.PERMISSION_BLUETOOTH); } else if
(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S
&& ContextCompat.checkSelfPermission(this,
Manifest.permission.BLUETOOTH_ADMIN) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new
String[]{Manifest.permission.BLUETOOTH_ADMIN},
MainActivity.PERMISSION_BLUETOOTH_ADMIN); } else if
(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S
&& ContextCompat.checkSelfPermission(this,
Manifest.permission.BLUETOOTH_CONNECT) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new
String[]{Manifest.permission.BLUETOOTH_CONNECT},
MainActivity.PERMISSION_BLUETOOTH_CONNECT); } else if
(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S
&& ContextCompat.checkSelfPermission(this,
Manifest.permission.BLUETOOTH_SCAN) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new
String[]{Manifest.permission.BLUETOOTH_SCAN},
MainActivity.PERMISSION_BLUETOOTH_SCAN); } else {
this.onBluetoothPermissionsGranted.onPermissionsGranted(); }
} private BluetoothConnection selectedDevice; public void
browseBluetoothDevice() { this.checkBluetoothPermissions(() ->
{ final BluetoothConnection[] bluetoothDevicesList = (new
BluetoothPrintersConnections()).getList(); if
(bluetoothDevicesList != null) { final String[] items =
new String[bluetoothDevicesList.length + 1]; items[0] =
"Default printer"; int i = 0; for
(BluetoothConnection device : bluetoothDevicesList) {
items[++i] = device.getDevice().getName(); }
AlertDialog.Builder alertDialog = new
AlertDialog.Builder(MainActivity.this);
alertDialog.setTitle("Bluetooth printer selection");
alertDialog.setItems( items,
(dialogInterface, i1) -> { int index = i1 - 1;
if (index == -1) {
selectedDevice = null; } else {
selectedDevice = bluetoothDevicesList[index];
} Button button = (Button)
findViewById(R.id.button_bluetooth_browse);
button.setText(items[i1]); } );
AlertDialog alert = alertDialog.create();
alert.setCanceledOnTouchOutside(false); alert.show();
} }); } public void printBluetooth() {
this.checkBluetoothPermissions(() -> { new
AsyncBluetoothEscPosPrint( this, new
AsyncEscPosPrint.OnPrintFinished() { @Override
public void onError(AsyncEscPosPrinter
asyncEscPosPrinter, int codeException) {
Log.e("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished : An
error occurred !"); }
@Override public void onSuccess(AsyncEscPosPrinter
asyncEscPosPrinter) {
Log.i("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished :
Print is finished !"); } }
)
.execute(this.getAsyncEscPosPrinter(selectedDevice)); });
} /*==============================================================
================================
===========================================USB
PART============================================= =================
======================================================================
=======*/ private static final String ACTION_USB_PERMISSION =
"com.android.example.USB_PERMISSION"; private final
BroadcastReceiver usbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction(); if
(MainActivity.ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) { UsbManager usbManager =
(UsbManager) getSystemService(Context.USB_SERVICE);
UsbDevice usbDevice = (UsbDevice)
intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED,
false)) { if (usbManager != null && usbDevice
!= null) { new AsyncUsbEscPosPrint(
context, new
AsyncEscPosPrint.OnPrintFinished() {
@Override public void
onError(AsyncEscPosPrinter asyncEscPosPrinter, int codeException) {
Log.e("Async.OnPrintFinished",
"AsyncEscPosPrint.OnPrintFinished : An error occurred !");
}
@Override public void
onSuccess(AsyncEscPosPrinter asyncEscPosPrinter) {
Log.i("Async.OnPrintFinished",
"AsyncEscPosPrint.OnPrintFinished : Print is finished !");
} }
)
.execute(getAsyncEscPosPrinter(new UsbConnection(usbManager,
usbDevice))); } }
} } } }; public void printUsb() {
UsbConnection usbConnection =
UsbPrintersConnections.selectFirstConnected(this); UsbManager
usbManager = (UsbManager)
this.getSystemService(Context.USB_SERVICE); if (usbConnection
== null || usbManager == null) { new
AlertDialog.Builder(this) .setTitle("USB Connection")
.setMessage("No USB printer found.")
.show(); return; } PendingIntent
permissionIntent = PendingIntent.getBroadcast( this,
0, new Intent(MainActivity.ACTION_USB_PERMISSION),
android.os.Build.VERSION.SDK_INT >=
android.os.Build.VERSION_CODES.S ? PendingIntent.FLAG_MUTABLE : 0
); IntentFilter filter = new
IntentFilter(MainActivity.ACTION_USB_PERMISSION);
registerReceiver(this.usbReceiver, filter);
usbManager.requestPermission(usbConnection.getDevice(),
permissionIntent); } /*========================================
======================================================
=========================================TCP
PART=============================================== ===============
======================================================================
=========*/ public void printTcp() { final EditText
ipAddress = (EditText) this.findViewById(R.id.edittext_tcp_ip);
final EditText portAddress = (EditText)
this.findViewById(R.id.edittext_tcp_port); try {
new AsyncTcpEscPosPrint( this, new
AsyncEscPosPrint.OnPrintFinished() { @Override
public void onError(AsyncEscPosPrinter
asyncEscPosPrinter, int codeException) {
Log.e("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished : An
error occurred !"); }
@Override public void onSuccess(AsyncEscPosPrinter
asyncEscPosPrinter) {
Log.i("Async.OnPrintFinished", "AsyncEscPosPrint.OnPrintFinished :
Print is finished !"); } }
) .execute(
this.getAsyncEscPosPrinter( new TcpConnection(
ipAddress.getText().toString(),
Integer.parseInt(portAddress.getText().toString())
) ) ); }
catch (NumberFormatException e) { new
AlertDialog.Builder(this) .setTitle("Invalid TCP port
address") .setMessage("Port field must be an
integer.") .show(); e.printStackTrace();
} } /*======================================================
========================================
===================================ESC/POS PRINTER
PART========================================= =====================
======================================================================
===*/ /** * Asynchronous printing */
@SuppressLint("SimpleDateFormat") public AsyncEscPosPrinter
getAsyncEscPosPrinter(DeviceConnection printerConnection) {
SimpleDateFormat format = new SimpleDateFormat("'on' yyyy-MM-dd 'at'
HH:mm:ss"); AsyncEscPosPrinter printer = new
AsyncEscPosPrinter(printerConnection, 203, 48f, 32); return
printer.addTextToPrint( "[C]
" +
PrinterTextParserImg.bitmapToHexadecimalString(printer, this.getApplic
ationContext().getResources().getDrawableForDensity(R.drawable.logo,
DisplayMetrics.DENSITY_MEDIUM)) + "\n" + "[L]\n"
+ "[C]ORDER N°045\n" +
"[L]\n" + "[C]" +
format.format(new Date()) + "\n" + "[C]\n" +
"[C]================================\n" +
"[L]\n" + "[L]BEAUTIFUL SHIRT[R]9.99€\n" +
"[L] + Size : S\n" + "[L]\n" +
"[L]AWESOME HAT[R]24.99€\n" + "[L] + Size :
57/58\n" + "[L]\n" +
"[C]--------------------------------\n" + "[R]TOTAL
PRICE :[R]34.98€\n" + "[R]TAX :[R]4.23€\n" +
"[L]\n" + "[C]================================\n"
+ "[L]\n" + "[L]Customer :\n" +
"[L]Raymond DUPONT\n" + "[L]5 rue des girafes\n" +
"[L]31547 PERPETES\n" + "[L]Tel :
+33801201456\n" + "\n" + "[C]831254784551\n" +
"[L]\n" + "[C]https://dantsu.com/\n" ); }}
----------------------------------------------------------------------
jmpessoa · 2023-05-28 18:40
Ok. I will try implement a "jEscPosPrinter" LAMW component!
Thank you!
----------------------------------------------------------------------
Mongkey · 2023-05-29 02:11
Thank you mr. JMP
----------------------------------------------------------------------
jmpessoa · 2023-05-31 23:51
Done!
New "jsEscPosThermalPrinter" component!
need:
1)AppCompat theme
2)gradle:
compileSdkVersion 33
targetSdkVersion 33
New demo "AppCompatEscPosThermalPrinterDemo1"
(please, test it! I dont have a thermal printer....)
----------------------------------------------------------------------
Insid3Code · 2023-06-01 15:41
Hi,
Tested...
Thank you for this Nice work!
----------------------------------------------------------------------
jmpessoa · 2023-06-01 16:15
QuoteBethoven composed much of his wonderful work without listening
anymore....
Doing a simple coding without having an instrument to test it, is
possible for mere mortals....
Thank you!
----------------------------------------------------------------------
Mongkey · 2023-06-02 00:09
Thank you!
Printing just like on kotlin
----------------------------------------------------------------------
Mongkey · 2023-06-02 01:56
Thank you, wishing you good health and happiness Mr. JMP,
My test result:
It really slow, on every print just like on first print, seems
getlist() printer first on all print,
Could you add selectFirstPaired() not getlist() on printing?
----------------------------------------------------------------------
Mongkey · 2023-06-02 03:16
I got another method very fast on printing Mr. JMP, you just need add
call procedure on jbluetoothclient, image, custom font already added.
this attachment is the result
----------------------------------------------------------------------
jmpessoa · 2023-06-02 03:21
QuoteCould you add selectFirstPaired() not getlist() on printing?
Yes, "selectFirstPaired()" is already the API used by LAMW
"InitConnection" for Bluetooth!
QuoteI got another method very fast on printing Mr. JMP....
What another method?
----------------------------------------------------------------------
Mongkey · 2023-06-02 03:27
jBluetoothclientsocket.java
you just need to make proper call procedure and improve, bridging from
java to pas is hard for me .
More and more simple step by step java to pas bridging tutorial would
be appreciated
Ability:
custom font
image
unicode
need improvement:
adding barcode print ability would be nice.
----------------------------------------------------------------------
jmpessoa · 2023-06-02 06:27
Quoteyou just need to make proper call procedure and improve, bridging
from java to pas is hard for me
Ok.
What functions from the new "jBluetoothclientsocket.java" you need a
bridge to be called from to Pascal/LAMW side?
----------------------------------------------------------------------
Mongkey · 2023-06-02 07:23
Hello Mr JMP, i already tried bridging, but still failed, how to
solve?
Code: Java [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i public
void print_Custom(String _message, int _size, int _align) {
printCustom(_message, _size, _align); // total 32 char in a single
line }
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
procedure print_Custom(var _message: string; _size:integer;
_align:integer); overload;
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
jBluetoothClientSocket.print_Custom(var _message: string;
_size:integer; _align:integer);begin //in designing component state:
set value here... if FInitialized then
jBluetoothClientSocket_print_Custom(gApp.jni.jEnv, FjObject,
_message, _size, _align);end;
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i procedure
jBluetoothClientSocket_print_Custom(env: PJNIEnv;
_jbluetoothclientsocket: JObject; var _message: string; _size:
integer; _align: integer);var jParams: array[0..0] of jValue;
jMethod: jMethodID=nil; jCls: jClass=nil;begin jParams[0].l:=
env^.NewStringUTF(env, PChar(_message)); jCls:=
env^.GetObjectClass(env, _jbluetoothclientsocket); jMethod:=
env^.GetMethodID(env, jCls, 'print_Custom', '(Ljava/lang/String;)V');
env^.CallVoidMethodA(env, _jbluetoothclientsocket, jMethod,
@jParams);env^.DeleteLocalRef(env,jParams[0].l);
env^.DeleteLocalRef(env, jCls);end;
f_bluetooth.jBluetoothClientSocket1.print_Custom('test',3,1);
this one still raising error:
u_order.pas(2696,43) Error: identifier idents no member "print_Custom"
Thank you.
----------------------------------------------------------------------
jmpessoa · 2023-06-02 08:50
......................
----------------------------------------------------------------------
jmpessoa · 2023-06-02 08:53
Using IDE menu "Tools" --> [LAMW ...] ---> "New jComponent Create"
: (see picture)
You got into the page/tab "Pascal":
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i unit
ujbluetoothclientsocket; {$mode delphi} interface uses Classes,
SysUtils, And_jni, AndroidWidget; type {warning: draft
"jBluetoothClientSocket" complement....}{ copy/add to
*jbluetoothclientsocket.pas" file} jBluetoothClientSocket =
class public procedure print_Custom(_message: string; _size:
integer; _align: integer); end; procedure
jBluetoothClientSocket_print_Custom(env: PJNIEnv;
_jbluetoothclientsocket: JObject; _message: string; _size: integer;
_align: integer); implementation {--------- jBluetoothClientSocket
--------------} procedure
jBluetoothClientSocket.print_Custom(_message: string; _size: integer;
_align: integer);begin //in designing component state: set value
here... if FInitialized then
jBluetoothClientSocket_print_Custom(gApp.jni.jEnv, FjObject, _message
,_size ,_align);end; {-------- jBluetoothClientSocket_JNI_Bridge
----------} procedure jBluetoothClientSocket_print_Custom(env:
PJNIEnv; _jbluetoothclientsocket: JObject; _message: string; _size:
integer; _align: integer);var jParams: array[0..2] of jValue;
jMethod: jMethodID=nil; jCls: jClass=nil;label
_exceptionOcurred;begin if (env = nil) or (_jbluetoothclientsocket =
nil) then exit; jCls:= env^.GetObjectClass(env,
_jbluetoothclientsocket); if jCls = nil then goto _exceptionOcurred;
jMethod:= env^.GetMethodID(env, jCls, 'print_Custom',
'(Ljava/lang/String;II)V'); if jMethod = nil then begin
env^.DeleteLocalRef(env, jCls); goto _exceptionOcurred; end;
jParams[0].l:= env^.NewStringUTF(env, PChar(_message));
jParams[1].i:= _size; jParams[2].i:= _align;
env^.CallVoidMethodA(env, _jbluetoothclientsocket, jMethod,
@jParams);env^.DeleteLocalRef(env,jParams[0].l);
env^.DeleteLocalRef(env, jCls); _exceptionOcurred:
jni_ExceptionOccurred(env);end; end.
Now copy the generated code "by parts' to the real
"bluetoothClientSocket.pas" in the folder "android_bridges"....
after that do a "Run" --> "Clean up and Build" on your LAMW
project.... do fix the
"Error: identifier idents no member "print_Custom""
----------------------------------------------------------------------
Mongkey · 2023-06-02 09:20
1 by 1, begin to understand, only print_Text, print_Line succeed , 2
others still fail.
just want to bring this 4:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
procedure print_line(); overload; procedure print_Text(_message:
string); overload; procedure print_Custom(_message: string;
_size:integer; _align:integer); overload; procedure
print_Photo(var _fullFilename: string); overload;
Seems got the failed suspect -> must be (Ljava/lang/String;II)
Thank you!
----------------------------------------------------------------------
jmpessoa · 2023-06-02 15:52
for "print_Custom":
Quote'(Ljava/lang/String;II)V'
But you don't need to code..... Use the code generator as shown in the
picture!
And yes, you can generate code for several methods at once .....
ref:
https://github.com/jmpessoa/lazandroidmodulewizard/blob/master/docs/ho
w_to_create_new_components.txt
----------------------------------------------------------------------
Mongkey · 2023-06-02 22:20
Thank you Mr. JMP, your tools are great!,
Let me try first , --> WORK like a pro, java to pas bridge
programmer
I tried jar file as component, but it always give list out of bound
index -> SOLVED , i add if listbox1 empty it notifies the importer to
re select java method.