For developers
Android apps
Print from your own Kotlin or Java app with a link or a share intent.
Open a rollcast://print link with setPackage("com.rollcast.app") to print text, HTML or ESC/POS. To print a PDF or image, share it with ACTION_SEND.
Note
Links from apps follow the same rules as web links: "Allow web prints" must be on, and at most one link per second is accepted. Shared files are not affected.
Print text (Kotlin)
Kotlin
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Base64
object RollCast {
const val PACKAGE = "com.rollcast.app"
fun printText(context: Context, text: String, printerId: String? = null) =
send(context, "text", text.toByteArray(Charsets.UTF_8), printerId)
fun printHtml(context: Context, html: String, printerId: String? = null) =
send(context, "html", html.toByteArray(Charsets.UTF_8), printerId)
fun printRaw(context: Context, bytes: ByteArray, printerId: String? = null) =
send(context, "raw", bytes, printerId)
private fun send(context: Context, type: String, bytes: ByteArray, printerId: String?) {
val data = Base64.encodeToString(
bytes,
Base64.URL_SAFE or Base64.NO_WRAP or Base64.NO_PADDING,
)
val uri = Uri.Builder()
.scheme("rollcast")
.authority("print")
.appendQueryParameter("type", type)
.appendQueryParameter("data", data)
.apply { if (printerId != null) appendQueryParameter("printer", printerId) }
.build()
val intent = Intent(Intent.ACTION_VIEW, uri).setPackage(PACKAGE)
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
openStore(context)
}
}
fun openStore(context: Context) {
val market = Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + PACKAGE))
try {
context.startActivity(market)
} catch (e: ActivityNotFoundException) {
context.startActivity(
Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + PACKAGE)),
)
}
}
}
// RollCast.printText(activity, "Order #42\nTea x2 40.00\n\n")Tip
Call it with an Activity context. From other contexts, add Intent.FLAG_ACTIVITY_NEW_TASK.
Print text (Java)
Java
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Base64;
import java.nio.charset.StandardCharsets;
public final class RollCast {
public static final String PACKAGE = "com.rollcast.app";
public static void printText(Context context, String text, String printerId) {
send(context, "text", text.getBytes(StandardCharsets.UTF_8), printerId);
}
public static void printRaw(Context context, byte[] bytes, String printerId) {
send(context, "raw", bytes, printerId);
}
private static void send(Context context, String type, byte[] bytes, String printerId) {
String data = Base64.encodeToString(bytes,
Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
Uri.Builder builder = new Uri.Builder()
.scheme("rollcast")
.authority("print")
.appendQueryParameter("type", type)
.appendQueryParameter("data", data);
if (printerId != null) builder.appendQueryParameter("printer", printerId);
Intent intent = new Intent(Intent.ACTION_VIEW, builder.build()).setPackage(PACKAGE);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
openStore(context);
}
}
public static void openStore(Context context) {
try {
context.startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("market://details?id=" + PACKAGE)));
} catch (ActivityNotFoundException e) {
context.startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("https://play.google.com/store/apps/details?id=" + PACKAGE)));
}
}
private RollCast() {}
}Raw ESC/POS bytes
Kotlin
import java.io.ByteArrayOutputStream
fun receiptBytes(): ByteArray {
val out = ByteArrayOutputStream()
fun ascii(s: String) = out.write(s.toByteArray(Charsets.US_ASCII))
out.write(byteArrayOf(0x1B, 0x40)) // ESC @ reset
out.write(byteArrayOf(0x1B, 0x45, 0x01)) // ESC E 1 bold on
ascii("MY SHOP\n")
out.write(byteArrayOf(0x1B, 0x45, 0x00)) // ESC E 0 bold off
ascii("Tea x2 40.00\n")
ascii("TOTAL 40.00\n")
out.write(byteArrayOf(0x1B, 0x64, 0x03)) // ESC d 3 feed 3 lines
out.write(byteArrayOf(0x1D, 0x56, 0x01)) // GS V 1 cut
return out.toByteArray()
}
// RollCast.printRaw(activity, receiptBytes())Java
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[] {0x1B, 0x40}, 0, 2); // ESC @ reset
out.write(new byte[] {0x1B, 0x45, 0x01}, 0, 3); // ESC E 1 bold on
byte[] title = "MY SHOP\n".getBytes(StandardCharsets.US_ASCII);
out.write(title, 0, title.length);
out.write(new byte[] {0x1B, 0x45, 0x00}, 0, 3); // ESC E 0 bold off
out.write(new byte[] {0x1B, 0x64, 0x03}, 0, 3); // ESC d 3 feed 3 lines
out.write(new byte[] {0x1D, 0x56, 0x01}, 0, 3); // GS V 1 cut
RollCast.printRaw(activity, out.toByteArray(), null);Share a PDF or image
Shared files always go to the user's default printer. Copy the file into your cache folder and share it through a FileProvider.
XML
<!-- AndroidManifest.xml, inside <application> -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<!-- res/xml/file_paths.xml -->
<paths>
<cache-path name="print" path="print/" />
</paths>Kotlin
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import androidx.core.content.FileProvider
import java.io.File
/** [file] must be inside cacheDir/print/. mimeType: "application/pdf", "image/png", ... */
fun shareToRollCast(context: Context, file: File, mimeType: String) {
val uri = FileProvider.getUriForFile(context, context.packageName + ".fileprovider", file)
val intent = Intent(Intent.ACTION_SEND)
.setType(mimeType)
.putExtra(Intent.EXTRA_STREAM, uri)
.setPackage(RollCast.PACKAGE)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
RollCast.openStore(context)
}
}Java
public static void shareToRollCast(Context context, File file, String mimeType) {
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", file);
Intent intent = new Intent(Intent.ACTION_SEND)
.setType(mimeType)
.putExtra(Intent.EXTRA_STREAM, uri)
.setPackage(RollCast.PACKAGE)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
RollCast.openStore(context);
}
}Tip
Accepted share types: text/plain, image/*, application/pdf. Up to 20 MB per file; ACTION_SEND_MULTIPLE takes up to 32 images.