Printer driver

Sunmi Printer Driver

 

Introduction

 

Sunmi V1, P1, T1 all have their built-in thermal printers, to allow App to directly print out the thermal receipts. As for the built-in printers of Sunmi products, two specifications are available in total:

•        80 mm wide, with cutter. Compatible with 58 mm. H10, T1 has been equipped with this type of printer.

•        58 mm wide, without cutter. V1, V2 has been equipped with this type of printer.

 

How App invokes the built-in thermal printer

App developers can invoke the built-in thermal printer with 3 types of methods:

1.      To connect the printer via Bluetooth

2.      To connect the printer via AIDL

3.      To invoke the printer via JS bridge

 

Take V1 device as an example as follows to introduce two types of invoke methods. This solution is also applicable for P1, T1 device.

One. To connect and invoke via Bluetooth

You can see an already matched and everlasting Bluetooth device in V1’s Bluetooth device list—“InnerPrinter”, which is a printer device virtualized by the operating system and does not exist in reality. Yet its communication method is almost identical to that of an external Bluetooth printer. It is used to make it easy for the developers who have already been familiar with ESC/POS commands to adapt to V1. In this way, they can quickly transfer the print code to V1 without modifying the code.

 

Thus, you are suggested to use Bluetooth connection mode if the following conditions are met: the developer has already been familiar with ESC/POS commands, or even his/her owned App has already completed the development in terms of ESC/POS commands,or it is expected to keep the versatility of the printing method, not to highly depend on the features of Sunmi devices.

 

If you are still not familiar with ESC/POS commands, you can click here to  download “Instructions for ESC/POS Commands” to realize the command set supported by V1.

 

The principle of completing the print via connecting InnerPrinter virtual printer is:

1.       Establish connection with this Bluetooth device

2.       Splice the commands & text content and transcode them to Bytes

3.       Send it to InnerPrinter

4.       The bottom layer print service drives the printing device to complete printing

 

As for how to connect “InnerPrinter”, the developers can search online the Bluetooth connection related basic course. To make it easy for reading, the development code of Bluetooth device connection is described in brief as follows, for the convenience of getting started quickly.

The following is the printing effect of Bluetooth Demo App, click here to download Demo Apk & source code 

 

Among it, 5 key operations are included:

1.        Add Bluetooth Permissions Statement in App project

  
    
    
    

2.       Obtain BluetoothAdapter of Bluetooth device

  BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBluetoothAdapter == null && !mBluetoothAdapter.isEnabled()) {
       Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  
       startActivityForResult(intent, REQUEST_ENABLE_BT);
    }

3.       Obtain Virtual Bluetooth device

 String innerprinter_address = "00:11:22:33:44:55";
    BluetoothDevice innerprinter_device = null;
    Set devices = mBluetoothAdapter.getBondedDevices();
    for(BluetoothDevice device : devices){
        if(device.getAddress().equals(innerprinter_address)){
              innerprinter_device = device;
         }
     }

4.       Obtain BluetoothSocket (Bluetooth socket)

 UUID PRINTER_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
   BluetoothSocket mSocket = 
   innerprinter_device.createRfcommSocketToServiceRecord(PRINTER_UUID);

5.       Send the print command Bytes that has already finished slicing to InnerPrinter via sendData (byte[]bytes) method

  OutputStream mOut = mSocket.getOutputStream();
   private void sendData(byte[] bytes) {
          if (mOut != null) {
              try {
                  mOut.write(bytes, 0, bytes.length);
                  mOut.flush();
              } catch (IOException e) {
                  Log.e("TAG", e.getMessage());
              } finally {
                 try {
                      mOut.close();
                  } catch (IOException e) { }
              }
          }
    }

The byte[]bytes parameter in the fifth key operation is the receipt content that is ready for printing, which is the content to be sliced with command Byte after the text has been converted to Byte via “GBK” code.

 

Each line of 58 mm printer contains 384 pixels. The default width of each Chinese character is 24 pixels while that of each English character is 12 pixels. Thus, 16 Chinese characters or 32 English characters can be printed out at maximum in one line, and automatic line wrap will be carried out after printing each line. You can certainly carry out mandatory line wrap by printing the character of “”.

The default height of each line is 30 pixels. You can control the font size by setting times of height & times of width with command, and control the text position of each line with alignment command.

 

Please refer to “Instructions for ESC/POS Commands” to know about more details of the control commands.

Note: the problem that several Apps initiate the print request at the same time may occur. We suggest that you’d better send the print data all at one time if you are going to print with Virtual Bluetooth.

 

 Two. Invoke the printer with AIDL

 Background

 

The inventor of receipt printer is EPSON, who also designed and defined the ESC/POS commands. It appeared before Android and had already been applied extensively in catering, retail industry before the popularization of Internet, with a history of above 15 years up to now

 

Therefore, the data processing method in the command is nearer to the bottom layer, and some developers that have experienced traditional software development may have their own encapsulation & accumulation at these command sets. However, to the emerging Internet developers, they’ll be loaded down with trivial details no matter it’s print text, picture or formatting, which require the investment of certain cost cycle to adapt to them.

 

Therefore, the V1 developers may also have built-in print service by use of AIDL connection of Android standard, and invoke the printer.

 

AIDL is the abbreviation for Android Interface Definition Language, which is a type of descriptive language for the communication interface of Android internal process. Through it, we can define the communication interface between processes. The developer may check the relevant online documentation for relevant instructions as for AIDL’s usage method.

Certainly, the developers may also temporarily skip the principles of AIDL, and quickly realize the invoke method via the short instructions & example code in the following text.

Course

 It is required to first download AIDL file & Demo, and the
compression document contains two parts of content:

 1.      Demo is the source code of print example project we prepare. The following effect is the receipt printed via Demo, T1.

2.      AIDL file is the interface method list exposed by all the print service, which is required to be integrated into its own App source code project.

 

The following is the interpretation of the concrete key operation invoking in Demo App:

 1.      Add AIDL file attached to the resource file to his/her own project:

(1)    Establish woyou.aidlservice.jiuiv package under src;

(2)    Add two files of IWoyouService.aidl, ICallback.aidl.

 

2.      Realize ServiceConnection in the code class to control the print.

 private ServiceConnection connService = new ServiceConnection() {
       @Override
        public void onServiceDisconnected(ComponentName name) {
                woyouService = null;
            }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
                woyouService = IWoyouService.Stub.asInterface(service);
                setButtonEnable(true);
           }
        };  

3.      Invoke ApplicationContext.bindService(), and transfer in the realization of ServiceConnection.

 Note: bindservice is a non-blocking invoke, which means that the binding is not successfully done immediately after completing the invoke, and it must be subject to serviceConnected.

 Intent intent=new Intent(); 
 intent.setPackage("woyou.aidlservice.jiuiv5"); 
 intent.setAction("woyou.aidlservice.jiuiv5.IWoyouService"); 
 startService(intent); bindService(intent, connService, 
 Context.BIND_AUTO_CREATE);

4.      In the realization of ServiceConnection.onServiceConnected(), you will receive an IBinder example (Service to be invoked).  Invoke IWoyouService.Stub.asInterface(service) and convert the parameters to IWoyouService type.

 

5.      Now it’s OK to invoke various methods defined at IWoyouService interface to carry out printing. In this step, you’ll always detect RemoteException exception, which are thrown out when disconnected, and thus requiring to be processed here. It will only be thrown out by remote method. In the interface method, ICallback can transfer null. When disconnected, ApplicationContext.unbindService() in the interface example is invoked.

Methods of printing a variety of data and controlling the format are encapsulated in IWoyouService, for example:

 woyouService.printText("this is a text",callback); 
 woyouService.printTextWithFont("this is a text with font","",36,callback); 
 woyouService.setFontSize(24,callback); 
 woyouservice.printColumnsText("print a line of a table!",12,0,callback);

This interface also contains at the same time the method of printing
the data sliced by ESC/POS:

 woyouService.sendRAWData(bytes,callback);

Note: the problem that several Apps initiate the print request at the same time may occur. We suggest that you use transaction printing if you are going to print via AIDL.

Three. Invoke the printer via JS in HTML

To invoke the printer with JS is in essence to operate android native code in HTML via JS bridge to realize printing, that is, to realize printing via Bluetooth printing or AIDL method. We have prepared a Demo for the developers. In this Demo, you may invoke a method already written in java by clicking one button in HTML, and then invoke the printer with AIDL method to print out a piece of self-checking receipt.

 

Concrete invoking procedure as follows:

 

1.       Define the method to be used in android in HTML.

document.getElementsByTagName('a')[0].addEventListener('click', function(){
          
          var a = "wellcome to sunmi";
                  javascript:lee.funAndroid(a);   
          return false;
      }, false);      

2.      Initialization of WebView.

    WebView mWebView = (WebView) findViewById(R.id.wv_view);
    // 设置编码
    mWebView.getSettings().setDefaultTextEncodingName("utf-8");
    // 支持js
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.setWebChromeClient(new WebChromeClient());

    Initialization of print service

Intent intent = new Intent();
intent.setPackage("woyou.aidlservice.jiuiv5");
intent.setAction("woyou.aidlservice.jiuiv5.IWoyouService");
startService(intent);//Start printer service
bindService(intent, connService, Context.BIND_AUTO_CREATE);

3.      Add monitor for WebView, invoke WebView.addJavascriptInterface(new JsObject(), ‘lee’) in the callback method of onPageFinished; In JsObject class, define the operating method specified in HTML via @JavascriptInterface, and print out a piece of receipt by invoking AIDL printing mode in this method.

mWebView.setWebViewClient(new WebViewClientDemo());//添加一个页面相应监听类

class WebViewClientDemo extends WebViewClient {

     @Override
     public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // 当打开新链接时,使用当前的 WebView,不会使用系统其他浏览器
         view.loadUrl(url);
         return true;
       }

      @Override
      public void onPageFinished(WebView view, String url) {
      super.onPageFinished(view, url);
         /**
          * 注册JavascriptInterface,其中"lee"的名字随便取,如果你用"lee",那么在html中只要用  lee.方法名()
          * 即可调用MyJavascriptInterface里的同名方法,参数也要一致
          */
           mWebView.addJavascriptInterface(new JsObject(), "lee");
                }

        }
        
        
        class JsObject {

                @JavascriptInterface
                public void funAndroid(final String i) {
                        Toast.makeText(getApplicationContext(), "calling the local method funAndroid by JS. " + i,
                        Toast.LENGTH_SHORT).show();
                                
                        try {
                                woyouService.printerSelfChecking(callback);//Using AIDL to print something. 
                        } catch (RemoteException e) {
                                e.printStackTrace();
                        }
                }
        }

4.       Load HTML file, and then it’s OK to print out a piece of receipt when clicking a button in HTML.

// 载入包含js的html
mWebView.loadData("", "text/html", null);
mWebView.loadUrl("file:///android_asset/test.html");//这里是您业务html所在的网页

 About invoking printer with jar package 

Due to the upgrade of our print service, the invoke of this method will no longer be compatible as for print service versions above 2.0.0. If you have already used this method for printing, we suggest that you judge whether it is greater than or equal to ‘2.0.0’ by obtaining the printer version number, so as to be compatible with print service with different versions. You may use the codes similar to those as follows:

   ... //绑定打印服务成功后得到一个IWoyouService类型的变量woyouService
    String version=woyouService.getServiceVersion(); //获取到打印服务的版本号
    if(version.compareTo("2.0.0")>=0){  //判断是否是新的打印服务
      ... //AIDL的方式调用打印服务
    }else{
      ... //依旧是通过jar包来调用打印服务
    }