feat: implementar descarga de PDF de factura y soporte para guardar en Android
This commit is contained in:
+58
-11
@@ -1,11 +1,17 @@
|
||||
package com.hdrdevs.turnosxpress;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import android.Manifest;
|
||||
import android.os.Bundle;
|
||||
import android.os.Build;
|
||||
import android.os.Message;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
@@ -33,6 +39,7 @@ import android.content.ContentResolver;
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private static final int LOGIN_REQUEST_CODE = 1;
|
||||
private static final int STORAGE_PERMISSION_REQUEST_CODE = 2;
|
||||
private WebView webView;
|
||||
private ValueCallback<Uri[]> fileChooserCallback;
|
||||
|
||||
@@ -43,6 +50,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
tokenResult = "";
|
||||
requestLegacyStoragePermissionIfNeeded();
|
||||
|
||||
// For Android Emulator, use 10.0.2.2 to access localhost on your development machine.
|
||||
// If testing on a physical device, replace 10.0.2.2 with your development machine's actual local IP address.
|
||||
@@ -220,6 +228,28 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
private void requestLegacyStoragePermissionIfNeeded() {
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P
|
||||
&& ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSION_REQUEST_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
private String safePdfFilename(String filename) {
|
||||
String safeName = filename == null ? "reporte.pdf" : filename.trim();
|
||||
safeName = safeName.replaceAll("[\\\\/:*?\"<>|]", "_");
|
||||
|
||||
if (safeName.length() == 0) {
|
||||
safeName = "reporte.pdf";
|
||||
}
|
||||
|
||||
if (!safeName.toLowerCase().endsWith(".pdf")) {
|
||||
safeName += ".pdf";
|
||||
}
|
||||
|
||||
return safeName;
|
||||
}
|
||||
|
||||
public class WebAppInterface {
|
||||
@JavascriptInterface
|
||||
public void startGoogleLogin() {
|
||||
@@ -235,16 +265,20 @@ public class MainActivity extends AppCompatActivity {
|
||||
|
||||
@JavascriptInterface
|
||||
public void savePdf(String base64Data, String filename) {
|
||||
String safeFilename = safePdfFilename(filename);
|
||||
|
||||
try {
|
||||
byte[] pdfAsBytes = Base64.decode(base64Data, 0);
|
||||
String normalizedBase64 = base64Data == null ? "" : base64Data.replaceFirst("^data:application/pdf;base64,", "");
|
||||
byte[] pdfAsBytes = Base64.decode(normalizedBase64, Base64.DEFAULT);
|
||||
boolean isSaved = false;
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ContentResolver resolver = getContentResolver();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, filename);
|
||||
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, safeFilename);
|
||||
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf");
|
||||
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
|
||||
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);
|
||||
|
||||
Uri uri = resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, contentValues);
|
||||
|
||||
@@ -253,18 +287,31 @@ public class MainActivity extends AppCompatActivity {
|
||||
outputStream.write(pdfAsBytes);
|
||||
isSaved = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Log.e("WEBVIEW", "Error writing PDF to MediaStore: " + safeFilename, e);
|
||||
resolver.delete(uri, null, null);
|
||||
}
|
||||
|
||||
if (isSaved) {
|
||||
ContentValues completedValues = new ContentValues();
|
||||
completedValues.put(MediaStore.MediaColumns.IS_PENDING, 0);
|
||||
resolver.update(uri, completedValues, null, null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||
File file = new File(path, filename);
|
||||
|
||||
try (FileOutputStream os = new FileOutputStream(file)) {
|
||||
os.write(pdfAsBytes);
|
||||
isSaved = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
if (!path.exists() && !path.mkdirs()) {
|
||||
Log.e("WEBVIEW", "Could not create Downloads directory: " + path.getAbsolutePath());
|
||||
} else {
|
||||
File file = new File(path, safeFilename);
|
||||
|
||||
try (FileOutputStream os = new FileOutputStream(file)) {
|
||||
os.write(pdfAsBytes);
|
||||
isSaved = true;
|
||||
MediaScannerConnection.scanFile(MainActivity.this, new String[]{file.getAbsolutePath()}, new String[]{"application/pdf"}, null);
|
||||
} catch (IOException e) {
|
||||
Log.e("WEBVIEW", "Error writing PDF to Downloads: " + safeFilename, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +322,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e("WEBVIEW", "Error saving PDF: " + safeFilename, e);
|
||||
runOnUiThread(() -> Toast.makeText(MainActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -844,7 +844,16 @@ export default function CashFlowMovementsList() {
|
||||
},
|
||||
};
|
||||
|
||||
(pdfMake as any).createPdf({ ...documentDefinition, content }).download(`factura-c-${invoice.pointOfSale || fiscalProfile.pointOfSale || 0}-${invoice.voucherNumber || 0}.pdf`);
|
||||
const filename = `factura-c-${invoice.pointOfSale || fiscalProfile.pointOfSale || 0}-${invoice.voucherNumber || 0}.pdf`;
|
||||
const pdf = (pdfMake as any).createPdf({ ...documentDefinition, content });
|
||||
|
||||
if ((window as unknown as { Android: any }).Android && (window as unknown as { Android: any }).Android.savePdf) {
|
||||
pdf.getBase64((data: string) => {
|
||||
(window as unknown as { Android: any }).Android?.savePdf(data, filename);
|
||||
});
|
||||
} else {
|
||||
pdf.download(filename);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error generating invoice PDF:", error);
|
||||
alert.showError("No pudimos generar el PDF de la factura.");
|
||||
|
||||
Reference in New Issue
Block a user