Dica/Ajuda com impressão Bluetooth usando webview

9 respostas
javaandroidjavascript
V

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>

9 Respostas

Lucas_Camara

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

V

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);
    }
Lucas_Camara

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.

V

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!

V

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.

V

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!

Lucas_Camara

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

V

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?

Antonio_Borges_Jr

Ola, conseguiu alguma solução, estou com o mesmo problema e não estou conseguindo resolver

Criado 28 de janeiro de 2022
Ultima resposta 17 de fev. de 2024
Respostas 9
Participantes 3