POS 58MM Printing, Java, Android

70 Views Asked by At

i have a website that is mobile responsive, then i turned it into a mobile app with webview, the IDE i used is Intellij, Programming language used is Java, it prints well with the POS 58MM printer on desktop, but for the mobile app, it is not, i'm making use of printerlibs.jar as a library

my java code

package com.example.mobileprinting;

import com.lvrenyang.io.IOCallBack;
import com.lvrenyang.io.Pos;
import com.lvrenyang.io.USBPrinting;

public class MainActivity extends AppCompatActivity  implements View.OnClickListener, IOCallBack {
    private LinearLayout linearlayoutdevices;

    Button btnDisconnect,btnPrint;
    static MainActivity mActivity;

    ExecutorService es = Executors.newScheduledThreadPool(30);
    Pos mPos = new Pos();
    USBPrinting mUsb = new USBPrinting();

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

        mPos.Set(mUsb);
        mUsb.SetCallBack(this);
        mActivity = this;

        linearlayoutdevices = (LinearLayout) findViewById(R.id.linearlayoutdevices);
        btnDisconnect = (Button) findViewById(R.id.buttonDisconnect);
        btnPrint = (Button) findViewById(R.id.buttonPrint);
        btnDisconnect.setOnClickListener(this);
        btnPrint.setOnClickListener(this);
        btnDisconnect.setEnabled(false);
        btnPrint.setEnabled(false);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
            probe();
        } else {
            finish();
        }

        WebView webView = findViewById(R.id.webView);
        ProgressBar progressBar = findViewById(R.id.progressBar);

        // Enable JavaScript (optional)
        webView.getSettings().setJavaScriptEnabled(true);

        webView.addJavascriptInterface(new WebAppInterface(this), "Android");

        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                // Handle the JavaScript alert
                // For simplicity, showing an AlertDialog
                new AlertDialog.Builder(MainActivity.this)
                        .setMessage(message)
                        .setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm())
                        .setCancelable(false)
                        .show();
                return true;
            }
        });

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                // Show the ProgressBar when the page starts loading
                progressBar.setVisibility(View.VISIBLE);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                // Hide the ProgressBar when the page has finished loading
                progressBar.setVisibility(View.GONE);

                printPage();
            }
        });

        // Load a URL
        webView.loadUrl("https://example.com.ng/app")
    }

    // This is where you add the WebAppInterface class as an inner class
    public class WebAppInterface {
        Context mContext;

        WebAppInterface(Context context) {
            mContext = context;
        }

        @JavascriptInterface
        public void printPage() {
            // Get a reference to the WebView
            WebView webView = ((Activity) mContext).findViewById(R.id.webView);

            // Create a WebViewClient to capture the content of the WebView
            webView.setWebViewClient(new WebViewClient() {
                @Override
                public void onPageFinished(WebView view, String url) {
                    // Create a bitmap of the WebView content
                    view.measure(View.MeasureSpec.makeMeasureSpec(
                                    View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
                            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
                    view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
                    view.setDrawingCacheEnabled(true);
                    view.buildDrawingCache();
                    Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(),
                            view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
                    view.draw(new Canvas(bitmap));

                    // Convert the bitmap to a byte array
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
                    byte[] bytes = byteArrayOutputStream.toByteArray();

                    // Send the byte array to the printer via USB
                    if (mUsb != null && mUsb.IsOpened()) {
                        // Write the bytes to the printer
                        int bytesWritten = mUsb.Write(bytes, 0, bytes.length);
                        if (bytesWritten != -1) {
                            // Printing successful
                            Log.d(TAG, "Printing successful");
                        } else {
                            // Printing failed
                            Log.e(TAG, "Printing failed");
                            // Show a message to the user indicating that printing failed
                            Toast.makeText(mContext, "Printing failed", Toast.LENGTH_SHORT).show();
                        }
                    } else {
                        // Printer is not connected, display a message
                        Log.e(TAG, "Printer is not connected");
                        Toast.makeText(mContext, "Printer is not connected", Toast.LENGTH_SHORT).show();
                    }
                }
            });

            // Reload the WebView to trigger onPageFinished and capture the content
            webView.reload();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        btnDisconnect.performClick();
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub
        if (arg0.getId() == R.id.buttonDisconnect) {
            es.submit(new MainActivity.TaskClose(mUsb));
        }

        else if (arg0.getId() == R.id.buttonPrint) {
            btnPrint.setEnabled(false);
        }
    }

    @Override
    public void OnOpen() {
        // TODO Auto-generated method stub
        this.runOnUiThread(new Runnable(){

            @Override
            public void run() {
                btnDisconnect.setEnabled(true);
                btnPrint.setEnabled(true);
                linearlayoutdevices.setEnabled(false);
                for(int i = 0; i < linearlayoutdevices.getChildCount(); ++i)
                {
                    Button btn = (Button)linearlayoutdevices.getChildAt(i);
                    btn.setEnabled(false);
                }
                Toast.makeText(mActivity, "Connected", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void OnOpenFailed() {
        // TODO Auto-generated method stub
        this.runOnUiThread(new Runnable(){

            @Override
            public void run() {
                btnDisconnect.setEnabled(false);
                btnPrint.setEnabled(false);
                linearlayoutdevices.setEnabled(true);
                for(int i = 0; i < linearlayoutdevices.getChildCount(); ++i)
                {
                    Button btn = (Button)linearlayoutdevices.getChildAt(i);
                    btn.setEnabled(true);
                }
                Toast.makeText(mActivity, "Failed", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void OnClose() {
        // TODO Auto-generated method stub
        this.runOnUiThread(new Runnable(){

            @Override
            public void run() {
                btnDisconnect.setEnabled(false);
                btnPrint.setEnabled(false);
                linearlayoutdevices.setEnabled(true);
                for(int i = 0; i < linearlayoutdevices.getChildCount(); ++i)
                {
                    Button btn = (Button)linearlayoutdevices.getChildAt(i);
                    btn.setEnabled(true);
                }
                probe(); // 如果因为打印机关机导致Close。那么这里需要重新枚举一下。
            }
        });
    }

    @SuppressLint("RtlHardcoded")
    private void probe() {
        linearlayoutdevices.removeAllViews();
        final UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        if (deviceList.size() > 0) {
            // 初始化选择对话框布局,并添加按钮和事件

            while (deviceIterator.hasNext()) { // 这里是if不是while,说明我只想支持一种device
                final UsbDevice device = deviceIterator.next();
                //Toast.makeText( this, "" + device.getDeviceId() + device.getDeviceName() + device.toString(), Toast.LENGTH_LONG).show();

                Button btDevice = new Button(
                        linearlayoutdevices.getContext());
                btDevice.setLayoutParams(new ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                btDevice.setGravity(android.view.Gravity.CENTER_VERTICAL
                        | Gravity.LEFT);
                btDevice.setText(String.format(" VID:%04X PID:%04X",
                        device.getVendorId(), device.getProductId()));
                btDevice.setOnClickListener(new View.OnClickListener() {

                    public void onClick(View v) {
                        // TODO Auto-generated method stub

                        PendingIntent mPermissionIntent = PendingIntent
                                .getBroadcast(
                                        MainActivity.this,
                                        0,
                                        new Intent(
                                                MainActivity.this
                                                        .getApplicationInfo().packageName),
                                        PendingIntent.FLAG_IMMUTABLE);

                        if (!mUsbManager.hasPermission(device)) {
                            mUsbManager.requestPermission(device,
                                    mPermissionIntent);
                            Toast.makeText(getApplicationContext(),
                                            "没有权限", Toast.LENGTH_LONG)
                                    .show();
                        } else {
                            Toast.makeText(mActivity, "Connecting...", Toast.LENGTH_SHORT).show();
                            linearlayoutdevices.setEnabled(false);
                            for(int i = 0; i < linearlayoutdevices.getChildCount(); ++i)
                            {
                                Button btn = (Button)linearlayoutdevices.getChildAt(i);
                                btn.setEnabled(false);
                            }
                            btnDisconnect.setEnabled(false);
                            btnPrint.setEnabled(false);
                            es.submit(new MainActivity.TaskOpen(mUsb,mUsbManager,device));
                            //es.submit(new TaskTest(mPos,mUsb,mUsbManager,device));
                        }
                    }
                });
                linearlayoutdevices.addView(btDevice);
            }
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // Handle the configuration change if needed
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        WebView webView = findViewById(R.id.webView);
        Intent intent;
        if (item.getItemId() == R.id.action_home) {
            // Handle the menu item click
            intent = new Intent(this, MainActivity.class);
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_refresh) {
            // Handle the refresh action here
            webView.reload();
            return true;
        } else if (item.getItemId() == R.id.action_exit) {
            // Handle the exit action here
            showExitConfirmationDialog();
            return true;
        } else if (item.getItemId() == R.id.action_print) {
            // Handle the menu item click
            intent = new Intent(this, ConnectUSBActivity.class);
            connectUsbLauncher.launch(intent);
            return true;
        }
        // Add more conditions for other menu items if needed
        return super.onOptionsItemSelected(item);
    }


    public class TaskOpen implements Runnable
    {
        USBPrinting usb = null;
        UsbManager usbManager = null;
        UsbDevice usbDevice = null;

        public TaskOpen(USBPrinting usb, UsbManager usbManager, UsbDevice usbDevice)
        {
            this.usb = usb;
            this.usbManager = usbManager;
            this.usbDevice = usbDevice;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            usb.Open(usbManager,usbDevice);
        }
    }

    static int dwWriteIndex = 1;
    public class TaskPrint implements Runnable
    {
        Pos pos = null;

        public TaskPrint(Pos pos)
        {
            this.pos = pos;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub

            final boolean bPrintResult = PrintTicket(AppStartActivity.nPrintWidth, AppStartActivity.bCutter, AppStartActivity.bDrawer, AppStartActivity.bBeeper, AppStartActivity.nPrintCount, AppStartActivity.nCompressMethod);
            final boolean bIsOpened = pos.GetIO().IsOpened();

            mActivity.runOnUiThread(new Runnable(){
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    Toast.makeText(mActivity.getApplicationContext(), bPrintResult ? getResources().getString(R.string.printsuccess) : getResources().getString(R.string.printfailed), Toast.LENGTH_SHORT).show();
                    mActivity.btnPrint.setEnabled(bIsOpened);
                }
            });

        }


        public boolean PrintTicket(int nPrintWidth, boolean bCutter, boolean bDrawer, boolean bBeeper, int nCount, int nCompressMethod)
        {
            boolean bPrintResult = false;

            byte[] status = new byte[1];
            if(pos.POS_QueryStatus(status, 3000, 2))
            {
                for(int i = 0; i < nCount; ++i)
                {
                    if(!pos.GetIO().IsOpened())
                        break;

                    pos.POS_FeedLine();
                    pos.POS_S_Align(1);
                    pos.POS_S_TextOut("REC" + String.format("%03d", i) + "\r\nCaysn Printer\r\n测试页\r\n\r\n", 0, 1, 1, 0, 0x100);
                    pos.POS_S_TextOut("扫二维码下载苹果APP\r\n", 0, 0, 0, 0, 0x100);
                    pos.POS_S_SetQRcode("https://appsto.re/cn/2KF_bb.i", 8, 0, 3);
                    pos.POS_FeedLine();
                    //pos.POS_S_SetBarcode("20160618", 0, 72, 3, 60, 0, 2);
                    pos.POS_S_SetBarcode("11606211111331200008", 0, 73, 2, 60, 0, 2);
                    pos.POS_FeedLine();

                }

                if(bBeeper)
                    pos.POS_Beep(1, 5);
                if(bCutter)
                    pos.POS_CutPaper();
                if(bDrawer)
                    pos.POS_KickDrawer(0, 100);

                int dwTicketIndex = dwWriteIndex++;
                bPrintResult = pos.POS_TicketSucceed(dwTicketIndex, 30000);
            }

            return bPrintResult;
        }
    }

    public class TaskClose implements Runnable
    {
        USBPrinting usb = null;

        public TaskClose(USBPrinting usb)
        {
            this.usb = usb;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            usb.Close();
        }
    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onBackPressed() {
        WebView webView = findViewById(R.id.webView);

        if (webView.canGoBack()) {
            webView.goBack(); // Navigate to the previous page
        } else {
            //super.onBackPressed(); // No previous page, so exit the app or perform another action

            //show dialog before exit
            showExitConfirmationDialog();
        }
    }

    //action to take when back button is pressed on last page or the exit button is pressed
    private void showExitConfirmationDialog() {
        new AlertDialog.Builder(this)
                .setTitle("Exit Confirmation")
                .setMessage("Are you sure you want to exit the app?")
                .setPositiveButton("Exit", (dialog, which) -> finishAffinity())
                .setNegativeButton("Cancel", null)
                .show();
    }
}
1

There are 1 best solutions below

2
Mortech On

The Code:

package com.example.mobileprinting;

import static android.content.ContentValues.TAG;
import static com.example.mobileprinting.AppStartActivity.nCompressMethod;
import static com.example.mobileprinting.AppStartActivity.nPrintWidth;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.JavascriptInterface;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.lvrenyang.io.IOCallBack;
import com.lvrenyang.io.Pos;
import com.lvrenyang.io.USBPrinting;

import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, IOCallBack {
    private LinearLayout linearlayoutdevices;

    Button btnDisconnect, btnPrint;
    static MainActivity mActivity;

    ExecutorService es = Executors.newScheduledThreadPool(30);
    Pos mPos = new Pos();
    USBPrinting mUsb = new USBPrinting();

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

        mPos.Set(mUsb);
        mUsb.SetCallBack(this);
        mActivity = this;

        linearlayoutdevices = (LinearLayout) findViewById(R.id.linearlayoutdevices);
        btnDisconnect = (Button) findViewById(R.id.buttonDisconnect);
        btnPrint = (Button) findViewById(R.id.buttonPrint);
        btnDisconnect.setOnClickListener(this);
        btnPrint.setOnClickListener(this);
        btnDisconnect.setEnabled(false);
        btnPrint.setEnabled(false);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
            probe();
        } else {
            finish();
        }

        WebView webView = findViewById(R.id.webView);
        ProgressBar progressBar = findViewById(R.id.progressBar);

        webView.getSettings().setJavaScriptEnabled(true);

        webView.addJavascriptInterface(new WebAppInterface(this), "Android");

        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                new AlertDialog.Builder(MainActivity.this)
                        .setMessage(message)
                        .setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm())
                        .setCancelable(false)
                        .show();
                return true;
            }
        });

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                // Show the ProgressBar when the page starts loading
                progressBar.setVisibility(View.VISIBLE);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                progressBar.setVisibility(View.GONE);
            }
        });

        webView.loadUrl("https://example.com.ng");
    }

    public class WebAppInterface {
        Context mContext;

        WebAppInterface(Context context) {
            mContext = context;
        }

        @JavascriptInterface
        public void printPage() {
            WebView webView = ((Activity) mContext).findViewById(R.id.webView);

            webView.measure(View.MeasureSpec.makeMeasureSpec(
                    View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            webView.layout(0, 0, webView.getMeasuredWidth(), webView.getMeasuredHeight());
            webView.setDrawingCacheEnabled(true);
            webView.buildDrawingCache();
            Bitmap bitmap = Bitmap.createBitmap(webView.getMeasuredWidth(),
                    webView.getMeasuredHeight(), Bitmap.Config.RGB_565);
            Canvas canvas = new Canvas(bitmap);
            webView.draw(canvas);
            adjustBrightness(bitmap);
            saveBitmapToFile(bitmap);
        }

        private void adjustBrightness(Bitmap bitmap) {
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            int[] pixels = new int[width * height];
            bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
            float brightnessFactor = 1.2f;
            for (int i = 0; i < pixels.length; i++) {
                int pixel = pixels[i];
                int alpha = Color.alpha(pixel);
                int red = (int) (Color.red(pixel) * brightnessFactor);
                int green = (int) (Color.green(pixel) * brightnessFactor);
                int blue = (int) (Color.blue(pixel) * brightnessFactor);
                red = Math.min(255, Math.max(0, red));
                green = Math.min(255, Math.max(0, green));
                blue = Math.min(255, Math.max(0, blue));

                pixels[i] = Color.argb(alpha, red, green, blue);
            }

            bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        }

        private void saveBitmapToFile(Bitmap bitmap) {
            printImage(bitmap);
        }

        private void printImage(Bitmap bitmap) {
            if (mUsb != null && mUsb.IsOpened()) {
                mPos.POS_PrintPicture(bitmap, nPrintWidth, 1, nCompressMethod);
            } else {
                Log.e(TAG, "Printer is not connected");
                Toast.makeText(mContext, "Printer is not connected", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        btnDisconnect.performClick();
    }

    @Override
    public void onClick(View arg0) {
        if (arg0.getId() == R.id.buttonDisconnect) {
            es.submit(new MainActivity.TaskClose(mUsb));
        } else if (arg0.getId() == R.id.buttonPrint) {
            new WebAppInterface(MainActivity.this).printPage();
        }
    }

    @Override
    public void OnOpen() {
        this.runOnUiThread(() -> {
            btnDisconnect.setEnabled(true);
            btnPrint.setEnabled(true);
            linearlayoutdevices.setEnabled(false);
            for (int i = 0; i < linearlayoutdevices.getChildCount(); ++i) {
                Button btn = (Button) linearlayoutdevices.getChildAt(i);
                btn.setEnabled(false);
            }
            Toast.makeText(mActivity, "Connected", Toast.LENGTH_SHORT).show();
        });
    }

    @Override
    public void OnOpenFailed() {
        this.runOnUiThread(() -> {
            btnDisconnect.setEnabled(false);
            btnPrint.setEnabled(false);
            linearlayoutdevices.setEnabled(true);
            for (int i = 0; i < linearlayoutdevices.getChildCount(); ++i) {
                Button btn = (Button) linearlayoutdevices.getChildAt(i);
                btn.setEnabled(true);
            }
            Toast.makeText(mActivity, "Failed", Toast.LENGTH_SHORT).show();
        });
    }

    @Override
    public void OnClose() {
        this.runOnUiThread(() -> {
            btnDisconnect.setEnabled(false);
            btnPrint.setEnabled(false);
            linearlayoutdevices.setEnabled(true);
            for (int i = 0; i < linearlayoutdevices.getChildCount(); ++i) {
                Button btn = (Button) linearlayoutdevices.getChildAt(i);
                btn.setEnabled(true);
            }
            probe();
        });
    }

    @SuppressLint("RtlHardcoded")
    private void probe() {
        linearlayoutdevices.removeAllViews();
        final UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        if (deviceList.size() > 0) {
            while (deviceIterator.hasNext()) {
                final UsbDevice device = deviceIterator.next();

                Button btDevice = new Button(
                        linearlayoutdevices.getContext());
                btDevice.setLayoutParams(new ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                btDevice.setGravity(android.view.Gravity.CENTER_VERTICAL
                        | Gravity.LEFT);
                btDevice.setText(String.format(" VID:%04X PID:%04X",
                        device.getVendorId(), device.getProductId()));
                btDevice.setOnClickListener(v -> {
                    PendingIntent mPermissionIntent = PendingIntent
                            .getBroadcast(
                                    MainActivity.this,
                                    0,
                                    new Intent(
                                            MainActivity.this
                                                    .getApplicationInfo().packageName),
                                    PendingIntent.FLAG_IMMUTABLE);

                    if (!mUsbManager.hasPermission(device)) {
                        mUsbManager.requestPermission(device,
                                mPermissionIntent);
                        Toast.makeText(getApplicationContext(),
                                "", Toast.LENGTH_LONG)
                                .show();
                    } else {
                        Toast.makeText(mActivity, "Connecting...", Toast.LENGTH_SHORT).show();
                        linearlayoutdevices.setEnabled(false);
                        for (int i = 0; i < linearlayoutdevices.getChildCount(); ++i) {
                            Button btn = (Button) linearlayoutdevices.getChildAt(i);
                            btn.setEnabled(false);
                        }
                        btnDisconnect.setEnabled(false);
                        btnPrint.setEnabled(false);
                        es.submit(new MainActivity.TaskOpen(mUsb, mUsbManager, device));
                    }
                });
                linearlayoutdevices.addView(btDevice);
            }
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        // Handle the configuration change if needed
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        WebView webView = findViewById(R.id.webView);
        Intent intent;
        if (item.getItemId() == R.id.action_home) {
            intent = new Intent(this, MainActivity.class);
            startActivity(intent);
            return true;
        } else if (item.getItemId() == R.id.action_refresh) {
            webView.reload();
            return true;
        } else if (item.getItemId() == R.id.action_exit) {
            showExitConfirmationDialog();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public class TaskOpen implements Runnable {
        USBPrinting usb = null;
        UsbManager usbManager = null;
        UsbDevice usbDevice = null;

        public TaskOpen(USBPrinting usb, UsbManager usbManager, UsbDevice usbDevice) {
            this.usb = usb;
            this.usbManager = usbManager;
            this.usbDevice = usbDevice;
        }

        @Override
        public void run() {
            usb.Open(usbManager, usbDevice);
        }
    }

    static int dwWriteIndex = 1;

    public class TaskPrint implements Runnable {
        Pos pos = null;

        public TaskPrint(Pos pos) {
            this.pos = pos;
        }

        @Override
        public void run() {
            final boolean bPrintResult = PrintTicket(nPrintWidth, AppStartActivity.bCutter, AppStartActivity.bDrawer, AppStartActivity.bBeeper, AppStartActivity.nPrintCount, nCompressMethod);
            final boolean bIsOpened = pos.GetIO().IsOpened();

            mActivity.runOnUiThread(() -> {
                Toast.makeText(mActivity.getApplicationContext(), bPrintResult ? getResources().getString(R.string.printsuccess) : getResources().getString(R.string.printfailed), Toast.LENGTH_SHORT).show();
                mActivity.btnPrint.setEnabled(bIsOpened);
            });
        }

        public boolean PrintTicket(int nPrintWidth, boolean bCutter, boolean bDrawer, boolean bBeeper, int nCount, int nCompressMethod) {
            boolean bPrintResult = false;

            byte[] status = new byte[1];
            if (pos.POS_QueryStatus(status, 3000, 2)) {
                for (int i = 0; i < nCount; ++i) {
                    if (!pos.GetIO().IsOpened())
                        break;

                    pos.POS_FeedLine();
                    pos.POS_S_Align(1);
                    pos.POS_S_TextOut("REC" + String.format("%03d", i) + "\r\nCaysn Printer\r\n\r\n\r\n", 0, 1, 1, 0, 0x100);
                    pos.POS_S_TextOut("APP\r\n", 0, 0, 0, 0, 0x100);
                    pos.POS_S_SetQRcode("https://appsto.re/cn/2KF_bb.i", 8, 0, 3);
                    pos.POS_FeedLine();
                    pos.POS_S_SetBarcode("11606211111331200008", 0, 73, 2, 60, 0, 2);
                    pos.POS_FeedLine();
                }

                if (bBeeper)
                    pos.POS_Beep(1, 5);
                if (bCutter)
                    pos.POS_CutPaper();
                if (bDrawer)
                    pos.POS_KickDrawer(0, 100);

                int dwTicketIndex = dwWriteIndex++;
                bPrintResult = pos.POS_TicketSucceed(dwTicketIndex, 30000);
            }

            return bPrintResult;
        }
    }

    public class TaskClose implements Runnable {
        USBPrinting usb = null;

        public TaskClose(USBPrinting usb) {
            this.usb = usb;
        }

        @Override
        public void run() {
            usb.Close();
        }
    }

    @SuppressLint("MissingSuperCall")
    @Override
    public void onBackPressed() {
        WebView webView = findViewById(R.id.webView);

        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            showExitConfirmationDialog();
        }
    }

    private void showExitConfirmationDialog() {
        new AlertDialog.Builder(this)
                .setTitle("Exit Confirmation")
                .setMessage("Are you sure you want to exit the app?")
                .setPositiveButton("Exit", (dialog, which) -> finishAffinity())
                .setNegativeButton("Cancel", null)
                .show();
    }
}