Write to PDF using PHP API from android device
1. Updated PHP API (generate_pdf_data.php)
This updated script retrieves URG_IMG, converts the BLOB if you have to a Base64-encoded string, and returns it alongside the rest of the details.
<?php
header('Content-Type: application/json');
include_once($_SERVER['DOCUMENT_ROOT']."/header.php");
$cert_id = isset($_REQUEST['CERT_ID']) ? trim($_REQUEST['CERT_ID']) : '';
if (empty($cert_id)) {
echo json_encode(array("success" => false, "message" => "CERT_ID is required"));
exit;
}
$sql = oci_parse($conn, "
SELECT
CERT_ID, CERT_NO, TO_CHAR(CREATED_DT, 'DD-MM-YYYY') AS CREATED_DT,
PL_NUMBER, ITEM_DESC, REQ_QTY, FIRM_NAME, INSPECTION_AGENCY, INDENT_NO,
CURRENT_STATUS, APRV_BY_AWM, APRV_BY_DYCMM, APRV_BY_CWE, APRV_BY_DYCME,
TO_CHAR(APRV_DT_AWM, 'DD-MM-YYYY') AS APRV_DT_AWM,
TO_CHAR(APRV_DT_DYCMM, 'DD-MM-YYYY') AS APRV_DT_DYCMM,
TO_CHAR(APRV_DT_CWE, 'DD-MM-YYYY') AS APRV_DT_CWE,
TO_CHAR(APRV_DT_DYCME, 'DD-MM-YYYY') AS APRV_DT_DYCME,
URG_IMG
FROM IOS.URG_PL_DTL
WHERE CERT_ID = :cert_id
");
oci_bind_by_name($sql, ":cert_id", $cert_id);
if (oci_execute($sql)) {
$row = oci_fetch_array($sql, OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
if ($row) {
if (strtoupper($row['CURRENT_STATUS']) !== 'APPROVED') {
echo json_encode(array(
"success" => false,
"message" => "PDF generation allowed only for APPROVED certificates."
));
} else {
// Encode BLOB image to Base64
if (!empty($row['URG_IMG'])) {
$row['URG_IMG'] = base64_encode($row['URG_IMG']);
} else {
$row['URG_IMG'] = "";
}
echo json_encode(array("success" => true, "data" => $row));
}
} else {
echo json_encode(array("success" => false, "message" => "Record not found"));
}
} else {
$e = oci_error($sql);
echo json_encode(array("success" => false, "message" => $e['message']));
}
oci_free_statement($sql);
oci_close($conn);
?>
2. Android PdfGenerator.java
This version decodes the Base64 image from the API, constructs Page 1 with certificate text/signatures, and adds Page 2 containing the "Referenced Documents" heading and the decoded URG_IMG scaled to fit the page cleanly.
public class PdfGenerator {
public interface PdfCallback {
void onSuccess(File pdfFile, Uri contentUri);
void onError(String error);
}
public static void generateAndSavePdf(Context context, String certId, PdfCallback callback) {
String fetchUrl = "https://jyotishgher.in/generate_pdf_data.php?CERT_ID=" + certId;
RequestQueue queue = Volley.newRequestQueue(context.getApplicationContext());
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, fetchUrl, null,
response -> {
try {
if (response.getBoolean("success")) {
JSONObject data = response.getJSONObject("data");
fetchSignaturesAndDraw(context.getApplicationContext(), data, callback);
} else {
callback.onError(response.optString("message", "Certificate not approved."));
}
} catch (Exception e) {
callback.onError("Parsing error: " + e.getMessage());
}
},
error -> callback.onError("Network error fetching certificate details")
);
queue.add(request);
}
private static void fetchSignaturesAndDraw(Context context, JSONObject data, PdfCallback callback) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
executor.execute(() -> {
try {
Bitmap sigAwm = downloadSignature(data.optString("APRV_BY_AWM"));
Bitmap sigDycmm = downloadSignature(data.optString("APRV_BY_DYCMM"));
Bitmap sigCwe = downloadSignature(data.optString("APRV_BY_CWE"));
Bitmap sigDycme = downloadSignature(data.optString("APRV_BY_DYCME"));
// Decode URG_IMG Base64 String
Bitmap urgImgBitmap = null;
String base64Img = data.optString("URG_IMG", "");
if (!base64Img.isEmpty() && !base64Img.equalsIgnoreCase("null")) {
try {
byte[] decodedString = Base64.decode(base64Img, Base64.DEFAULT);
urgImgBitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
} catch (Exception e) {
Log.e("URG_IMG_ERR", "Error decoding BLOB image: " + e.getMessage());
}
}
String fileName = "Urgency_Certificate_" + data.optString("CERT_ID") + ".pdf";
// Save PDF
File outputFile = buildPdfFile(context, data, sigAwm, sigDycmm, sigCwe, sigDycme, urgImgBitmap, fileName);
Uri contentUri = saveToDownloads(context, outputFile, fileName);
handler.post(() -> callback.onSuccess(outputFile, contentUri));
} catch (Exception e) {
Log.e("PDF_GEN_ERR", "Error building PDF", e);
handler.post(() -> callback.onError("PDF Build failed: " + e.getMessage()));
}
});
}
private static Bitmap downloadSignature(String empNo) {
if (empNo == null || empNo.isEmpty() || empNo.equalsIgnoreCase("null")) return null;
try {
String sigUrl = "https://rcfkapurthala.in/cmms/urgency/signatureimage.php?EMPNO=" + empNo;
URL url = new URL(sigUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
return BitmapFactory.decodeStream(input);
} catch (Exception e) {
Log.e("SIG_ERR", "Error loading signature for " + empNo, e);
return null;
}
}
private static File buildPdfFile(Context context, JSONObject data, Bitmap sigAwm, Bitmap sigDycmm, Bitmap sigCwe, Bitmap sigDycme, Bitmap urgImgBitmap, String fileName) throws Exception {
PdfDocument pdfDocument = new PdfDocument();
// ================= PAGE 1 =================
PdfDocument.PageInfo page1Info = new PdfDocument.PageInfo.Builder(595, 842, 1).create(); // A4 Standard
PdfDocument.Page page1 = pdfDocument.startPage(page1Info);
Canvas canvas1 = page1.getCanvas();
Paint paint = new Paint();
Paint titlePaint = new Paint();
Paint subTitlePaint = new Paint();
titlePaint.setTextSize(18);
titlePaint.setFakeBoldText(true);
titlePaint.setColor(Color.BLACK);
subTitlePaint.setTextSize(14);
subTitlePaint.setFakeBoldText(true);
subTitlePaint.setColor(Color.BLACK);
paint.setTextSize(11);
paint.setColor(Color.BLACK);
int x = 40;
int y = 50;
// Header
canvas1.drawText("RCF", x, y, titlePaint);
y += 40;
canvas1.drawText("RAIL COACH FACTORY - (KAPURTHALA)", x + 80, y, subTitlePaint);
canvas1.drawLine(x + 80, y + 4, x + 380, y + 4, paint);
y += 30;
canvas1.drawText("No. " + data.optString("CERT_ID"), x, y, paint);
canvas1.drawText("Date: " + data.optString("CREATED_DT"), x + 350, y, paint);
y += 40;
canvas1.drawText("Sub: Urgency.", x + 60, y, paint);
y += 30;
canvas1.drawText("The following item is urgent and is not available at Shop Floor.", x, y, paint);
y += 30;
canvas1.drawText("1. PL.No. : " + data.optString("PL_NUMBER"), x, y, paint);
y += 25;
canvas1.drawText("2. Item : " + data.optString("ITEM_DESC"), x, y, paint);
y += 35;
canvas1.drawText("You are requested to issue " + data.optString("CERT_NO"), x, y, paint);
canvas1.drawLine(x + 160, y + 2, x + 500, y + 2, paint);
y += 25;
canvas1.drawText("immediately so that work does not suffer. Coaches are held up. Coaches are", x, y, paint);
y += 20;
canvas1.drawText("suffering in want of said material.", x, y, paint);
y += 70;
// Signatures Layout
int col1 = x;
int col2 = x + 130;
int col3 = x + 260;
int col4 = x + 390;
drawSignatureSlot(canvas1, sigDycmm, "Dy.CMM/D", data.optString("APRV_DT_DYCMM"), col1, y, paint);
drawSignatureSlot(canvas1, sigCwe, "CWE/FUR", data.optString("APRV_DT_CWE"), col2, y, paint);
drawSignatureSlot(canvas1, sigDycme, "Dy.CME/FF", data.optString("APRV_DT_DYCME"), col3, y, paint);
drawSignatureSlot(canvas1, sigAwm, "AWM/FP", data.optString("APRV_DT_AWM"), col4, y, paint);
y += 90;
// Footer Metadata
canvas1.drawText("Firm: " + data.optString("FIRM_NAME"), x, y, paint);
canvas1.drawText("Recd.On: ___________", x + 260, y, paint);
y += 30;
canvas1.drawText("Inspection: " + data.optString("INSPECTION_AGENCY"), x, y, paint);
canvas1.drawText("Qty: " + data.optString("REQ_QTY"), x + 260, y, paint);
y += 30;
canvas1.drawText("Qty earlier drawn on urgency: ___________", x, y, paint);
canvas1.drawText("Dated: ___________", x + 260, y, paint);
pdfDocument.finishPage(page1);
// ================= PAGE 2 (Referenced Documents) =================
PdfDocument.PageInfo page2Info = new PdfDocument.PageInfo.Builder(595, 842, 2).create();
PdfDocument.Page page2 = pdfDocument.startPage(page2Info);
Canvas canvas2 = page2.getCanvas();
int p2Y = 50;
canvas2.drawText("Referenced Documents", x, p2Y, titlePaint);
canvas2.drawLine(x, p2Y + 6, x + 220, p2Y + 6, titlePaint);
p2Y += 40;
String referenceDocNo = data.optString("INDENT_NO", "N/A");
canvas2.drawText("Reference Doc / Indent No: " + referenceDocNo, x, p2Y, subTitlePaint);
p2Y += 30;
// Render URG_IMG BLOB on Page 2
if (urgImgBitmap != null) {
int maxImgWidth = 515; // 595 page width - 80 margins
int maxImgHeight = 650; // Max available vertical space on page 2
int imgWidth = urgImgBitmap.getWidth();
int imgHeight = urgImgBitmap.getHeight();
float scale = Math.min((float) maxImgWidth / imgWidth, (float) maxImgHeight / imgHeight);
int scaledWidth = Math.round(imgWidth * scale);
int scaledHeight = Math.round(imgHeight * scale);
Bitmap scaledImg = Bitmap.createScaledBitmap(urgImgBitmap, scaledWidth, scaledHeight, true);
canvas2.drawBitmap(scaledImg, x, p2Y, paint);
} else {
canvas2.drawText("No image document attached.", x, p2Y, paint);
}
pdfDocument.finishPage(page2);
// Output File Writing
File pdfDir = new File(context.getCacheDir(), "pdfs");
if (!pdfDir.exists()) pdfDir.mkdirs();
File outputFile = new File(pdfDir, fileName);
FileOutputStream fos = new FileOutputStream(outputFile);
pdfDocument.writeTo(fos);
fos.flush();
fos.close();
pdfDocument.close();
return outputFile;
}
private static Uri saveToDownloads(Context context, File sourceFile, String fileName) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
values.put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf");
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
Uri uri = context.getContentResolver().insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
if (uri != null) {
try (OutputStream os = context.getContentResolver().openOutputStream(uri);
InputStream is = new java.io.FileInputStream(sourceFile)) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) > 0) {
os.write(buffer, 0, len);
}
os.flush();
return uri;
} catch (Exception e) {
Log.e("SAVE_DOWNLOAD_ERR", "Error saving via MediaStore", e);
}
}
} else {
File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File destFile = new File(downloadsDir, fileName);
try (InputStream is = new java.io.FileInputStream(sourceFile);
OutputStream os = new FileOutputStream(destFile)) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) > 0) {
os.write(buffer, 0, len);
}
os.flush();
return Uri.fromFile(destFile);
} catch (Exception e) {
Log.e("SAVE_DOWNLOAD_ERR", "Error saving legacy file", e);
}
}
return FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", sourceFile);
}
private static void drawSignatureSlot(Canvas canvas, Bitmap sig, String title, String dateStr, int x, int y, Paint paint) {
if (sig != null) {
Bitmap scaledSig = Bitmap.createScaledBitmap(sig, 80, 40, false);
canvas.drawBitmap(scaledSig, x, y - 45, paint);
}
canvas.drawText(title, x, y, paint);
if (dateStr != null && !dateStr.isEmpty() && !dateStr.equalsIgnoreCase("null")) {
canvas.drawText(dateStr, x, y + 15, paint);
}
}
public static void openOrSharePdf(Context context, Uri uri) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "application/pdf");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(Intent.createChooser(intent, "Open Urgency Certificate PDF"));
} catch (Exception e) {
Log.e("OPEN_PDF_ERR", "No PDF viewer found", e);
}
}
Button Click Event Implementation
Android PDF Generation & Sharing Handler
Add FileProvider to your AndroidManifest.xml:
res/xml/file_paths.xml:

Post a Comment
0Comments