Dica/Ajuda com impressão Bluetooth usando webview

Pessoal, estou tentando fazer a impressão em uma impressora Bluetooth, e seguindo o tutorial: https://developer.android.com/training/printing/html-docs?hl=pt-BR, fiz o seguinte:

public class MainActivity extends AppCompatActivity {
  
  WebView mywebView;
  WebView mWebView;
  private static final String TAG = "MainActivity";
  
  @SuppressLint("JavascriptInterface")
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mywebView = (WebView) findViewById(R.id.webview);
    
    WebSettings webSettings = mywebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    getSupportActionBar().hide();
    mywebView.setInitialScale(1);
    mywebView.getSettings().setUseWideViewPort(true);            
    webSettings.setLoadWithOverviewMode(true);
    
    mywebView.getSettings().setDomStorageEnabled(true);
    mywebView.getSettings().setDatabaseEnabled(true);
    mywebView.getSettings().setMinimumFontSize(1); //opcional
    mywebView.getSettings().setMinimumLogicalFontSize(1); //opcional
    mywebView.getSettings().setSupportZoom(false); //opcional
    mywebView.getSettings().setAllowFileAccess(true);
    mywebView.getSettings().setAllowContentAccess(true);
    mywebView.loadUrl("http://192.168.1.17:8080/teste/");

    mywebView.setWebViewClient(new WebViewClient());
  }
  
  class MyJavascriptInterface {
    Context context;
    WebView view;
    
    public MyJavascriptInterface(Context context, WebView view) {
      this.context = context;
      this.view = view;
    }
    
    @JavascriptInterface
    public void doPrint() {
      createWebPrintJob(view);
    }
    
    private void doWebViewPrint(WebView webView) {
      WebView webView2 = (WebView) findViewById(R.id.webview);
      
      webView2.setWebViewClient(new WebViewClient() {
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
          return false;
        }
        
        @Override
        public void onPageFinished(WebView view, String url) {
          Log.i(TAG, "page finished loading " + url);
          createWebPrintJob(view);
          mWebView = null;
        }
      });
      
      mywebView.loadUrl("http://192.168.1.17:8080/teste/paginas/imprime.xhtml");
      mWebView = webView;
    }
  }
  
  private void createWebPrintJob(WebView webView) {
    // Get a PrintManager instance
    PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
    String jobName = getString(R.string.app_name) + " Document";
    
    // Get a print adapter instance
    PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(jobName);
    
    // Create a print job with name and adapter instance
    PrintJob printJob = printManager.print(jobName, printAdapter, new PrintAttributes.Builder().build());
    
    // Save the job object for later status checking
    // printJobs.add(printJob);
  }
  
  public void onBackPressed() {
    if (mywebView.canGoBack()) {
      mywebView.goBack();
    } else {
      super.onBackPressed();
    }
  }
}

Hoje a situação é: Na pagina inicial, escolho 5 números e, após clicar em finalizar, exibo as dezenas na pagina imprime.xhtml, e gostaria de imprimir usando uma impressora Bluetooth através do meu WebView.

Na página imprime.xhtml, coloquei 2 botões. 1 para imprimir pelo computador e outro para android. Só que quando executo no Android não acontece nada. Minha página:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui">

<h:head>
  <h:outputStylesheet library="css" name="estilos.css" />
  <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0" />
</h:head>

<body>	
  <h:outputText value="Dezenas Escolhidas:"/><br></br>
  <h:outputText value="#{imprimeController.dezena.b1} - "></h:outputText>
  <h:outputText value="#{imprimeController.dezena.b2} - "></h:outputText>
  <h:outputText value="#{imprimeController.dezena.b3} - "></h:outputText>
  <h:outputText value="#{imprimeController.dezena.b4} - "></h:outputText>
  <h:outputText value="#{imprimeController.dezena.b5} - "></h:outputText>
  
  <input type="button" value="Imprimir" onClick="window.print()" />
  <input type="button" value="Android" onClick="doWebViewPrint()" />
  
  <script type="text/javascript">
    function doWebViewPrint() {
      Android.doPrint();
    }
  </script>
</body>

</html>

O que é essa chamada: Android.doPrint();? Ela deveria invocar algo no app?

olá, Lucas! Pelo exemplo que vi o Android.doPrint() na pagina xhtml chamaria o método criado no app. No entanto nada acontece… Gostaria que o app que é um WebView conseguisse imprimir a pagina ou se eu conseguisse passar de alguma forma os dados para que pudesse imprimir no app. O método criado no webview seria esse:

 @JavascriptInterface
    public void doPrint() {
        createWebPrintJob(view);
    }

Dando uma pesquisada, parece que vc teria que fazer isso no seu app:

mywebView.addJavascriptInterface(new MyJavascriptInterface(this, mWebView), "app");

Fiquei confuso com seu código pq tem duas WebView declaradas. Isso está certo?

Uma dica, qdo vc estiver com problemas ao tentar implementar algo, é ir fazendo as coisas por partes usando apenas o código necessário para funcionar. Ex.: Primeiro faça com que a comunicação entre a página do webview e seu app funcione, não se preocupe com o resto. Coloque apenas para imprimir algo no console para ver se funcionou. Depois de funcionar, faça a implementação que quer.

Verdade que precisava declarar a interface pra ser chamada na página Web e agora tenho acesso ao método: doPrint() da classe MyJavascriptInterface.

 public class MyJavascriptInterface {
        Context context;
        WebView view;

    public MyJavascriptInterface(Context context, WebView view) {
        this.context = context;
        this.view = view;
    }

        @JavascriptInterface
        public void doPrint() {
            Log.i(TAG, "CHAMANDO METODO DOPRINT() -------------------------");
                      
            BluetoothAdapter lbtAdapter = BluetoothAdapter.getDefaultAdapter();
            Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();     

            if (pairedDevices.size() > 0) {
                for (BluetoothDevice device : pairedDevices) {
                    Log.i(TAG, "DEVICE pareadass ********************************      ---- "+device.getName());
                    //adapter.add(device.getName() + "\n" + device.getAddress());
                }
            }
            doWebViewPrint();
        }

        @JavascriptInterface
        public void doWebViewPrint() {
            Log.i(TAG, "CHAMANDO O DO WEB PRINT       ==============================");

            WebView webView2 = (WebView) findViewById(R.id.webview);

             // Dá erro nessa linha...
            webView2.setWebViewClient(new WebViewClient() {

                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    return false;
                }

                @Override
                public void onPageFinished(WebView view, String url) {
                    Log.i(TAG, "page finished loading " + url);

                    createWebPrintJob(view);
                    mywebView = null;
                }
            });
            Log.i(TAG, "CHAMANDO O DO WEB PRINT     11111111  ==============================");

            mywebView.loadUrl("http://192.168.1.17:8080/clubedos10/paginas/jogo/imprimeJogo.xhtml");


        }

    }

coloquei pra listar as impressoras pareadas e exibe, no entanto ao chamar o método doWebViewPrint() na linha: webView2.setWebViewClient(new WebViewClient() retorna o seguinte erro:

java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread.

Imaginava algo tipo:
Listar as impressoras e enviar a pagina ou arquivo para ser impresso, mas não consegui!

Alterei a chamada do método que cria o serviço de impressão e ficou assim:

 @JavascriptInterface
    public void doPrint() {
    mywebView.post(new Runnable() {
                @Override
                public void run() {
                    doWebViewPrint();
                }
     });

Após clicar no botão de imprimir exibe a tela para impressão, no entanto não exibe as devices pareadas com a maquina pra poder selecionar a impressora.

Consegui fazer a impressão de um texto seguindo os seguintes passos:

  @JavascriptInterface
        public void doPrint() throws IOException {
            Log.i(TAG, "CHAMANDO METODO DOPRINT() -------------------------");
            BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
           Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
            if (pairedDevices.size() > 0) {
                for (BluetoothDevice device : pairedDevices) {                       
                    if (device.getName().equalsIgnoreCase("Bluetooth Printer")){                         
                        Log.i(TAG, "--------------- Achei minha Impressora  ******* "+device.getName());
                        bluetoothDevice = device;
                        break;
                    }
                }
            }

     openBluetoothPrinter();
     printData();
 }


 void openBluetoothPrinter() throws IOException {
        try{
            UUID uuidSting = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
            bluetoothSocket=bluetoothDevice.createRfcommSocketToServiceRecord(uuidSting);
            bluetoothSocket.connect();
            outputStream=bluetoothSocket.getOutputStream();
            inputStream=bluetoothSocket.getInputStream();

            beginListenData();

        }catch (Exception ex){

        }
    }

    void beginListenData(){
        try{

            final Handler handler =new Handler();
            final byte delimiter=10;
            stopWorker =false;
            readBufferPosition=0;
            readBuffer = new byte[1024];

            thread=new Thread(new Runnable() {
                @Override
                public void run() {

                    while (!Thread.currentThread().isInterrupted() && !stopWorker){
                        try{
                            int byteAvailable = inputStream.available();
                            if(byteAvailable>0){
                                byte[] packetByte = new byte[byteAvailable];
                                inputStream.read(packetByte);

                                for(int i=0; i<byteAvailable; i++){
                                    byte b = packetByte[i];
                                    if(b==delimiter){
                                        byte[] encodedByte = new byte[readBufferPosition];
                                        System.arraycopy(
                                                readBuffer,0,
                                                encodedByte,0,
                                                encodedByte.length
                                        );
                                        final String data = new String(encodedByte,"US-ASCII");
                                        readBufferPosition=0;
                                        handler.post(new Runnable() {
                                            @Override
                                            public void run() {
                                                //lblPrinterName.setText(data);
                                            }
                                        });
                                    }else{
                                        readBuffer[readBufferPosition++]=b;
                                    }
                                }
                            }
                        }catch(Exception ex){
                            stopWorker=true;
                        }
                    }

                }
            });

            thread.start();
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

    void printData() throws  IOException{
        try{
            String msg = "MEUTEXTO A IMPRIMIR";
            String msg2 = "Meu Texto da Segunda linha----";

            msg+="\n";
            msg2+="\n";               
            outputStream.write(msg.getBytes());
            outputStream.write(msg2.getBytes());

           // lblPrinterName.setText("Printing Text...");
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

A Questão agora é: Como Posso montar minha impressão da aplicação Web? Alguém poderia me dá essa dica/ajuda? Tipo: passar a URL para impressão. Ou então pegar os dados da página web e passar para o WebView e ter controle de “desenhar” o relatório. Desde já, agradeço. Obrigado!

Será que daria certo passar parâmetro para esse método doPrint?

Estou procurando alguma solução porque na verdade não sei como fazer essa impressão! rsrs.
Quando faz no Java utilizando o JasperReport, por exemplo, tem o relatorio .jasper e pode usar o JRPdfExportere enviar direto para impressora. Mas no Android eu ainda nao sei como proceder… Tem que “desenhar na mão”? Existe alguma ferramenta de suporte para criar relatórios e chamar no app?