diff --git a/.gitignore b/.gitignore
index 4587336..bf136d7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Built application files
*.apk
*.aar
+!app/libs/BluetoothBinding.aar
*.ap_
*.aab
diff --git a/app/build.gradle b/app/build.gradle
index 2893805..023b81b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -18,8 +18,8 @@ android {
applicationId "com.sunmi.printerconfig"
minSdk 21
targetSdk 35
- versionCode 2
- versionName "1.0.1"
+ versionCode 11
+ versionName "1.0.10"
}
signingConfigs {
@@ -56,6 +56,7 @@ android {
}
dependencies {
+ implementation files('libs/BluetoothBinding.aar')
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
diff --git a/app/libs/BluetoothBinding.aar b/app/libs/BluetoothBinding.aar
new file mode 100644
index 0000000..75464c7
Binary files /dev/null and b/app/libs/BluetoothBinding.aar differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 406e5bf..ee900f7 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -10,3 +10,12 @@
# Keep printer configuration classes
-keep class com.sunmi.printerconfig.** { *; }
+
+# Keep Sunmi SDK callback interfaces/classes used during Wi-Fi configuration.
+-keep class com.sunmi.cloudprinter.** { *; }
+-keep interface com.sunmi.cloudprinter.** { *; }
+
+# Keep callback implementers and SDK internals that may be invoked reflectively.
+-keep class * implements com.sunmi.cloudprinter.presenter.SunmiPrinterClient$IPrinterClient { *; }
+-keep class library.** { *; }
+-keep class com.inuker.bluetooth.library.** { *; }
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 87b4a00..2094e9d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,11 +13,14 @@
-
+
+
diff --git a/app/src/main/java/com/sunmi/printerconfig/DiscoveredPrinter.java b/app/src/main/java/com/sunmi/printerconfig/DiscoveredPrinter.java
new file mode 100644
index 0000000..84cf6e8
--- /dev/null
+++ b/app/src/main/java/com/sunmi/printerconfig/DiscoveredPrinter.java
@@ -0,0 +1,38 @@
+package com.sunmi.printerconfig;
+
+import java.util.Objects;
+
+public final class DiscoveredPrinter {
+ private final String address;
+ private final String name;
+
+ public DiscoveredPrinter(String address, String name) {
+ this.address = address == null ? "" : address.trim();
+ this.name = name == null ? "" : name.trim();
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof DiscoveredPrinter)) {
+ return false;
+ }
+ DiscoveredPrinter that = (DiscoveredPrinter) other;
+ return Objects.equals(address, that.address);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(address);
+ }
+}
diff --git a/app/src/main/java/com/sunmi/printerconfig/BluetoothDeviceAdapter.java b/app/src/main/java/com/sunmi/printerconfig/DiscoveredPrinterAdapter.java
similarity index 50%
rename from app/src/main/java/com/sunmi/printerconfig/BluetoothDeviceAdapter.java
rename to app/src/main/java/com/sunmi/printerconfig/DiscoveredPrinterAdapter.java
index a11dd47..11b7bbe 100644
--- a/app/src/main/java/com/sunmi/printerconfig/BluetoothDeviceAdapter.java
+++ b/app/src/main/java/com/sunmi/printerconfig/DiscoveredPrinterAdapter.java
@@ -1,29 +1,24 @@
package com.sunmi.printerconfig;
-import android.Manifest;
-import android.bluetooth.BluetoothDevice;
-import android.content.pm.PackageManager;
-import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
-public class BluetoothDeviceAdapter extends RecyclerView.Adapter {
- private final List devices;
+public class DiscoveredPrinterAdapter extends RecyclerView.Adapter {
+ private final List devices;
private final OnDeviceClickListener listener;
public interface OnDeviceClickListener {
- void onDeviceClick(BluetoothDevice device);
+ void onDeviceClick(DiscoveredPrinter device);
}
- public BluetoothDeviceAdapter(List devices, OnDeviceClickListener listener) {
+ public DiscoveredPrinterAdapter(List devices, OnDeviceClickListener listener) {
this.devices = devices;
this.listener = listener;
}
@@ -38,24 +33,18 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
- BluetoothDevice device = devices.get(position);
- boolean hasPermission = true;
+ DiscoveredPrinter device = devices.get(position);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- hasPermission = ContextCompat.checkSelfPermission(holder.itemView.getContext(),
- Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;
- }
+ String baseName = device.getName().isEmpty()
+ ? holder.itemView.getContext().getString(R.string.unknown_device)
+ : device.getName();
- if (hasPermission) {
- String name = device.getName();
- String address = device.getAddress();
- holder.deviceName.setText(name != null ? name : "Unknown Device");
- holder.deviceAddress.setText(address);
- } else {
- holder.deviceName.setText("Permission Required");
- holder.deviceAddress.setText("");
+ if (PrinterDeviceClassifier.isLikelySunmi(device.getName())) {
+ baseName = baseName + " \u2022 " + holder.itemView.getContext().getString(R.string.likely_sunmi);
}
+ holder.deviceName.setText(baseName);
+ holder.deviceAddress.setText(device.getAddress());
holder.itemView.setOnClickListener(v -> listener.onDeviceClick(device));
}
@@ -65,8 +54,8 @@ public int getItemCount() {
}
static class ViewHolder extends RecyclerView.ViewHolder {
- TextView deviceName;
- TextView deviceAddress;
+ private final TextView deviceName;
+ private final TextView deviceAddress;
ViewHolder(View itemView) {
super(itemView);
diff --git a/app/src/main/java/com/sunmi/printerconfig/MainActivity.java b/app/src/main/java/com/sunmi/printerconfig/MainActivity.java
index 556ee58..ef18ead 100644
--- a/app/src/main/java/com/sunmi/printerconfig/MainActivity.java
+++ b/app/src/main/java/com/sunmi/printerconfig/MainActivity.java
@@ -2,14 +2,12 @@
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.BroadcastReceiver;
-import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
@@ -22,49 +20,53 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import com.sunmi.cloudprinter.bean.PrinterDevice;
+import com.sunmi.cloudprinter.bean.Router;
+import com.sunmi.cloudprinter.presenter.SunmiPrinterClient;
+
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
-public class MainActivity extends AppCompatActivity {
+public class MainActivity extends AppCompatActivity implements SunmiPrinterClient.IPrinterClient {
private static final int PERMISSION_REQUEST_CODE = 1;
private static final int REQUEST_ENABLE_BT = 2;
+ private static final int PRINTER_SCAN_TIMEOUT_MS = 12_000;
+ private static final int PRINTER_CONNECTION_TIMEOUT_MS = 10_000;
private BluetoothAdapter bluetoothAdapter;
private Button scanButton;
private ProgressBar progressBar;
private TextView statusText;
private RecyclerView devicesRecyclerView;
- private BluetoothDeviceAdapter deviceAdapter;
- private List deviceList;
-
- private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (BluetoothDevice.ACTION_FOUND.equals(action)) {
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if (device != null && checkBluetoothPermission()) {
- String deviceName = device.getName();
- // Filter for Sunmi printers
- if (deviceName != null && (deviceName.startsWith("NT311") ||
- deviceName.contains("CloudPrinter") ||
- deviceName.contains("SUNMI"))) {
- if (!deviceList.contains(device)) {
- deviceList.add(device);
- deviceAdapter.notifyDataSetChanged();
- }
- }
- }
- } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
- progressBar.setVisibility(View.GONE);
- scanButton.setEnabled(true);
- scanButton.setText(R.string.scan_bluetooth);
- if (deviceList.isEmpty()) {
- statusText.setText(R.string.no_devices_found);
- } else {
- statusText.setText("");
- }
- }
+ private DiscoveredPrinterAdapter deviceAdapter;
+ private final List deviceList = new ArrayList<>();
+ private final Set discoveredAddresses = new HashSet<>();
+
+ private SunmiPrinterClient sunmiPrinterClient;
+ private final Handler scanTimeoutHandler = new Handler(Looper.getMainLooper());
+ private final Handler connectionTimeoutHandler = new Handler(Looper.getMainLooper());
+
+ private String pendingPrinterAddress;
+ private String pendingPrinterName;
+ private boolean scanInProgress = false;
+ private boolean waitingForPrinterConnection = false;
+
+ private final Runnable scanTimeoutRunnable = () -> {
+ if (!scanInProgress || waitingForPrinterConnection) {
+ return;
+ }
+
+ stopPrinterScan(true);
+ if (deviceList.isEmpty()) {
+ statusText.setText(R.string.no_compatible_printers_found);
+ }
+ };
+
+ private final Runnable connectionTimeoutRunnable = () -> {
+ if (waitingForPrinterConnection) {
+ handlePrinterConnectionFailure(getString(R.string.printer_connection_timeout));
}
};
@@ -78,9 +80,7 @@ protected void onCreate(Bundle savedInstanceState) {
statusText = findViewById(R.id.statusText);
devicesRecyclerView = findViewById(R.id.devicesRecyclerView);
- deviceList = new ArrayList<>();
- deviceAdapter = new BluetoothDeviceAdapter(deviceList, this::onDeviceClick);
-
+ deviceAdapter = new DiscoveredPrinterAdapter(deviceList, this::onDeviceClick);
devicesRecyclerView.setLayoutManager(new LinearLayoutManager(this));
devicesRecyclerView.setAdapter(deviceAdapter);
@@ -91,6 +91,11 @@ protected void onCreate(Bundle savedInstanceState) {
return;
}
+ sunmiPrinterClient = new SunmiPrinterClient(
+ new ReceiverSafeContext(getApplicationContext()),
+ this
+ );
+
scanButton.setOnClickListener(v -> {
if (checkPermissions()) {
startBluetoothScan();
@@ -98,22 +103,16 @@ protected void onCreate(Bundle savedInstanceState) {
requestPermissions();
}
});
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothDevice.ACTION_FOUND);
- filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- registerReceiver(bluetoothReceiver, filter);
}
private boolean checkPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- return ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED &&
- ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;
- } else {
- return ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
- ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED &&
- ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
+ return ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED
+ && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;
}
+ return ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED
+ && ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED
+ && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
private void requestPermissions() {
@@ -122,60 +121,199 @@ private void requestPermissions() {
new String[]{
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_CONNECT
- }, PERMISSION_REQUEST_CODE);
- } else {
- ActivityCompat.requestPermissions(this,
- new String[]{
- Manifest.permission.BLUETOOTH,
- Manifest.permission.BLUETOOTH_ADMIN,
- Manifest.permission.ACCESS_FINE_LOCATION
- }, PERMISSION_REQUEST_CODE);
+ },
+ PERMISSION_REQUEST_CODE);
+ return;
}
- }
- private boolean checkBluetoothPermission() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- return ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;
- }
- return true;
+ ActivityCompat.requestPermissions(this,
+ new String[]{
+ Manifest.permission.BLUETOOTH,
+ Manifest.permission.BLUETOOTH_ADMIN,
+ Manifest.permission.ACCESS_FINE_LOCATION
+ },
+ PERMISSION_REQUEST_CODE);
}
private void startBluetoothScan() {
if (!bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- if (checkBluetoothPermission()) {
- startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
- }
+ startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
return;
}
+ waitingForPrinterConnection = false;
+ stopPrinterScan(false);
+
+ scanInProgress = true;
+ scanTimeoutHandler.removeCallbacks(scanTimeoutRunnable);
+ connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);
+
+ discoveredAddresses.clear();
deviceList.clear();
deviceAdapter.notifyDataSetChanged();
statusText.setText(R.string.scanning);
- if (checkBluetoothPermission() && bluetoothAdapter.isDiscovering()) {
- bluetoothAdapter.cancelDiscovery();
- }
-
scanButton.setEnabled(false);
scanButton.setText(R.string.scanning);
progressBar.setVisibility(View.VISIBLE);
- if (checkBluetoothPermission()) {
- bluetoothAdapter.startDiscovery();
+ try {
+ sunmiPrinterClient.startScan();
+ scanTimeoutHandler.postDelayed(scanTimeoutRunnable, PRINTER_SCAN_TIMEOUT_MS);
+ } catch (Throwable t) {
+ stopPrinterScan(true);
+ statusText.setText(getString(R.string.error, getString(R.string.printer_scan_failed)));
+ }
+ }
+
+ private void stopPrinterScan(boolean resetUi) {
+ scanTimeoutHandler.removeCallbacks(scanTimeoutRunnable);
+ if (scanInProgress) {
+ scanInProgress = false;
+ try {
+ sunmiPrinterClient.stopScan();
+ } catch (Throwable ignored) {
+ }
+ }
+ if (resetUi && !waitingForPrinterConnection) {
+ progressBar.setVisibility(View.GONE);
+ scanButton.setEnabled(true);
+ scanButton.setText(R.string.scan_bluetooth);
}
}
- private void onDeviceClick(BluetoothDevice device) {
- if (checkBluetoothPermission() && bluetoothAdapter.isDiscovering()) {
- bluetoothAdapter.cancelDiscovery();
+ private void onDeviceClick(DiscoveredPrinter device) {
+ stopPrinterScan(false);
+
+ pendingPrinterAddress = device.getAddress();
+ pendingPrinterName = device.getName().isEmpty()
+ ? getString(R.string.unknown_device)
+ : device.getName();
+
+ if (pendingPrinterAddress.isEmpty()) {
+ Toast.makeText(this, R.string.printer_address_unavailable, Toast.LENGTH_LONG).show();
+ progressBar.setVisibility(View.GONE);
+ scanButton.setEnabled(true);
+ scanButton.setText(R.string.scan_bluetooth);
+ return;
}
+ waitingForPrinterConnection = true;
+ progressBar.setVisibility(View.VISIBLE);
+ scanButton.setEnabled(false);
+ statusText.setText(R.string.connecting_to_printer);
+
+ connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);
+ connectionTimeoutHandler.postDelayed(connectionTimeoutRunnable, PRINTER_CONNECTION_TIMEOUT_MS);
+
+ try {
+ // Match the known stable flow: establish BLE session before Wi-Fi config screen.
+ sunmiPrinterClient.getPrinterSn(pendingPrinterAddress);
+ } catch (Throwable t) {
+ handlePrinterConnectionFailure(getString(R.string.printer_connection_failed));
+ }
+ }
+
+ private void openWifiConfigScreen() {
Intent intent = new Intent(this, WifiConfigActivity.class);
- intent.putExtra("device", device);
+ intent.putExtra("device_address", pendingPrinterAddress);
+ intent.putExtra("device_name", pendingPrinterName);
startActivity(intent);
}
+ private void handlePrinterConnectionFailure(String message) {
+ waitingForPrinterConnection = false;
+ connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);
+
+ runOnUiThread(() -> {
+ progressBar.setVisibility(View.GONE);
+ scanButton.setEnabled(true);
+ scanButton.setText(R.string.scan_bluetooth);
+ statusText.setText(getString(R.string.error, message));
+ Toast.makeText(this, message, Toast.LENGTH_LONG).show();
+ });
+ }
+
+ @Override
+ public void onPrinterFount(PrinterDevice printerDevice) {
+ if (printerDevice == null) {
+ return;
+ }
+
+ String address = printerDevice.getAddress();
+ if (address == null || address.trim().isEmpty()) {
+ return;
+ }
+
+ String name = printerDevice.getName();
+ runOnUiThread(() -> {
+ if (!scanInProgress || !discoveredAddresses.add(address)) {
+ return;
+ }
+
+ deviceList.add(new DiscoveredPrinter(address, name));
+ deviceAdapter.notifyDataSetChanged();
+ statusText.setText(getString(R.string.printers_found, deviceList.size()));
+ });
+ }
+
+ @Override
+ public void routerFound(Router router) {
+ // Not used in this activity.
+ }
+
+ @Override
+ public void onGetWifiListFinish() {
+ // Not used in this activity.
+ }
+
+ @Override
+ public void onGetWifiListFail() {
+ // Not used in this activity.
+ }
+
+ @Override
+ public void onSetWifiSuccess() {
+ // Not used in this activity.
+ }
+
+ @Override
+ public void wifiConfigSuccess() {
+ // Not used in this activity.
+ }
+
+ @Override
+ public void onWifiConfigFail() {
+ // Not used in this activity.
+ }
+
+ @Override
+ public void sendDataFail(int code, String msg) {
+ String failure = getString(R.string.wifi_push_error_with_code, code, msg == null ? "Unknown" : msg);
+ handlePrinterConnectionFailure(failure);
+ }
+
+ @Override
+ public void getSnRequestSuccess() {
+ // Wait for onSnReceived callback.
+ }
+
+ @Override
+ public void onSnReceived(String sn) {
+ stopPrinterScan(false);
+ waitingForPrinterConnection = false;
+ connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);
+
+ runOnUiThread(() -> {
+ progressBar.setVisibility(View.GONE);
+ scanButton.setEnabled(true);
+ scanButton.setText(R.string.scan_bluetooth);
+ statusText.setText("");
+ openWifiConfigScreen();
+ });
+ }
+
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
@@ -198,13 +336,15 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in
@Override
protected void onDestroy() {
super.onDestroy();
- try {
- unregisterReceiver(bluetoothReceiver);
- } catch (Exception e) {
- e.printStackTrace();
- }
- if (bluetoothAdapter != null && checkBluetoothPermission() && bluetoothAdapter.isDiscovering()) {
- bluetoothAdapter.cancelDiscovery();
+ stopPrinterScan(false);
+ scanTimeoutHandler.removeCallbacks(scanTimeoutRunnable);
+ connectionTimeoutHandler.removeCallbacks(connectionTimeoutRunnable);
+
+ if (sunmiPrinterClient != null && pendingPrinterAddress != null && !pendingPrinterAddress.isEmpty()) {
+ try {
+ sunmiPrinterClient.disconnect(pendingPrinterAddress);
+ } catch (Throwable ignored) {
+ }
}
}
}
diff --git a/app/src/main/java/com/sunmi/printerconfig/PrinterConfigHelper.java b/app/src/main/java/com/sunmi/printerconfig/PrinterConfigHelper.java
deleted file mode 100644
index 96eff1e..0000000
--- a/app/src/main/java/com/sunmi/printerconfig/PrinterConfigHelper.java
+++ /dev/null
@@ -1,165 +0,0 @@
-package com.sunmi.printerconfig;
-
-import android.Manifest;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothSocket;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.util.Log;
-
-import androidx.core.content.ContextCompat;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.UUID;
-
-public class PrinterConfigHelper {
- private static final String TAG = "PrinterConfigHelper";
- // Standard SPP UUID for Bluetooth Serial Port Profile
- private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
-
- private final Context context;
-
- public PrinterConfigHelper(Context context) {
- this.context = context;
- }
-
- /**
- * Configure Sunmi printer Wi-Fi settings via Bluetooth
- * @param device The Bluetooth device (printer)
- * @param ssid Wi-Fi network SSID
- * @param password Wi-Fi network password
- * @return true if configuration was sent successfully
- */
- public boolean configurePrinterWifi(BluetoothDevice device, String ssid, String password) {
- BluetoothSocket socket = null;
- OutputStream outputStream = null;
-
- try {
- // Check Bluetooth permission
- if (!checkBluetoothPermission()) {
- Log.e(TAG, "Bluetooth permission not granted");
- return false;
- }
-
- // Create Bluetooth socket
- socket = device.createRfcommSocketToServiceRecord(SPP_UUID);
-
- // Connect to the device
- Log.d(TAG, "Connecting to printer...");
- socket.connect();
- Log.d(TAG, "Connected successfully");
-
- // Get output stream
- outputStream = socket.getOutputStream();
-
- // Send Wi-Fi configuration commands
- boolean success = sendWifiConfig(outputStream, ssid, password);
-
- Log.d(TAG, "Configuration sent: " + success);
- return success;
-
- } catch (IOException e) {
- Log.e(TAG, "Error configuring printer: " + e.getMessage(), e);
- return false;
- } finally {
- // Clean up resources
- try {
- if (outputStream != null) {
- outputStream.close();
- }
- if (socket != null) {
- socket.close();
- }
- } catch (IOException e) {
- Log.e(TAG, "Error closing connection: " + e.getMessage());
- }
- }
- }
-
- /**
- * Send Wi-Fi configuration to the printer
- * This uses ESC/POS commands specific to Sunmi printers
- */
- private boolean sendWifiConfig(OutputStream out, String ssid, String password) {
- try {
- // ESC/POS command header for Sunmi Wi-Fi configuration
- // Format: ESC @ (initialize printer)
- // Then: Custom command for Wi-Fi setup
-
- // Initialize printer
- out.write(new byte[]{0x1B, 0x40}); // ESC @
- Thread.sleep(100);
-
- // Sunmi Wi-Fi configuration command format:
- // Command structure: 0x1F 0x1B 0x1F [subcommand] [data length] [SSID] [password]
-
- // Method 1: Using Sunmi's proprietary Wi-Fi config command
- // Header: 0x1F 0x1B 0x1F 0x91 (Wi-Fi config command)
- byte[] header = new byte[]{0x1F, 0x1B, 0x1F, (byte) 0x91};
- out.write(header);
-
- // SSID length (1 byte) + SSID
- byte[] ssidBytes = ssid.getBytes(StandardCharsets.UTF_8);
- out.write(ssidBytes.length);
- out.write(ssidBytes);
-
- // Password length (1 byte) + Password
- byte[] passwordBytes = password.getBytes(StandardCharsets.UTF_8);
- out.write(passwordBytes.length);
- out.write(passwordBytes);
-
- // Security type (1 byte): 3 = WPA2-PSK (most common)
- out.write(0x03);
-
- out.flush();
- Thread.sleep(500);
-
- // Method 2: Alternative format using AT-style commands
- // Some Sunmi printers accept AT commands for configuration
- String atCommand = String.format("AT+WIFI_CONF=\"%s\",\"%s\"\r\n", ssid, password);
- out.write(atCommand.getBytes(StandardCharsets.UTF_8));
- out.flush();
- Thread.sleep(500);
-
- // Method 3: ESC/POS extension command format
- // Some models use this format
- String configCommand = String.format("\u001B\u001F\u0010WIFI:%s,%s\n", ssid, password);
- out.write(configCommand.getBytes(StandardCharsets.UTF_8));
- out.flush();
- Thread.sleep(500);
-
- // Send end marker
- out.write(new byte[]{0x0A}); // Line feed
- out.flush();
-
- Log.d(TAG, "Wi-Fi configuration commands sent to printer");
- Log.d(TAG, "SSID: " + ssid);
-
- return true;
-
- } catch (IOException | InterruptedException e) {
- Log.e(TAG, "Error sending Wi-Fi config: " + e.getMessage());
- return false;
- }
- }
-
- private boolean checkBluetoothPermission() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- return ContextCompat.checkSelfPermission(context,
- Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;
- }
- return true;
- }
-
- // Helper method to convert string to hex for debugging
- private String bytesToHex(byte[] bytes) {
- StringBuilder sb = new StringBuilder();
- for (byte b : bytes) {
- sb.append(String.format("%02X ", b));
- }
- return sb.toString();
- }
-}
diff --git a/app/src/main/java/com/sunmi/printerconfig/PrinterDeviceClassifier.java b/app/src/main/java/com/sunmi/printerconfig/PrinterDeviceClassifier.java
new file mode 100644
index 0000000..efd8a7f
--- /dev/null
+++ b/app/src/main/java/com/sunmi/printerconfig/PrinterDeviceClassifier.java
@@ -0,0 +1,20 @@
+package com.sunmi.printerconfig;
+
+import java.util.Locale;
+
+public final class PrinterDeviceClassifier {
+ private PrinterDeviceClassifier() {
+ }
+
+ public static boolean isLikelySunmi(String deviceName) {
+ if (deviceName == null || deviceName.trim().isEmpty()) {
+ return false;
+ }
+
+ String normalizedName = deviceName.toUpperCase(Locale.ROOT);
+ return normalizedName.startsWith("NT311")
+ || normalizedName.contains("CLOUDPRINTER")
+ || normalizedName.contains("CLOUD PRINT")
+ || normalizedName.contains("SUNMI");
+ }
+}
diff --git a/app/src/main/java/com/sunmi/printerconfig/ReceiverSafeContext.java b/app/src/main/java/com/sunmi/printerconfig/ReceiverSafeContext.java
new file mode 100644
index 0000000..0c24a91
--- /dev/null
+++ b/app/src/main/java/com/sunmi/printerconfig/ReceiverSafeContext.java
@@ -0,0 +1,50 @@
+package com.sunmi.printerconfig;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Build;
+import android.os.Handler;
+
+/**
+ * Wraps context receiver registration so legacy SDK code works on Android 13+.
+ */
+public class ReceiverSafeContext extends ContextWrapper {
+ public ReceiverSafeContext(Context base) {
+ super(base);
+ }
+
+ @Override
+ public Context getApplicationContext() {
+ return this;
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ return super.registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED);
+ }
+ return super.registerReceiver(receiver, filter);
+ }
+
+ @Override
+ public Intent registerReceiver(
+ BroadcastReceiver receiver,
+ IntentFilter filter,
+ String broadcastPermission,
+ Handler scheduler
+ ) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ return super.registerReceiver(
+ receiver,
+ filter,
+ broadcastPermission,
+ scheduler,
+ Context.RECEIVER_NOT_EXPORTED
+ );
+ }
+ return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
+ }
+}
diff --git a/app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java b/app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java
index 31770ae..b70ec02 100644
--- a/app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java
+++ b/app/src/main/java/com/sunmi/printerconfig/WifiConfigActivity.java
@@ -1,215 +1,373 @@
package com.sunmi.printerconfig;
-import android.Manifest;
import android.bluetooth.BluetoothDevice;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiManager;
-import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.view.View;
+import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
+import com.sunmi.cloudprinter.bean.PrinterDevice;
+import com.sunmi.cloudprinter.bean.Router;
+import com.sunmi.cloudprinter.presenter.SunmiPrinterClient;
+
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
-public class WifiConfigActivity extends AppCompatActivity {
- private static final int PERMISSION_REQUEST_CODE = 3;
+public class WifiConfigActivity extends AppCompatActivity implements SunmiPrinterClient.IPrinterClient {
+ private static final int WIFI_CONFIG_TIMEOUT_MS = 25_000;
+
+ private String printerAddress;
+ private String printerName;
- private BluetoothDevice device;
private TextView printerNameText;
private Spinner wifiSpinner;
private EditText passwordInput;
+ private EditText manualSsidInput;
+ private LinearLayout manualSsidContainer;
private Button configureButton;
private ProgressBar progressBar;
private TextView statusText;
- private WifiManager wifiManager;
- private PrinterConfigHelper printerHelper;
+
+ private SunmiPrinterClient sunmiPrinterClient;
+
+ private ArrayAdapter wifiAdapter;
+ private final List availableRouters = new ArrayList<>();
+ private boolean waitingForWifiConfigResult = false;
+
+ private final Handler wifiConfigTimeoutHandler = new Handler(Looper.getMainLooper());
+ private final Runnable wifiConfigTimeoutRunnable = () -> {
+ if (waitingForWifiConfigResult) {
+ handleConfigurationFailure(getString(R.string.printer_wifi_config_timeout));
+ }
+ };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wifi_config);
- device = getIntent().getParcelableExtra("device");
- if (device == null) {
- Toast.makeText(this, "Error: No device selected", Toast.LENGTH_SHORT).show();
+ printerAddress = getIntent().getStringExtra("device_address");
+ printerName = getIntent().getStringExtra("device_name");
+
+ if ((printerAddress == null || printerAddress.isEmpty()) || printerName == null) {
+ BluetoothDevice device = getIntent().getParcelableExtra("device");
+ if (device != null) {
+ printerAddress = safeGetDeviceAddress(device);
+ if (printerName == null || printerName.isEmpty()) {
+ printerName = safeGetDeviceName(device);
+ }
+ }
+ }
+
+ if (printerAddress == null || printerAddress.isEmpty()) {
+ Toast.makeText(this, R.string.printer_address_unavailable, Toast.LENGTH_LONG).show();
finish();
return;
}
+ if (printerName == null || printerName.isEmpty()) {
+ printerName = getString(R.string.unknown_device);
+ }
+
printerNameText = findViewById(R.id.printerNameText);
wifiSpinner = findViewById(R.id.wifiSpinner);
passwordInput = findViewById(R.id.passwordInput);
+ manualSsidInput = findViewById(R.id.manualSsidInput);
+ manualSsidContainer = findViewById(R.id.manualSsidContainer);
configureButton = findViewById(R.id.configureButton);
progressBar = findViewById(R.id.progressBar);
statusText = findViewById(R.id.statusText);
- wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
- printerHelper = new PrinterConfigHelper(this);
+ sunmiPrinterClient = new SunmiPrinterClient(
+ new ReceiverSafeContext(getApplicationContext()),
+ this
+ );
- boolean hasPermission = true;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- hasPermission = ContextCompat.checkSelfPermission(this,
- Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;
- }
-
- if (hasPermission) {
- String deviceName = device.getName();
- printerNameText.setText(getString(R.string.connected_to, deviceName != null ? deviceName : "Unknown"));
- }
+ printerNameText.setText(getString(R.string.connected_to, printerName));
- loadWifiNetworks();
+ setupWifiSpinner();
configureButton.setOnClickListener(v -> {
- String selectedSsid = (String) wifiSpinner.getSelectedItem();
+ Router selectedRouter = resolveSelectedRouter();
+ String manualSsid = manualSsidInput.getText().toString().trim();
String password = passwordInput.getText().toString();
- if (selectedSsid == null || selectedSsid.isEmpty()) {
- Toast.makeText(this, "Please select a Wi-Fi network", Toast.LENGTH_SHORT).show();
+ if (selectedRouter == null) {
+ if (manualSsid.isEmpty()) {
+ Toast.makeText(this, R.string.select_or_enter_wifi_network, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ configurePrinter(buildManualRouter(manualSsid), password);
return;
}
- if (password.isEmpty()) {
- Toast.makeText(this, "Please enter Wi-Fi password", Toast.LENGTH_SHORT).show();
+ if (selectedRouter.isHasPwd() && password.isEmpty()) {
+ Toast.makeText(this, R.string.enter_wifi_password, Toast.LENGTH_SHORT).show();
return;
}
- configurePrinter(selectedSsid, password);
+ configurePrinter(selectedRouter, password);
});
}
- private void loadWifiNetworks() {
- if (!checkWifiPermissions()) {
- requestWifiPermissions();
- return;
+ @Override
+ protected void onStart() {
+ super.onStart();
+ loadNetworksFromPrinter();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ waitingForWifiConfigResult = false;
+ wifiConfigTimeoutHandler.removeCallbacks(wifiConfigTimeoutRunnable);
+
+ if (sunmiPrinterClient != null && printerAddress != null && !printerAddress.isEmpty()) {
+ try {
+ sunmiPrinterClient.disconnect(printerAddress);
+ } catch (Throwable ignored) {
+ }
+ }
+ }
+
+ private String safeGetDeviceAddress(BluetoothDevice device) {
+ try {
+ return device.getAddress() == null ? "" : device.getAddress();
+ } catch (SecurityException e) {
+ return "";
}
+ }
- List networkList = new ArrayList<>();
+ private String safeGetDeviceName(BluetoothDevice device) {
+ try {
+ return device.getName() == null ? getString(R.string.unknown_device) : device.getName();
+ } catch (SecurityException e) {
+ return getString(R.string.unknown_device);
+ }
+ }
- // Get configured networks (the tablet's saved networks)
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
- boolean hasLocationPermission = ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
- boolean hasWifiStatePermission = ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_WIFI_STATE) == PackageManager.PERMISSION_GRANTED;
+ private void setupWifiSpinner() {
+ wifiAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, new ArrayList<>());
+ wifiAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ wifiSpinner.setAdapter(wifiAdapter);
- if (!hasLocationPermission) {
- requestWifiPermissions();
- return;
+ wifiSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ boolean manualSelected = isManualEntrySelected(position);
+ manualSsidContainer.setVisibility(manualSelected ? View.VISIBLE : View.GONE);
+ if (!manualSelected) {
+ manualSsidInput.setText("");
+ }
}
- if (hasWifiStatePermission) {
- try {
- List configs = wifiManager.getConfiguredNetworks();
- if (configs != null) {
- for (WifiConfiguration config : configs) {
- String ssid = config.SSID.replace("\"", "");
- if (!networkList.contains(ssid)) {
- networkList.add(ssid);
- }
- }
- }
- } catch (SecurityException ignored) {
- // Fall back to manual network entry below.
- }
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ manualSsidContainer.setVisibility(View.GONE);
}
+ });
+
+ updateWifiSpinner();
+ }
+
+ private Router resolveSelectedRouter() {
+ int selectedPosition = wifiSpinner.getSelectedItemPosition();
+
+ if (selectedPosition < 0 || selectedPosition >= availableRouters.size()) {
+ return null;
}
- // Add some common network detection
- // Note: On Android 10+, scanning requires location and is limited
- if (networkList.isEmpty()) {
- // Add placeholder for manual entry if scanning fails
- networkList.add("Enter manually below");
+ if (isManualEntrySelected(selectedPosition)) {
+ return null;
}
- ArrayAdapter adapter = new ArrayAdapter<>(this,
- android.R.layout.simple_spinner_item, networkList);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- wifiSpinner.setAdapter(adapter);
+ return availableRouters.get(selectedPosition);
}
- private boolean checkWifiPermissions() {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
- return true;
+ private boolean isManualEntrySelected(int position) {
+ return wifiAdapter != null && position == wifiAdapter.getCount() - 1;
+ }
+
+ private void updateWifiSpinner() {
+ List options = new ArrayList<>();
+ for (Router router : availableRouters) {
+ options.add(getRouterDisplayName(router));
+ }
+ options.add(getString(R.string.manual_entry_option));
+
+ wifiAdapter.clear();
+ wifiAdapter.addAll(options);
+ wifiAdapter.notifyDataSetChanged();
+
+ if (!availableRouters.isEmpty()) {
+ wifiSpinner.setSelection(0);
+ manualSsidContainer.setVisibility(View.GONE);
+ configureButton.setEnabled(true);
+ } else {
+ wifiSpinner.setSelection(wifiAdapter.getCount() - 1);
+ manualSsidContainer.setVisibility(View.VISIBLE);
+ configureButton.setEnabled(true);
}
- return ContextCompat.checkSelfPermission(this,
- Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
- private void requestWifiPermissions() {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
- loadWifiNetworks();
- return;
+ private String getRouterDisplayName(Router router) {
+ String name = router.getName();
+ if (name != null && !name.trim().isEmpty()) {
+ return name.trim();
}
- ActivityCompat.requestPermissions(this,
- new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_REQUEST_CODE);
+
+ byte[] essid = router.getEssid();
+ if (essid == null || essid.length == 0) {
+ return getString(R.string.unknown_device);
+ }
+
+ return new String(essid, StandardCharsets.UTF_8).trim();
+ }
+
+ private Router buildManualRouter(String ssid) {
+ Router router = new Router();
+ router.setName(ssid);
+ router.setEssid(ssid.getBytes(StandardCharsets.UTF_8));
+ router.setHasPwd(true);
+ return router;
}
- private void configurePrinter(String ssid, String password) {
+ private void loadNetworksFromPrinter() {
configureButton.setEnabled(false);
progressBar.setVisibility(View.VISIBLE);
- statusText.setText(R.string.configuring);
+ statusText.setText(R.string.printer_wifi_scanning);
- // Run configuration in background thread
- new Thread(() -> {
- try {
- boolean success = printerHelper.configurePrinterWifi(device, ssid, password);
-
- runOnUiThread(() -> {
- progressBar.setVisibility(View.GONE);
- configureButton.setEnabled(true);
-
- if (success) {
- statusText.setText(R.string.success);
- Toast.makeText(this, R.string.success, Toast.LENGTH_LONG).show();
- // Return to main activity after success
- finish();
- } else {
- statusText.setText(getString(R.string.error, "Configuration failed"));
- Toast.makeText(this, "Configuration failed. Please try again.",
- Toast.LENGTH_LONG).show();
- }
- });
- } catch (Exception e) {
- runOnUiThread(() -> {
- progressBar.setVisibility(View.GONE);
- configureButton.setEnabled(true);
- statusText.setText(getString(R.string.error, e.getMessage()));
- Toast.makeText(this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
- });
- }
- }).start();
+ availableRouters.clear();
+ updateWifiSpinner();
+
+ try {
+ sunmiPrinterClient.getPrinterWifiList(printerAddress);
+ } catch (Throwable t) {
+ progressBar.setVisibility(View.GONE);
+ statusText.setText(R.string.printer_wifi_scan_failed);
+ configureButton.setEnabled(true);
+ }
+ }
+
+ private void configurePrinter(Router router, String password) {
+ waitingForWifiConfigResult = true;
+ wifiConfigTimeoutHandler.removeCallbacks(wifiConfigTimeoutRunnable);
+ wifiConfigTimeoutHandler.postDelayed(wifiConfigTimeoutRunnable, WIFI_CONFIG_TIMEOUT_MS);
+
+ configureButton.setEnabled(false);
+ progressBar.setVisibility(View.VISIBLE);
+ statusText.setText(R.string.sending_wifi_to_printer);
+
+ try {
+ sunmiPrinterClient.setPrinterWifi(printerAddress, router.getEssid(), password == null ? "" : password);
+ } catch (Throwable t) {
+ handleConfigurationFailure(getString(R.string.wifi_push_failed_try_24g));
+ }
+ }
+
+ private void handleConfigurationSuccess() {
+ waitingForWifiConfigResult = false;
+ wifiConfigTimeoutHandler.removeCallbacks(wifiConfigTimeoutRunnable);
+
+ runOnUiThread(() -> {
+ progressBar.setVisibility(View.GONE);
+ configureButton.setEnabled(true);
+ statusText.setText(R.string.success);
+ Toast.makeText(this, R.string.success, Toast.LENGTH_LONG).show();
+ finish();
+ });
+ }
+
+ private void handleConfigurationFailure(String message) {
+ waitingForWifiConfigResult = false;
+ wifiConfigTimeoutHandler.removeCallbacks(wifiConfigTimeoutRunnable);
+
+ runOnUiThread(() -> {
+ progressBar.setVisibility(View.GONE);
+ configureButton.setEnabled(true);
+ statusText.setText(getString(R.string.error, message));
+ Toast.makeText(this, message, Toast.LENGTH_LONG).show();
+ });
}
@Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- if (requestCode == PERMISSION_REQUEST_CODE) {
- boolean allGranted = true;
- for (int result : grantResults) {
- if (result != PackageManager.PERMISSION_GRANTED) {
- allGranted = false;
- break;
- }
- }
- if (allGranted) {
- loadWifiNetworks();
+ public void onPrinterFount(PrinterDevice printerDevice) {
+ // Not used in this activity.
+ }
+
+ @Override
+ public void routerFound(Router router) {
+ runOnUiThread(() -> {
+ availableRouters.add(router);
+ updateWifiSpinner();
+ });
+ }
+
+ @Override
+ public void onGetWifiListFinish() {
+ runOnUiThread(() -> {
+ progressBar.setVisibility(View.GONE);
+ configureButton.setEnabled(true);
+
+ if (availableRouters.isEmpty()) {
+ statusText.setText(R.string.printer_wifi_no_networks_found);
+ manualSsidContainer.setVisibility(View.VISIBLE);
} else {
- Toast.makeText(this, "Permissions required to scan Wi-Fi networks",
- Toast.LENGTH_SHORT).show();
+ statusText.setText(getString(R.string.wifi_networks_found, availableRouters.size()));
}
- }
+ });
+ }
+
+ @Override
+ public void onGetWifiListFail() {
+ runOnUiThread(() -> {
+ progressBar.setVisibility(View.GONE);
+ configureButton.setEnabled(true);
+ statusText.setText(R.string.printer_wifi_scan_failed);
+ manualSsidContainer.setVisibility(View.VISIBLE);
+ });
+ }
+
+ @Override
+ public void onSetWifiSuccess() {
+ runOnUiThread(() -> statusText.setText(R.string.configuring));
+ }
+
+ @Override
+ public void wifiConfigSuccess() {
+ handleConfigurationSuccess();
+ }
+
+ @Override
+ public void onWifiConfigFail() {
+ handleConfigurationFailure(getString(R.string.wifi_push_failed_try_24g));
+ }
+
+ @Override
+ public void sendDataFail(int code, String msg) {
+ String failureMessage = getString(R.string.wifi_push_error_with_code, code, msg == null ? "Unknown" : msg);
+ handleConfigurationFailure(failureMessage);
+ }
+
+ @Override
+ public void getSnRequestSuccess() {
+ // Not used in this activity.
+ }
+
+ @Override
+ public void onSnReceived(String sn) {
+ // Not used in this activity.
}
}
diff --git a/app/src/main/res/layout/activity_wifi_config.xml b/app/src/main/res/layout/activity_wifi_config.xml
index 08f313c..b339b5d 100644
--- a/app/src/main/res/layout/activity_wifi_config.xml
+++ b/app/src/main/res/layout/activity_wifi_config.xml
@@ -46,13 +46,39 @@
android:layout_marginTop="8dp"
android:minHeight="48dp"/>
+
+
+
+
+
+
+
Success! Printer configured.
Error: %s
Connected to: %s
+ Unknown Device
+ Likely Sunmi
+ Permission Required
+ Enter SSID manually
+ Wi-Fi SSID
+ Enter Wi-Fi network name
+ Scanning Wi-Fi networks...
+ Permissions are required to scan Wi-Fi networks
+ Turn on Wi-Fi to scan networks
+ Turn on Location to scan Wi-Fi networks
+ No Wi-Fi networks found. Enter SSID manually.
+ %1$d Wi-Fi networks found
+ Unable to refresh Wi-Fi scan results
+ Getting Wi-Fi networks from printer...
+ Failed to get Wi-Fi networks from printer. Use manual SSID.
+ No networks reported by printer. Use manual SSID.
+ Please select or enter a Wi-Fi network
+ Please enter Wi-Fi password
+ Connecting to printer...
+ Sending Wi-Fi credentials to printer...
+ Printer connection timed out. Keep the printer close and retry.
+ Failed to scan for compatible printers.
+ No compatible printers found. Make sure the printer is in pairing/config mode and retry.
+ %1$d compatible printer(s) found
+ Printer did not confirm Wi-Fi configuration in time. Check Wi-Fi (2.4GHz/WPA2) and retry.
+ Unable to connect to printer over Bluetooth.
+ Failed to configure Wi-Fi. Confirm 2.4GHz WPA/WPA2 network and retry.
+ Printer communication error (%1$d): %2$s
+ Printer Bluetooth address is unavailable.