From 8aa4ad392181f9336459d7eb4752e63f20f8a6e0 Mon Sep 17 00:00:00 2001 From: OnlyPapy98 Date: Thu, 14 May 2026 15:04:10 +0000 Subject: [PATCH] pre prod version for test --- app/build.gradle.kts | 1 + app/src/main/AndroidManifest.xml | 9 + .../sagereal/printer/PrinterInterface.aidl | 21 + .../java/com/example/quiz/BetValidation.java | 419 ++++++++++++------ .../java/com/example/quiz/DerniersParis.java | 207 ++++++--- .../main/java/com/example/quiz/PageQuiz.java | 6 +- app/src/main/java/com/example/quiz/Sold.java | 80 +++- .../java/com/example/quiz/SoldByCourse.java | 78 +++- .../example/quiz/data/remote/ApiService.java | 5 +- .../com/example/quiz/utils/BitMapUtils.java | 185 ++++++++ .../quiz/utils/MobiIotPrinterManager.java | 242 ++++++++++ .../quiz/utils/SunmiPrinterManager.java | 214 +++++++-- .../com/sagereal/print/util/BitmapUtils.java | 18 + .../print/util/DataFormatConversion.java | 18 + .../sagereal/print/util/QrcodeOrBarcode.java | 101 +++++ printama/src/main/AndroidManifest.xml | 7 + 16 files changed, 1360 insertions(+), 251 deletions(-) create mode 100644 app/src/main/aidl/com/sagereal/printer/PrinterInterface.aidl create mode 100644 app/src/main/java/com/example/quiz/utils/BitMapUtils.java create mode 100644 app/src/main/java/com/example/quiz/utils/MobiIotPrinterManager.java create mode 100644 app/src/main/java/com/sagereal/print/util/BitmapUtils.java create mode 100644 app/src/main/java/com/sagereal/print/util/DataFormatConversion.java create mode 100644 app/src/main/java/com/sagereal/print/util/QrcodeOrBarcode.java diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5d85022..77fb674 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -57,6 +57,7 @@ android { buildFeatures { viewBinding = true + aidl = true } kotlinOptions { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 55ff5dd..a7a6970 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,15 @@ + + + + + + + + + diff --git a/app/src/main/aidl/com/sagereal/printer/PrinterInterface.aidl b/app/src/main/aidl/com/sagereal/printer/PrinterInterface.aidl new file mode 100644 index 0000000..92678d7 --- /dev/null +++ b/app/src/main/aidl/com/sagereal/printer/PrinterInterface.aidl @@ -0,0 +1,21 @@ +package com.sagereal.printer; + +interface PrinterInterface { + void printText(String str); + void printText_isBold(String str, boolean z); + void printText_isUnderline(String str, boolean z); + void printText_size(String str, int i); + void printText_font(String str, int i); + void printText_size_font(String str, int i, int i2); + int printText_FullParm(String str, int i, int i2, int i3, int i4, boolean z, boolean z2); + void printBitmap(String str); + void printEndLine(); + void printBitmap_bDate(in byte[] bArr); + void printBitmap_bDate_speed(in byte[] bArr, int i); + int getPrinterStatus(); + int getPrinterCacheStatus(); + void printBitmap_in(in byte[] bArr); + void printBitmap_inIs(in byte[] bArr, int i); + int getCurrentVoltageStatus(); + int getLastError(); +} \ No newline at end of file diff --git a/app/src/main/java/com/example/quiz/BetValidation.java b/app/src/main/java/com/example/quiz/BetValidation.java index a4caec2..921b668 100644 --- a/app/src/main/java/com/example/quiz/BetValidation.java +++ b/app/src/main/java/com/example/quiz/BetValidation.java @@ -26,6 +26,9 @@ import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; +import android.os.Handler; +import android.os.Looper; +import android.os.RemoteException; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; @@ -49,9 +52,11 @@ import com.example.quiz.data.model.TypeOfBet; import com.example.quiz.data.model.dtos.NotifPayload; import com.example.quiz.data.remote.StompManager; import com.example.quiz.databinding.FragmentBetValidationBinding; +import com.example.quiz.utils.BitMapUtils; import com.example.quiz.utils.BluetoothUtils; import com.example.quiz.utils.LoaderDialog; import com.example.quiz.utils.MessageDialog; +import com.example.quiz.utils.MobiIotPrinterManager; import com.example.quiz.utils.Result; import com.example.quiz.utils.SharedPrefsHelper; import com.example.quiz.utils.SunmiPrinterManager; @@ -67,6 +72,11 @@ import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.lang.reflect.Type; import java.time.LocalDateTime; @@ -77,6 +87,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Observable; import java.util.stream.Collectors; @@ -106,6 +117,9 @@ public class BetValidation extends Fragment { private AlertDialog dialog; + + Map listProduits = Map.of("QUINTE", 5, "QUARTE", 4, "TIERCE", 3, "COUPLE_GAGNANT", 2, "COUPLE_PLACE", 2); + @Inject StompManager stompManager; @@ -122,6 +136,9 @@ public class BetValidation extends Fragment { String mobileName; + ParisResponse pariNotPrint; + + private TypeOfBet typeOfBet; @@ -166,7 +183,10 @@ public class BetValidation extends Fragment { if(mobileName.toLowerCase().contains("sunmi")){ sunmiPrinterManager.connectPrinter(status ->{ isPrinterReady.setValue(status); + sunmiPrinterManager.disableSystemMessages(); }); + }else{ + MobiIotPrinterManager.getInstance().init(requireContext()); } } @@ -177,6 +197,7 @@ public class BetValidation extends Fragment { binding = FragmentBetValidationBinding.inflate(inflater, container, false); loader = new LoaderDialog(getContext()); logsViewModel = new ViewModelProvider(this).get(LogsViewModel.class); + pariViewModel = new ViewModelProvider(this).get(PariViewModel.class); binding.coeff.setText(String.valueOf(1)); coeff = Integer.parseInt(binding.coeff.getText().toString()); binding.coeff.addTextChangedListener(new TextWatcher() { @@ -286,6 +307,60 @@ public class BetValidation extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + if(prefsHelper!=null && prefsHelper.get("pariNoPrintId") != null && !prefsHelper.get("pariNoPrintId").isEmpty()){ + pariViewModel.getPariByNumero(prefsHelper.get("pariNoPrintId")).observe(getViewLifecycleOwner(), pariResult -> { + switch (pariResult.status){ + case LOADING: { + loader.show("Recuperation du pari non imprimé"); + break; + } + case SUCCESS:{ + loader.dismiss(); + new android.app.AlertDialog.Builder(getContext()) + .setTitle("Réimpréssion du pari "+ pariResult.data.getNumeroTicket()) + .setMessage("Veuillez réimprimer le ticket SVP") + .setPositiveButton("OK", (dlg, which) -> { + if(mobileName.toLowerCase().contains("sunmi")){ + if(isPrinterReady.getValue() != null && !isPrinterReady.getValue()){ + sunmiPrinterManager.connectPrinter(status ->{ + isPrinterReady.setValue(status); + }); + } + if(sunmiPrinterManager.printerStatus() != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + }else{ + try { + int mobiPrintStatus = MobiIotPrinterManager.getInstance().getPrinterStatus(); + if(mobiPrintStatus != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + try { + printPari(pariResult.data); + dlg.dismiss(); + prefsHelper.save("pariNoPrintId", null); + } catch (WriterException e) { + throw new RuntimeException(e); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + }).setCancelable(false).show(); + break; + } + case ERROR:{ + MessageDialog.showError(getContext(), "Erreur lors de la récupération!"); + break; + } + + } + }); + } super.onViewCreated(view, savedInstanceState); shared = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); pariMiseViewModel = new ViewModelProvider(this).get(PariMiseViewModel.class); @@ -412,6 +487,58 @@ public class BetValidation extends Fragment { Toast.makeText(getContext(), "Pari non valide", Toast.LENGTH_SHORT).show(); return; } + if(prefsHelper!=null && prefsHelper.get("pariNoPrintId") != null && !prefsHelper.get("pariNoPrintId").isEmpty()){ + pariViewModel.getPariByNumero(prefsHelper.get("pariNoPrintId")).observe(getViewLifecycleOwner(), pariResult -> { + switch (pariResult.status){ + case LOADING: { + loader.show("Recuperation du pari non imprimé"); + break; + } + case SUCCESS:{ + loader.dismiss(); + new android.app.AlertDialog.Builder(getContext()) + .setTitle("Réimpréssion du pari "+ pariResult.data.getNumeroTicket()) + .setMessage("Veuillez réimprimer le ticket SVP") + .setPositiveButton("OK", (dlg, which) -> { + if(mobileName.toLowerCase().contains("sunmi")){ + if(isPrinterReady.getValue() != null && !isPrinterReady.getValue()){ + sunmiPrinterManager.connectPrinter(status ->{ + isPrinterReady.setValue(status); + }); + if(sunmiPrinterManager.printerStatus() != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + } + }else{ + try { + int mobiPrinterStatus = MobiIotPrinterManager.getInstance().getPrinterStatus(); + if(mobiPrinterStatus != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + try { + printPari(pariResult.data); + dlg.dismiss(); + prefsHelper.save("pariNoPrintId", null); + } catch (WriterException | FileNotFoundException e) { + throw new RuntimeException(e); + } + }).setCancelable(false).show(); + break; + } + case ERROR:{ + MessageDialog.showError(getContext(), "Erreur lors de la récupération du pari!"); + break; + } + } + }); + return; + } Pari pari = new Pari( OffsetDateTime.now(ZoneOffset.UTC).toString(), @@ -501,117 +628,165 @@ public class BetValidation extends Fragment { } } - public void printPari(ParisResponse pari) throws WriterException { + public void printPari(ParisResponse pari) throws WriterException, FileNotFoundException { Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo); - Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100); + Bitmap barcode = BitMapUtils.generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100); StringBuilder tspl = new StringBuilder(); tspl.append("Bamako").append("\n"); - tspl.append(shared.selectedCourse.getValue().getNom()).append("\n"); - OffsetDateTime dateTime = OffsetDateTime.parse(shared.selectedCourse.getValue().getHeureDepartPrevue()); + tspl.append(pari.getCourseNom()).append("\n"); + OffsetDateTime dateTime = OffsetDateTime.parse(pari.getHeureDepartPrevue()); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"); String formattedDate = dateTime.format(formatter); tspl.append(formattedDate).append("\n"); - tspl.append("Course ").append(String.valueOf(shared.selectedCourse.getValue().getId())).append("\n"); + tspl.append("Course ").append(String.valueOf(pari.getCourseId())).append("\n"); tspl.append(sunmiPrinterManager.separationText()+ "\n"); - boolean isElargie = selectedHorses.getValue().size() > shared.typeOfBet.getValue().getNumberOfHorse(); + if(selectedHorses.getValue() == null){ + selectedHorses.setValue(Arrays.stream(pari.getCombinaison().split(",")).collect(Collectors.toList())); + } + int requireHorseNumber = shared != null && shared.typeOfBet != null? shared.typeOfBet.getValue().getNumberOfHorse():listProduits.get(pari.getTypesParisMises().get(0)); + boolean isElargie = selectedHorses.getValue().size() > requireHorseNumber; String typePari = pari.getTypesParisMises().get(0).getTypePari(); tspl.append(isElargie ? typePari + "/Elargie" : typePari).append("\n"); - tspl.append(order ? "COMBINAISON COMPLETE" + "\n" : ""); - String combinationText = formatLineWithNumbers(selectedHorses.getValue().stream().map(String::valueOf).toArray(String[]::new), "-") ; + tspl.append(pari.getFormules().contains("FORMULE_COMPLETE") ?"COMBINAISON COMPLETE"+"\n":""); + String combinationText = BitMapUtils.formatLineWithNumbers(selectedHorses.getValue().stream().map(String::valueOf).toArray(String[]::new), "-", requireHorseNumber); tspl.append(combinationText).append("\n"); - tspl.append("COEF: ").append(String.valueOf(coeff)).append(".0"); + tspl.append("COEF: ").append(String.valueOf(pari.getCoefficient())); tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n"); tspl.append("MONTANT: ").append(pari.getTypesParisMises().get(0).getMiseTotale()).append(" XOF"); tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n"); tspl.append("AGENT: ").append(prefsHelper.get("code")).append("\n"); - tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(LocalDateTime.now())).append("\n"); + tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(OffsetDateTime.parse(pari.getDateHeurePrise()))).append("\n"); if(mobileName.toLowerCase().contains("sunmi")){ String pariText = tspl.toString(); - if(!sunmiPrinterManager.printPari(resizeToPrinterWidth(bitmap, 384), barcode, pari.getNumeroTicket(), pariText)){ - MessageDialog.showError(getContext(), "Erreur d'impression"); - prefsHelper.save("noPrintId", String.valueOf(pari.getId())); - return; - }; + sunmiPrinterManager.printPari(BitMapUtils.resizeToPrinterWidth(bitmap, 384), barcode, pari.getNumeroTicket(), pariText, new SunmiPrinterManager.PrintStatusListener() { + @Override + public void onStatusChanged(boolean status) { + if(!status){ + prefsHelper.save("pariNoPrintId", String.valueOf(pari.getNumeroTicket())); + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + new AlertDialog.Builder(getContext()) + .setTitle("Echec de l'impression") + .setMessage("L'impréssion du ticket "+pari.getNumeroTicket()+" n'a pu aboutir, "+"\n"+"Veuillez vérifier le papier puis rééssayez!") + .setPositiveButton("Ok", (dlg, which)->{ + if(sunmiPrinterManager.printerStatus() != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + try { + printPari(pari); + dlg.dismiss(); + prefsHelper.save("pariNoPrintId", null); + } catch (WriterException e) { + throw new RuntimeException(e); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + }) + .setCancelable(false) + .show(); + } + }); + }else{ + prefsHelper.save("pariNoPrintId", null); + } + } + }); _initializeToZero(); return; } - try { - if (BluetoothUtils.needsBluetoothPermissions()) { - if (!BluetoothUtils.hasBluetoothPermission(requireContext())) { - // Demande la permission si non accordée - BluetoothUtils.requestBluetoothPermission(requireActivity()); - return; // arrête ici, la popup va apparaître +// MobiIotPrinterManager.getInstance().testImagePrinting(bitmap); + + MobiIotPrinterManager.getInstance().printPari(BitMapUtils.bitmapToBmp(BitMapUtils.resizeToPrinterWidth(bitmap, 384)), BitMapUtils.bitmapToBmp(BitMapUtils.resizeToPrinterWidth(barcode, 384)), pari.getNumeroTicket(), tspl.toString(), new MobiIotPrinterManager.MobiIotPrinterStatus() { + @Override + public void printStatusCode(int status) { + if(status!=1){ + prefsHelper.save("pariNoPrintId", String.valueOf(pari.getNumeroTicket())); + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + new AlertDialog.Builder(getContext()) + .setTitle("Echec de l'impression") + .setMessage("L'impréssion du ticket "+pari.getNumeroTicket()+" n'a pu aboutir, "+"\n"+"Veuillez vérifier le papier puis rééssayez!") + .setPositiveButton("Ok", (dlg, which)->{ + try { + int mobiPrinterStatus = MobiIotPrinterManager.getInstance().getPrinterStatus(); + if(mobiPrinterStatus != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + } catch (RemoteException e) { + throw new RuntimeException(e); + } + + try { + printPari(pari); + dlg.dismiss(); + prefsHelper.save("pariNoPrintId", null); + } catch (WriterException | FileNotFoundException e) { + throw new RuntimeException(e); + } + }) + .setCancelable(false) + .show(); + } + }); + }else{ + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + prefsHelper.save("pariNoPrintId", null); + _initializeToZero(); + } + }); } + } + }); - // 2️⃣ Permission OK, on peut afficher la liste - - Printama.with(getContext()).printTextBuilder(tspl, bitmap, pari.getNumeroTicket(), barcode, new Printama.PrintCallback() { - @Override - public void onResult(boolean success, String errorMessage) { - if (!success) { - new android.app.AlertDialog.Builder(getContext()) - .setTitle("Impréssion pari") - .setMessage("Voulez-vous rééimprimer ce ticket?") - .setPositiveButton("Oui", (dialog, which) -> { - try { - printPari(pari); - } catch (WriterException e) { - throw new RuntimeException(e); - } - }) - .setNegativeButton("Non", (dialog, which) -> { - dialog.dismiss(); - }); - } else { - _initializeToZero(); - } - } - }); - } catch (SecurityException e) { - Toast.makeText(requireContext(), - "Permission Bluetooth non accordée", Toast.LENGTH_SHORT).show(); - } +// try { +// if (BluetoothUtils.needsBluetoothPermissions()) { +// if (!BluetoothUtils.hasBluetoothPermission(requireContext())) { +// // Demande la permission si non accordée +// BluetoothUtils.requestBluetoothPermission(requireActivity()); +// return; // arrête ici, la popup va apparaître +// } +// } +// +// // 2️⃣ Permission OK, on peut afficher la liste +// +// Printama.with(getContext()).printTextBuilder(tspl, bitmap, pari.getNumeroTicket(), barcode, new Printama.PrintCallback() { +// @Override +// public void onResult(boolean success, String errorMessage) { +// if (!success) { +// new android.app.AlertDialog.Builder(getContext()) +// .setTitle("Impréssion pari") +// .setMessage("Voulez-vous rééimprimer ce ticket?") +// .setPositiveButton("Oui", (dialog, which) -> { +// try { +// printPari(pari); +// } catch (WriterException e) { +// throw new RuntimeException(e); +// } +// }) +// .setNegativeButton("Non", (dialog, which) -> { +// dialog.dismiss(); +// }); +// } else { +// _initializeToZero(); +// } +// } +// }); +// } catch (SecurityException e) { +// Toast.makeText(requireContext(), +// "Permission Bluetooth non accordée", Toast.LENGTH_SHORT).show(); +// } } - public String formatLineWithNumbers(String[] numbers, String separator) { - StringBuilder currentLine = new StringBuilder(); - StringBuilder finalOutput = new StringBuilder(); - List formatted = new ArrayList<>(); - int requiredHorse = shared.typeOfBet.getValue().getNumberOfHorse(); - if(Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList()).contains("X")){ - if(numbers.length <= requiredHorse){ - return Arrays.stream(numbers).map(String::valueOf).collect(Collectors.joining("-")).toString(); - } - List firstPart = Arrays.stream(numbers).limit(requiredHorse).map(String::valueOf).collect(Collectors.toList()); - List secondPart = Arrays.stream(numbers).skip(requiredHorse).map(String::valueOf).collect(Collectors.toList()); - formatted.addAll(firstPart); - formatted.add("R"); - formatted.addAll(secondPart); - }else{ - formatted = Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList()); - } - for (String number : formatted) { - String element = (currentLine.length() == 0 ? "":separator) + number; - - // Si l'ajout dépasse la largeur max, on termine la ligne et on recommence - if (currentLine.length() + element.length() > sunmiPrinterManager.getMaxChar()) { - finalOutput.append(currentLine.toString()).append("\n"); - currentLine = new StringBuilder(number); - } else { - currentLine.append(element); - } - } - - if (currentLine.length() > 0) { - finalOutput.append(currentLine.toString()); - } - - return finalOutput.toString(); - } @SuppressLint({"MissingInflatedId", "SetTextI18n"}) @@ -669,6 +844,16 @@ public class BetValidation extends Fragment { } } + try { + int printerStatus = MobiIotPrinterManager.getInstance().getPrinterStatus(); + Log.e("TAG", "### "+String.valueOf(printerStatus)); + if(printerStatus != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion."+"\n"+" Veuillez vérifier le papier puis rééssayer!"); + return; + } + } catch (RemoteException e) { + throw new RuntimeException(e); + } pariViewModel.createPari(pari).observe(getViewLifecycleOwner(), new Observer>() { @Override public void onChanged(Result pariResult) { @@ -692,6 +877,8 @@ public class BetValidation extends Fragment { loader.dismiss(); MessageDialog.showError(getContext(), e.getMessage()); throw new RuntimeException(e); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); } break; } @@ -815,61 +1002,25 @@ public class BetValidation extends Fragment { } - private Bitmap resizeToPrinterWidth(Bitmap originalBitmap, int printerWidthPx) { - int originalWidth = originalBitmap.getWidth(); - int originalHeight = originalBitmap.getHeight(); - int newHeight = (originalHeight * printerWidthPx) / originalWidth; + public String getFilePath(Bitmap bitmap, String fileName) { + // Utiliser cacheDir au lieu de filesDir (fichiers temporaires) + File logo = new File(getContext().getCacheDir(), fileName); - // 1. Redimensionner sans filtre (conserve les contours nets) - Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, - printerWidthPx, - newHeight, - false); - - // 2. Créer un bitmap ARGB_8888 (meilleure qualité que RGB_565) - Bitmap result = Bitmap.createBitmap(printerWidthPx, newHeight, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(result); - canvas.drawColor(Color.WHITE); - - // 3. Dessiner avec un Paint qui préserve les couleurs - Paint paint = new Paint(); - paint.setAntiAlias(false); // Pas d'anti-aliasing (évite le flou) - canvas.drawBitmap(scaledBitmap, 0, 0, paint); - - // 4. Seuillage intelligent pour garder les détails - for (int x = 0; x < result.getWidth(); x++) { - for (int y = 0; y < result.getHeight(); y++) { - int pixel = result.getPixel(x, y); - int r = Color.red(pixel); - int g = Color.green(pixel); - int b = Color.blue(pixel); - - // Calculer la luminosité - int gray = (r + g + b) / 3; - - // Seuil adaptatif : si c'est sombre, deviens noir - if (gray < 130) { // Seuil à 200 pour garder les gris clairs - result.setPixel(x, y, Color.BLACK); - } else { - result.setPixel(x, y, Color.WHITE); - } - } + try (FileOutputStream fos = new FileOutputStream(logo)) { + // JPEG au lieu de PNG, qualité 85% + bitmap.compress(Bitmap.CompressFormat.JPEG, 85, fos); + return logo.getAbsolutePath(); + } catch (IOException e) { + return null; } - - return result; } - public Bitmap generateBarcodeBitmap(String contents, int width, int height) throws WriterException { - BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.CODE_128, width, height); - Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - bmp.setPixel(x, y, bitMatrix.get(x, y) ? android.graphics.Color.BLACK : android.graphics.Color.WHITE); - } - } - return bmp; - } + + // Écrire un mot (16 bits) en little-endian + + // Écrire un double mot (32 bits) en little-endian + public static String generate12Digits() { StringBuilder sb = new StringBuilder(); diff --git a/app/src/main/java/com/example/quiz/DerniersParis.java b/app/src/main/java/com/example/quiz/DerniersParis.java index 38539dc..d8c9ee8 100644 --- a/app/src/main/java/com/example/quiz/DerniersParis.java +++ b/app/src/main/java/com/example/quiz/DerniersParis.java @@ -3,8 +3,11 @@ package com.example.quiz; import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; import android.graphics.drawable.ColorDrawable; +import android.os.Build; import android.os.Bundle; import androidx.annotation.NonNull; @@ -12,11 +15,15 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import android.os.Handler; +import android.os.Looper; +import android.os.RemoteException; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -30,11 +37,14 @@ import com.example.quiz.data.model.Course; import com.example.quiz.data.model.Pari; import com.example.quiz.data.model.ParisResponse; import com.example.quiz.databinding.FragmentDerniersParisBinding; +import com.example.quiz.utils.BitMapUtils; import com.example.quiz.utils.BluetoothUtils; import com.example.quiz.utils.LoaderDialog; import com.example.quiz.utils.MessageDialog; +import com.example.quiz.utils.MobiIotPrinterManager; import com.example.quiz.utils.Result; import com.example.quiz.utils.SharedPrefsHelper; +import com.example.quiz.utils.SunmiPrinterManager; import com.example.quiz.viewModel.LogsViewModel; import com.example.quiz.viewModel.PariViewModel; import com.google.android.material.appbar.MaterialToolbar; @@ -75,6 +85,11 @@ public class DerniersParis extends Fragment { AlertDialog dialog; LastBetsAdapter adapter; + String mobileName; + + MutableLiveData isPrinterConnected = new MutableLiveData<>(false); + + SunmiPrinterManager sunmiPrinterManager; Map listProduits = Map.of("QUINTE", 5, "QUARTE", 4, "TIERCE", 3, "COUPLE_GAGNANT", 2, "COUPLE_PLACE", 2); @@ -94,6 +109,15 @@ public class DerniersParis extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); prefsHelper = SharedPrefsHelper.getInstance(getContext()); + mobileName = Build.MANUFACTURER; + sunmiPrinterManager = SunmiPrinterManager.getInstance(requireContext()); + if(Build.MANUFACTURER.toLowerCase().contains("sunmi")){ + sunmiPrinterManager.connectPrinter(status ->{ + isPrinterConnected.setValue(status); + }); + }else{ + MobiIotPrinterManager.getInstance().init(getContext()); + } } @@ -224,6 +248,46 @@ public class DerniersParis extends Fragment { dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); view.findViewById(R.id.alert_validate).setOnClickListener(v->{ + if(mobileName.toLowerCase().contains("sunmi")){ + if(isPrinterConnected.getValue() != null && !isPrinterConnected.getValue()){ + sunmiPrinterManager.connectPrinter(status ->{ + isPrinterConnected.setValue(status); + }); + } + switch (sunmiPrinterManager.printerStatus()){ + case 2:{ + MessageDialog.showError(getContext(), "L'imprimante n'est pas connectée!"); + return; + } + case 3:{ + MessageDialog.showError(getContext(), "L'imprimante n'est pas disponible!"); + return; + } + case 4:{ + MessageDialog.showError(getContext(), "Veuillez insérer du papier dans l'imprimante, SVP!"); + return; + } + case 5: { + MessageDialog.showError(getContext(), "Suchauffe iminante de l'imprimante, Veuillez laisser reposer!"); + return; + } + case 6: { + MessageDialog.showError(getContext(), "Le capot est ouvert, veuillez fermer SVP!"); + return; + } + + } + }else{ + try { + int printerStatus = MobiIotPrinterManager.getInstance().getPrinterStatus(); + if(printerStatus != 1){ + MessageDialog.showError(getContext(), "L'imprimante n'est pas connectée!"); + return; + } + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } try { _printPari(pari); dialog.dismiss(); @@ -240,70 +304,87 @@ public class DerniersParis extends Fragment { void _printPari(ParisResponse pari) throws WriterException { - try { - Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo); - Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100); - StringBuilder tspl = new StringBuilder(); - Printama printama = Printama.with(getContext()); - tspl.append("Bamako").append("\n"); - tspl.append(pari.getCourseNom()).append("\n"); - OffsetDateTime dateTime = OffsetDateTime.parse(pari.getHeureDepartPrevue() != null ? pari.getHeureDepartPrevue() : OffsetDateTime.now().toString()); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"); - String formattedDate = dateTime.format(formatter); - tspl.append(formattedDate).append("\n"); - tspl.append("Course ").append(String.valueOf(pari.getCourseId())).append("\n"); - tspl.append(printama.lineSeparator()+"\n"); - List selectedHorses = Arrays.stream(pari.getCombinaison().split(",")).collect(Collectors.toList()); - boolean isElargie = selectedHorses.size()> listProduits.get(pari.getTypesParisMises().get(0).getTypePari()); - String typePari = pari.getTypesParisMises().get(0).getTypePari(); - tspl.append(isElargie?typePari+"/Elargie":typePari).append("\n"); - tspl.append(pari.getFormules().contains("FORMULE_COMPLETE") ?"COMBINAISON COMPLETE"+"\n":""); - String combinationText = selectedHorses.stream() - .map(String::valueOf) - .collect(Collectors.joining("-")); - tspl.append(combinationText).append("\n"); - tspl.append("COEF: ").append(String.valueOf(pari.getCoefficient())); - tspl.append("\n").append(printama.lineSeparator()).append("\n"); - tspl.append("MONTANT: ").append(pari.getMiseTotale()).append(" XOF"); - tspl.append("\n").append(printama.lineSeparator()).append("\n"); - tspl.append("AGENT: ").append(pari.getAgentCode()).append("\n"); - tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(OffsetDateTime.parse(pari.getDateHeurePrise()))).append("\n"); - if (BluetoothUtils.needsBluetoothPermissions()) { - if (!BluetoothUtils.hasBluetoothPermission(requireContext())) { - // Demande la permission si non accordée - BluetoothUtils.requestBluetoothPermission(requireActivity()); - return; // arrête ici, la popup va apparaître - } - } - - // 2️⃣ Permission OK, on peut afficher la liste - - Printama.with(getContext()).printTextBuilder(tspl, bitmap, pari.getNumeroTicket(), barcode, new Printama.PrintCallback() { - @Override - public void onResult(boolean success, String errorMessage) { - if(!success){ - MessageDialog.showError(getContext(), errorMessage); - }else{ - MessageDialog.showSuccess(getContext(), "Pari imprimé avec succès"); + Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo); + Bitmap barcode = BitMapUtils.generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100); + StringBuilder tspl = new StringBuilder(); + tspl.append("Bamako").append("\n"); + tspl.append(pari.getCourseNom()).append("\n"); + OffsetDateTime dateTime = OffsetDateTime.parse(pari.getHeureDepartPrevue() != null ? pari.getHeureDepartPrevue() : OffsetDateTime.now().toString()); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"); + String formattedDate = dateTime.format(formatter); + tspl.append(formattedDate).append("\n"); + tspl.append("Course ").append(String.valueOf(pari.getCourseId())).append("\n"); + tspl.append(sunmiPrinterManager.separationText()+"\n"); + List selectedHorses = Arrays.stream(pari.getCombinaison().split(",")).collect(Collectors.toList()); + boolean isElargie = selectedHorses.size()> listProduits.get(pari.getTypesParisMises().get(0).getTypePari()); + String typePari = pari.getTypesParisMises().get(0).getTypePari(); + tspl.append(isElargie?typePari+"/Elargie":typePari).append("\n"); + tspl.append(pari.getFormules().contains("FORMULE_COMPLETE") ?"COMBINAISON COMPLETE"+"\n":""); + String combinationText = BitMapUtils.formatLineWithNumbers(selectedHorses.stream().map(String::valueOf).toArray(String[]::new), "-", listProduits.get(pari.getTypesParisMises().get(0).getTypePari())); + tspl.append(combinationText).append("\n"); + tspl.append("COEF: ").append(String.valueOf(pari.getCoefficient())); + tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n"); + tspl.append("MONTANT: ").append(pari.getMiseTotale()).append(" XOF"); + tspl.append("\n").append(sunmiPrinterManager.separationText()).append("\n"); + tspl.append("AGENT: ").append(pari.getAgentCode()).append("\n"); + tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(OffsetDateTime.parse(pari.getDateHeurePrise()))).append("\n"); + if(Build.MANUFACTURER.toLowerCase().contains("sunmi")){ + if(Boolean.FALSE.equals(isPrinterConnected.getValue())){ + MessageDialog.showError(getContext(), "Printer not connected"); + return; + } + sunmiPrinterManager.printPari(BitMapUtils.resizeToPrinterWidth(bitmap, 384), barcode, pari.getNumeroTicket(), tspl.toString(), new SunmiPrinterManager.PrintStatusListener() { + @Override + public void onStatusChanged(boolean status) { + if(!status){ + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + MessageDialog.showError(getContext(), "Erreur lors de l'impression."+"\n"+"Veuillez rééssayer SVP"); + } + }); } - } - }); - } catch (SecurityException e) { - Toast.makeText(requireContext(), - "Permission Bluetooth non accordée", Toast.LENGTH_SHORT).show(); - } - } - - - public Bitmap generateBarcodeBitmap(String contents, int width, int height) throws WriterException { - BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.CODE_128, width, height); - Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - bmp.setPixel(x, y, bitMatrix.get(x, y) ? android.graphics.Color.BLACK : android.graphics.Color.WHITE); - } - } - return bmp; + } + }); + return; + } + MobiIotPrinterManager.getInstance().printPari(BitMapUtils.bitmapToBmp(BitMapUtils.resizeToPrinterWidth(bitmap, 384)), BitMapUtils.bitmapToBmp(barcode), pari.getNumeroTicket(), tspl.toString(), new MobiIotPrinterManager.MobiIotPrinterStatus() { + @Override + public void printStatusCode(int status) { + if(status != 1){ + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + MessageDialog.showError(getContext(), "Erreur lors de l'impression."+"\n"+"Veuillez rééssayer SVP"); + } + }); + } + } + }); +// try { +// if (BluetoothUtils.needsBluetoothPermissions()) { +// if (!BluetoothUtils.hasBluetoothPermission(requireContext())) { +// // Demande la permission si non accordée +// BluetoothUtils.requestBluetoothPermission(requireActivity()); +// return; // arrête ici, la popup va apparaître +// } +// } +// // 2️⃣ Permission OK, on peut afficher la liste +// +// Printama.with(getContext()).printTextBuilder(tspl, bitmap, pari.getNumeroTicket(), barcode, new Printama.PrintCallback() { +// @Override +// public void onResult(boolean success, String errorMessage) { +// if(!success){ +// MessageDialog.showError(getContext(), errorMessage); +// }else{ +// MessageDialog.showSuccess(getContext(), "Pari imprimé avec succès"); +// } +// } +// }); +// } catch (SecurityException e) { +// Toast.makeText(requireContext(), +// "Permission Bluetooth non accordée", Toast.LENGTH_SHORT).show(); +// } } diff --git a/app/src/main/java/com/example/quiz/PageQuiz.java b/app/src/main/java/com/example/quiz/PageQuiz.java index 2b4fa12..2d405ee 100644 --- a/app/src/main/java/com/example/quiz/PageQuiz.java +++ b/app/src/main/java/com/example/quiz/PageQuiz.java @@ -228,9 +228,9 @@ public class PageQuiz extends AppCompatActivity { @Override protected void onResume() { - if(!mobileName.toLowerCase().contains("sunmi")){ - checkPermission(); - } +// if(!mobileName.toLowerCase().contains("sunmi")){ +// checkPermission(); +// } super.onResume(); handler = new Handler(Looper.getMainLooper()); checkRunnable = new Runnable() { diff --git a/app/src/main/java/com/example/quiz/Sold.java b/app/src/main/java/com/example/quiz/Sold.java index f8c7ffc..8cbad1f 100644 --- a/app/src/main/java/com/example/quiz/Sold.java +++ b/app/src/main/java/com/example/quiz/Sold.java @@ -5,6 +5,7 @@ import android.app.DatePickerDialog; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.os.Build; import android.os.Bundle; import androidx.annotation.NonNull; @@ -14,9 +15,13 @@ import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; +import android.os.Handler; +import android.os.Looper; +import android.os.RemoteException; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -26,10 +31,13 @@ import android.widget.Toast; import com.anggastudio.printama.Printama; import com.example.quiz.data.model.dtos.paris.SoldeResponse; import com.example.quiz.databinding.FragmentSoldBinding; +import com.example.quiz.utils.BitMapUtils; import com.example.quiz.utils.LoaderDialog; import com.example.quiz.utils.MessageDialog; +import com.example.quiz.utils.MobiIotPrinterManager; import com.example.quiz.utils.Result; import com.example.quiz.utils.SharedPrefsHelper; +import com.example.quiz.utils.SunmiPrinterManager; import com.example.quiz.viewModel.LogsViewModel; import com.example.quiz.viewModel.PariViewModel; import com.google.android.material.appbar.MaterialToolbar; @@ -51,6 +59,11 @@ public class Sold extends Fragment { FragmentSoldBinding binding; + SunmiPrinterManager sunmiPrinterManager; + + MutableLiveData isPrinterReady = new MutableLiveData<>(false); + String mobileName; + LoaderDialog dialog; PariViewModel pariViewModel; @@ -73,6 +86,16 @@ public class Sold extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); prefsHelper = SharedPrefsHelper.getInstance(getContext()); + mobileName = Build.MANUFACTURER; + sunmiPrinterManager = SunmiPrinterManager.getInstance(requireContext()); + if(mobileName.toLowerCase().contains("sunmi")){ + sunmiPrinterManager.connectPrinter(status ->{ + isPrinterReady.setValue(status); + sunmiPrinterManager.disableSystemMessages(); + }); + }else{ + MobiIotPrinterManager.getInstance().init(requireContext()); + } AppCompatActivity activity = (AppCompatActivity) getActivity(); if(activity != null){ MaterialToolbar toolbar = activity.findViewById(R.id.toolbar); @@ -171,7 +194,27 @@ public class Sold extends Fragment { dialog.dismiss(); }) .setPositiveButton("Imprimer", (dialog, which)->{ - Printama printama = Printama.with(getContext()); + if(mobileName.toLowerCase().contains("sunmi")){ + if(isPrinterReady.getValue() == null || !isPrinterReady.getValue()){ + sunmiPrinterManager.connectPrinter(status ->{ + isPrinterReady.setValue(status); + }); + } + if(sunmiPrinterManager.printerStatus() != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + }else{ + try { + int status = MobiIotPrinterManager.getInstance().getPrinterStatus(); + if(status != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } Bitmap logo = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo); String title = "SOLDE AU "+date; StringBuilder text = new StringBuilder(); @@ -180,14 +223,43 @@ public class Sold extends Fragment { text.append("PAIEMENTS: ").append(String.valueOf(soldeResponse.getMontantPaiements())).append(" XOF").append("\n"); text.append("NBR. ANNULATIONS: ").append(soldeResponse.getNombreAnnulations()).append("\n"); text.append("ANNULATIONS: ").append(String.valueOf(soldeResponse.getMontantAnnulations())).append(" XOF").append("\n"); - text.append(printama.lineSeparator()).append("\n"); + text.append(sunmiPrinterManager.separationText()).append("\n"); text.append("SOLDE: ").append(String.valueOf(solde)).append(" XOF").append("\n"); - text.append(printama.lineSeparator()).append("\n"); + text.append(sunmiPrinterManager.separationText()).append("\n"); text.append("AGENT : ").append(prefsHelper.get("code")).append("\n"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); String now = formatter.format(LocalDateTime.now()); text.append("DATE : ").append(now).append("\n"); - printama.printSold(logo, title, text); + if(mobileName.toLowerCase().contains("sunmi")){ + sunmiPrinterManager.printSold(BitMapUtils.resizeToPrinterWidth(logo, 384), title, text, status -> { + if(!status){ + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + MessageDialog.showError(getContext(), "Erreur d'impression"+"\n"+"Veuillez rééssayer SVP."); + } + }); + } + }); + }else{ + try { + MobiIotPrinterManager.getInstance().printSold(BitMapUtils.bitmapToBmp(BitMapUtils.resizeToPrinterWidth(logo, 384)), title, text, new MobiIotPrinterManager.MobiIotPrinterStatus() { + @Override + public void printStatusCode(int status) { + if(status != 1){ + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + MessageDialog.showError(getContext(), "Erreur d'impression"+"\n"+"Veuillez rééssayer SVP."); + } + }); + } + } + }); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } }) .show(); }catch (SecurityException e){ diff --git a/app/src/main/java/com/example/quiz/SoldByCourse.java b/app/src/main/java/com/example/quiz/SoldByCourse.java index 7e9e3b7..e4e45f8 100644 --- a/app/src/main/java/com/example/quiz/SoldByCourse.java +++ b/app/src/main/java/com/example/quiz/SoldByCourse.java @@ -4,15 +4,20 @@ import android.app.AlertDialog; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.os.Build; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; import androidx.fragment.app.Fragment; +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; +import android.os.Handler; +import android.os.Looper; +import android.os.RemoteException; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -21,10 +26,13 @@ import android.widget.Toast; import com.anggastudio.printama.Printama; import com.example.quiz.data.model.dtos.paris.SoldeResponse; import com.example.quiz.databinding.FragmentSoldByCourseBinding; +import com.example.quiz.utils.BitMapUtils; import com.example.quiz.utils.LoaderDialog; import com.example.quiz.utils.MessageDialog; +import com.example.quiz.utils.MobiIotPrinterManager; import com.example.quiz.utils.Result; import com.example.quiz.utils.SharedPrefsHelper; +import com.example.quiz.utils.SunmiPrinterManager; import com.example.quiz.viewModel.LogsViewModel; import com.example.quiz.viewModel.PariViewModel; import com.google.zxing.WriterException; @@ -44,6 +52,9 @@ import dagger.hilt.android.AndroidEntryPoint; public class SoldByCourse extends Fragment { FragmentSoldByCourseBinding binding; + String mobileName; + SunmiPrinterManager sunmiPrinterManager; + MutableLiveData isPrinterReady = new MutableLiveData<>(false); LoaderDialog loader; @@ -74,6 +85,16 @@ public class SoldByCourse extends Fragment { // Inflate the layout for this fragment binding = FragmentSoldByCourseBinding.inflate(inflater, container, false); logsViewModel = new ViewModelProvider(this).get(LogsViewModel.class); + sunmiPrinterManager = SunmiPrinterManager.getInstance(requireContext()); + mobileName = Build.MANUFACTURER; + if(mobileName.toLowerCase().contains("sunmi")) { + sunmiPrinterManager.connectPrinter(status -> { + isPrinterReady.setValue(status); + sunmiPrinterManager.disableSystemMessages(); + }); + }else{ + MobiIotPrinterManager.getInstance().init(requireContext()); + } return binding.getRoot(); } @@ -128,7 +149,27 @@ public class SoldByCourse extends Fragment { dialog.dismiss(); }) .setPositiveButton("Imprimer", (dialog, which)->{ - Printama printama = Printama.with(getContext()); + if(mobileName.toLowerCase().contains("sunmi")){ + if(isPrinterReady.getValue() == null || !isPrinterReady.getValue()){ + sunmiPrinterManager.connectPrinter(status ->{ + isPrinterReady.setValue(status); + }); + } + if(sunmiPrinterManager.printerStatus() != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + }else{ + try { + int status = MobiIotPrinterManager.getInstance().getPrinterStatus(); + if(status != 1){ + MessageDialog.showError(getContext(), "Erreur lors de l'impréssion, Veuillez rééssayer S.V.P!"); + return; + } + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } Bitmap logo = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo); String title = "SOLDE DE LA COURSE "+numero; StringBuilder text = new StringBuilder(); @@ -137,14 +178,43 @@ public class SoldByCourse extends Fragment { text.append("PAIEMENTS: ").append(String.valueOf(soldeResponse.getMontantPaiements())).append(" XOF").append("\n"); text.append("NBR. ANNULATIONS: ").append(soldeResponse.getNombreAnnulations()).append("\n"); text.append("ANNULATIONS: ").append(String.valueOf(soldeResponse.getMontantAnnulations())).append(" XOF").append("\n"); - text.append(printama.lineSeparator()).append("\n"); + text.append(sunmiPrinterManager.separationText()).append("\n"); text.append("SOLDE: ").append(String.valueOf(solde)).append(" XOF").append("\n"); - text.append(printama.lineSeparator()).append("\n"); + text.append(sunmiPrinterManager.separationText()).append("\n"); text.append("AGENT : ").append(prefsHelper.get("code")).append("\n"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"); String now = formatter.format(LocalDateTime.now()); text.append("DATE : ").append(now).append("\n"); - printama.printSold(logo, title, text); + if(mobileName.toLowerCase().contains("sunmi")){ + sunmiPrinterManager.printSold(BitMapUtils.resizeToPrinterWidth(logo, 384), title, text, status -> { + if(!status){ + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + MessageDialog.showError(getContext(), "Une erreur s'est produite lors de l'impréssion."+"\n"+"Veuillez rééssayer S.V.P!"); + } + }); + } + }); + }else{ + try { + MobiIotPrinterManager.getInstance().printSold(BitMapUtils.bitmapToBmp(BitMapUtils.resizeToPrinterWidth(logo, 384)), title, text, new MobiIotPrinterManager.MobiIotPrinterStatus() { + @Override + public void printStatusCode(int status) { + if(status != 1){ + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + MessageDialog.showError(getContext(), "Une erreur s'est produite lors de l'impréssion."+"\n"+"Veuillez rééssayer S.V.P!"); + } + }); + } + } + }); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } }) .show(); }catch (SecurityException e){ diff --git a/app/src/main/java/com/example/quiz/data/remote/ApiService.java b/app/src/main/java/com/example/quiz/data/remote/ApiService.java index 6311d3b..d0004f1 100644 --- a/app/src/main/java/com/example/quiz/data/remote/ApiService.java +++ b/app/src/main/java/com/example/quiz/data/remote/ApiService.java @@ -15,17 +15,14 @@ import com.example.quiz.data.model.dtos.auth.LoginPayload; import com.example.quiz.data.model.dtos.auth.LoginResponse; import com.example.quiz.data.model.TpeResponse; import com.example.quiz.data.model.dtos.auth.User; -import com.example.quiz.data.model.dtos.paris.CancelParisPaylaod; import com.example.quiz.data.model.dtos.paris.SoldeResponse; - import java.util.List; - import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.GET; import retrofit2.http.PATCH; import retrofit2.http.POST; -import retrofit2.http.PUT; + import retrofit2.http.Path; import retrofit2.http.Query; diff --git a/app/src/main/java/com/example/quiz/utils/BitMapUtils.java b/app/src/main/java/com/example/quiz/utils/BitMapUtils.java new file mode 100644 index 0000000..2dca5d8 --- /dev/null +++ b/app/src/main/java/com/example/quiz/utils/BitMapUtils.java @@ -0,0 +1,185 @@ +package com.example.quiz.utils; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class BitMapUtils { + + private static final int MAX_CHAR_2_INCH = 32; + + private static void writeDWord(ByteArrayOutputStream baos, int value) { + baos.write(value & 0xFF); + baos.write((value >> 8) & 0xFF); + baos.write((value >> 16) & 0xFF); + baos.write((value >> 24) & 0xFF); + } + private static void writeWord(ByteArrayOutputStream baos, int value) { + baos.write(value & 0xFF); + baos.write((value >> 8) & 0xFF); + } + public static byte[] bitmapToBmp(Bitmap bitmap) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int width = bitmap.getWidth(); + int height = bitmap.getHeight(); + + // Calcul de la taille des données image (lignes alignées sur 32 bits) + int rowSize = ((width * 3 + 3) & ~3); // 3 bytes par pixel (RGB), aligné sur 4 octets + int imageDataSize = rowSize * height; + int fileSize = 54 + imageDataSize; // 54 = taille entête BMP + + // Entête BITMAPFILEHEADER (14 octets) + writeWord(baos, 0x4D42); // Signature "BM" + writeDWord(baos, fileSize); // Taille du fichier + writeWord(baos, 0); // Réservé + writeWord(baos, 0); // Réservé + writeDWord(baos, 54); // Offset des données pixel + + // Entête BITMAPINFOHEADER (40 octets) + writeDWord(baos, 40); // Taille de l'entête + writeDWord(baos, width); // Largeur + writeDWord(baos, height); // Hauteur + writeWord(baos, 1); // Nombre de plans + writeWord(baos, 24); // Bits par pixel (RGB) + writeDWord(baos, 0); // Compression (0 = BI_RGB) + writeDWord(baos, imageDataSize); // Taille des données image + writeDWord(baos, 0); // Résolution horizontale (peut être 0) + writeDWord(baos, 0); // Résolution verticale + writeDWord(baos, 0); // Couleurs utilisées + writeDWord(baos, 0); // Couleurs importantes + + // Extraction des pixels (BMP stocke de bas en haut) + byte[] pixels = new byte[imageDataSize]; + for (int y = height - 1; y >= 0; y--) { + int rowStart = (height - 1 - y) * rowSize; + for (int x = 0; x < width; x++) { + int pixel = bitmap.getPixel(x, y); + + // Extraire les composantes ARGB + int blue = pixel & 0xFF; + int green = (pixel >> 8) & 0xFF; + int red = (pixel >> 16) & 0xFF; + // Alpha ignoré pour BMP 24 bits + + int pos = rowStart + x * 3; + pixels[pos] = (byte) (blue); + pixels[pos + 1] = (byte) (green); + pixels[pos + 2] = (byte) (red); + } + } + + try { + baos.write(pixels); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + return baos.toByteArray(); + } + + public static Bitmap resizeToPrinterWidth(Bitmap originalBitmap, int printerWidthPx) { + int originalWidth = originalBitmap.getWidth(); + int originalHeight = originalBitmap.getHeight(); + int newHeight = (originalHeight * printerWidthPx) / originalWidth; + + // 1. Redimensionner sans filtre (conserve les contours nets) + Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, + printerWidthPx, + newHeight, + false); + + // 2. Créer un bitmap ARGB_8888 (meilleure qualité que RGB_565) + Bitmap result = Bitmap.createBitmap(printerWidthPx, newHeight, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(result); + canvas.drawColor(Color.WHITE); + + // 3. Dessiner avec un Paint qui préserve les couleurs + Paint paint = new Paint(); + paint.setAntiAlias(false); // Pas d'anti-aliasing (évite le flou) + canvas.drawBitmap(scaledBitmap, 0, 0, paint); + + // 4. Seuillage intelligent pour garder les détails + for (int x = 0; x < result.getWidth(); x++) { + for (int y = 0; y < result.getHeight(); y++) { + int pixel = result.getPixel(x, y); + int r = Color.red(pixel); + int g = Color.green(pixel); + int b = Color.blue(pixel); + + // Calculer la luminosité + int gray = (r + g + b) / 3; + + // Seuil adaptatif : si c'est sombre, deviens noir + if (gray < 130) { // Seuil à 200 pour garder les gris clairs + result.setPixel(x, y, Color.BLACK); + } else { + result.setPixel(x, y, Color.WHITE); + } + } + } + + return result; + } + + public static Bitmap generateBarcodeBitmap(String contents, int width, int height) throws WriterException { + BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.CODE_128, width, height); + Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + bmp.setPixel(x, y, bitMatrix.get(x, y) ? android.graphics.Color.BLACK : android.graphics.Color.WHITE); + } + } + return bmp; + } + + public static String formatLineWithNumbers(String[] numbers, String separator, int requiredHorse) { + StringBuilder currentLine = new StringBuilder(); + StringBuilder finalOutput = new StringBuilder(); + List formatted = new ArrayList<>(); + if(Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList()).contains("X")){ + if(numbers.length <= requiredHorse){ + return Arrays.stream(numbers).map(String::valueOf).collect(Collectors.joining("-")).toString(); + } + List firstPart = Arrays.stream(numbers).limit(requiredHorse).map(String::valueOf).collect(Collectors.toList()); + List secondPart = Arrays.stream(numbers).skip(requiredHorse).map(String::valueOf).collect(Collectors.toList()); + formatted.addAll(firstPart); + formatted.add("R"); + formatted.addAll(secondPart); + }else{ + formatted = Arrays.stream(numbers).map(String::valueOf).collect(Collectors.toList()); + } + + for (String number : formatted) { + String element = (currentLine.length() == 0 ? "":separator) + number; + + // Si l'ajout dépasse la largeur max, on termine la ligne et on recommence + if (currentLine.length() + element.length() > MAX_CHAR_2_INCH) { + finalOutput.append(currentLine.toString()).append("\n"); + currentLine = new StringBuilder(number); + } else { + currentLine.append(element); + } + } + + if (currentLine.length() > 0) { + finalOutput.append(currentLine.toString()); + } + + return finalOutput.toString(); + } + +} diff --git a/app/src/main/java/com/example/quiz/utils/MobiIotPrinterManager.java b/app/src/main/java/com/example/quiz/utils/MobiIotPrinterManager.java new file mode 100644 index 0000000..be8be9c --- /dev/null +++ b/app/src/main/java/com/example/quiz/utils/MobiIotPrinterManager.java @@ -0,0 +1,242 @@ +package com.example.quiz.utils; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.sagereal.printer.PrinterInterface; + +import java.io.ByteArrayOutputStream; + +public class MobiIotPrinterManager { + private PrinterInterface mPrinter; + private static MobiIotPrinterManager instance; + private boolean isBinding = false; + String TAG = "MOBITAG"; + + private static final int MAX_CHAR_2_INCH = 32; + + private MobiIotPrinterManager() { + } + + public static synchronized MobiIotPrinterManager getInstance() { + if (instance == null) { + instance = new MobiIotPrinterManager(); + } + return instance; + } + + private ServiceConnection mConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + mPrinter = PrinterInterface.Stub.asInterface(iBinder); + isBinding = false; + Log.d("PrinterManager", "✅ Service d'impression connecté !"); + + // Test rapide pour voir si l'imprimante répond + testPrinterStatus(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + mPrinter = null; + Log.d("PrinterManager", "❌ Service d'impression déconnecté."); + } + }; + + private void testPrinterStatus() { + new Thread(() -> { + try { + if (mPrinter != null) { + int status = mPrinter.getPrinterStatus(); + Log.d("PrinterManager", "Statut imprimante au démarrage : " + status); + } + } catch (Exception e) { + Log.e("PrinterManager", "Erreur test statut", e); + } + }).start(); + } + + // Initialisation CORRIGÉE + public void init(Context context) { + if (mPrinter != null) { + Log.d("PrinterManager", "Service déjà connecté"); + return; + } + + if (isBinding) { + Log.d("PrinterManager", "Connexion déjà en cours"); + return; + } + + // Utiliser l'action correcte trouvée dans le dump + Intent intent = new Intent("sagereal.intent.action.START_PRINTER_SERVICE_AIDL"); + intent.setPackage("com.sagereal.printer"); + + try { + isBinding = true; + boolean success = context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + if (!success) { + isBinding = false; + Log.e("PrinterManager", "Impossible de binder le service. Vérifiez les permissions."); + } else { + Log.d("PrinterManager", "Tentative de connexion au service..."); + } + } catch (SecurityException e) { + isBinding = false; + Log.e("PrinterManager", "Permission refusée. Ajoutez les permissions système.", e); + } + } + + public void printText(String text) { + if (mPrinter == null) { + Log.e("PrinterManager", "❌ L'imprimante n'est pas connectée"); + return; + } + + new Thread(() -> { + try { + // Vérifier le statut avant d'imprimer + int status = mPrinter.getPrinterStatus(); + Log.d("PrinterManager", "Statut avant impression : " + status); + + if (status == 1) { // 0 = Prêt + mPrinter.printText(text); + mPrinter.printEndLine(); + Log.d("PrinterManager", "✅ Impression réussie"); + } else { + Log.e("PrinterManager", "Imprimante non prête, statut : " + status); + + Log.e("PrinterManager", "Erreur : Impression non effectuée!"); + } + } catch (Exception e) { + Log.e("PrinterManager", "Erreur lors de l'impression", e); + } + }).start(); + } + + public void printPari(byte[] logo, byte[] barcode, String numeroTicket, String pariText, MobiIotPrinterStatus listener) { + if (mPrinter == null) { + Log.e("PrinterManager", "❌ L'imprimante n'est pas connectée"); + listener.printStatusCode(0); + return; + } + new Thread(()->{ + try { + int status = mPrinter.getPrinterStatus(); + if (status != 1) { + listener.printStatusCode(2); + return; + } + mPrinter.printBitmap_in(logo); + mPrinter.printText_FullParm("-".repeat(MAX_CHAR_2_INCH), 0, 0, 0, 1, false, false); + mPrinter.printBitmap_in(barcode); + mPrinter.printText_FullParm("\n" + numeroTicket, 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm("-".repeat(MAX_CHAR_2_INCH), 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm(pariText, 0, 0, 0, 0, false, false); + mPrinter.printText_FullParm("-".repeat(MAX_CHAR_2_INCH), 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm("Powered by PMU-MALI", 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm("-".repeat(MAX_CHAR_2_INCH), 0, 0, 0, 0, false, false); + mPrinter.printText_FullParm("\n\n\n\n\n\n", 0, 10, 0, 0, false, false); + Thread.sleep(3000); + if (getPrinterStatus() != 1) { + listener.printStatusCode(0); + } else { + listener.printStatusCode(1); + } + } catch (RemoteException | InterruptedException e) { + throw new RuntimeException(e); + } + }).start(); + } + + public void printSold(byte[] logo, String title, StringBuilder text, MobiIotPrinterStatus listener) throws RemoteException { + if (mPrinter == null) { + Log.e("PrinterManager", "❌ L'imprimante n'est pas connectée"); + listener.printStatusCode(0); + return; + } + new Thread(()->{ + try { + mPrinter.printBitmap_in(logo); + mPrinter.printText_FullParm("-".repeat(MAX_CHAR_2_INCH), 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm(title, 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm("-".repeat(MAX_CHAR_2_INCH), 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm(text.toString(), 0, 0, 0, 0, false, false); + mPrinter.printText_FullParm("-".repeat(MAX_CHAR_2_INCH), 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm("Powered by PMU-MALI", 0, 0, 0, 1, false, false); + mPrinter.printText_FullParm("-".repeat(MAX_CHAR_2_INCH), 0, 0, 0, 0, false, false); + mPrinter.printText_FullParm("\n\n\n\n\n\n", 0, 10, 0, 0, false, false); + Thread.sleep(3000); + if (getPrinterStatus() != 1) { + listener.printStatusCode(0); + } else { + listener.printStatusCode(1); + } + } catch (RemoteException | InterruptedException e) { + throw new RuntimeException(e); + } + }).start(); + + } + + + public int getPrinterStatus() throws RemoteException { + return mPrinter.getPrinterStatus(); + } + + public void printTestText(String text) throws RemoteException { + Log.d(TAG, "#### " + String.valueOf(mPrinter.getPrinterStatus())); + mPrinter.printText_FullParm(text, 0, 0, 0, 0, false, false); + } + + private byte[] pathToPrintableBytes(String path) { + Bitmap bitmap = BitmapFactory.decodeFile(path); + if (bitmap == null) return null; + + // Redimensionnement à 384px (largeur standard 58mm) + int width = 384; + int height = (int) (bitmap.getHeight() * (384.0 / bitmap.getWidth())); + Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, width, height, true); + + // Conversion en binaire (8 pixels par byte) + int bwWidth = (width + 7) / 8 * 8; + byte[] data = new byte[(bwWidth / 8) * height]; + int k = 0; + + for (int y = 0; y < height; y++) { + for (int x = 0; x < bwWidth; x += 8) { + byte value = 0; + for (int bit = 0; bit < 8; bit++) { + if (x + bit < scaledBitmap.getWidth()) { + int pixel = scaledBitmap.getPixel(x + bit, y); + int gray = (int) (Color.red(pixel) * 0.3 + Color.green(pixel) * 0.59 + Color.blue(pixel) * 0.11); + if (gray < 128) value |= (1 << (7 - bit)); + } + } + data[k++] = value; + } + } + return data; + } + + + public void disconnect(Context context) { + if (mPrinter != null) { + context.unbindService(mConnection); + mPrinter = null; + Log.d("PrinterManager", "Service déconnecté"); + } + } + + public interface MobiIotPrinterStatus { + void printStatusCode(int status); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/quiz/utils/SunmiPrinterManager.java b/app/src/main/java/com/example/quiz/utils/SunmiPrinterManager.java index 34436ee..e9a6b30 100644 --- a/app/src/main/java/com/example/quiz/utils/SunmiPrinterManager.java +++ b/app/src/main/java/com/example/quiz/utils/SunmiPrinterManager.java @@ -33,6 +33,29 @@ public class SunmiPrinterManager { return instance; } + public void disableSystemMessages() { + try { + // Commande ESC/POS pour désactiver les messages d'erreur système + // Format standard Sunmi : 1F 11 12 n (n=0 pour désactiver) + byte[] command = new byte[]{0x1F, 0x11, 0x12, 0x00}; + + sunmiPrinter.sendRAWData(command, new InnerResultCallback() { + @Override + public void onRunResult(boolean isSuccess) { + Log.d(TAG, "Messages système désactivés via RAW : " + isSuccess); + } + @Override + public void onReturnString(String result) {} + @Override + public void onRaiseException(int code, String msg) {} + @Override + public void onPrintResult(int code, String msg) {} + }); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + // 🔌 Bind UNE SEULE FOIS public void connectPrinter(Consumer status) { Log.d("######", "Point d'entrée printer"); @@ -66,13 +89,7 @@ public class SunmiPrinterManager { @Override public void onRunResult(boolean isSuccess) { - if(!isSuccess){ - try { - throw new Exception("Impression", new Throwable("Erreur lors d'impression!")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } + } @Override @@ -95,6 +112,7 @@ public class SunmiPrinterManager { }); } catch (Exception e) { + Log.e(TAG, "Fassery: "+e.getMessage()); if (listener != null) { listener.onError(e.getMessage()); } @@ -105,12 +123,17 @@ public class SunmiPrinterManager { return MAX_CHAR_2_INCH; } - public boolean printPari(Bitmap logo, Bitmap barcode, String numeroTicket, String text){ + public void printPari(Bitmap logo, Bitmap barcode, String numeroTicket, String text, PrintStatusListener listener){ try{ + sunmiPrinter.enterPrinterBuffer(true); printSimpleImage(logo); - printTextSimple("\n"+separationText()+"\n"); + printTextSimple("\n" + separationText() + "\n"); printSimpleImage(barcode); setAlignment(1, new PrinterListener() { + @Override + public void onSuccess(boolean isSuccess) { + + } @Override public void onResult(int code) { @@ -123,29 +146,152 @@ public class SunmiPrinterManager { printTextSimple(numeroTicket); printTextSimple("\n"+separationText()+"\n"); setAlignment(0, new PrinterListener() { + @Override + public void onSuccess(boolean isSuccess) { + } + @Override public void onResult(int code) {} @Override public void onError(String errorMessage) {} }); printTextSimple(text); - printTextSimple("\n"+separationText()+"\n"); + printTextSimple("\n" + separationText() + "\n"); setAlignment(1, new PrinterListener() { + @Override + public void onSuccess(boolean isSuccess) { + + } @Override public void onResult(int code) {} @Override public void onError(String errorMessage) {} }); printTextSimple("Powered by PMU-MALI"); - printTextSimple("\n"+separationText()+"\n"); + printTextSimple("\n" + separationText() + "\n"); printTextSimple(" "); printTextSimple(" "); - return true; + sunmiPrinter.exitPrinterBufferWithCallback(true, new InnerResultCallback() { + @Override + public void onRunResult(boolean isSuccess) throws RemoteException { + + } + + @Override + public void onReturnString(String result) throws RemoteException { + Log.e(TAG, "onReturnString: "+result); + } + + @Override + public void onRaiseException(int code, String msg) throws RemoteException { + + } + + @Override + public void onPrintResult(int code, String msg) throws RemoteException { + listener.onStatusChanged(code == 0); + } + }); } catch (Exception e) { throw new RuntimeException(e); } } + public void printSold(Bitmap logo, String title, StringBuilder text, PrintStatusListener listener){ + try{ + sunmiPrinter.enterPrinterBuffer(true); + printSimpleImage(logo); + setAlignment(1, new PrinterListener() { + @Override + public void onSuccess(boolean isSuccess) { + + } + @Override + public void onResult(int code) { + + } + @Override + public void onError(String errorMessage) { + + } + }); + printTextSimple("\n" + separationText() + "\n"); + setAlignment(1, new PrinterListener() { + @Override + public void onSuccess(boolean isSuccess) { + + } + @Override + public void onResult(int code) { + + } + @Override + public void onError(String errorMessage) { + + } + }); + printTextSimple(title); + printTextSimple("\n"+separationText()+"\n"); + setAlignment(0, new PrinterListener() { + @Override + public void onSuccess(boolean isSuccess) { + + } + @Override + public void onResult(int code) { + + } + @Override + public void onError(String errorMessage) { + + } + }); + printTextSimple(text.toString()); + printTextSimple("\n" + separationText() + "\n"); + setAlignment(1, new PrinterListener() { + @Override + public void onSuccess(boolean isSuccess) { + + } + @Override + public void onResult(int code) {} + @Override + public void onError(String errorMessage) {} + }); + printTextSimple("Powered by PMU-MALI"); + printTextSimple("\n" + separationText() + "\n"); + printTextSimple(" "); + printTextSimple(" "); + sunmiPrinter.exitPrinterBufferWithCallback(true, new InnerResultCallback() { + @Override + public void onRunResult(boolean isSuccess) throws RemoteException { + + } + + @Override + public void onReturnString(String result) throws RemoteException { + Log.e(TAG, "onReturnString: "+result); + } + + @Override + public void onRaiseException(int code, String msg) throws RemoteException { + + } + + @Override + public void onPrintResult(int code, String msg) throws RemoteException { + listener.onStatusChanged(code == 0); + } + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private boolean readyForPrinting(){ + return printerStatus() == 1; + } + public String separationText(){ return "-".repeat(MAX_CHAR_2_INCH); } @@ -154,13 +300,11 @@ public class SunmiPrinterManager { public void printSimpleImage(Bitmap bitmap){ printImage(bitmap, new PrinterListener() { @Override - public void onResult(int code) { - Log.d(TAG, "Print OK"); - } + public void onSuccess(boolean isSuccess) {} @Override - public void onError(String errorMessage) { - Log.e(TAG, errorMessage); - } + public void onResult(int code) {} + @Override + public void onError(String errorMessage) {} }); } @@ -168,14 +312,12 @@ public class SunmiPrinterManager { public void printTextSimple(String text) { printText(text, new PrinterListener() { @Override - public void onResult(int code) { - Log.d(TAG, "Print OK"); - } + public void onSuccess(boolean isSuccess) {} + @Override + public void onResult(int code) {} @Override - public void onError(String errorMessage) { - Log.e(TAG, errorMessage); - } + public void onError(String errorMessage) {} }); } @@ -223,24 +365,13 @@ public class SunmiPrinterManager { // Le paramètre '0' correspond généralement à l'alignement (0 = gauche) sunmiPrinter.printBitmap(bitmap, new InnerResultCallback() { @Override - public void onRunResult(boolean isSuccess) { - if(!isSuccess){ - try { - throw new Exception("Impression", new Throwable("Erreur lors d'impression d'une image!")); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } + public void onRunResult(boolean isSuccess) {} @Override - public void onReturnString(String result) { - // Pas utile - } + public void onReturnString(String result) {} @Override public void onRaiseException(int code, String msg) { - Log.e(TAG, "onRaiseException: "+String.valueOf(code)); listener.onResult(code); listener.onError(msg); } @@ -248,8 +379,8 @@ public class SunmiPrinterManager { @Override public void onPrintResult(int code, String msg) { Log.e(TAG, "onPrintResult: "+String.valueOf(code)); - listener.onResult(code); - listener.onError(msg); + listener.onResult(code); + listener.onError(msg); } // N'oublie pas les autres callbacks vides (onRunResult, etc.) }); @@ -268,7 +399,12 @@ public class SunmiPrinterManager { } } + public interface PrintStatusListener { + void onStatusChanged(boolean status); + } + public interface PrinterListener { + void onSuccess(boolean isSuccess); void onResult(int code); void onError(String errorMessage); } diff --git a/app/src/main/java/com/sagereal/print/util/BitmapUtils.java b/app/src/main/java/com/sagereal/print/util/BitmapUtils.java new file mode 100644 index 0000000..f1c259e --- /dev/null +++ b/app/src/main/java/com/sagereal/print/util/BitmapUtils.java @@ -0,0 +1,18 @@ +package com.sagereal.print.util; + +import android.graphics.Bitmap; +import android.graphics.Matrix; +import android.net.Uri; + +/* JADX INFO: loaded from: classes.dex */ +public class BitmapUtils { + private static final Uri imageUri = Uri.parse("file:///sdcard/test.bmp"); + + public static Bitmap zoomImg(Bitmap bitmap, int i, int i2) { + int width = bitmap.getWidth(); + int height = bitmap.getHeight(); + Matrix matrix = new Matrix(); + matrix.postScale(i / width, i2 / height); + return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sagereal/print/util/DataFormatConversion.java b/app/src/main/java/com/sagereal/print/util/DataFormatConversion.java new file mode 100644 index 0000000..3327995 --- /dev/null +++ b/app/src/main/java/com/sagereal/print/util/DataFormatConversion.java @@ -0,0 +1,18 @@ +package com.sagereal.print.util; + +import java.io.IOException; + +/* JADX INFO: loaded from: classes.dex */ +public class DataFormatConversion { + public static byte[] writeDword(long j) throws IOException { + return new byte[]{(byte) (j & 255), (byte) ((j >> 8) & 255), (byte) ((j >> 16) & 255), (byte) ((j >> 24) & 255)}; + } + + public static byte[] writeLong(long j) throws IOException { + return new byte[]{(byte) (j & 255), (byte) ((j >> 8) & 255), (byte) ((j >> 16) & 255), (byte) ((j >> 24) & 255)}; + } + + public static byte[] writeWord(int i) { + return new byte[]{(byte) (i & 255), (byte) ((i >> 8) & 255)}; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sagereal/print/util/QrcodeOrBarcode.java b/app/src/main/java/com/sagereal/print/util/QrcodeOrBarcode.java new file mode 100644 index 0000000..597a1f4 --- /dev/null +++ b/app/src/main/java/com/sagereal/print/util/QrcodeOrBarcode.java @@ -0,0 +1,101 @@ +package com.sagereal.print.util; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.util.Log; +import java.lang.ref.WeakReference; +import java.util.Arrays; + +/* JADX INFO: loaded from: classes.dex */ +public class QrcodeOrBarcode { + private static int height; + private static int width; + + public static byte[] getPrintPhotoByteArray(Bitmap bitmap) { + if (bitmap == null) { + return null; + } + try { + int i = (height * 384) / width; + Bitmap bitmapZoomImg = BitmapUtils.zoomImg(bitmap, 384, i); + int width2 = bitmapZoomImg.getWidth(); + int height2 = bitmapZoomImg.getHeight(); + int i2 = width2 * 3; + int i3 = ((width2 % 4) + i2) * height2; + int i4 = i3 + 54; + byte[] bArr = new byte[i4]; + int i5 = 0; + System.arraycopy(DataFormatConversion.writeWord(19778), 0, bArr, 0, 2); + System.arraycopy(DataFormatConversion.writeDword(i4), 0, bArr, 2, 4); + long j = 0; + System.arraycopy(DataFormatConversion.writeDword(j), 0, bArr, 6, 2); + System.arraycopy(DataFormatConversion.writeDword(j), 0, bArr, 8, 2); + System.arraycopy(DataFormatConversion.writeDword(54L), 0, bArr, 10, 4); + Log.d("jiangcunbin", "totalSize14 : " + Arrays.toString(bArr)); + Bitmap bitmap2 = bitmapZoomImg; + System.arraycopy(DataFormatConversion.writeDword(40L), 0, bArr, 14, 4); + System.arraycopy(DataFormatConversion.writeLong((long) width2), 0, bArr, 18, 4); + System.arraycopy(DataFormatConversion.writeLong(height2), 0, bArr, 22, 4); + System.arraycopy(DataFormatConversion.writeWord(1), 0, bArr, 26, 2); + System.arraycopy(DataFormatConversion.writeWord(24), 0, bArr, 28, 2); + System.arraycopy(DataFormatConversion.writeDword(0L), 0, bArr, 30, 4); + System.arraycopy(DataFormatConversion.writeDword(((long) i) * 1152), 0, bArr, 34, 4); + System.arraycopy(DataFormatConversion.writeLong(0L), 0, bArr, 38, 4); + System.arraycopy(DataFormatConversion.writeLong(0L), 0, bArr, 42, 4); + System.arraycopy(DataFormatConversion.writeDword(0L), 0, bArr, 46, 4); + System.arraycopy(DataFormatConversion.writeDword(0L), 0, bArr, 50, 4); + Log.d("jiangcunbin", "totalSize54 : " + Arrays.toString(bArr)); + byte[] bArr2 = new byte[i3]; + int i6 = i2 + (width2 % 4); + int i7 = height2 + (-1); + int i8 = 0; + while (i8 < height2) { + int i9 = i5; + int i10 = i9; + while (i9 < width2) { + Bitmap bitmap3 = bitmap2; + int pixel = bitmap3.getPixel(i9, i8); + int i11 = (i7 * i6) + i10; + bArr2[i11] = (byte) Color.blue(pixel); + bArr2[i11 + 1] = (byte) Color.green(pixel); + bArr2[i11 + 2] = (byte) Color.red(pixel); + i9++; + i10 += 3; + bitmap2 = bitmap3; + } + i8++; + i7--; + i5 = 0; + } + System.arraycopy(bArr2, 0, bArr, 54, i3); + return bArr; + } catch (Exception e) { + Log.d("jiangcunbin", " Exception print QRcode" + e.getMessage()); + e.printStackTrace(); + return null; + } + } + + public static Bitmap convertToBitmap(String str) { + float f; + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + BitmapFactory.decodeFile(str, options); + width = options.outWidth; + height = options.outHeight; + int i = (height * 384) / width; + Log.e("jiangcunbin", "photo height is : " + height); + float f2 = 0.0f; + if (width > 384 || height > i) { + f2 = width / 384; + f = height / i; + } else { + f = 0.0f; + } + options.inJustDecodeBounds = false; + options.inSampleSize = (int) Math.max(f2, f); + return Bitmap.createScaledBitmap((Bitmap) new WeakReference(BitmapFactory.decodeFile(str, options)).get(), 384, i, true); + } +} \ No newline at end of file diff --git a/printama/src/main/AndroidManifest.xml b/printama/src/main/AndroidManifest.xml index 751322c..c8ad91e 100644 --- a/printama/src/main/AndroidManifest.xml +++ b/printama/src/main/AndroidManifest.xml @@ -1,6 +1,13 @@ + + + + + + +