How do I pretty print JSON string in JSON-Java?

In JSON-Java we can make a pretty-printed JSON string by specifying an indentFactor to the JSONObject‘s toString() method. The indent factor is the number of spaces to add to each level of indentation.

If indentFactor > 0 and the JSONObject has only one key, the JSON string will be printed a single line, and if the JSONObject has 2 or more keys, the JSON string will be printed in multiple lines.

Let’s create a pretty-printed JSONObject text using the code below.

package org.kodejava.json;

import org.json.JSONArray;
import org.json.JSONObject;

public class PrettyPrintJSON {
    public static void main(String[] args) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", 1L);
        jsonObject.put("name", "Alice");
        jsonObject.put("age", 20);
        JSONArray courses = new JSONArray(
                new String[]{"Engineering", "Finance"});
        jsonObject.put("courses", courses);

        // Default print without indent factor
        System.out.println(jsonObject);

        // Pretty print with 2 indent factor
        System.out.println(jsonObject.toString(2));
    }
}

Running this code produces the following output:

{"courses":["Engineering","Finance"],"name":"Alice","id":1,"age":20}
{
  "courses": [
    "Engineering",
    "Finance"
  ],
  "name": "Alice",
  "id": 1,
  "age": 20
}

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20220924/json-20220924.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20220924</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

How do I create JSONArray object?

A JSONArray object represent an ordered sequence of values. We use the put() method to add or replace values in the JSONArray object. The value can be of the following types: Boolean, JSONArray, JSONObject, Number, String or the JSONObject.NULL object.

Beside using the put() method we can also create and add data into JSONArray in the following ways:

  • Using constructor to create JSONArray from string wrapped in square bracket [], where the values are separated by comma. JSONException maybe thrown if the string is not a valid JSON string.
  • Creating JSONArray by passing an array as an argument to its constructor, for example an array of String[].
  • Using constructor to create JSONArray from a Collection, such as an ArrayList object.

The following example show you how to create JSONArray object.

package org.kodejava.json;

import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class CreateJSONArray {
    public static void main(String[] args) {
        // Create JSONArray and put some values
        JSONArray jsonArray = new JSONArray();
        jsonArray.put("Java");
        jsonArray.put("Kotlin");
        jsonArray.put("Go");
        System.out.println(jsonArray);

        // Create JSONArray from a string wrapped in bracket and
        // the values separated by comma. String value can be 
        // quoted with single quote.
        JSONArray colorArray = new JSONArray("[1, 'Apple', 2022-02-07]");
        System.out.println(colorArray);

        // Create JSONArray from an array of String.
        JSONArray stringArray =
                new JSONArray(new String[]{"January", "February", "March"});
        System.out.println(stringArray);

        // Create JSONArray by passing a List to its constructor
        List<String> list = new ArrayList<>();
        list.add("Red");
        list.add("Green");
        list.add("Blue");
        JSONArray listArray = new JSONArray(list);
        System.out.println(listArray);

        // Using for loop to get each value from the array
        for (int i = 0; i < listArray.length(); i++) {
            System.out.println("Color: " + listArray.get(i));
        }

        // Put JSONArray into a JSONObject.
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("colors", listArray);
        System.out.println(jsonObject);
    }
}

Running the code above produces the following result:

["Java","Kotlin","Go"]
[1,"Apple","2022-02-07"]
["January","February","March"]
["Red","Green","Blue"]
Color: Red
Color: Green
Color: Blue
{"colors":["Red","Green","Blue"]}

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20220924/json-20220924.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20220924</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

How do I read values from JSONObject?

A JSONObject is an unordered collection of key-value pairs. To read values from the JSONObject we can use the get(String key) and opt(String key) methods. These generic methods return an Object, which you can cast to a certain type.

There are also typed get and opt methods to read value in specific type such as getString(), getInt(), getDouble(), optString(), optFloat(), optBigInteger(), optBoolean(), optEnum(), etc. For more detail, you can check the JSONObject API documentation.

The get methods throws JSONException when the key is not found in the JSONObject, while the opt methods does not throw exception but return null, and we can also pass a default value argument that will be returned when the key is not found.

The code below give you a simple example to read values from JSONObject.

package org.kodejava.json;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class ReadJSONValue {
    public static void main(String[] args) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", 1L);
        jsonObject.put("name", "Alice");
        jsonObject.put("age", 20);
        jsonObject.put("courses",
                new JSONArray(new String[] {"Engineering", "Finance"}));
        System.out.println(jsonObject);

        // Using get() and opt() methods we need to cast
        // the returned value to the type its store.
        long id1 = (long) jsonObject.get("id");
        String name1 = (String) jsonObject.get("name");
        int age1 = (int) jsonObject.get("age");
        JSONArray courses1 = (JSONArray) jsonObject.get("courses");

        // This will throw exception because JSONObject
        // does not have the address key in it.
        String address1;
        try {
            address1 = (String) jsonObject.get("address");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        // Using opt() method to read address, does not throw
        // exception
        address1 = (String) jsonObject.opt("address");

        System.out.println("id1      = " + id1);
        System.out.println("name1    = " + name1);
        System.out.println("age1     = " + age1);
        System.out.println("address1 = " + address1);
        System.out.println("courses1 = " + courses1);
        System.out.println();

        // Using data type specific get() and opt() methods.
        // We don't have to cast the return from the getXXX()
        // and optXXX() methods.
        long id2 = jsonObject.getLong("id");
        String name2 = jsonObject.getString("name");
        int age2 = jsonObject.optInt("age");

        // Using optString() to read address and provide default
        // value when address is not found.
        String address2 = jsonObject.optString("address", "No Address");
        JSONArray courses2 = jsonObject.optJSONArray("courses");

        System.out.println("id2      = " + id2);
        System.out.println("name2    = " + name2);
        System.out.println("age2     = " + age2);
        System.out.println("address2 = " + address2);
        System.out.println("courses2 = " + courses2);
    }
}

Running this code produces the following results:

{"courses":["Engineering","Finance"],"name":"Alice","id":1,"age":20}
org.json.JSONException: JSONObject["address"] not found.
    at org.json.JSONObject.get(JSONObject.java:580)
    at org.kodejava.json.ReadJSONValue.main(ReadJSONValue.java:28)

id1      = 1
name1    = Alice
age1     = 20
address1 = null
courses1 = ["Engineering","Finance"]

id2      = 1
name2    = Alice
age2     = 20
address2 = No Address
courses2 = ["Engineering","Finance"]

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20220924/json-20220924.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20220924</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

How do I convert Java Object to JSON?

To convert Java objects or POJOs (Plain Old Java Objects) to JSON we can use one of JSONObject constructor that takes an object as its argument. In the following example we will convert Student POJO into JSON string. Student class must provide the getter methods, JSONObject creates JSON string by calling these methods.

In this code snippet we do as follows:

  • Creates Student object and set its properties using the setter methods.
  • Create JSONObject called object and use the Student object as argument to its constructor.
  • JSONObject use getter methods to produces JSON string.
  • Call object.toString() method to get the JSON string.
package org.kodejava.json;

import org.json.JSONObject;
import org.kodejava.json.support.Student;

import java.util.Arrays;

public class PojoToJSON {
    public static void main(String[] args) {
        Student student = new Student();
        student.setId(1L);
        student.setName("Alice");
        student.setAge(20);
        student.setCourses(Arrays.asList("Engineering", "Finance", "Chemistry"));

        JSONObject object = new JSONObject(student);
        String json = object.toString();
        System.out.println(json);
    }
}

Running this code produces the following result:

{"courses":["Engineering","Finance","Chemistry"],"name":"Alice","id":1,"age":20}

The Student class use in the code above:

package org.kodejava.json.support;

import java.util.List;

public class Student {
    private Long id;
    private String name;
    private int age;
    private List<String> courses;

    // Getters and Setters removed for simplicity
}

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20220924/json-20220924.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20220924</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

How do I create JSON from a Map?

In the previous example we use JSONObject to directly put key-value pairs to create JSON string, using the various put() methods. Instead of doing that, we can also create JSON from a Map object. We create a Map with some key-value pairs in it, and pass it as an argument when instantiating a JSONObject.

These are the steps for creating JSON from a Map:

  • Create a Map object using a HashMap class.
  • Put some key-value pairs into the map object.
  • Create a JSONObject and pass the map as argument to its constructor.
  • Print the JSONObject, we call object.toString() to get the JSON string.

Let’s try the following code snippet.

package org.kodejava.json;

import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

public class JSONFromMap {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("id", "1");
        map.put("name", "Alice");
        map.put("age", "20");

        JSONObject object = new JSONObject(map);
        System.out.println(object);
    }
}

Running this code produces the following output:

{"name":"Alice","age":"20","id":"1"}

Maven Dependencies

<dependencies>
    <!-- https://search.maven.org/remotecontent?filepath=org/json/json/20220924/json-20220924.jar -->
    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20220924</version>
        <type>bundle</type>
    </dependency>
</dependencies>

Maven Central

How do I connect to ssh server using JSch?

JSch is a pure Java implementation of SSH-2. SSH (Secure Shell) is a cryptographic network protocol for operating network services securely over an unsecured network. The following code snippet shows you how to open a connection to an ssh server.

package org.kodejava.jsch;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

public class SSHConnect {
    public static void main(String[] args) {
        try {
            JSch jSch = new JSch();
            Session session = jSch.getSession("demo", "localhost", 22);
            session.setPassword("password");

            // Skip host-key check
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            System.out.println("Connected...");
            session.disconnect();
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }
}

Maven Dependencies

<dependencies>
    <!--https://search.maven.org/remotecontent?filepath=com/jcraft/jsch/0.1.55/jsch-0.1.55.jar-->
    <dependency>
        <groupId>com.jcraft</groupId>
        <artifactId>jsch</artifactId>
        <version>0.1.55</version>
    </dependency>
</dependencies>

Maven Central

How do I mail merge Word document in Java?

The following example will show you how to use the E-iceblue‘s free Spire.Doc for Java to perform mail merge operations on MS Word documents.

Create Maven Project and Add Dependencies

Create a maven project and add the following dependencies and repositories in your project’s pom.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    ...
    ...

    <dependencies>
        <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.doc.free</artifactId>
            <version>5.2.0</version>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>
</project>

Create Mail Merge Template in Microsoft Word

  • Create a new Word document.
  • Place your cursor where you want to add a merge field.

MS Word Mail Merge Template

  • Click the Insert menu, Quick Parts, Fields…
  • In the Field names select MergeField and enter the field name and press OK.

Merge Field

  • To create merge field for image you need to prefix the field name with Image:
  • When finished save the document.

The Mail Merge Code Snippet

The code snippet reads the mail merge template from a file called Receipt.docx. For the image we use a duke.png. Both of these files must be placed in the /src/main/resources directory in your maven project so that the code can read it.

package org.kodejava.example.spire;

import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.reporting.MergeImageFieldEventArgs;
import com.spire.doc.reporting.MergeImageFieldEventHandler;

import java.awt.Dimension;
import java.io.FileOutputStream;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class MailMergeExample {
    public static final Locale LOCALE = new Locale("id", "ID");
    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMMM-yyyy", LOCALE);
    public static final NumberFormat NUMBER_FORMAT = NumberFormat.getCurrencyInstance(LOCALE);

    public static void main(String[] args) {
        String[] fieldNames = new String[]{
                "academicYear",
                "registrationNumber",
                "fullName",
                "gender",
                "telephone",
                "address",
                "paymentAmount",
                "inWords",
                "paymentDate",
                "receivedBy",
                "picture"
        };
        String[] fieldValues = new String[]{
                "2021/2022",
                "0001/REG/2021",
                "Foo Bar",
                "M",
                "081234567890",
                "Sudirman Street 100",
                NUMBER_FORMAT.format(1575000),
                "One Million Five Hundred Seventy Five Thousand",
                DATE_FORMAT.format(new Date()),
                "John Doe",
                "/duke.png"
        };

        try {
            Document document = new Document();
            document.loadFromStream(MailMergeExample.class.getResourceAsStream("/Receipt.docx"), FileFormat.Auto);
            document.getMailMerge().MergeImageField = new MergeImageFieldEventHandler() {
                @Override
                public void invoke(Object o, MergeImageFieldEventArgs field) {
                    field.setPictureSize(new Dimension(66, 88));

                    String path = field.getImageFileName();
                    if (path != null && !path.isEmpty()) {
                        try {
                            field.setImage(MailMergeExample.class.getResourceAsStream(path));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            };
            document.getMailMerge().execute(fieldNames, fieldValues);

            String fileName = "Receipt.pdf";
            FileOutputStream fos = new FileOutputStream(fileName);
            document.saveToStream(fos, FileFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Running the code will create a file called Receipt.pdf with the content as shown in the image below.

Mail Merge Result Document

How do I format EditText for currency input in Android?

The following Android code snippet shows you how to customize the input value format of an EditText component for accepting currency number. To format the input value we will create a text watcher class called MoneyTextWatcher, this class implements of the android.text.TextWatcher interface.

In the MoneyTextWatcher class we implement the afterTextChanged(EditText s) method, in this method the currency formatting takes place by adding currency symbol before the digit on numbers.

To apply this text watcher class we call the addTextChangedListener() method of the EditText object of the currency input and pass an instance of MoneyTextWatcher. Below is the working example of the activity class and the text watcher.

package org.kodejava.android;

import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

import java.math.BigDecimal;

public class MainActivity extends AppCompatActivity {
    private EditText editText;
    private TextView textView;

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

        editText = findViewById(R.id.editText);
        editText.addTextChangedListener(new MoneyTextWatcher(editText));
        editText.setText("0");

        textView = findViewById(R.id.textView);
    }

    public void doGetValue(View view) {
        BigDecimal value = MoneyTextWatcher.parseCurrencyValue(editText.getText().toString());
        textView.setText(String.valueOf(value));
    }
}

When the EditText input is changed the afterTextChanged() method of the text watcher will be called. In this method we’ll take the input text and format the input value with currency symbol and a number, this is done by the NumberFormat.getCurrencyInstance() object.

The static helper method parseCurrencyValue() will get the number part of the EditText by removing the currency symbol and return the input number.

package org.kodejava.android;

import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.widget.EditText;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Locale;
import java.util.Objects;

public class MoneyTextWatcher implements TextWatcher {
    private static final Locale locale = new Locale("id", "ID");
    private static final DecimalFormat formatter = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
    private final WeakReference<EditText> editTextWeakReference;

    public MoneyTextWatcher(EditText editText) {
        editTextWeakReference = new WeakReference<>(editText);
        formatter.setMaximumFractionDigits(0);
        formatter.setRoundingMode(RoundingMode.FLOOR);

        DecimalFormatSymbols symbol = new DecimalFormatSymbols(locale);
        symbol.setCurrencySymbol(symbol.getCurrencySymbol() + " ");
        formatter.setDecimalFormatSymbols(symbol);
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
        EditText editText = editTextWeakReference.get();
        if (editText == null || editText.getText().toString().isEmpty()) {
            return;
        }
        editText.removeTextChangedListener(this);

        BigDecimal parsed = parseCurrencyValue(editText.getText().toString());
        String formatted = formatter.format(parsed);

        editText.setText(formatted);
        editText.setSelection(formatted.length());
        editText.addTextChangedListener(this);
    }

    public static BigDecimal parseCurrencyValue(String value) {
        try {
            String replaceRegex = String.format("[%s,.\\s]",
                    Objects.requireNonNull(formatter.getCurrency()).getSymbol(locale));
            String currencyValue = value.replaceAll(replaceRegex, "");
            currencyValue = "".equals(currencyValue) ? "0" : currencyValue;
            return new BigDecimal(currencyValue);
        } catch (Exception e) {
            Log.e("App", e.getMessage(), e);
        }
        return BigDecimal.ZERO;
    }
}

The following animation is the result of our code snippet above, and you can find to complete source code here: Android Currency EditText Example



How do I get Android Device ID or IMEI?

The following code snippets shows you how to get a Device ID of an Android phone. To be able to read the Device ID you need to update the AndroidManifest.xml file and add the READ_PHONE_STATE permission.

<?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.READ_PHONE_STATE" />

    ...
    ...
</manifest>
package org.kodejava.android;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {

    private static final int PERMISSIONS_READ_PHONE_STATE = 1;

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

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

        String deviceId = null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            deviceId = Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);
        } else {
            TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
            if (telephonyManager.getImei() != null) {
                deviceId = telephonyManager.getImei();
            } else if (telephonyManager.getMeid() != null) {
                deviceId = telephonyManager.getMeid();
            }
        }

        Log.d("MyApp", "Device ID: " + deviceId);
    }
}

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.