How do I print to a Bluetooth thermal printer in Android?

In this example we are going to create a simple Android application to print texts to a Bluetooth thermal printer. We’ll be using the Android library for ESC/POS Thermal Printer to develop this example.

We begin by creating an Android project with an Empty Activity. After the project is created we need to edit the app/build.gradle to add the required dependencies and the repository from which it will be downloaded.

...
...

dependencies {
    ...
    ...
    implementation 'com.github.dantsu:escpos-thermalprinter-android:2.0.11'
}

allprojects {
    repositories {
        maven { url 'https://jitpack.io' }
    }
}

Next, add the permission to access Bluetooth in the AndriodManifest.xml file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="org.kodejava.android">

    <uses-permission android:name="android.permission.BLUETOOTH" />

    ...
    ...
</manifest>

Let’s now jump to the code snippet that will actually print our store receipt to the printer. The steps are quite simple.

After added the uses-permission in the AndroidManigest.xml we also need to check permission in the application, you’ll do it like this.

if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH}, MainActivity.PERMISSION_BLUETOOTH);
}

Open the connection to Bluetooth printer by calling the selectFirstPaired() method of the BluetoothPrintersConnections class. This will give us an instance of BluetoothConnection. If the connection is good we create an instance of EscPosPrinter by passing some parameters like the connection, printer dpi, width in millimeter and the printer’s number of character per line.

BluetoothConnection connection = BluetoothPrintersConnections.selectFirstPaired();
EscPosPrinter printer = new EscPosPrinter(connection, 203, 48f, 32);

The next step is to prepare the text to be printed and called the printFormattedText() of the printer object and pass the text to be printed.

String text = "[C]Hello World!\n";
printer.printFormattedText(text);

Here is the full code snippet for our application.

package org.kodejava.android;

import android.Manifest;
import android.content.pm.PackageManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.dantsu.escposprinter.EscPosPrinter;
import com.dantsu.escposprinter.connection.bluetooth.BluetoothConnection;
import com.dantsu.escposprinter.connection.bluetooth.BluetoothPrintersConnections;
import com.dantsu.escposprinter.textparser.PrinterTextParserImg;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {
    public static final int PERMISSION_BLUETOOTH = 1;

    private final Locale locale = new Locale("id", "ID");
    private final DateFormat df = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss a", locale);
    private final NumberFormat nf = NumberFormat.getCurrencyInstance(locale);

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

    public void doPrint(View view) {
        try {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH}, MainActivity.PERMISSION_BLUETOOTH);
            } else {
                BluetoothConnection connection = BluetoothPrintersConnections.selectFirstPaired();
                if (connection != null) {
                    EscPosPrinter printer = new EscPosPrinter(connection, 203, 48f, 32);
                    final String text = "[C]<img>" + PrinterTextParserImg.bitmapToHexadecimalString(printer,
                            this.getApplicationContext().getResources().getDrawableForDensity(R.drawable.logo,
                                    DisplayMetrics.DENSITY_LOW, getTheme())) + "</img>\n" +
                            "[L]\n" +
                            "[L]" + df.format(new Date()) + "\n" +
                            "[C]================================\n" +
                            "[L]<b>Effective Java</b>\n" +
                            "[L]    1 pcs[R]" + nf.format(25000) + "\n" +
                            "[L]<b>Headfirst Android Development</b>\n" +
                            "[L]    1 pcs[R]" + nf.format(45000) + "\n" +
                            "[L]<b>The Martian</b>\n" +
                            "[L]    1 pcs[R]" + nf.format(20000) + "\n" +
                            "[C]--------------------------------\n" +
                            "[L]TOTAL[R]" + nf.format(90000) + "\n" +
                            "[L]DISCOUNT 15%[R]" + nf.format(13500) + "\n" +
                            "[L]TAX 10%[R]" + nf.format(7650) + "\n" +
                            "[L]<b>GRAND TOTAL[R]" + nf.format(84150) + "</b>\n" +
                            "[C]--------------------------------\n" +
                            "[C]<barcode type='ean13' height='10'>202105160005</barcode>\n" +
                            "[C]--------------------------------\n" +
                            "[C]Thanks For Shopping\n" +
                            "[C]https://kodejava.org\n" +
                            "[L]\n" +
                            "[L]<qrcode>https://kodejava.org</qrcode>\n";

                    printer.printFormattedText(text);
                } else {
                    Toast.makeText(this, "No printer was connected!", Toast.LENGTH_SHORT).show();
                }
            }
        } catch (Exception e) {
            Log.e("APP", "Can't print", e);
        }
    }
}

The following image is the result of our code snippet printed on 48 mm thermal printer.

Android Bluetooth Thermal Printer

Android Bluetooth Thermal Printer

You can find the complete source code in the following repository Android Bluetooth Thermal Printer Example. For more information on formatted text syntax guideline you can visit the project documentation website.

How do I read MySQL data from Android using JDBC?

This example show you how to connect and read data from MySQL database directly from Android. The following steps and code snippet will show you how to do it.

Add the MySQL JDBC driver into your project dependencies. Open the app/build.gradle file and add the dependency.

...
...

dependencies {
    ...
    ...
    implementation 'mysql:mysql-connector-java:5.1.49'
}

If you want to connect to MariaDB you can change the JDBC driver dependency using 'org.mariadb.jdbc:mariadb-java-client:1.8.0', also update the JDBC url in the code snippet by replacing mysql with mariadb.

Next, add internet permission to our application in AndroidManifest.xml file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="org.kodejava.android">

    <uses-permission android:name="android.permission.INTERNET" />

    ...
    ...

</manifest>

Let’s connect, read data from the database and display the information on the screen. In the code snippet we create an AsyncTask to read the information from the database. In the doInBackground() method we open a connection to the database, create a PreparedStatement, execute a query, get a ResultSet and read the information from it. We pack the data into a Map and return it.

After the doInBackground() method finish its execution the onPostExecute() method will be called. In this method we take the result, the Map returned by the doInBackground() method, and set the values into the TextView components for display.

package org.kodejava.android;

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {
    private static final String URL = "jdbc:mysql://192.168.0.107:3306/kodejava";
    private static final String USER = "kodejava";
    private static final String PASSWORD = "kodejava";

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

        new InfoAsyncTask().execute();
    }

    @SuppressLint("StaticFieldLeak")
    public class InfoAsyncTask extends AsyncTask<Void, Void, Map<String, String>> {
        @Override
        protected Map<String, String> doInBackground(Void... voids) {
            Map<String, String> info = new HashMap<>();

            try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD)) {
                String sql = "SELECT name, address, phone_number FROM school_info LIMIT 1";
                PreparedStatement statement = connection.prepareStatement(sql);
                ResultSet resultSet = statement.executeQuery();
                if (resultSet.next()) {
                    info.put("name", resultSet.getString("name"));
                    info.put("address", resultSet.getString("address"));
                    info.put("phone_number", resultSet.getString("phone_number"));
                }                
            } catch (Exception e) {
                Log.e("InfoAsyncTask", "Error reading school information", e);
            }

            return info;
        }

        @Override
        protected void onPostExecute(Map<String, String> result) {
            if (!result.isEmpty()) {
                TextView textViewName = findViewById(R.id.textViewName);
                TextView textViewAddress = findViewById(R.id.textViewAddress);
                TextView textViewPhoneNumber = findViewById(R.id.textViewPhone);

                textViewName.setText(result.get("name"));
                textViewAddress.setText(result.get("address"));
                textViewPhoneNumber.setText(result.get("phone_number"));
            }
        }
    }
}
  • Finally, here is the screenshot of our Android application.
Android - MySQL JDBC

Android – MySQL JDBC

The complete source code can be accesses in our GitHub repository here: android-mysql-example.

Basic Operators in Java

This article covers basic operators of Java syntax, and how they function. By thorough discussion and coding examples, you’ll be able to use basic operators in your programs like a pro.

What are basic operators?

Java provides different sets of operators to perform simple computations like addition/ subtraction and other advanced operators for decision-making or individual bitwise calculations.

Here are some major categories of operators

  • Arithmetic Operators (+, -, *, /)
  • Relational Operators (==, !=)
  • Logical Operators (&&, ||)
  • Assignment Operators (=, +=, -=)
  • Unary Operators (pre/post-fix)
  • Shift Operators (>>, << )
  • Bitwise Operators (&, |, ^)
  • Ternary/Conditional Operator (?:)
  • Misc Operators

The scope of this article encompass arithmetic, relational and logical operators only.

Arithmetic Operators

You can use basic arithmetic operators to perform a mathematical calculation and impact the value of any variable. Let’s see how it works in Java.

package com.basicoperators.core;

public class ArithmeticOperators {
    public static void main(String[] args) {
        // Addition 
        int apples = 5;
        int oranges = 7;
        int totalFruits = apples + oranges;

        System.out.println("\n-------------Addition---------------- " );
        System.out.println("Apples: " + apples);
        System.out.println("Oranges: " + oranges);
        System.out.println("Total Fruits: " + totalFruits);

        // Subtraction      
        int totalBananas = 24;
        int bananasSold = 12;
        int bananasLeft = totalBananas - bananasSold;

        System.out.println("\n----------------Subtraction--------------- " );
        System.out.println("Total Bananas: " + totalBananas);
        System.out.println("Bananas Sold: " + bananasSold);
        System.out.println("Bananas Left: " + bananasLeft);

        // Multiplication   
        int weeks = 3;
        int daysInAWeek = 7;
        int totalNumberOfDays = weeks * daysInAWeek;

        System.out.println("\n--------------Multiplication-------------- " );
        System.out.println("Days In A Week: " + daysInAWeek);
        System.out.println("Days In A Week: " + daysInAWeek);
        System.out.println("Total Number Of Days: " + totalNumberOfDays);

        // Division
        int totalMinutesConsumed = 420;
        int minutesInOneHour = 60;
        int numOfHours = totalMinutesConsumed / minutesInOneHour;

        System.out.println("\n----------------Division---------------- " );

        System.out.println("Total Minutes: " + totalMinutesConsumed);
        System.out.println("Minutes In One Hour: " + minutesInOneHour);
        System.out.println("Num Of Hours: " + numOfHours);    
    }
}

Output

----------------------Addition---------------------- 
Apples: 5
Oranges: 7
Total Fruits: 12

---------------------Subtraction--------------------- 
Total Bananas: 24
Bananas Sold: 12
Bananas Left: 12

--------------------Multiplication------------------- 
Days In A Week: 7
Days In A Week: 7
Total Number Of Days: 21

----------------------Division---------------------- 
Total Minutes Consumed: 420
Minutes In One Hour: 60
Num Of Hours: 7

Relational Operators

As the name implies, relational operators define the relationship of one instance with another. This means you can compare two numbers and see what relationship do they share. If they are equal to each other, one is greater than or smaller than the other number. Like 2 is less than 3. According to Java syntax, both instances should be of the same data type. For example, you can not compare if an integer is less than a string. Here is a small snippet explaining how you can use basic relational operators in Java.

package com.basicoperators.core;

public class RelationalOperators {
    public static void main(String[] args) {
        int even = 2;
        int odd = 3;

        System.out.println("Even = " + even);
        System.out.println("Odd = " + odd);

        // prints if even is equal to odd
        boolean check = even == odd;
        System.out.println("Is Even equal to Odd? " + check);

        // prints if even is not equal to odd
        check = even != odd;
        System.out.println("Is Even not equal to Odd? " + check);

        // prints if even is greater than odd
        check = even > odd;
        System.out.println("Is Even greater than Odd? " + check);

        // prints if even is less than odd
        check = even < odd;
        System.out.println("Is Even less than Odd? " + check);

        // prints if even is greater than equal to odd
        check = even >= odd;
        System.out.println("Is Even greater than equal to Odd? " + check);

        // prints if even is less than equal to odd
        check = even <= odd;
        System.out.println("Is Even less than equal to Odd? " + check);
    }
}

Output

Even = 2
Odd = 3
Is Even equal to Odd? false
Is Even not equal to Odd? true
Is Even greater than Odd? false
Is Even less than Odd? true
Is Even greater than equal to Odd? false
Is Even less than equal to Odd? true

Logical Operators

Logical Operators in Java are used for decision-making. They allow the programmer to test if the combination of given expressions are true or false. Based on the result of your expression, you can make a decision.

  • AND – returns “true” only if both expressions are true
  • OR – returns “true” if any of the given expressions is true
  • NOT – returns the “inverse” of any given boolean expression

For your better understanding, let’s look at the following snippet.

package com.basicoperators.core;

public class LogicalOperators {
    public static void main(String[] args) {
        String myPet1 = "doggo";
        String myPet2 = "kitty";

        System.out.println("Pet1: " + myPet1);
        System.out.println("Pet2: " + myPet2);

        // implements AND
        boolean check = myPet1.equals("doggo") && myPet2.equals("kitty");
        // returns true only when both conditions are true
        System.out.println("Does my first pet name \"doggo\", and second one \"kitty\"? " + check);

        check = myPet1.equals("dog") && myPet2.equals("kitty");
        // returns "false" even if single condition is false 
        // remember these conditions are case sensitive
        System.out.println("Does my first pet name \"dog\", and second one \"kitty\"? " + check);

        // implements OR
        check = myPet1.equals("doggo") || myPet2.equals("lion");
        // returns "true" even when single condition is true
        System.out.println("Does any of my pet name \"doggo\"? " + check);

        check = myPet1.equals("cat") || myPet2.equals("tiger");
        // returns "false" because both conditions are false
        System.out.println("Does any of my pet name \"tiger\"? " + check);

        // implements NOT
        check = !(myPet1.equals("bingo") && myPet2.equals("kate"));
        // returns "true" when both conditions are true (inverse of statement)
        System.out.println("Does my first pet name \"bingo\", and second one \"kate\"? " + check);

        check = !(myPet1.equals("doggo") && myPet2.equals("kitty"));
        // returns "false" because both conditions are true
        System.out.println("Does my first pet name \"doggo\", and second one \"kitty\"? " + check);
    }
}

Output

Pet1: doggo
Pet2: kitty
Does my first pet name "doggo", and second one "kitty"? true
Does my first pet name "dog", and second one "kitty"? false
Does any of my pet name "doggo"? true
Does any of my pet name "tiger"? false
Does my first pet name "bingo", and second one "kate"? true
Does my first pet name "doggo", and second one "kitty"? false

Conclusion

The basic operators in Java are pretty simple to learn and easy to use. You might get overwhelmed by studying the different operators all at once. However, we recommend you practicing one set at a time. This way, you’ll master all of them soon. As always, you’re welcome to plug-in in case of any confusion. Happy learning!

How do I install Calibri font in Ubuntu?

I need to create a Microsoft Word Mail Merge document in my Java Spring MVC application. But running it in Ubuntu server resulting in a document that missing the default font use in the document, which is the Calibri font. So I need to install the font in Ubuntu to make the document looks as expected.

Here what I need to do to install the font in my Ubuntu box. Starts by updating the repository package list to get latest packages information for upgrades or new package installation.

sudo apt-get update

Then install FontForge in our system. FontForge is a free and open source font editor, but in this case it will help to do the font conversion in the installation script on the upcoming step.

sudo apt-get install fontforge

Install the Microsoft Cabinet file un-packer. This is required for the next script to successfully install the fonts.

sudo apt-get install cabextract

The following script will install Microsoft Vista TrueType Fonts (TTF) in Ubuntu. It includes the following fonts, Calibri, Cambria, Candara, Consolas, Constantia, and Corbel.

wget https://gist.githubusercontent.com/maxwelleite/10774746/raw/ttf-vista-fonts-installer.sh -q -O - | sudo bash

Run the next command to see if the font successfully installed. You will see the Calibri fonts in the result if the fonts successfully installed.

fc-list | grep Calibri

Here are the list of installed Calibri fonts.

/usr/share/fonts/truetype/vista/calibriz.ttf: Calibri:style=Bold Italic
/usr/share/fonts/truetype/vista/calibrii.ttf: Calibri:style=Italic
/usr/share/fonts/truetype/vista/calibrib.ttf: Calibri:style=Bold
/usr/share/fonts/truetype/vista/calibri.ttf: Calibri:style=Regular

How do I create a generic class in Java?

In this example you will learn how to create a generic class in Java. In some previous post in this blog you might have read how to use generic for working with Java collection API such as List, Set and Map. Now it is time to learn to create a simple generic class.

As an example in this post will create a class called GenericMachine and we can plug different type of engine into this machine that will be use by the machine to operate. For this demo we will create two engine type, a DieselEngine and a JetEngine. So let’s see how the classes are implemented in generic.

package org.kodejava.generics;

public class GenericMachine<T> {
    private final T engine;

    public GenericMachine(T engine) {
        this.engine = engine;
    }

    public static void main(String[] args) {
        // Creates a generic machine with diesel engine.
        GenericMachine<DieselEngine> machine = new GenericMachine<>(new DieselEngine());
        machine.start();

        // Creates another generic machine with jet engine.
        GenericMachine<JetEngine> anotherMachine = new GenericMachine<>(new JetEngine());
        anotherMachine.start();
    }

    private void start() {
        System.out.println("This machine running on: " + engine);
    }
}

Now, for the two engine class we will only create an empty class so that the GenericMachine class can be compiled successfully. And here are the engine classes:

package org.kodejava.generics;

public class DieselEngine {
}
package org.kodejava.generics;

public class JetEngine {
}

The <T> in the class declaration tell that we want the GenericMachine class to have type parameter. We also use the T type parameter at the class constructor to pass the engine.