commit a2c69a20c5d14c179383e0b8134f208d89beeb33 Author: fakz9 Date: Mon Nov 13 02:25:19 2023 +0300 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..f6b68cc --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..ae388c2 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..21da02b --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..8978d23 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..f20cd86 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,54 @@ +plugins { + id("com.android.application") +} + +android { + namespace = "com.denco.assemblrprintingservice" + compileSdk = 34 + + defaultConfig { + applicationId = "com.denco.assemblrprintingservice" + minSdk = 29 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + buildFeatures { + viewBinding = true + } + packagingOptions { + exclude("META-INF/*") + } +} + +dependencies { + + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.10.0") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") + implementation("androidx.navigation:navigation-fragment:2.5.3") + implementation("androidx.navigation:navigation-ui:2.5.3") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + implementation(files("libs/printer-lib-2.2.4.aar")) + implementation("io.vertx:vertx-web:4.4.6") + implementation("org.apache.pdfbox:pdfbox:2.0.1") + +} + diff --git a/app/libs/printer-lib-2.2.4.aar b/app/libs/printer-lib-2.2.4.aar new file mode 100644 index 0000000..08fd737 Binary files /dev/null and b/app/libs/printer-lib-2.2.4.aar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/denco/assemblrprintingservice/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/denco/assemblrprintingservice/ExampleInstrumentedTest.java new file mode 100644 index 0000000..5f72baf --- /dev/null +++ b/app/src/androidTest/java/com/denco/assemblrprintingservice/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.denco.assemblrprintingservice; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.denco.assemblrprintingservice", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..4dc7805 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/denco/assemblrprintingservice/MainActivity.java b/app/src/main/java/com/denco/assemblrprintingservice/MainActivity.java new file mode 100644 index 0000000..e9bca24 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/MainActivity.java @@ -0,0 +1,97 @@ +package com.denco.assemblrprintingservice; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; + +import com.google.android.material.bottomnavigation.BottomNavigationView; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.navigation.NavController; +import androidx.navigation.Navigation; +import androidx.navigation.ui.AppBarConfiguration; +import androidx.navigation.ui.NavigationUI; + +import com.denco.assemblrprintingservice.databinding.ActivityMainBinding; + +import net.posprinter.CPCLConst; +import net.posprinter.CPCLPrinter; +import net.posprinter.IDeviceConnection; +import net.posprinter.IPOSListener; +import net.posprinter.POSConnect; +import net.posprinter.TSCConst; +import net.posprinter.TSCPrinter; +import net.posprinter.ZPLPrinter; + +public class MainActivity extends AppCompatActivity { + + private ActivityMainBinding binding; + private boolean isRunning = false; + private SharedPreferences preferences; + private Button button; + private EditText ozonText; + private EditText wbText; + + private void loadSettings() { + String ozonAddress = preferences.getString("ozon_printer_address", "default_value"); + String wbAddress = preferences.getString("wb_printer_address", "default_value"); + if (!ozonAddress.equals("default_value")) ozonText.setText(ozonAddress); + if (!wbAddress.equals("default_value")) wbText.setText(wbAddress); + } + + private void saveSettings() { + SharedPreferences.Editor editor = preferences.edit(); + editor.putString("ozon_printer_address", ozonText.getText().toString()); + editor.putString("wb_printer_address", wbText.getText().toString()); + editor.commit(); + } + + private void start() { + saveSettings(); + startService(new Intent(this, PrintingService.class)); + this.ozonText.setEnabled(false); + this.wbText.setEnabled(false); + this.button.setText("Остановить"); + this.isRunning = true; + } + + private void stop() { + stopService(new Intent(this, PrintingService.class)); + this.ozonText.setEnabled(true); + this.wbText.setEnabled(true); + this.button.setText("Запустить"); + this.isRunning = false; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + + binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + // Initializing controls + this.button = (Button) findViewById(R.id.startBtn); + this.ozonText = ((EditText) findViewById(R.id.ozonPrinterAddr)); + this.wbText = ((EditText) findViewById(R.id.wbPrinterAddr)); + this.preferences = getSharedPreferences("printers_settings", MODE_PRIVATE); + + this.loadSettings(); + + this.button.setOnClickListener(e -> { + if (!isRunning) { + start(); + } else { + stop(); + } + }); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/denco/assemblrprintingservice/NotificationUtils.java b/app/src/main/java/com/denco/assemblrprintingservice/NotificationUtils.java new file mode 100644 index 0000000..dae5043 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/NotificationUtils.java @@ -0,0 +1,44 @@ +package com.denco.assemblrprintingservice; + +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import androidx.core.app.NotificationCompat; +import com.denco.assemblrprintingservice.MainActivity; +import com.denco.assemblrprintingservice.R; + +public class NotificationUtils { + private static final int NOTIFICATION_ID = 1; + private static final String NOTIFICATION_CHANNEL_ID = "Channel_Id"; + + public static void createNotificationChannel(Service service) { + CharSequence name = service.getString(R.string.channel_name); + String description = service.getString(R.string.channel_description); + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name, importance); + channel.setDescription(description); + NotificationManager notificationManager = service.getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + } + + public static void startForeground(Service service) { + Intent notificationIntent = new Intent(service, MainActivity.class); + + PendingIntent pendingIntent = PendingIntent.getActivity(service, 0, + notificationIntent, PendingIntent.FLAG_IMMUTABLE); + + android.app.Notification notification = new NotificationCompat.Builder(service, + NOTIFICATION_CHANNEL_ID) + .setOngoing(true) + .setSmallIcon(R.drawable.ic_notifications_black_24dp) + .setContentTitle(service.getString(R.string.app_name)) + .setContentText("Service is running background") + .setContentIntent(pendingIntent) + .build(); + + service.startForeground(NOTIFICATION_ID, notification); + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/PrintingController.java b/app/src/main/java/com/denco/assemblrprintingservice/PrintingController.java new file mode 100644 index 0000000..cb74c3f --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/PrintingController.java @@ -0,0 +1,83 @@ +package com.denco.assemblrprintingservice; + +import android.content.Context; + +import com.denco.assemblrprintingservice.printing.PrinterConnector; +import com.denco.assemblrprintingservice.printing.PrinterConnectorConfig; +import com.denco.assemblrprintingservice.server.PrintingServer; +import com.denco.assemblrprintingservice.server.PrintingServerConfig; +import com.denco.assemblrprintingservice.server.PrintingServerListener; + +import java.util.HashMap; +import java.util.Map; + + +public class PrintingController implements PrintingServerListener { + + private final Context context; + + private final PrinterConnectorConfig[] connectorConfigs; + + private final PrintingServerConfig serverConfig; + private PrintingServer printingServer; + + private final Map printerConnectorMap = new HashMap<>(); + + public PrintingController(Context context, PrinterConnectorConfig[] connectorConfigs, PrintingServerConfig serverConfig) { + this.connectorConfigs = connectorConfigs; + this.serverConfig = serverConfig; + this.context = context; + } + + public void initialize() { + this.initServer(); + this.initConnectors(); + } + + public void stop() { + this.printingServer.stop(); + for (PrinterConnector connector : this.printerConnectorMap.values()) { + connector.stop(); + } + } + + private void initServer() { + this.printingServer = new PrintingServer(this.serverConfig, this); + Thread printingServerThread = new Thread(() -> { + this.printingServer.start(); + }); + printingServerThread.start(); + } + + private void initConnectors() { + for (PrinterConnectorConfig connectorConfig : this.connectorConfigs) { + this.printerConnectorMap.put(connectorConfig.getName(), new PrinterConnector(this.context, connectorConfig)); + } + } + + + private boolean isPrinterReady(String printerName) { + if (!this.printerConnectorMap.containsKey(printerName)) return false; + // return this.printerConnectorMap.get(printerName).isReady(); + return true; + } + + @Override + public boolean onImageRequest(String printerName, byte[] imageData) { + if (!this.isPrinterReady(printerName)) return false; + PrinterConnector printer = this.printerConnectorMap.get(printerName); + printer.reconnect(); + printer.printImage(imageData); + return true; + } + + @Override + public boolean onPdfRequest(String printerName, byte[] pdfData) { + if (!this.isPrinterReady(printerName)) return false; + PrinterConnector printer = this.printerConnectorMap.get(printerName); + printer.reconnect(); + printer.printPdf(pdfData); + + return true; + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/PrintingService.java b/app/src/main/java/com/denco/assemblrprintingservice/PrintingService.java new file mode 100644 index 0000000..2389d39 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/PrintingService.java @@ -0,0 +1,67 @@ +package com.denco.assemblrprintingservice; + +import android.app.Service; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.IBinder; +import android.util.Log; + +import androidx.annotation.Nullable; + +import com.denco.assemblrprintingservice.printing.Dimensions; +import com.denco.assemblrprintingservice.printing.PrinterConnector; +import com.denco.assemblrprintingservice.printing.PrinterConnectorConfig; +import com.denco.assemblrprintingservice.server.PrintingServerConfig; + +import java.util.List; + + +public class PrintingService extends Service { + private PrintingController printingController; + + private void initPrinterController() { + int listenPort = 2282; + PrintingServerConfig serverConfig = new PrintingServerConfig(listenPort); + + + SharedPreferences preferences = getSharedPreferences("printers_settings", MODE_PRIVATE); + String ozonAddress = preferences.getString("ozon_printer_address", "default_value"); + String wbAddress = preferences.getString("wb_printer_address", "default_value"); + + Dimensions wildberriesDimensions = new Dimensions(58, 40); + Dimensions ozonDimensions = new Dimensions(75, 120); + PrinterConnectorConfig wildberriesConfig = new PrinterConnectorConfig("wildberries", wbAddress, wildberriesDimensions, true); + PrinterConnectorConfig ozonConfig = new PrinterConnectorConfig("ozon", ozonAddress, ozonDimensions, true); + PrinterConnectorConfig[] configs = new PrinterConnectorConfig[]{wildberriesConfig, ozonConfig}; + this.printingController = new PrintingController(this, configs, serverConfig); + this.printingController.initialize(); + + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + NotificationUtils.createNotificationChannel(this); + NotificationUtils.startForeground(this); + this.initPrinterController(); + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onCreate() { + super.onCreate(); + } + + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onDestroy() { + + printingController.stop(); + super.onDestroy(); + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/printing/Dimensions.java b/app/src/main/java/com/denco/assemblrprintingservice/printing/Dimensions.java new file mode 100644 index 0000000..ee24844 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/printing/Dimensions.java @@ -0,0 +1,32 @@ +package com.denco.assemblrprintingservice.printing; + +public class Dimensions { + private int width; + private int height; + + public Dimensions(int width, int height) { + this.width = width; + this.height = height; + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public void setWidth(int width) { + this.width = width; + } + + public void setHeight(int height) { + this.height = height; + } + + @Override + public String toString() { + return "Width: " + width + ", Height: " + height; + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/printing/PDFUtils.java b/app/src/main/java/com/denco/assemblrprintingservice/printing/PDFUtils.java new file mode 100644 index 0000000..7d384b0 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/printing/PDFUtils.java @@ -0,0 +1,31 @@ +package com.denco.assemblrprintingservice.printing; + +import android.graphics.Bitmap; + +import androidx.annotation.NonNull; + +import java.util.Iterator; +import java.util.List; +import java.util.Spliterator; +import java.util.function.Consumer; + +public class PDFUtils implements Iterable { + + + @NonNull + @Override + public Iterator iterator() { + return null; + } + + @Override + public void forEach(@NonNull Consumer action) { + Iterable.super.forEach(action); + } + + @NonNull + @Override + public Spliterator spliterator() { + return Iterable.super.spliterator(); + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/printing/PrinterConnector.java b/app/src/main/java/com/denco/assemblrprintingservice/printing/PrinterConnector.java new file mode 100644 index 0000000..44248f5 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/printing/PrinterConnector.java @@ -0,0 +1,130 @@ +package com.denco.assemblrprintingservice.printing; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.Log; + +import com.denco.assemblrprintingservice.printing.pdf.PdfToBitmapIterable; + +import net.posprinter.IDeviceConnection; +import net.posprinter.IPOSListener; +import net.posprinter.POSConnect; +import net.posprinter.TSCConst; +import net.posprinter.TSCPrinter; + +import java.util.WeakHashMap; + +public class PrinterConnector implements IPOSListener { + private final int PRINTER_DPI = 203; + private final Context context; + private final PrinterConnectorConfig config; + + private IDeviceConnection printerConnection; + private TSCPrinter printer; + private boolean isReady; + + public PrinterConnector(Context context, PrinterConnectorConfig config) { + this.context = context; + this.config = config; + this.initialize(); + } + + private void initialize() { + POSConnect.init(this.context); + this.connect(); + } + + public void stop() { + if (this.printerConnection.isConnect()) this.printerConnection.close(); + POSConnect.exit(); + } + + private void connect() { + this.printerConnection = POSConnect.createDevice(POSConnect.DEVICE_TYPE_ETHERNET); + this.printerConnection.connect(this.config.getIpAddress(), this); + } + + private void disconnect() { + printer = null; + this.printerConnection.close(); + + POSConnect.exit(); + } + + public void reconnect() { + this.disconnect(); + this.initialize(); + + } + + private int mmToDots(double mm) { + double inches = mm / 25.4; + return (int) (inches * this.PRINTER_DPI); + } + + public void printBitmap(Bitmap bitmap) { + + Dimensions dimensions = this.config.getDimensions(); + + int widthInDots = mmToDots(dimensions.getWidth()); + int heightInDots = mmToDots(dimensions.getHeight()); + bitmap = Bitmap.createScaledBitmap(bitmap, widthInDots, heightInDots, true); + printer.sizeMm(dimensions.getWidth(), dimensions.getHeight()) + .gapMm(0, 0) + .cls() + .bitmap(0, 0, TSCConst.BMP_MODE_OVERWRITE, widthInDots, bitmap) + .print(1); + + } + + public void printImage(byte[] imageData) { + Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.length); + this.printBitmap(bitmap); + } + + public void printPdf(byte[] pdfData) { + try { + + PdfToBitmapIterable pdfToBitmapIterable = new PdfToBitmapIterable(this.context, pdfData); + for (Bitmap bitmap : pdfToBitmapIterable) { + this.printBitmap(bitmap); + } + } catch (Exception ignored) { + + } + + } + + @Override + public void onStatus(int code, String description) { + String currentStatus = ""; + switch (code) { + case POSConnect.CONNECT_SUCCESS: + currentStatus = "Connection successful"; + this.printer = new TSCPrinter(this.printerConnection); + this.isReady = true; + break; + case POSConnect.CONNECT_FAIL: + currentStatus = "Connection failed"; + break; + case POSConnect.CONNECT_INTERRUPT: + currentStatus = "Connection has been interrupted"; + this.isReady = false; + if (this.config.isAutoReconnect()) { + this.reconnect(); + } + break; + case POSConnect.SEND_FAIL: + currentStatus = "Send failed"; + break; + default: + currentStatus = "Unknown status"; + break; + } + } + + public boolean isReady() { + return isReady; + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/printing/PrinterConnectorConfig.java b/app/src/main/java/com/denco/assemblrprintingservice/printing/PrinterConnectorConfig.java new file mode 100644 index 0000000..78c6b0a --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/printing/PrinterConnectorConfig.java @@ -0,0 +1,31 @@ +package com.denco.assemblrprintingservice.printing; + +public class PrinterConnectorConfig { + private final Dimensions dimensions; + private final String ipAddress; + private final boolean autoReconnect; + private final String name; + + public PrinterConnectorConfig(String name, String ipAddress, Dimensions dimensions, boolean autoReconnect) { + this.ipAddress = ipAddress; + this.dimensions = dimensions; + this.autoReconnect = autoReconnect; + this.name = name; + } + + public String getIpAddress() { + return ipAddress; + } + + public Dimensions getDimensions() { + return dimensions; + } + + public String getName() { + return name; + } + + public boolean isAutoReconnect() { + return autoReconnect; + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/printing/pdf/PdfToBitmapIterable.java b/app/src/main/java/com/denco/assemblrprintingservice/printing/pdf/PdfToBitmapIterable.java new file mode 100644 index 0000000..0fa010f --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/printing/pdf/PdfToBitmapIterable.java @@ -0,0 +1,60 @@ +package com.denco.assemblrprintingservice.printing.pdf; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.pdf.PdfRenderer; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.Iterator; + +public class PdfToBitmapIterable implements Iterable { + private final byte[] pdfBytes; + private final Context context; + + public PdfToBitmapIterable(Context context, byte[] pdfBytes) { + this.context = context; + this.pdfBytes = pdfBytes; + } + + @Override + public Iterator iterator() { + return new Iterator() { + private int currentIndex = 0; + private PdfRenderer pdfRenderer; + private PdfRenderer.Page currentPage; + + { + try { + File tempFile = File.createTempFile("tempPdf", ".pdf", context.getCacheDir()); + try (FileOutputStream fos = new FileOutputStream(tempFile)) { + fos.write(pdfBytes); + } + ParcelFileDescriptor fd = ParcelFileDescriptor.open(tempFile, ParcelFileDescriptor.MODE_READ_ONLY); + pdfRenderer = new PdfRenderer(fd); + } catch (Exception e) { + throw new RuntimeException("Failed to initialize PdfRenderer", e); + } + } + + @Override + public boolean hasNext() { + return currentIndex < pdfRenderer.getPageCount(); + } + + @Override + public Bitmap next() { + currentPage = pdfRenderer.openPage(currentIndex); + int scaleFactor = 2; + if (currentPage.getWidth() < 100) scaleFactor = 100; + Bitmap bitmap = Bitmap.createBitmap(currentPage.getWidth() * scaleFactor, currentPage.getHeight() * scaleFactor, Bitmap.Config.ARGB_8888); + currentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY); + currentPage.close(); + currentIndex++; + return bitmap; + } + }; + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServer.java b/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServer.java new file mode 100644 index 0000000..ac76aee --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServer.java @@ -0,0 +1,76 @@ +package com.denco.assemblrprintingservice.server; + +import android.util.Log; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Vertx; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.HttpServer; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.web.Router; + +public class PrintingServer extends AbstractVerticle { + private final PrintingServerConfig config; + HttpServer server; + Router router; + PrintingServerListener printingServerListener; + + public PrintingServer(PrintingServerConfig config, PrintingServerListener printingServerListener) { + this.vertx = Vertx.vertx(); + this.server = this.vertx.createHttpServer(); + this.router = Router.router(this.vertx); + this.printingServerListener = printingServerListener; + this.config = config; + + this.initialize(); + } + + private void initialize() { + this.server.requestHandler(this.router); + router.route(HttpMethod.POST, "/print/:printerName/image").handler(event -> { + event.request().body().onSuccess(requestBody -> { + boolean booleanResponse = false; + try { + + String printerName = event.request().getParam("printerName"); + byte[] imageBytes = requestBody.getBytes(); + boolean printerResponse = printingServerListener.onImageRequest(printerName, imageBytes); + } catch (Exception ignored) { + } + JsonObject response = new JsonObject().put("ok", booleanResponse); + + event.response().putHeader("content-type", "application/json") + .end(response.encode()); + }); + }); + router.route(HttpMethod.POST, "/print/:printerName/pdf").handler(event -> { + event.request().body().onSuccess(requestBody -> { + boolean booleanResponse = false; + try { + String printerName = event.request().getParam("printerName"); + byte[] pdfBytes = requestBody.getBytes(); + booleanResponse = printingServerListener.onPdfRequest(printerName, pdfBytes); + } catch (Exception ignored) { + } + + JsonObject response = new JsonObject().put("ok", booleanResponse); + + event.response().putHeader("content-type", "application/json") + .end(response.encode()); + }); + }); + + } + + public void start() { + this.server.listen(this.config.getListenPort()); + } + + public void stop() { + this.server.close(e -> { + Log.i("MY_LOG", "Server has been stopped"); + }); + } + + +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServerConfig.java b/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServerConfig.java new file mode 100644 index 0000000..aa95a9b --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServerConfig.java @@ -0,0 +1,14 @@ +package com.denco.assemblrprintingservice.server; + +public class PrintingServerConfig { + + private final int listenPort; + + public PrintingServerConfig(int listenPort) { + this.listenPort = listenPort; + } + + public int getListenPort() { + return listenPort; + } +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServerListener.java b/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServerListener.java new file mode 100644 index 0000000..d8bcfd9 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/server/PrintingServerListener.java @@ -0,0 +1,8 @@ +package com.denco.assemblrprintingservice.server; + +public interface PrintingServerListener { + boolean onImageRequest(String printerName, byte[] imageData); + + boolean onPdfRequest(String printerName, byte[] pdfData); + +} diff --git a/app/src/main/java/com/denco/assemblrprintingservice/ui/dashboard/DashboardFragment.java b/app/src/main/java/com/denco/assemblrprintingservice/ui/dashboard/DashboardFragment.java new file mode 100644 index 0000000..4037074 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/ui/dashboard/DashboardFragment.java @@ -0,0 +1,37 @@ +package com.denco.assemblrprintingservice.ui.dashboard; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import com.denco.assemblrprintingservice.databinding.FragmentDashboardBinding; + +public class DashboardFragment extends Fragment { + + private FragmentDashboardBinding binding; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + DashboardViewModel dashboardViewModel = + new ViewModelProvider(this).get(DashboardViewModel.class); + + binding = FragmentDashboardBinding.inflate(inflater, container, false); + View root = binding.getRoot(); + + final TextView textView = binding.textDashboard; + dashboardViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); + return root; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/denco/assemblrprintingservice/ui/dashboard/DashboardViewModel.java b/app/src/main/java/com/denco/assemblrprintingservice/ui/dashboard/DashboardViewModel.java new file mode 100644 index 0000000..7a7548b --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/ui/dashboard/DashboardViewModel.java @@ -0,0 +1,19 @@ +package com.denco.assemblrprintingservice.ui.dashboard; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class DashboardViewModel extends ViewModel { + + private final MutableLiveData mText; + + public DashboardViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is dashboard fragment"); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/denco/assemblrprintingservice/ui/home/HomeFragment.java b/app/src/main/java/com/denco/assemblrprintingservice/ui/home/HomeFragment.java new file mode 100644 index 0000000..af19f6e --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/ui/home/HomeFragment.java @@ -0,0 +1,37 @@ +package com.denco.assemblrprintingservice.ui.home; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import com.denco.assemblrprintingservice.databinding.FragmentHomeBinding; + +public class HomeFragment extends Fragment { + + private FragmentHomeBinding binding; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + HomeViewModel homeViewModel = + new ViewModelProvider(this).get(HomeViewModel.class); + + binding = FragmentHomeBinding.inflate(inflater, container, false); + View root = binding.getRoot(); + + final TextView textView = binding.textHome; + homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); + return root; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/denco/assemblrprintingservice/ui/home/HomeViewModel.java b/app/src/main/java/com/denco/assemblrprintingservice/ui/home/HomeViewModel.java new file mode 100644 index 0000000..72c0026 --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/ui/home/HomeViewModel.java @@ -0,0 +1,19 @@ +package com.denco.assemblrprintingservice.ui.home; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class HomeViewModel extends ViewModel { + + private final MutableLiveData mText; + + public HomeViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is home fragment"); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/denco/assemblrprintingservice/ui/notifications/NotificationsFragment.java b/app/src/main/java/com/denco/assemblrprintingservice/ui/notifications/NotificationsFragment.java new file mode 100644 index 0000000..82b76ff --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/ui/notifications/NotificationsFragment.java @@ -0,0 +1,37 @@ +package com.denco.assemblrprintingservice.ui.notifications; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; + +import com.denco.assemblrprintingservice.databinding.FragmentNotificationsBinding; + +public class NotificationsFragment extends Fragment { + + private FragmentNotificationsBinding binding; + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + NotificationsViewModel notificationsViewModel = + new ViewModelProvider(this).get(NotificationsViewModel.class); + + binding = FragmentNotificationsBinding.inflate(inflater, container, false); + View root = binding.getRoot(); + + final TextView textView = binding.textNotifications; + notificationsViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); + return root; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + binding = null; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/denco/assemblrprintingservice/ui/notifications/NotificationsViewModel.java b/app/src/main/java/com/denco/assemblrprintingservice/ui/notifications/NotificationsViewModel.java new file mode 100644 index 0000000..0b2579f --- /dev/null +++ b/app/src/main/java/com/denco/assemblrprintingservice/ui/notifications/NotificationsViewModel.java @@ -0,0 +1,19 @@ +package com.denco.assemblrprintingservice.ui.notifications; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class NotificationsViewModel extends ViewModel { + + private final MutableLiveData mText; + + public NotificationsViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is notifications fragment"); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_dashboard_black_24dp.xml b/app/src/main/res/drawable/ic_dashboard_black_24dp.xml new file mode 100644 index 0000000..46fc8de --- /dev/null +++ b/app/src/main/res/drawable/ic_dashboard_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_black_24dp.xml b/app/src/main/res/drawable/ic_home_black_24dp.xml new file mode 100644 index 0000000..f8bb0b5 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/app/src/main/res/drawable/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..78b75c3 --- /dev/null +++ b/app/src/main/res/drawable/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..e497992 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,44 @@ + + + + + + + + + +