diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index b799aea5..ab05fdce 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -10,10 +10,15 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- api-level: [19, 28]
+ api-level: [21, 29]
steps:
- name: Checkout
uses: actions/checkout@v4
+ - name: Enable KVM
+ run: |
+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
+ sudo udevadm control --reload-rules
+ sudo udevadm trigger --name-match=kvm
- name: Set up environment
uses: actions/setup-java@v4
with:
@@ -26,7 +31,7 @@ jobs:
id: avd-cache
with:
path: |
- ~.android/avd/*
+ ~/.android/avd/*
~/.android/adb*
key: avd-${{ matrix.api-level }}
- name: Create AVD and generate snapshot for caching
@@ -47,4 +52,4 @@ jobs:
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
- script: ./gradlew connectedCheck
\ No newline at end of file
+ script: adb uninstall com.enioka.scanner.sdk.mock.test; adb uninstall com.enioka.scanner.service; ./gradlew connectedCheck --stacktrace
diff --git a/demoscannerapp/build.gradle b/demoscannerapp/build.gradle
index 4aaea072..7a81d975 100644
--- a/demoscannerapp/build.gradle
+++ b/demoscannerapp/build.gradle
@@ -8,14 +8,21 @@ android {
targetSdkVersion 28
versionCode 1
versionName "1.0"
-
+ vectorDrawables.useSupportLibrary = true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
- minifyEnabled false
+ minifyEnabled true
+ shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ debuggable false
+ applicationIdSuffix ".release"
+ }
+ debug {
+ debuggable true
+ applicationIdSuffix ".debug"
}
}
lint {
@@ -63,6 +70,7 @@ dependencies {
//noinspection GradleCompatible
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
+ implementation 'com.google.android.material:material:1.12.0'
// Useless test stuff
testImplementation 'junit:junit:4.12'
diff --git a/demoscannerapp/src/main/AndroidManifest.xml b/demoscannerapp/src/main/AndroidManifest.xml
index d4602ac3..b519be2e 100644
--- a/demoscannerapp/src/main/AndroidManifest.xml
+++ b/demoscannerapp/src/main/AndroidManifest.xml
@@ -1,6 +1,8 @@
+
+
-
-
+
-
+
-
-
\ No newline at end of file
diff --git a/demoscannerapp/src/main/java/com/enioka/scanner/demo/ScannerTesterActivity.java b/demoscannerapp/src/main/java/com/enioka/scanner/demo/ScannerTesterActivity.java
deleted file mode 100644
index b2de84fb..00000000
--- a/demoscannerapp/src/main/java/com/enioka/scanner/demo/ScannerTesterActivity.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.enioka.scanner.demo;
-
-import android.Manifest;
-import android.app.Activity;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.app.ActivityCompat;
-import androidx.core.content.ContextCompat;
-import android.util.Log;
-
-import com.enioka.scanner.activities.ScannerCompatActivity;
-import com.enioka.scanner.data.Barcode;
-
-import java.io.BufferedWriter;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.nio.charset.Charset;
-import java.util.Date;
-import java.util.List;
-
-public class ScannerTesterActivity extends ScannerCompatActivity {
- private static final String LOG_TAG = "ScannerTesterActivity";
-
- private Uri logFileUri = null;
- private int WRITE_REQUEST_CODE = 123;
- private int WRITE_PERMISSION_REQUEST_CODE = 124;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
- createLog();
- } else {
- ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_PERMISSION_REQUEST_CODE);
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
-
- if (requestCode == WRITE_PERMISSION_REQUEST_CODE && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- createLog();
- }
- }
-
- private boolean isExternalStorageWritable() {
- String state = Environment.getExternalStorageState();
- return Environment.MEDIA_MOUNTED.equals(state);
- }
-
- private void createLog() {
- if (!isExternalStorageWritable()) {
- return;
- }
-
- String fileName = (new Date()).getTime() + "_scanner_test_log.csv";
-
- Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("text/csv");
- intent.putExtra(Intent.EXTRA_TITLE, fileName);
- startActivityForResult(intent, WRITE_REQUEST_CODE);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
- logFileUri = data.getData();
- if (logFileUri != null) {
- Log.i(LOG_TAG, "Log file will be written at: " + logFileUri.toString());
- }
- }
- }
-
- private synchronized void writeResultToLog(Barcode data) {
- String dataLine = (new Date()).getTime() + "," + data.getBarcode() + "," + data.getBarcodeType().code;
-
- try (OutputStream os = getContentResolver().openOutputStream(logFileUri, "wa")) {
- if (os == null) {
- return;
- }
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, Charset.forName("UTF8")));
- writer.write(dataLine, 0, dataLine.length());
- writer.newLine();
- writer.flush();
- Log.d(LOG_TAG, dataLine);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public void onData(List data) {
- super.onData(data);
-
- if (logFileUri != null) {
- for (Barcode br : data) {
- writeResultToLog(br);
- }
- }
- }
-}
diff --git a/demoscannerapp/src/main/java/com/enioka/scanner/demo/SettingsActivity.java b/demoscannerapp/src/main/java/com/enioka/scanner/demo/SettingsActivity.java
index 4c8b45f3..a969dfa0 100644
--- a/demoscannerapp/src/main/java/com/enioka/scanner/demo/SettingsActivity.java
+++ b/demoscannerapp/src/main/java/com/enioka/scanner/demo/SettingsActivity.java
@@ -5,21 +5,26 @@
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;
+import androidx.core.content.ContextCompat;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
-import android.widget.Switch;
-import android.widget.TextView;
import com.enioka.scanner.api.ScannerSearchOptions;
import com.enioka.scanner.data.BarcodeType;
import com.enioka.scanner.service.ScannerService;
import com.enioka.scanner.service.ScannerServiceApi;
+import com.google.android.material.appbar.MaterialToolbar;
+import com.google.android.material.button.MaterialButton;
+import com.google.android.material.checkbox.MaterialCheckBox;
+import com.google.android.material.materialswitch.MaterialSwitch;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
public class SettingsActivity extends AppCompatActivity {
@@ -28,24 +33,94 @@ public class SettingsActivity extends AppCompatActivity {
*/
protected String[] availableProvidersKey = null;
+ /**
+ * Segmented button preferences keys
+ */
+ protected static final String PREFS_KEY = "segmentedButton";
+
+ /**
+ * Enable logging preferences key
+ */
+ public static final String ENABLE_LOGGING_KEY = "enableLogging";
+ /**
+ * Allow camera fallback preferences key
+ */
+ public static final String ALLOW_CAMERA_FALLBACK_KEY = "allowCameraFallback";
+ /**
+ * Enable keep aspect ratio preferences key
+ */
+ public static final String ENABLE_KEEP_ASPECT_RATIO_KEY = "enableKeepAspectRatio";
+
+ /**
+ * List of provider views ids
+ */
+ protected List providerViews = new ArrayList<>();
+
+ /**
+ * Save button
+ */
+ protected MaterialButton buttonSave;
+
+ /**
+ * topAppBar
+ */
+ protected MaterialToolbar topAppBar;
+
+ /**
+ * Select all segmented button
+ */
+ protected MaterialButton bt_all;
+
+ /**
+ * Select specific segmented button
+ */
+ protected MaterialButton bt_spec;
+
+ /**
+ * Select none segmented button
+ */
+ protected MaterialButton bt_none;
+
+ /**
+ * SegmentedButtons state
+ */
+ protected int segmentedButtonState = 0;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
+ // Setup save button listener
+ buttonSave = findViewById(R.id.button_save);
+ buttonSave.setOnClickListener(this::onClickSave);
+
+ // Segmented toggle buttons
+ bt_all = findViewById(R.id.button_all);
+ bt_spec = findViewById(R.id.button_specific);
+ bt_none = findViewById(R.id.button_none);
+
+ // Add listener to segmented toggle buttons
+ bindToggleButton();
+
final SharedPreferences preferences = this.getSharedPreferences("ScannerSearchPreferences", MODE_PRIVATE);
final ScannerSearchOptions options = ScannerSearchOptions.defaultOptions();
- ((Switch) findViewById(R.id.switchWaitDisconnected)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_WAIT_DISCONNECTED_BOOLEAN, options.waitDisconnected));
- ((Switch) findViewById(R.id.switchReturnOnlyFirst)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_RETURN_ONLY_FIRST_BOOLEAN, options.returnOnlyFirst));
- ((Switch) findViewById(R.id.switchBluetooth)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_BT_BOOLEAN, options.useBlueTooth));
- ((Switch) findViewById(R.id.switchLaterConnections)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_KEEP_SEARCHING_BOOLEAN, options.allowLaterConnections));
- ((Switch) findViewById(R.id.switchInitialSearch)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_INITIAL_SEARCH_BOOLEAN, options.allowInitialSearch));
- ((Switch) findViewById(R.id.switchPairingFlow)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_PAIRING_FLOW_BOOLEAN, options.allowPairingFlow));
- ((Switch) findViewById(R.id.switchIntentDevices)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_INTENT_BOOLEAN, options.allowIntentDevices));
+ ((MaterialSwitch) findViewById(R.id.switchWaitDisconnected)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_WAIT_DISCONNECTED_BOOLEAN, options.waitDisconnected));
+ ((MaterialSwitch) findViewById(R.id.switchReturnOnlyFirst)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_RETURN_ONLY_FIRST_BOOLEAN, options.returnOnlyFirst));
+ ((MaterialSwitch) findViewById(R.id.switchBluetooth)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_BT_BOOLEAN, options.useBlueTooth));
+ ((MaterialSwitch) findViewById(R.id.switchLaterConnections)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_KEEP_SEARCHING_BOOLEAN, options.allowLaterConnections));
+ ((MaterialSwitch) findViewById(R.id.switchInitialSearch)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_INITIAL_SEARCH_BOOLEAN, options.allowInitialSearch));
+ ((MaterialSwitch) findViewById(R.id.switchPairingFlow)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_PAIRING_FLOW_BOOLEAN, options.allowPairingFlow));
+ ((MaterialSwitch) findViewById(R.id.switchIntentDevices)).setChecked(preferences.getBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_INTENT_BOOLEAN, options.allowIntentDevices));
+ ((MaterialSwitch) findViewById(R.id.switchEnableLogging)).setChecked(preferences.getBoolean(ENABLE_LOGGING_KEY, false));
+ ((MaterialSwitch) findViewById(R.id.switchAllowCameraFallback)).setChecked(preferences.getBoolean(ALLOW_CAMERA_FALLBACK_KEY, false));
+ ((MaterialSwitch) findViewById(R.id.switchEnableKeepAspectRatio)).setChecked(preferences.getBoolean(ENABLE_KEEP_ASPECT_RATIO_KEY, false));
final Set allowedProviderKeys = preferences.getStringSet(ScannerServiceApi.EXTRA_SEARCH_ALLOWED_PROVIDERS_STRING_ARRAY, Collections.emptySet());
- final Set excludedProviderKeys = preferences.getStringSet(ScannerServiceApi.EXTRA_SEARCH_EXCLUDED_PROVIDERS_STRING_ARRAY, Collections.emptySet());
+
+ // Set the state of the segmented button
+ segmentedButtonState = preferences.getInt(PREFS_KEY, 0);
final Set symbologySelection = new HashSet<>();
for(String symbology: preferences.getStringSet(ScannerServiceApi.EXTRA_SYMBOLOGY_SELECTION, ScannerService.defaultSymbologyByName())) {
@@ -69,99 +144,58 @@ protected void onCreate(Bundle savedInstanceState) {
}
// Create the UI
- int topViewIdAllowed = R.id.textViewAllowedProviders;
- int topViewIdExcluded = R.id.textViewExcludedProviders;
+ int topViewId = R.id.toggleButtonProvider;
for (String providerKey : availableProvidersKey) {
// Create the UI for the allowed providers
- TextView textViewAllowed = generateTextView(providerKey, topViewIdAllowed);
- textViewAllowed.setTag("allowed_text_" + providerKey);
- CheckBox checkBoxAllowed = generateCheckBox(providerKey, topViewIdAllowed, textViewAllowed.getId());
- checkBoxAllowed.setTag("allowed_check_" + providerKey);
+ CheckBox checkBox = generateCheckBox(providerKey, topViewId);
+ checkBox.setTag("checkbox_" + providerKey);
if (allowedProviderKeys.contains(providerKey)) {
- checkBoxAllowed.setChecked(true);
+ checkBox.setChecked(true);
}
- // Create the UI for the excluded providers
- TextView textViewExcluded = generateTextView(providerKey, topViewIdExcluded);
- textViewExcluded.setTag("excluded_text_" + providerKey);
- CheckBox checkBoxExcluded = generateCheckBox(providerKey, topViewIdExcluded, textViewExcluded.getId());
- checkBoxExcluded.setTag("excluded_check_" + providerKey);
-
- if (excludedProviderKeys.contains(providerKey)) {
- checkBoxExcluded.setChecked(true);
- }
+ topViewId = checkBox.getId();
+ }
- topViewIdAllowed = textViewAllowed.getId();
- topViewIdExcluded = textViewExcluded.getId();
+ if (availableProvidersKey.length == 0) {
+ // Hide the provider toggle button
+ findViewById(R.id.toggleButtonProvider).setVisibility(View.GONE);
+ findViewById(R.id.textEmptyProviderList).setVisibility(View.VISIBLE);
+ } else {
+ // Update the layout
+ updateConstraintLayout(topViewId);
}
- // Update the layout
- updateConstraintLayout(topViewIdAllowed, topViewIdExcluded);
+ // Set the state of the segmented button (default is all)
+ setSegmentedButtonState();
}
- private void updateConstraintLayout(int topViewIdAllowed, int topViewIdExcluded) {
+ private void updateConstraintLayout(int topViewId) {
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone((ConstraintLayout) findViewById(R.id.constraintLayoutSettings));
// Init marginTop
- int marginTop = getResources().getDimensionPixelSize(R.dimen.layout_margin_top_header_text);
+ int marginTop = getResources().getDimensionPixelSize(R.dimen.layout_margin_top_divider);
// Set top bottom constraints
- constraintSet.connect(R.id.textViewExcludedProviders, ConstraintSet.TOP, topViewIdAllowed, ConstraintSet.BOTTOM, marginTop);
- constraintSet.connect(R.id.textSymbologySelection, ConstraintSet.TOP, topViewIdExcluded, ConstraintSet.BOTTOM, marginTop);
+ constraintSet.connect(R.id.dividerSettingsSymbology, ConstraintSet.TOP, topViewId, ConstraintSet.BOTTOM, marginTop);
// Apply constraints
constraintSet.applyTo(findViewById(R.id.constraintLayoutSettings));
}
- private TextView generateTextView(String providerKey, int topViewId) {
- TextView textView = new TextView(this);
- textView.setId(View.generateViewId());
-
- // Add TextView to the parent layout
- ViewGroup parentLayout = findViewById(R.id.constraintLayoutSettings);
- parentLayout.addView(textView);
-
- // Set layout parameters
- ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- getResources().getDimensionPixelSize(R.dimen.layout_height));
-
- textView.setLayoutParams(layoutParams);
-
- // Get the right text if the provider is known
- int textResources = getResources().getIdentifier(providerKey, "string", this.getPackageName());
-
- if (textResources != 0) {
- textView.setText(textResources);
- } else {
- textView.setText(providerKey);
- }
-
- ConstraintSet constraintSet = new ConstraintSet();
- constraintSet.clone((ConstraintLayout) parentLayout);
- // Set margins
- int marginStart = getResources().getDimensionPixelSize(R.dimen.layout_margin_start_text);
- int marginEnd = getResources().getDimensionPixelSize(R.dimen.layout_margin_end);
- int marginTop = getResources().getDimensionPixelSize(R.dimen.layout_margin_top);
+ private CheckBox generateCheckBox(String providerKey, int topViewId) {
+ MaterialCheckBox checkBox = new MaterialCheckBox(this);
- // Set constraints for the TextView
- constraintSet.connect(textView.getId(), ConstraintSet.START, parentLayout.getId(), ConstraintSet.START, marginStart);
- constraintSet.connect(textView.getId(), ConstraintSet.END, parentLayout.getId(), ConstraintSet.END, marginEnd);
- constraintSet.connect(textView.getId(), ConstraintSet.TOP, topViewId, ConstraintSet.BOTTOM, marginTop);
- constraintSet.applyTo((ConstraintLayout) parentLayout);
-
- return textView;
- }
+ // Gen checkBox id
+ int checkBoxId = View.generateViewId();
+ checkBox.setId(checkBoxId);
+ providerViews.add(checkBoxId);
- private CheckBox generateCheckBox(String providerKey, int topViewId, int rightViewId) {
- CheckBox checkBox = new CheckBox(this);
- checkBox.setId(View.generateViewId());
ViewGroup parentLayout = findViewById(R.id.constraintLayoutSettings);
// Add CheckBox to the parent layout
@@ -186,24 +220,37 @@ private CheckBox generateCheckBox(String providerKey, int topViewId, int rightVi
constraintSet.connect(checkBox.getId(), ConstraintSet.START, parentLayout.getId(), ConstraintSet.START, marginStart);
constraintSet.connect(checkBox.getId(), ConstraintSet.END, parentLayout.getId(), ConstraintSet.END, marginEnd);
constraintSet.connect(checkBox.getId(), ConstraintSet.TOP, topViewId, ConstraintSet.BOTTOM, marginTop);
- constraintSet.connect(checkBox.getId(), ConstraintSet.RIGHT, rightViewId, ConstraintSet.LEFT, 0);
constraintSet.applyTo((ConstraintLayout) parentLayout);
checkBox.setChecked(false);
+ // Get the right text if the provider is known
+ int textResources = getResources().getIdentifier(providerKey, "string", this.getPackageName());
+
+ if (textResources != 0) {
+ // Set the custom text if available
+ checkBox.setText(textResources);
+ } else {
+ // Otherwise set to the provider key
+ checkBox.setText(providerKey);
+ }
+
return checkBox;
}
public void onClickSave(View v) {
final SharedPreferences.Editor editor = this.getSharedPreferences("ScannerSearchPreferences", MODE_PRIVATE).edit();
- editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_WAIT_DISCONNECTED_BOOLEAN, ((Switch) findViewById(R.id.switchWaitDisconnected)).isChecked());
- editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_RETURN_ONLY_FIRST_BOOLEAN, ((Switch) findViewById(R.id.switchReturnOnlyFirst)).isChecked());
- editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_BT_BOOLEAN, ((Switch) findViewById(R.id.switchBluetooth)).isChecked());
- editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_KEEP_SEARCHING_BOOLEAN, ((Switch) findViewById(R.id.switchLaterConnections)).isChecked());
- editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_INITIAL_SEARCH_BOOLEAN, ((Switch) findViewById(R.id.switchInitialSearch)).isChecked());
- editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_PAIRING_FLOW_BOOLEAN, ((Switch) findViewById(R.id.switchPairingFlow)).isChecked());
- editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_INTENT_BOOLEAN, ((Switch) findViewById(R.id.switchIntentDevices)).isChecked());
+ editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_WAIT_DISCONNECTED_BOOLEAN, ((MaterialSwitch) findViewById(R.id.switchWaitDisconnected)).isChecked());
+ editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_RETURN_ONLY_FIRST_BOOLEAN, ((MaterialSwitch) findViewById(R.id.switchReturnOnlyFirst)).isChecked());
+ editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_BT_BOOLEAN, ((MaterialSwitch) findViewById(R.id.switchBluetooth)).isChecked());
+ editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_KEEP_SEARCHING_BOOLEAN, ((MaterialSwitch) findViewById(R.id.switchLaterConnections)).isChecked());
+ editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_INITIAL_SEARCH_BOOLEAN, ((MaterialSwitch) findViewById(R.id.switchInitialSearch)).isChecked());
+ editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_PAIRING_FLOW_BOOLEAN, ((MaterialSwitch) findViewById(R.id.switchPairingFlow)).isChecked());
+ editor.putBoolean(ScannerServiceApi.EXTRA_SEARCH_ALLOW_INTENT_BOOLEAN, ((MaterialSwitch) findViewById(R.id.switchIntentDevices)).isChecked());
+ editor.putBoolean(ENABLE_LOGGING_KEY, ((MaterialSwitch) findViewById(R.id.switchEnableLogging)).isChecked());
+ editor.putBoolean(ALLOW_CAMERA_FALLBACK_KEY, ((MaterialSwitch) findViewById(R.id.switchAllowCameraFallback)).isChecked());
+ editor.putBoolean(ENABLE_KEEP_ASPECT_RATIO_KEY, ((MaterialSwitch) findViewById(R.id.switchEnableKeepAspectRatio)).isChecked());
final Set allowedProviderKeys = new HashSet<>();
final Set excludedProviderKeys = new HashSet<>();
@@ -214,14 +261,16 @@ public void onClickSave(View v) {
// Save the CheckBoxes state for allowed and excluded providers
for (String providerKey : availableProvidersKey) {
// Retrieve the CheckBoxes with tags
- CheckBox checkBoxAllowed = parentLayout.findViewWithTag("allowed_check_" + providerKey);
- CheckBox checkBoxExcluded = parentLayout.findViewWithTag("excluded_check_" + providerKey);
+ CheckBox checkBoxAllowed = parentLayout.findViewWithTag("checkbox_" + providerKey);
- if (checkBoxAllowed.isChecked()) {
- allowedProviderKeys.add(providerKey);
+ if (checkBoxAllowed == null) {
+ Log.w("SettingsActivity", "CheckBox not found for providerKey: " + providerKey);
+ continue;
}
- if (checkBoxExcluded.isChecked()) {
+ if (checkBoxAllowed.isChecked()) {
+ allowedProviderKeys.add(providerKey);
+ } else {
excludedProviderKeys.add(providerKey);
}
}
@@ -229,6 +278,8 @@ public void onClickSave(View v) {
editor.putStringSet(ScannerServiceApi.EXTRA_SEARCH_ALLOWED_PROVIDERS_STRING_ARRAY, allowedProviderKeys);
editor.putStringSet(ScannerServiceApi.EXTRA_SEARCH_EXCLUDED_PROVIDERS_STRING_ARRAY, excludedProviderKeys);
+ editor.putInt(PREFS_KEY, segmentedButtonState);
+
final Set symbologySelection = new HashSet<>();
if (((CheckBox) findViewById(R.id.checkSelectCode128)).isChecked()) { symbologySelection.add(BarcodeType.CODE128.name()); }
if (((CheckBox) findViewById(R.id.checkSelectCode39)).isChecked()) { symbologySelection.add(BarcodeType.CODE39.name()); }
@@ -242,4 +293,78 @@ public void onClickSave(View v) {
editor.apply();
finish();
}
+
+
+ /**
+ * Bind toggle buttons
+ */
+ private void bindToggleButton() {
+ bt_all.setOnClickListener(v -> {
+ if (bt_all.isChecked()) {
+ bt_all.setIcon(ContextCompat.getDrawable(this, R.drawable.check_all));
+ bt_spec.setIcon(null);
+ bt_none.setIcon(null);
+
+ for (int providerViewId : providerViews) {
+ // Force check and disable
+ ((CheckBox) findViewById(providerViewId)).setChecked(true);
+ findViewById(providerViewId).setEnabled(false);
+ }
+
+ segmentedButtonState = 0;
+ }
+ });
+ bt_spec.setOnClickListener(v -> {
+ if (bt_spec.isChecked()) {
+ bt_spec.setIcon(ContextCompat.getDrawable(this, R.drawable.search));
+ bt_all.setIcon(null);
+ bt_none.setIcon(null);
+
+ for (int providerViewId : providerViews) {
+ // Force enable
+ findViewById(providerViewId).setEnabled(true);
+ }
+
+ segmentedButtonState = 1;
+ }
+ });
+ bt_none.setOnClickListener(v -> {
+ if (bt_none.isChecked()) {
+ bt_none.setIcon(ContextCompat.getDrawable(this, R.drawable.cross));
+ bt_spec.setIcon(null);
+ bt_all.setIcon(null);
+
+ for (int providerViewId : providerViews) {
+ // Force uncheck and disable
+ ((CheckBox) findViewById(providerViewId)).setChecked(false);
+ findViewById(providerViewId).setEnabled(false);
+ }
+
+ segmentedButtonState = 2;
+ }
+ });
+ }
+
+ /**
+ * Set the state of segmented button
+ */
+ private void setSegmentedButtonState() {
+ switch (segmentedButtonState) {
+ case 0:
+ bt_all.performClick();
+ bt_spec.setChecked(false);
+ bt_none.setChecked(false);
+ break;
+ case 1:
+ bt_all.setChecked(false);
+ bt_spec.performClick();
+ bt_none.setChecked(false);
+ break;
+ case 2:
+ bt_all.setChecked(false);
+ bt_spec.setChecked(false);
+ bt_none.performClick();
+ break;
+ }
+ }
}
diff --git a/demoscannerapp/src/main/java/com/enioka/scanner/demo/WelcomeActivity.java b/demoscannerapp/src/main/java/com/enioka/scanner/demo/WelcomeActivity.java
index b80675ab..8f0f63ea 100644
--- a/demoscannerapp/src/main/java/com/enioka/scanner/demo/WelcomeActivity.java
+++ b/demoscannerapp/src/main/java/com/enioka/scanner/demo/WelcomeActivity.java
@@ -2,27 +2,72 @@
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.net.Uri;
import android.os.Bundle;
+
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
+import android.widget.LinearLayout;
import com.enioka.scanner.LaserScanner;
import com.enioka.scanner.api.ScannerSearchOptions;
import com.enioka.scanner.service.ScannerService;
import com.enioka.scanner.service.ScannerServiceApi;
+import com.google.android.material.appbar.MaterialToolbar;
+import com.google.android.material.button.MaterialButton;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.ArrayList;
import java.util.List;
public class WelcomeActivity extends AppCompatActivity {
private List availableProviders = new ArrayList<>();
+ protected MaterialButton bt1 = null;
+ protected FloatingActionButton bugReportBt = null;
+ protected MaterialButton bt5 = null;
+
+ protected MaterialToolbar toolbar = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ boolean landscape = this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
+
setContentView(R.layout.activity_welcome);
+ // Dynamically switch the layout based on the orientation
+ if (landscape) {
+ switchWelcomeActivity(false);
+ }
+
LaserScanner.discoverProviders(this, () -> {});
availableProviders = LaserScanner.getProviderCache();
+ initViews();
+ }
+
+ // Show the menu in the top action tool bar
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ return true;
+ }
+
+ private void initViews() {
+ bt1 = findViewById(R.id.bt_scanner);
+ bt5 = findViewById(R.id.bt_settings);
+ toolbar = findViewById(R.id.topAppBar);
+ bugReportBt = findViewById(R.id.bug_report_button);
+
+ bt1.setOnClickListener(this::onClickBt1);
+ bt5.setOnClickListener(this::onClickBt5);
+ bugReportBt.setOnClickListener(this::onClickReportBug);
+ setSupportActionBar(toolbar);
}
// Scanner activity
@@ -45,20 +90,59 @@ public void onClickBt1(View v) {
// add symbology
final String[] symbologies = preferences.getStringSet(ScannerServiceApi.EXTRA_SYMBOLOGY_SELECTION, ScannerService.defaultSymbologyByName()).toArray(new String[0]);
intent.putExtra(ScannerServiceApi.EXTRA_SYMBOLOGY_SELECTION, symbologies);
+ // add logging intent extra
+ intent.putExtra(SettingsActivity.ENABLE_LOGGING_KEY, preferences.getBoolean(SettingsActivity.ENABLE_LOGGING_KEY, false));
+ // add allow camera fallback intent extra
+ intent.putExtra(SettingsActivity.ALLOW_CAMERA_FALLBACK_KEY, preferences.getBoolean(SettingsActivity.ALLOW_CAMERA_FALLBACK_KEY, false));
+ // add enable keep aspect ratio intent extra
+ intent.putExtra(SettingsActivity.ENABLE_KEEP_ASPECT_RATIO_KEY, preferences.getBoolean(SettingsActivity.ENABLE_KEEP_ASPECT_RATIO_KEY, false) ? 1 : 0);
startActivity(intent);
}
- // Scanner Test activity
- public void onClickBt4(View v) {
- Intent intent = new Intent(this, ScannerTesterActivity.class);
- startActivity(intent);
- }
-
// Scanner settings activity
public void onClickBt5(View v) {
Intent intent = new Intent(this, SettingsActivity.class);
intent.putStringArrayListExtra("providers", (ArrayList) availableProviders);
startActivity(intent);
}
+
+ // Report bug function button
+ public void onClickReportBug(View v) {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/enioka-Haute-Couture/enioka_scan/issues/new"));
+ startActivity(browserIntent);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.github_button) {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/enioka-Haute-Couture/enioka_scan"));
+ startActivity(browserIntent);
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onConfigurationChanged(@NonNull Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ switchWelcomeActivity(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT);
+ }
+
+ public void switchWelcomeActivity(boolean portrait) {
+ View welcome_card = findViewById(R.id.welcome_card);
+ View barcode_image = findViewById(R.id.barcode);
+ ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) welcome_card.getLayoutParams();
+ LinearLayout.LayoutParams paramsBarcode = (LinearLayout.LayoutParams) barcode_image.getLayoutParams();
+
+ if (portrait) {
+ params.matchConstraintPercentWidth = 0.8f;
+ paramsBarcode.height = 90 * (int) getResources().getDisplayMetrics().density;
+ } else {
+ params.matchConstraintPercentWidth = 0.5f;
+ paramsBarcode.height = 100 * (int) getResources().getDisplayMetrics().density;
+ }
+ welcome_card.setLayoutParams(params);
+ barcode_image.setLayoutParams(paramsBarcode);
+ }
}
diff --git a/demoscannerapp/src/main/res/drawable/arrow_left.xml b/demoscannerapp/src/main/res/drawable/arrow_left.xml
new file mode 100644
index 00000000..8629664c
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/arrow_left.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/baseline_settings_24.xml b/demoscannerapp/src/main/res/drawable/baseline_settings_24.xml
new file mode 100644
index 00000000..6593f3a4
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/baseline_settings_24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/check_all.xml b/demoscannerapp/src/main/res/drawable/check_all.xml
new file mode 100644
index 00000000..c9f30e74
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/check_all.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/cross.xml b/demoscannerapp/src/main/res/drawable/cross.xml
new file mode 100644
index 00000000..3e3047fa
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/cross.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/gear_fill.xml b/demoscannerapp/src/main/res/drawable/gear_fill.xml
new file mode 100644
index 00000000..ceb5a79e
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/gear_fill.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/github.xml b/demoscannerapp/src/main/res/drawable/github.xml
new file mode 100644
index 00000000..7f70a1f9
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/github.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/rounded_barcode_scanner_24.xml b/demoscannerapp/src/main/res/drawable/rounded_barcode_scanner_24.xml
new file mode 100644
index 00000000..be8fdb02
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/rounded_barcode_scanner_24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/search.xml b/demoscannerapp/src/main/res/drawable/search.xml
new file mode 100644
index 00000000..ca831a97
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/search.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/upc.xml b/demoscannerapp/src/main/res/drawable/upc.xml
new file mode 100644
index 00000000..627d8ed2
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/upc.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/demoscannerapp/src/main/res/drawable/upc_scan.xml b/demoscannerapp/src/main/res/drawable/upc_scan.xml
new file mode 100644
index 00000000..530c2e9f
--- /dev/null
+++ b/demoscannerapp/src/main/res/drawable/upc_scan.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/demoscannerapp/src/main/res/layout/activity_settings.xml b/demoscannerapp/src/main/res/layout/activity_settings.xml
index bd69fb07..e0678f3c 100644
--- a/demoscannerapp/src/main/res/layout/activity_settings.xml
+++ b/demoscannerapp/src/main/res/layout/activity_settings.xml
@@ -6,244 +6,459 @@
android:layout_height="match_parent"
tools:context="com.enioka.scanner.demo.SettingsActivity">
+
+
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/topAppBarSettings">
-
-
-
-
-
-
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"/>
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@+id/linearLayoutEnableKeepAspectRatio"/>
-
+
+ app:layout_constraintTop_toBottomOf="@+id/dividerSettingsAllowedProvider" />
-
-
+ app:layout_constraintTop_toBottomOf="@+id/textViewAllowedProviders">
-
+
-
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@+id/toggleButtonProvider" />
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/textEmptyProviderList"/>
+ app:layout_constraintTop_toBottomOf="@+id/dividerSettingsSymbology" />
+
-
+
+ app:layout_constraintTop_toBottomOf="@+id/textSymbologySelectionCaption" />
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/checkSelectCode128" />
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/checkSelectCode39" />
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/checkSelectDis25" />
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/checkSelectInt25" />
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/checkSelectEan13" />
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/checkSelectQrCode" />
-
-
-
-
+ app:layout_constraintTop_toBottomOf="@+id/checkSelectAztec" />
+
+
+
+
+
\ No newline at end of file
diff --git a/demoscannerapp/src/main/res/layout/activity_welcome.xml b/demoscannerapp/src/main/res/layout/activity_welcome.xml
index 98188417..6c0433c7 100644
--- a/demoscannerapp/src/main/res/layout/activity_welcome.xml
+++ b/demoscannerapp/src/main/res/layout/activity_welcome.xml
@@ -1,4 +1,5 @@
+
-
-
-
+
+
+
-
-
diff --git a/demoscannerapp/src/main/res/menu/menu_main.xml b/demoscannerapp/src/main/res/menu/menu_main.xml
new file mode 100644
index 00000000..0503becf
--- /dev/null
+++ b/demoscannerapp/src/main/res/menu/menu_main.xml
@@ -0,0 +1,10 @@
+
+
diff --git a/demoscannerapp/src/main/res/values-fr/strings.xml b/demoscannerapp/src/main/res/values-fr/strings.xml
index 05876ff7..2b92a52c 100644
--- a/demoscannerapp/src/main/res/values-fr/strings.xml
+++ b/demoscannerapp/src/main/res/values-fr/strings.xml
@@ -1,22 +1,30 @@
- Test scanner
+ enioka Scan
Testeur de scanner
- Tester la librairie de scan
- Paramètres du scanner
+ Commencer à scanner
+ Paramètres
+
+ GitHub
Paramètres
- Attendre les scanners déconnectés:
- Premier connecté uniquement:
- Utiliser le Bluetooth:
- Autoriser la recherche initiale:
- Autoriser les connexions retardataires:
- Autoriser les séquences d\'appairage:
- Autoriser les scanners fonctionnant par Intent:
- Providers Autorisés (vide = tous):
- Providers Exclus (vide = aucun):
- Selection de la symbology (vide = EAN,128):
+ Général
+ Attendre que les appareils occupés se déconnectent
+ Utiliser le premier appareil disponible
+ Utiliser le Bluetooth pour la recherche d\'appareils
+ Autoriser la recherche initiale d\'appareils
+ Autoriser les connexions d\'appareils retardataires
+ Autoriser les séquences d\'appairage
+ Autoriser les scanners fonctionnant par Intent
+ Activation de l\'historique des scans
+ Activation par défaut de l\'appareil photo si aucun scanneur n\'est trouvé
+ Conserver le rapport hauteur/largeur de la caméra (remplir l\'espace disponible par défaut)
+ Providers autorisés
+ Providers exclus
+ Sélection de la symbologie
+ Aucun provider disponible
+ vide = EAN,128
Enregistrer
Athesi [SPA45…]
@@ -37,4 +45,11 @@
EAN13
QRCode
Aztec
+
+ Tous
+ Choisir
+ Aucun
+
+ code-barre
+ parametres
\ No newline at end of file
diff --git a/demoscannerapp/src/main/res/values/dimen.xml b/demoscannerapp/src/main/res/values/dimen.xml
index 503cf4c0..00536c12 100644
--- a/demoscannerapp/src/main/res/values/dimen.xml
+++ b/demoscannerapp/src/main/res/values/dimen.xml
@@ -1,9 +1,8 @@
24dp
- 48dp
16dp
16dp
- 10dp
- 16dp
+ 12dp
+ 16dp
\ No newline at end of file
diff --git a/demoscannerapp/src/main/res/values/strings.xml b/demoscannerapp/src/main/res/values/strings.xml
index b3364e32..b9040725 100644
--- a/demoscannerapp/src/main/res/values/strings.xml
+++ b/demoscannerapp/src/main/res/values/strings.xml
@@ -1,21 +1,29 @@
- Scanner test
+ enioka Scan
Scanner tester
- Test scanner library
- Scanner settings
+ Start scanning
+ Settings
+
+ GitHub
Settings
- Wait Disconnected:
- Return Only First:
- Use Bluetooth:
- Allow Initial Search:
- Allow Later Connections:
- Allow Pairing Flow:
- Allow Intent Devices
- Allowed Providers (empty = all):
- Excluded Providers (empty = none):
- Allowed Symbology (empty = EAN,128):
+ General
+ Wait for busy devices to disconnect
+ Use the first available device
+ Use Bluetooth for device search
+ Allow initial device search
+ Allow later device connections
+ Allow pairing flow
+ Allow intent devices
+ Enable scan history
+ Default to camera if no scanner is found
+ Maintain camera aspect ratio (fill all available space by default)
+ Allowed Providers
+ Excluded Providers
+ Allowed Symbology
+ No provider available
+ empty = EAN,128
Save
Athesi [SPA45…]
@@ -37,4 +45,10 @@
QRCode
Aztec
+ All
+ Select
+ None
+
+ barcode
+ settings
diff --git a/demoscannerapp/src/main/res/values/styles.xml b/demoscannerapp/src/main/res/values/styles.xml
index 5885930d..c98be290 100644
--- a/demoscannerapp/src/main/res/values/styles.xml
+++ b/demoscannerapp/src/main/res/values/styles.xml
@@ -1,11 +1,8 @@
-
diff --git a/docs/api/camera.md b/docs/api/camera.md
index 147ce496..205590e6 100644
--- a/docs/api/camera.md
+++ b/docs/api/camera.md
@@ -17,6 +17,18 @@ the device's properties.
For most users, this is the class they will interact with if they need to interact with the Camera
hardware and not just the [`Scanner` instance](scanner.md#the-scanner-interface).
+:::{method} setPreviewRatioMode(int mode) -> void
+
+Change the preview aspect ratio mode of the camera. This change will not take effect until the next
+view refresh. You can force a refresh by pausing and resuming the camera.
+
+:param int mode: The mode to use for filling the camera preview. Can be one of the following values:
+ - `0`: `fillAvailableSpace` (default): The preview will fill the available space, by squashing
+ or stretching the preview if needed.
+ - `1`: `fitToPicture`: The preview will be scaled to fit the picture, with black bars on the
+ sides if needed. The aspect ratio of the preview will be kept.
+:::
+
:::{method} setReaderMode(CameraReader readerMode) -> void
Change the library used to read barcodes from the camera feed.
@@ -76,6 +88,13 @@ Pauses the camera's capture.
Resumes the camera's capture.
:::
+:::{methode} orientationChanged() -> void
+
+Notifies the view that the orientation of the device has changed by calling
+`setDisplayOrientation()` with the correct clockwise rotation of the camera preview, depending on
+the device's orientation.
+:::
+
:::{method} getLatestSuccessfulScanJpeg() -> byte[]
:returns: The JPEG data of the image used in the latest successful scan, or null if there is no
diff --git a/docs/api/scanner_activity.md b/docs/api/scanner_activity.md
index 297ac2f6..c2953f91 100644
--- a/docs/api/scanner_activity.md
+++ b/docs/api/scanner_activity.md
@@ -48,20 +48,34 @@ service. **This does not affect scanner search options**.
:::{cpp:var} int layoutIdLaser = R.layout.activity_main
-The layout used by the activity when using regular scanner devices. May be replaced with your own.
-:::
-
-:::{cpp:var} Integer layoutIdCamera = null
-
-The layout used by the activity when using the camera as a scanner. May be replaced with your own.
-If the camera SDK is included, it will be defined to :::{cpp:var}R.layout.activity_main_alt
-:::
-
-:::{cpp:var} Integer cameraViewId = null
-
-If the camera SDK is included, it will be set to :::{cpp:var}R.id.camera_scan_view
-It is the ID of the [`CameraBarcodeScanView`](camera.md#the-camerabarcodescanview-class) inside the
-`layoutIdCamera` layout.
+The layout used by the activity when using regular scanner devices. May be replaced with
+your own.
+:::
+
+:::{cpp:var} HashMap cameraResources = null;
+
+The hashmap containing the IDs of the views used by the camera scanner. May be replaced with your
+own.
+
+If the camera SDK is included, it will be set to a map containing the following values:
+- layout_id_camera: The ID of the layout containing the camera view
+:::{cpp:var}R.layout.activity_main_alt:::.
+- camera_view_id: The ID of the camera view in the layout :::{cpp:var}R.id.camera_scan_view:::.
+ It is the ID of the [`CameraBarcodeScanView`](camera.md#the-camerabarcodescanview-class) inside the
+ `layout_id_camera` layout.
+ :::.
+- scanner_toggle_view_id: It is the ID of the optional ImageButton on which to press to toggle the
+zxing/zbar camera scan library :::{cpp:var}R.id.scanner_switch_zxing:::.
+- scanner_toggle_pause_id: The ID of the optional toggle button on which to press to pause/unpause
+the scanner :::{cpp:var}R.id.scanner_switch_pause:::.
+- card_last_scan_id: ID of the card view that displays the last scan
+:::{cpp:var}R.id.card_camera_last_scan:::.
+- constraint_layout_id: The ID of the constraint layout inside the camera layout
+:::{cpp:var}R.id.constraint_layout_main_activity:::.
+- scanner_flashlight_id: The ID of the optional ImageButton on which to press to toggle the
+flashlight/illumination :::{cpp:var}R.id.scanner_flashlight:::.
+- scanner_bt_provider_logs: The ID of the optional ImageButton on which to press to manually access
+available providers logs :::{cpp:var}R.id.scanner_bt_provider_logs:::.
:::
:::{cpp:var} int cameraToggleId = R.id.scanner_bt_camera
@@ -74,20 +88,6 @@ The ID of the optional ImageButton on which to press to manually switch to camer
The ID of the optional ImageButton on which to press to toggle the flashlight/illumination.
:::
-:::{cpp:var} Integer scannerModeToggleViewId = null
-
-If the camera SDK is included, it will be set to :::{cpp:var}R.id.scanner_switch_zxing.
-It is the ID of the optional ImageButton on which to press to toggle the zxing/zbar camera scan
-library.
-:::
-
-:::{cpp:var} Integer scannerModeTogglePauseId =
-
-The ID of the optional toggle button on which to press to pause/unpause the scanner.
-If the camera SDK is included and it is not overwrite, it will be set by default to
-:::{cpp:var}R.id.scanner_switch_pause.
-:::
-
:::{cpp:var} int keyboardOpenViewId = R.id.scanner_bt_keyboard
The ID of the optional toggle button on which to display the manual input fragment.
@@ -128,6 +128,11 @@ Can be used to access some methods of `CameraBarcodeScanViewScanner`. Should not
Initialized by the [`initCamera()`](#scannercompatactivity-methods) method.
:::
+:::{cpp:var} int openLinkId = R.id.open_link;
+
+The ID of the of the optional button on which to press to open a link when a QRCode URL is scanned.
+:::
+
## `ScannerCompatActivity` methods
:::{method} getServiceInitExtras() -> Bundle
diff --git a/docs/api/scanner_service.md b/docs/api/scanner_service.md
index 68f9a4f2..8c6badfb 100644
--- a/docs/api/scanner_service.md
+++ b/docs/api/scanner_service.md
@@ -161,7 +161,7 @@ If true, bluetooth devices will be searched for compatible scanners.
Corresponds to the `ScannerServiceApi.EXTRA_SEARCH_ALLOW_BT_BOOLEAN` extra.
:::
-:::{cpp:var} boolean allowIntentDevices = false
+:::{cpp:var} boolean allowIntentDevices = true
If true, providers using another application for controlling scanners will be allowed.
This is important as most of the time, it is impossible to say if these apps are actually installed,
@@ -195,7 +195,7 @@ Mostly used to let bluetooth providers contact known devices during search.
Corresponds to the `ScannerServiceApi.EXTRA_SEARCH_ALLOW_INITIAL_SEARCH_BOOLEAN` extra.
:::
-:::{cpp:var} boolean allowPairingFlow = false
+:::{cpp:var} boolean allowPairingFlow = true
If true, the providers which needs a pairing done by their own SDK (for example, BLE on-the-fly
pairing) will be allowed to do so.
diff --git a/enioka_scan/build.gradle b/enioka_scan/build.gradle
index 661bca20..69ce76e4 100644
--- a/enioka_scan/build.gradle
+++ b/enioka_scan/build.gradle
@@ -7,7 +7,10 @@ android {
defaultConfig {
minSdkVersion 19
targetSdkVersion 28
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
+ vectorDrawables.useSupportLibrary = true
+ multiDexKeepProguard file('multidex.pro')
+ multiDexEnabled true
}
buildTypes {
release {
@@ -34,6 +37,9 @@ dependencies {
//noinspection GradleCompatible
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
+ implementation 'com.google.android.material:material:1.12.0'
+ implementation "androidx.multidex:multidex:2.0.1"
+
// ZBAR & ZXING (Zebra Crossing) = camera. From Maven Central.
api('me.dm7.barcodescanner:zbar:1.9.8') {
diff --git a/enioka_scan/multidex.pro b/enioka_scan/multidex.pro
new file mode 100644
index 00000000..5bb944dc
--- /dev/null
+++ b/enioka_scan/multidex.pro
@@ -0,0 +1 @@
+-keep class **Test { *; }
\ No newline at end of file
diff --git a/enioka_scan/src/main/AndroidManifest.xml b/enioka_scan/src/main/AndroidManifest.xml
index 0b081c9c..9b4d2101 100644
--- a/enioka_scan/src/main/AndroidManifest.xml
+++ b/enioka_scan/src/main/AndroidManifest.xml
@@ -4,7 +4,9 @@
+ android:supportsRtl="true"
+ android:hardwareAccelerated="true"
+ android:theme="@style/AppTheme">
dialog.dismiss())
+ .show();
+ }
+}
diff --git a/enioka_scan/src/main/java/com/enioka/scanner/activities/ScannerCompatActivity.java b/enioka_scan/src/main/java/com/enioka/scanner/activities/ScannerCompatActivity.java
index 1938c76b..608872bb 100644
--- a/enioka_scan/src/main/java/com/enioka/scanner/activities/ScannerCompatActivity.java
+++ b/enioka_scan/src/main/java/com/enioka/scanner/activities/ScannerCompatActivity.java
@@ -5,24 +5,34 @@
import static com.enioka.scanner.helpers.Permissions.hasPermissionSet;
import static com.enioka.scanner.helpers.Permissions.requestPermissionSet;
+import android.Manifest;
import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
-import android.graphics.PorterDuff;
+import android.content.res.Configuration;
+import android.net.Uri;
import android.os.Bundle;
+import android.os.Environment;
import android.os.IBinder;
+
+import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat;
import androidx.appcompat.app.AppCompatActivity;
+
+import android.text.Html;
+import android.text.Spanned;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
-import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
@@ -40,25 +50,40 @@
import com.enioka.scanner.service.ScannerService;
import com.enioka.scanner.service.ScannerServiceApi;
import com.enioka.scanner.service.ScannerServiceBinderHelper;
-
+import com.google.android.material.card.MaterialCardView;
+import com.google.android.material.materialswitch.MaterialSwitch;
+import com.google.android.material.snackbar.Snackbar;
+
+import java.io.BufferedWriter;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.Timer;
+import java.util.concurrent.TimeUnit;
/**
* A helper activity which implements all scan functions: laser, camera, HID.
Basic usage is trivial : just inherit this class, and that's all.
* You may want to override {@link #onData(List)} to get barcode data, and {@link #onStatusChanged(Scanner, ScannerStatusCallback.Status)} to display status messages from the scanners.
- * It is also useful to change inside onCreate {@link #layoutIdLaser} and {@link #layoutIdCamera} to a layout ID (from R.id...) corresponding to your application.
+ * It is also useful to change inside onCreate {@link #layoutIdLaser} and layout_id_camera inside {@link #cameraResources} to a layout ID (from R.id...) corresponding to your application.
* By default, a basic test layout is provided.
- * Also, {@link #cameraViewId} points to the camera view inside your camera layout.
+ * Also, camera_view_id {@link #cameraResources} points to the camera view inside your camera layout.
*/
public class ScannerCompatActivity extends AppCompatActivity implements ScannerClient {
protected final static String LOG_TAG = "ScannerActivity";
protected final static String CAMERA_SDK_PACKAGE = "com.enioka.scanner.sdk.camera";
protected final static int PERMISSION_REQUEST_ID_CAMERA = 1790;
protected final static int PERMISSION_REQUEST_ID_BT = 1792;
+ protected final static int PERMISSION_REQUEST_ID_WRITE = 124;
+ protected final static int WRITE_REQUEST_CODE = 123;
/**
* Don't start camera mode, even if no lasers are available
@@ -85,19 +110,23 @@ public class ScannerCompatActivity extends AppCompatActivity implements ScannerC
*/
protected int layoutIdLaser = R.layout.activity_main;
/**
- * The layout to use when using camera scanner.
+ * Hashmap containing the ID resources from the camera scanner provider.
+ * Contains the following keys:
+ * - layout_id_camera: The ID of the layout containing the camera view.
+ * - camera_view_id: The ID of the camera view in the layout.
+ * - scanner_toggle_view_id: The ID of the view that toggles the scanner library reader.
+ * - scanner_toggle_pause_id: The ID of the view that toggles the pause of the scanner.
+ * - card_last_scan_id: ID of the card view that displays the last scan.
+ * - constraint_layout_id: The ID of the constraint layout inside the camera layout.
+ * - scanner_flashlight_id: The ID of the optional ImageButton on which to press to toggle the flashlight/illumination.
+ * - scanner_bt_provider_logs: The ID of the optional ImageButton on which to press to manually access available providers logs
*/
- protected Integer layoutIdCamera = null;
+ protected HashMap cameraResources = null;
/**
- * Use {@link #cameraViewId} instead.
+ * Use camera_view_id inside the {@link #cameraResources} instead.
*/
@Deprecated
protected Integer zbarViewId = null;
- /**
- * The ID of the CameraBarcodeScanView inside the {@link #layoutIdCamera} layout.
- */
- protected Integer cameraViewId = null;
-
/**
* The ID of the ImageButton on which to press to manually switch to camera mode.
*/
@@ -108,14 +137,7 @@ public class ScannerCompatActivity extends AppCompatActivity implements ScannerC
*/
protected int flashlightViewId = R.id.scanner_flashlight;
- /**
- * The ID of the optional ImageButton on which to press to toggle the zxing/zbar camera scan library.
- */
- protected Integer scannerModeToggleViewId = null;
-
- protected Integer scannerModeTogglePauseId = null;
-
- protected int keyboardOpenViewId = R.id.scanner_bt_keyboard;
+ protected int providerLogOpenViewId = R.id.scanner_bt_provider_logs;
/**
* An optional fragment allowing to input a value with the soft keyboard (for cases when scanners do not work).
@@ -148,6 +170,54 @@ public class ScannerCompatActivity extends AppCompatActivity implements ScannerC
*/
protected CameraScannerProvider cameraScannerProvider = null;
+ /**
+ * Material card view for the scanner status.
+ */
+ private MaterialCardView scannerStatusCard;
+
+ /**
+ * Delay in milliseconds before resetting the scanner status card style.
+ */
+ private static final long STATUS_CARD_RESET_DELAY = 170;
+
+ /**
+ * Define if the log is enabled or not.
+ */
+ protected boolean loggingEnabled = false;
+
+ /**
+ * Define if the fallback to camera is allowed.
+ */
+ protected boolean allowCameraFallback = false;
+ /**
+ * Camera preview ratio mode.
+ */
+ protected int previewRatioMode = -1;
+
+ /**
+ * Define if the activity should go back to the scanner view or main view.
+ */
+ private boolean backScannerView = true;
+
+ /**
+ * The URI of the log file to write to.
+ */
+ private Uri logFileUri = null;
+
+ /**
+ * The ID of the open link button.
+ */
+ protected int openLinkId = R.id.open_link;
+
+ /**
+ * The String URL of the open link button.
+ */
+ private String openLinkUrl = null;
+
+ /**
+ * Logs and status of all detected providers
+ */
+ private String providerLogs = "";
////////////////////////////////////////////////////////////////////////////////////////////////
// Activity lifecycle callbacks
@@ -161,10 +231,25 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
// Set content immediately - that way our callbacks can draw on the layout.
setViewContent();
+ linkBackCallback();
// Ascending compatibility
if (zbarViewId != null) {
- cameraViewId = zbarViewId;
+ cameraResources.put("camera_view_id", zbarViewId);
+ }
+
+ // Get the intent extras
+ loggingEnabled = getIntent().getBooleanExtra("enableLogging", false);
+ allowCameraFallback = getIntent().getBooleanExtra("allowCameraFallback", false);
+ previewRatioMode = getIntent().getIntExtra("enableKeepAspectRatio", -1);
+
+ // Init logging if enabled
+ if (loggingEnabled) {
+ if (hasPermissionSet(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE})) {
+ createLog();
+ } else {
+ requestPermissionSet(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_ID_WRITE);
+ }
}
// init fields
@@ -195,6 +280,8 @@ protected void onStart() {
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
Log.i(LOG_TAG, "Could not instantiate camera provider", e);
hasCameraScannerSdk = false;
+ // Disable switch to camera button
+ findViewById(cameraToggleId).setVisibility(View.GONE);
}
}
@@ -219,13 +306,28 @@ protected void onResume() {
if (findViewById(R.id.scanner_text_last_scan) != null) {
((TextView) findViewById(R.id.scanner_text_last_scan)).setText(null);
}
- if (findViewById(R.id.scanner_text_scanner_status) != null) {
- ((TextView) findViewById(R.id.scanner_text_scanner_status)).setText(null);
+
+ if (findViewById(R.id.scanner_provider_status_card) != null) {
+ findViewById(R.id.scanner_provider_status_card).setVisibility(View.GONE);
+ }
+
+ if (findViewById(R.id.scanner_provider_text) != null) {
+ ((TextView) findViewById(R.id.scanner_provider_text)).setText("");
}
+ if (findViewById(R.id.scanner_provider_status_text) != null) {
+ ((TextView) findViewById(R.id.scanner_provider_status_text)).setText("");
+ }
+
+ // Hide the open link button
+ findViewById(openLinkId).setVisibility(View.GONE);
+
+ // Set scanner card last scan to not clickable
+ scannerStatusCard.setClickable(false);
+
// Immediately set some buttons (which do no need to wait for scanners).
displayCameraButton();
- displayManualInputButton();
+ displayManualProviderLogButton();
// Register this activity on the scanner service (hooks onData) and ask it to hook possible scanners needing foreground control onto this activity.
// If no scanners are available at all, this will still call onForegroundScannerInitEnded with 0 scanners, and the activity will launch the camera.
@@ -268,12 +370,31 @@ protected void onDestroy() {
}
private void setViewContent() {
- if (enableScan && goToCamera && hasPermissionSet(this, PERMISSIONS_CAMERA) && hasCameraScannerSdk) {
+ int orientation = getResources().getConfiguration().orientation;
+
+ if (cameraResources != null && enableScan && goToCamera && hasPermissionSet(this, PERMISSIONS_CAMERA) && hasCameraScannerSdk) {
// Can only add/open a camera view if camera is allowed.
- setContentView(layoutIdCamera);
+ Integer cameraLayoutId = cameraResources.get("layout_id_camera");
+
+ if (cameraLayoutId == null) {
+ throw new IllegalStateException("Camera layout not set");
+ }
+
+ setContentView(cameraLayoutId);
+
+ View view = findViewById(flashlightViewId).getRootView();
+ ViewSwitcher.switchCameraOrientation(this, view, cameraResources, orientation == Configuration.ORIENTATION_PORTRAIT);
} else {
setContentView(layoutIdLaser);
+
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ View view = findViewById(flashlightViewId).getRootView();
+ ViewSwitcher.switchLaserOrientation(this, view, flashlightViewId, false);
+ }
+ scannerStatusCard = findViewById(R.id.scanner_card_last_scan);
}
+ // Init last scan card button
+ InitCopyClipBoard();
}
@@ -363,16 +484,21 @@ protected void initCamera() {
if (hasPermissionSet(this, PERMISSIONS_CAMERA)) {
if (!activityStartedInCameraMode) {
// The view needs permissions BEFORE initializing. And it initializes as soon as the layout is set.
- if (layoutIdCamera == null) {
+ Integer cameraLayoutId = cameraResources.get("layout_id_camera");
+ if (cameraLayoutId == null) {
throw new IllegalStateException("Camera layout not set");
}
- setContentView(layoutIdCamera);
+ setViewContent();
}
initCameraScanner();
// Reinit text
- if (findViewById(R.id.scanner_text_scanner_status) != null) {
- TextView tv = findViewById(R.id.scanner_text_scanner_status);
+ if (findViewById(R.id.scanner_provider_text) != null) {
+ TextView tv = findViewById(R.id.scanner_provider_text);
+ tv.setText("");
+ }
+ if (findViewById(R.id.scanner_provider_status_text) != null) {
+ TextView tv = findViewById(R.id.scanner_provider_status_text);
tv.setText("");
}
} else {
@@ -381,20 +507,8 @@ protected void initCamera() {
}
private void setCameraViewId() {
- if (this.layoutIdCamera == null) {
- this.layoutIdCamera = cameraScannerProvider.getLayoutIdCamera();
- }
-
- if (this.cameraViewId == null) {
- this.cameraViewId = cameraScannerProvider.getCameraViewId();
- }
-
- if (this.scannerModeToggleViewId == null) {
- this.scannerModeToggleViewId = cameraScannerProvider.getScannerToggleViewId();
- }
-
- if (this.scannerModeTogglePauseId == null) {
- this.scannerModeTogglePauseId = cameraScannerProvider.getScannerTogglePauseId();
+ if (cameraResources == null) {
+ cameraResources = cameraScannerProvider.getIdResources();
}
}
@@ -403,12 +517,17 @@ private void initCameraScanner() {
return;
}
// TODO: should be in camera constructor, not here...
- View cameraView = findViewById(cameraViewId);
+ Integer cameraViewId = cameraResources.get("camera_view_id");
+ View cameraView = cameraViewId != null ? findViewById(cameraViewId) : null;
if (cameraView == null) {
Toast.makeText(this, R.string.scanner_status_no_camera, Toast.LENGTH_SHORT).show();
return;
}
+ // Set the content view to the camera layout
+ Integer cardLastScanId = cameraResources.get("card_last_scan_id");
+ scannerStatusCard = cardLastScanId != null ? findViewById(cardLastScanId) : null;
+
final Set symbologies = new HashSet<>();
if (getIntent().getExtras() != null && getIntent().getExtras().getStringArray(ScannerServiceApi.EXTRA_SYMBOLOGY_SELECTION) != null) {
for (final String symbology : Objects.requireNonNull(getIntent().getExtras().getStringArray(ScannerServiceApi.EXTRA_SYMBOLOGY_SELECTION))) {
@@ -420,12 +539,21 @@ private void initCameraScanner() {
}
cameraScannerProvider.getCameraScanner(cameraView, new ScannerDataCallbackProxy((s, data) -> ScannerCompatActivity.this.onData(data)), new ScannerStatusCallbackProxy(this), symbologies);
+ // Set the preview ratio mode
+ cameraScannerProvider.setPreviewRatioMode(cameraView, previewRatioMode);
+
+ InitCopyClipBoard();
if (findViewById(R.id.scanner_text_last_scan) != null) {
((TextView) findViewById(R.id.scanner_text_last_scan)).setText(null);
}
+
+ if (scannerStatusCard != null) {
+ scannerStatusCard.setClickable(false);
+ }
+
displayTorch();
- displayManualInputButton();
+ displayManualProviderLogButton();
displayCameraReaderToggle();
displayCameraPauseToggle();
}
@@ -460,6 +588,12 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
}
break;
}
+ case PERMISSION_REQUEST_ID_WRITE: {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ createLog();
+ }
+ break;
+ }
}
}
@@ -471,27 +605,51 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
@SuppressLint("SetTextI18n") // Text is already localized, only special characters remain.
@Override
public void onStatusChanged(final Scanner scanner, final ScannerStatusCallback.Status newStatus) {
- if (findViewById(R.id.scanner_text_scanner_status) != null) {
- TextView tv = findViewById(R.id.scanner_text_scanner_status);
- tv.setText((scanner == null ? "" : (scanner.getProviderKey() + ": ")) + newStatus + " --- " + newStatus.getLocalizedMessage(this) + "\n" + tv.getText());
+ if (scanner != null && newStatus != null) {
+ providerLogs += scanner.getProviderKey() + " " + newStatus + "\n";
+ }
+
+ TextView providerText = findViewById(R.id.scanner_provider_text);
+ TextView providerStatusText = findViewById(R.id.scanner_provider_status_text);
+
+ if (scanner != null && providerText != null && providerStatusText != null && (newStatus == Status.CONNECTED || newStatus == Status.READY)) {
+ if (goToCamera && newStatus == Status.READY) {
+ return;
+ }
+
+ String connectedProvider = providerText.getText().toString();
+
+ // Update text list of connect providers
+ if (!connectedProvider.contains(scanner.getProviderKey())) {
+ providerText.setText(connectedProvider + (connectedProvider.isEmpty() ? "" : "\n") + scanner.getProviderKey());
+ }
+
+ // Set status
+ providerStatusText.setText(newStatus.toString());
+
+ // Update visibility of the scanner status card
+ findViewById(R.id.scanner_provider_status_card).setVisibility(View.VISIBLE);
}
+
}
@Override
public void onScannerInitEnded(int scannerCount) {
Log.i(LOG_TAG, "Activity can now use all received scanners (" + scannerCount + ")");
- if (scannerCount == 0 && !laserModeOnly && enableScan && hasCameraScannerSdk) {
+ if (scannerCount == 0 && !laserModeOnly && enableScan && hasCameraScannerSdk && allowCameraFallback) {
// In that case try to connect to a camera.
initCamera();
+ backScannerView = false;
}
if (scannerCount > 0) {
displayTorch();
displayToggleLedButton();
- displayEnableScanButton();
- displayDisableScanButton();
+ displaySwitchScanButton();
displayBellButton();
+ } else {
+
}
}
@@ -507,25 +665,168 @@ public void onProviderDiscoveryEnded() {
@Override
public void onData(List data) {
+ if (scannerStatusCard != null) {
+ scannerStatusCard.setClickable(true);
+ scannerStatusCard.setStrokeColor(ContextCompat.getColor(ScannerCompatActivity.this, R.color.doneItemColor));
+ scannerStatusCard.setStrokeWidth(4);
+
+ resetStatusCardStyle();
+ }
+
StringBuilder res = new StringBuilder();
for (Barcode b : data) {
Log.d(LOG_TAG, "Received barcode from scanner: " + b.getBarcode() + " - " + b.getBarcodeType().code);
- res.append(b.getBarcode()).append("\n").append(b.getBarcodeType().code).append("\n");
+ res.append(buildBarcodeText(b.getBarcodeType().code, b.getBarcode()));
+
+ if (logFileUri != null) {
+ writeResultToLog(b);
+ }
+
+ try {
+ // Check if content is an URL
+ openLinkUrl = new URL(b.getBarcode()).toURI().toString();
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(openLinkUrl));
+
+ findViewById(openLinkId).setVisibility(View.VISIBLE);
+ findViewById(openLinkId).setOnClickListener(v -> {
+ // Pause camera or laser scanner
+ startActivity(intent);
+ findViewById(openLinkId).setVisibility(View.GONE);
+ });
+ } catch (Exception ignored) {
+ // Not a URL
+ findViewById(openLinkId).setVisibility(View.GONE);
+ }
}
- if (findViewById(R.id.scanner_text_last_scan) != null) {
- ((TextView) findViewById(R.id.scanner_text_last_scan)).setText(res.toString());
+
+ TextView textLastScan = findViewById(R.id.scanner_text_last_scan);
+ if (textLastScan != null) {
+ textLastScan.setText(Html.fromHtml(res.toString()));
+ resizeScannerLastText(textLastScan);
+ }
+
+ // Disable the scannerSwitch when a barcode is found
+ MaterialSwitch scannerSwitch = (MaterialSwitch) findViewById(R.id.scanner_trigger_on);
+ if (scannerSwitch != null) {
+ scannerSwitch.setChecked(false);
}
+
if (manualInputFragment != null) {
manualInputFragment = null;
scannerService.resume();
}
}
+ /**
+ * Dynamically resize the last scan text view to fit the content.
+ * Called when a new data is received, or on orientation change.
+ */
+ private void resizeScannerLastText(TextView text) {
+ if (text == null) {
+ return;
+ }
+ // Set the last scan text
+ text.setSingleLine(false);
+
+ text.post(() -> {
+ float textSizeInSp = text.getTextSize() / getResources().getDisplayMetrics().scaledDensity;
+ float minTextSizeInSp = getResources().getDimension(R.dimen.min_text_size_last_scan) / getResources().getDisplayMetrics().scaledDensity;
+
+ // Activate marquee effect if the text size is the minimum size
+ if (textSizeInSp == minTextSizeInSp) {
+ text.setSingleLine(true);
+ text.setSelected(true);
+ }
+ });
+ }
+
+ /**
+ * Build the text to display in the scanner status card.
+ */
+ private String buildBarcodeText(String barcodeType, String barcodeData) {
+ if (barcodeType.isEmpty() || barcodeData.isEmpty()) {
+ return "";
+ }
+
+ return "TYPE: " + barcodeType + " " + barcodeData + "";
+ }
+
+ /**
+ * Reset stroke color and width of the scanner status card after a delay.
+ */
+ private void resetStatusCardStyle() {
+ new Timer().schedule(new java.util.TimerTask() {
+ @Override
+ public void run() {
+ runOnUiThread(() -> {
+ scannerStatusCard.setStrokeColor(ContextCompat.getColor(ScannerCompatActivity.this, R.color.cardBackgroundColor));
+ scannerStatusCard.setStrokeWidth(1);
+ });
+ }
+ }, TimeUnit.MILLISECONDS.toMillis(STATUS_CARD_RESET_DELAY));
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////
// Button and input initialization
////////////////////////////////////////////////////////////////////////////////////////////////
+ /**
+ *
+ */
+ private void linkBackCallback() {
+ OnBackPressedCallback callback = new OnBackPressedCallback(true) {
+ @Override
+ public void handleOnBackPressed() {
+ // Get name of current view
+
+ if (backScannerView && goToCamera) {
+ goToCamera = false;
+
+ Log.i(LOG_TAG, "Scanner activity is being reset, going back to scanner view " + this.hashCode());
+ if (serviceBound) {
+ scannerService.pause();
+ }
+
+ if (cameraScannerProvider != null && cameraScannerProvider.isCameraScannerInitialized()) {
+ cameraScannerProvider.disconnect();
+ cameraScannerProvider.reset();
+ }
+
+ setViewContent();
+ onResume();
+ } else {
+ finish();
+ }
+ }
+ };
+
+ // Add the callback to the activity's lifecycle
+ getOnBackPressedDispatcher().addCallback(this, callback);
+ }
+
+ /**
+ * Copy last scan text to clipboard when clicking on the scanner status card.
+ */
+ private void InitCopyClipBoard() {
+ // Setup clipboard copy button
+ scannerStatusCard.setOnClickListener(v -> {
+ TextView lastScan = findViewById(R.id.scanner_text_last_scan);
+
+ if (lastScan.getText().length() != 0) {
+ ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+ String[] lastScanText = lastScan.getText().toString().split(" ");
+ ClipData clip = ClipData.newPlainText("barcode", lastScanText[lastScanText.length - 1]);
+
+ clipboard.setPrimaryClip(clip);
+
+ Snackbar snackbar = Snackbar.make(v, R.string.last_scan_clipboard, Snackbar.LENGTH_SHORT);
+ snackbar.show();
+ }
+ });
+ scannerStatusCard.setClickable(false);
+ }
+
/**
* Display the torch button "on" or "off" is the device has capability.
**/
@@ -566,11 +867,19 @@ private void toggleTorch() {
flashlight.setVisibility(View.VISIBLE);
}
- boolean isOn = anyScannerHasIlluminationOn() || (cameraScannerProvider != null && cameraScannerProvider.isIlluminationOn());
- int iconId = isOn ? R.drawable.icn_flash_off_on : R.drawable.icn_flash_off;
+ boolean isOn = (!goToCamera && anyScannerHasIlluminationOn()) || (cameraScannerProvider != null && cameraScannerProvider.isIlluminationOn());
+
+ int iconId;
+
+ // If we are in camera mode, the icon should be the camera flash icon.
+ // Otherwise, the icon should be the flashlight icon.
+ if (goToCamera) {
+ iconId = isOn ? R.drawable.flash : R.drawable.flash_off;
+ } else {
+ iconId = isOn ? R.drawable.flashlight : R.drawable.flashlight_off;
+
+ }
- final int newColor = getResources().getColor(R.color.flashButtonColor);
- flashlight.setColorFilter(newColor, PorterDuff.Mode.SRC_ATOP);
flashlight.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), iconId));
}
@@ -599,39 +908,19 @@ protected boolean anyScannerHasIlluminationOn() {
}
/**
- * Display a manual input (keyboard) button for manual input.
+ * Display a manual input button to launch an alert dialog that contains provider logs.
*/
- private void displayManualInputButton() {
- final View bt = findViewById(keyboardOpenViewId);
+ private void displayManualProviderLogButton() {
+ final View bt = findViewById(providerLogOpenViewId);
if (bt == null) {
return;
}
bt.setVisibility(View.VISIBLE);
- bt.setOnClickListener(view -> {
- // Pause camera or laser scanner during manual input.
- scannerService.pause();
-
- manualInputFragment = ManualInputFragment.newInstance();
- manualInputFragment.setAutocompletionItems(autocompletionItems, threshold);
- manualInputFragment.setDialogInterface(new DialogInterface() {
- @Override
- public void cancel() {
- if (serviceBound) {
- scannerService.resume();
- }
- }
-
- @Override
- public void dismiss() {
- if (serviceBound) {
- scannerService.resume();
- }
- }
- });
- manualInputFragment.show(getSupportFragmentManager(), "manual");
- });
+ String providerLogTitle = getResources().getString(R.string.provider_log_dialog_title);
+ String textButton = getResources().getString(R.string.provider_log_dialog_close);
+ bt.setOnClickListener(view -> ManualLogDialog.launchDialog(this, providerLogTitle, providerLogs, textButton));
}
/**
@@ -652,27 +941,34 @@ private void displayCameraButton() {
}
private void displayCameraReaderToggle() {
- final Switch toggle = findViewById(scannerModeToggleViewId);
+ Integer scannerToggleViewId = cameraResources.get("scanner_toggle_view_id");
+ final SwitchCompat toggle = scannerToggleViewId != null ? findViewById(scannerToggleViewId) : null;
if (toggle == null) {
return;
}
toggle.setOnCheckedChangeListener((buttonView, isChecked) -> {
Log.i(LOG_TAG, "Changing reader mode");
- View cameraView = findViewById(cameraViewId);
+ Integer cameraViewId = cameraResources.get("camera_view_id");
+ View cameraView = cameraViewId != null ? findViewById(cameraViewId) : null;
cameraScannerProvider.setReaderMode(cameraView, isChecked);
+
+ // Show snackbar message informing the user of the change
+ Snackbar.make(buttonView, isChecked ? R.string.snack_message_zxing : R.string.snack_message_zbar, Snackbar.LENGTH_SHORT).show();
});
}
private void displayCameraPauseToggle() {
- final Switch toggle = findViewById(scannerModeTogglePauseId);
+ Integer scannerToggleViewId = cameraResources.get("scanner_toggle_pause_id");
+ final SwitchCompat toggle = scannerToggleViewId != null ? findViewById(scannerToggleViewId) : null;
if (toggle == null) {
return;
}
toggle.setOnCheckedChangeListener((buttonView, isChecked) -> {
Log.i(LOG_TAG, "Toggling camera pause");
- View cameraView = findViewById(cameraViewId);
+ Integer cameraViewId = cameraResources.get("camera_view_id");
+ View cameraView = cameraViewId != null ? findViewById(cameraViewId) : null;
if (isChecked) {
cameraScannerProvider.pauseCamera(cameraView);
} else {
@@ -721,34 +1017,28 @@ private void displayToggleLedButton() {
}
- private void displayDisableScanButton() {
- View scannerTriggerOff = findViewById(R.id.scanner_trigger_off);
+ private void displaySwitchScanButton() {
+ View scannerTriggerOff = findViewById(R.id.scanner_trigger_on);
if (scannerTriggerOff != null) {
scannerTriggerOff.setVisibility(View.VISIBLE);
- scannerTriggerOff.setOnClickListener(view -> {
- for (final Scanner s : scannerService.getConnectedScanners()) {
- if (s.getTriggerSupport() != null)
- s.getTriggerSupport().releaseScanTrigger();
- }
- });
- }
- }
-
- private void displayEnableScanButton() {
- View scannerTriggerOnView = findViewById(R.id.scanner_trigger_on);
- if (scannerTriggerOnView!= null) {
- scannerTriggerOnView.setVisibility(View.VISIBLE);
- scannerTriggerOnView.setOnClickListener(view -> {
+ MaterialSwitch switchCompat = (MaterialSwitch) scannerTriggerOff;
+ switchCompat.setOnCheckedChangeListener((view, checked) -> {
for (final Scanner s : scannerService.getConnectedScanners()) {
- if (s.getTriggerSupport() != null)
- s.getTriggerSupport().pressScanTrigger();
+ if (s.getTriggerSupport() != null) {
+ if (checked) {
+ s.getTriggerSupport().pressScanTrigger();
+ } else {
+ s.getTriggerSupport().releaseScanTrigger();
+ }
+ }
}
});
}
}
+
private void displayBellButton() {
View scannerBellView = findViewById(R.id.scanner_bell);
@@ -762,4 +1052,84 @@ private void displayBellButton() {
});
}
}
-}
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Logger
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+
+ private boolean isExternalStorageWritable() {
+ String state = Environment.getExternalStorageState();
+ return Environment.MEDIA_MOUNTED.equals(state);
+ }
+
+ private void createLog() {
+ if (!isExternalStorageWritable()) {
+ return;
+ }
+
+ String fileName = "scans_scanner_test_" + (new Date()).getTime() + ".csv";
+
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("text/csv");
+ intent.putExtra(Intent.EXTRA_TITLE, fileName);
+ startActivityForResult(intent, WRITE_REQUEST_CODE);
+ }
+
+ private synchronized void writeResultToLog(Barcode data) {
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd_HHmmss");
+ String dataLine = formatter.format(new Date()) + "," + data.getBarcode() + "," + data.getBarcodeType().code;
+
+ try (OutputStream os = getContentResolver().openOutputStream(logFileUri, "wa")) {
+ if (os == null) {
+ return;
+ }
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, Charset.forName("UTF8")));
+ writer.write(dataLine, 0, dataLine.length());
+ writer.newLine();
+ writer.flush();
+ Log.d(LOG_TAG, dataLine);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ if (requestCode == WRITE_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
+ logFileUri = data.getData();
+ if (logFileUri != null) {
+ Log.i(LOG_TAG, "Log file will be written at: " + logFileUri.toString());
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ // Screen orientation
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public void onConfigurationChanged(@NonNull Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ boolean switchCamera = enableScan && goToCamera && hasPermissionSet(this, PERMISSIONS_CAMERA) && hasCameraScannerSdk;
+ int orientation = getResources().getConfiguration().orientation;
+ View view = findViewById(flashlightViewId).getRootView();
+
+ if (switchCamera) {
+ Integer cameraViewId = cameraResources.get("camera_view_id");
+
+ if (cameraViewId != null && cameraScannerProvider != null) {
+ cameraScannerProvider.orientationChanged(findViewById(cameraViewId));
+ }
+
+ ViewSwitcher.switchCameraOrientation(this, view, cameraResources, orientation == Configuration.ORIENTATION_PORTRAIT);
+ } else {
+ ViewSwitcher.switchLaserOrientation(this, view, flashlightViewId, orientation == Configuration.ORIENTATION_PORTRAIT);
+ }
+
+ resizeScannerLastText((TextView) findViewById(R.id.scanner_text_last_scan));
+ }
+}
\ No newline at end of file
diff --git a/enioka_scan/src/main/java/com/enioka/scanner/activities/ViewSwitcher.java b/enioka_scan/src/main/java/com/enioka/scanner/activities/ViewSwitcher.java
new file mode 100644
index 00000000..831870c0
--- /dev/null
+++ b/enioka_scan/src/main/java/com/enioka/scanner/activities/ViewSwitcher.java
@@ -0,0 +1,146 @@
+package com.enioka.scanner.activities;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.constraintlayout.widget.ConstraintSet;
+
+import com.enioka.scanner.R;
+
+import java.util.HashMap;
+
+/**
+ * An helper class to manage the dynamic switch of UI between portrait and landscape mode, for the
+ * camera and the laser activity.
+ */
+public class ViewSwitcher {
+ protected final static String LOG_TAG = "ScannerActivity";
+ public static void switchCameraOrientation(Context context, View view, HashMap cameraResources, boolean portrait) {
+ Integer constraintLayoutId = cameraResources.get("constraint_layout_id");
+ Integer scannerFlashlightId = cameraResources.get("scanner_flashlight_id");
+ Integer scannerBtKeyboardId = cameraResources.get("scanner_bt_provider_logs");
+ int openLinkBtId = view.getResources().getIdentifier("open_link", "id", context.getPackageName());
+
+ if (constraintLayoutId == null || scannerFlashlightId == null || scannerBtKeyboardId == null) {
+ Log.w(LOG_TAG, "Cannot switch to landscape mode: missing resources");
+ return;
+ }
+
+ ConstraintLayout constraintLayout = view.findViewById(constraintLayoutId);
+
+ ConstraintSet constraintSet = new ConstraintSet();
+ constraintSet.clone(constraintLayout);
+ int margin = context.getResources().getDimensionPixelSize(R.dimen.layout_margin_border);
+
+ // Set left constraints
+ if (portrait) {
+ constraintSet.connect(scannerFlashlightId, ConstraintSet.RIGHT, constraintLayout.getId(), ConstraintSet.RIGHT, margin);
+ constraintSet.connect(scannerBtKeyboardId, ConstraintSet.RIGHT, constraintLayout.getId(), ConstraintSet.RIGHT, margin);
+ constraintSet.connect(openLinkBtId, ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.LEFT, margin);
+
+ constraintSet.clear(scannerFlashlightId, ConstraintSet.LEFT);
+ constraintSet.clear(scannerBtKeyboardId, ConstraintSet.LEFT);
+ constraintSet.clear(openLinkBtId, ConstraintSet.RIGHT);
+ } else {
+ constraintSet.connect(scannerFlashlightId, ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.LEFT, margin);
+ constraintSet.connect(scannerBtKeyboardId, ConstraintSet.LEFT, constraintLayout.getId(), ConstraintSet.LEFT, margin);
+ constraintSet.connect(openLinkBtId, ConstraintSet.RIGHT, constraintLayout.getId(), ConstraintSet.RIGHT, margin);
+
+ constraintSet.clear(scannerFlashlightId, ConstraintSet.RIGHT);
+ constraintSet.clear(scannerBtKeyboardId, ConstraintSet.RIGHT);
+ constraintSet.clear(openLinkBtId, ConstraintSet.LEFT);
+ }
+
+ // Apply constraints
+ constraintSet.applyTo(constraintLayout);
+ }
+
+ public static void switchLaserOrientation(Context context, View view, int flashlightViewId, boolean portrait) {
+ ConstraintLayout mainConstraintLayout = view.findViewById(R.id.constraint_layout);
+ LinearLayout linearLayout = view.findViewById(R.id.bottom_layout);
+ View scannerFlashlight = view.findViewById(flashlightViewId);
+ View scannerBell = view.findViewById(R.id.scanner_bell);
+ View scannerRedLed = view.findViewById(R.id.scanner_red_led);
+ View buttonLogProvider = view.findViewById(R.id.scanner_bt_provider_logs);
+
+ if (portrait) {
+ // Move elements to main constraint layout
+ linearLayout.removeView(scannerFlashlight);
+ linearLayout.removeView(scannerBell);
+ linearLayout.removeView(scannerRedLed);
+
+ LinearLayout.LayoutParams oldParamsFlashLight = (LinearLayout.LayoutParams) scannerFlashlight.getLayoutParams();
+ LinearLayout.LayoutParams oldParamsBell = (LinearLayout.LayoutParams) scannerBell.getLayoutParams();
+ LinearLayout.LayoutParams oldParamsRedLed = (LinearLayout.LayoutParams) scannerRedLed.getLayoutParams();
+
+ ConstraintLayout.LayoutParams newParamsFlashLight = new ConstraintLayout.LayoutParams(oldParamsFlashLight.width, oldParamsFlashLight.height);
+ newParamsFlashLight.setMargins(oldParamsFlashLight.leftMargin, oldParamsFlashLight.topMargin, oldParamsFlashLight.rightMargin, oldParamsFlashLight.bottomMargin);
+
+ ConstraintLayout.LayoutParams newParamsBell = new ConstraintLayout.LayoutParams(oldParamsBell.width, oldParamsBell.height);
+ newParamsBell.setMargins(oldParamsBell.leftMargin, oldParamsBell.topMargin, oldParamsBell.rightMargin, oldParamsBell.bottomMargin);
+
+ ConstraintLayout.LayoutParams newParamsRedLed = new ConstraintLayout.LayoutParams(oldParamsRedLed.width, oldParamsRedLed.height);
+ newParamsRedLed.setMargins(oldParamsRedLed.leftMargin, oldParamsRedLed.topMargin, oldParamsRedLed.rightMargin, oldParamsRedLed.bottomMargin);
+
+ mainConstraintLayout.addView(scannerFlashlight, newParamsFlashLight);
+ mainConstraintLayout.addView(scannerBell, newParamsBell);
+ mainConstraintLayout.addView(scannerRedLed, newParamsRedLed);
+
+ // Apply constraints
+ ConstraintSet constraintSet = new ConstraintSet();
+ constraintSet.clone(mainConstraintLayout);
+
+ int margin = context.getResources().getDimensionPixelSize(R.dimen.layout_margin_border);
+
+ constraintSet.connect(scannerFlashlight.getId(), ConstraintSet.TOP, R.id.scanner_enable_text, ConstraintSet.BOTTOM, margin);
+ constraintSet.connect(scannerFlashlight.getId(), ConstraintSet.END, mainConstraintLayout.getId(), ConstraintSet.END, margin);
+
+ constraintSet.connect(scannerBell.getId(), ConstraintSet.TOP, scannerFlashlight.getId(), ConstraintSet.BOTTOM, margin);
+ constraintSet.connect(scannerBell.getId(), ConstraintSet.END, mainConstraintLayout.getId(), ConstraintSet.END, margin);
+
+ constraintSet.connect(scannerRedLed.getId(), ConstraintSet.TOP, scannerBell.getId(), ConstraintSet.BOTTOM, margin);
+ constraintSet.connect(scannerRedLed.getId(), ConstraintSet.END, mainConstraintLayout.getId(), ConstraintSet.END, margin);
+
+ constraintSet.applyTo(mainConstraintLayout);
+
+ // Apply constraints on show log button
+ LinearLayout.LayoutParams paramsLogButton = (LinearLayout.LayoutParams) buttonLogProvider.getLayoutParams();
+ paramsLogButton.width = LinearLayout.LayoutParams.WRAP_CONTENT;
+ paramsLogButton.weight = 0;
+
+ buttonLogProvider.setLayoutParams(paramsLogButton);
+ } else {
+ // Move elements to linear layout
+ mainConstraintLayout.removeView(scannerFlashlight);
+ mainConstraintLayout.removeView(scannerBell);
+ mainConstraintLayout.removeView(scannerRedLed);
+
+ ConstraintLayout.LayoutParams oldParamsFlashLight = (ConstraintLayout.LayoutParams) scannerFlashlight.getLayoutParams();
+ ConstraintLayout.LayoutParams oldParamsBell = (ConstraintLayout.LayoutParams) scannerBell.getLayoutParams();
+ ConstraintLayout.LayoutParams oldParamsRedLed = (ConstraintLayout.LayoutParams) scannerRedLed.getLayoutParams();
+
+ LinearLayout.LayoutParams newParamsFlashLight = new LinearLayout.LayoutParams(oldParamsFlashLight.width, oldParamsFlashLight.height);
+ newParamsFlashLight.setMargins(0, oldParamsFlashLight.topMargin, oldParamsFlashLight.rightMargin, oldParamsFlashLight.bottomMargin);
+
+ LinearLayout.LayoutParams newParamsBell = new LinearLayout.LayoutParams(oldParamsBell.width, oldParamsBell.height);
+ newParamsBell.setMargins(0, oldParamsBell.topMargin, oldParamsBell.rightMargin, oldParamsBell.bottomMargin);
+
+ LinearLayout.LayoutParams newParamsRedLed = new LinearLayout.LayoutParams(oldParamsRedLed.width, oldParamsRedLed.height);
+ newParamsRedLed.setMargins(0, oldParamsRedLed.topMargin, oldParamsRedLed.rightMargin, oldParamsRedLed.bottomMargin);
+
+ linearLayout.addView(scannerFlashlight, newParamsFlashLight);
+ linearLayout.addView(scannerBell, newParamsBell);
+ linearLayout.addView(scannerRedLed, newParamsRedLed);
+
+ // Apply constraints on show log button
+ LinearLayout.LayoutParams paramsLogButton = (LinearLayout.LayoutParams) buttonLogProvider.getLayoutParams();
+ paramsLogButton.width = 0;
+ paramsLogButton.weight = 1;
+
+ buttonLogProvider.setLayoutParams(paramsLogButton);
+ }
+ }
+}
diff --git a/enioka_scan/src/main/java/com/enioka/scanner/api/ScannerSearchOptions.java b/enioka_scan/src/main/java/com/enioka/scanner/api/ScannerSearchOptions.java
index 29fcbd30..492b70af 100644
--- a/enioka_scan/src/main/java/com/enioka/scanner/api/ScannerSearchOptions.java
+++ b/enioka_scan/src/main/java/com/enioka/scanner/api/ScannerSearchOptions.java
@@ -36,7 +36,7 @@ public class ScannerSearchOptions {
/**
* If true, providers using another application for controlling scanners will be allowed. This is important as most of the time, it is impossible to say if these apps are actually installed, and therefore it is impossible to detect the presence of an actual laser scanner or not.
*/
- public boolean allowIntentDevices = false;
+ public boolean allowIntentDevices = true;
/**
* If true, some providers may retrieve scanners after initial search.
@@ -51,7 +51,7 @@ public class ScannerSearchOptions {
/**
* If true, the providers which need a pairing done by their own SDKs (like a BLE on the fly pairing) will be allowed to do so.
*/
- public boolean allowPairingFlow = false;
+ public boolean allowPairingFlow = true;
/**
* Restrict search to this list of providers. Ignored if null or empty.
diff --git a/enioka_scan/src/main/java/com/enioka/scanner/sdk/camera/CameraScannerProvider.java b/enioka_scan/src/main/java/com/enioka/scanner/sdk/camera/CameraScannerProvider.java
index 6fac8372..76f90342 100644
--- a/enioka_scan/src/main/java/com/enioka/scanner/sdk/camera/CameraScannerProvider.java
+++ b/enioka_scan/src/main/java/com/enioka/scanner/sdk/camera/CameraScannerProvider.java
@@ -6,6 +6,7 @@
import com.enioka.scanner.api.proxies.ScannerStatusCallbackProxy;
import com.enioka.scanner.data.BarcodeType;
+import java.util.HashMap;
import java.util.Set;
/**
@@ -13,24 +14,18 @@
*/
public interface CameraScannerProvider {
/**
- * Returns the ID of the camera view in the layout.
+ * Returns hashmap of the ID resources.
+ * Contains the following keys:
+ * - layout_id_camera: The ID of the layout containing the camera view.
+ * - camera_view_id: The ID of the camera view in the layout.
+ * - scanner_toggle_view_id: The ID of the view that toggles the scanner library reader.
+ * - scanner_toggle_pause_id: The ID of the view that toggles the pause of the scanner.
+ * - card_last_scan_id: ID of the card view that displays the last scan.
+ * - constraint_layout_id: The ID of the constraint layout inside the camera layout.
+ * - scanner_flashlight_id: The ID of the optional ImageButton on which to press to toggle the flashlight/illumination.
+ * - scanner_bt_provider_logs: The ID of the optional ImageButton on which to press to manually access available providers logs
*/
- public int getCameraViewId();
-
- /**
- * Returns the ID of the layout containing the camera view.
- */
- public int getLayoutIdCamera();
-
- /**
- * Returns the ID of the view that toggles the scanner library reader.
- */
- public int getScannerToggleViewId();
-
- /**
- * Returns the ID of the view that toggles the pause of the scanner.
- */
- public int getScannerTogglePauseId();
+ public HashMap getIdResources();
/**
* Called to initialize the camera scanner with the given view and callbacks.
@@ -72,8 +67,20 @@ public interface CameraScannerProvider {
*/
public boolean isIlluminationOn();
+ /**
+ * Sets the preview ratio mode of the camera scanner.
+ */
+ public void setPreviewRatioMode(View cameraView, int previewRatioMode);
+
/**
* Sets the reader engine of the camera scanner.
*/
public void setReaderMode(View cameraView, boolean readerMode);
+
+ /**
+ * Some scanner devices get trouble with the camera when the orientation changes.
+ * This method should be called when the orientation changes.
+ * Mainly used for devices that are using CameraBarcodeScanViewV1 API.
+ */
+ public void orientationChanged(View cameraView);
}
diff --git a/enioka_scan/src/main/java/com/enioka/scanner/service/ScannerService.java b/enioka_scan/src/main/java/com/enioka/scanner/service/ScannerService.java
index bca55940..33d16c40 100644
--- a/enioka_scan/src/main/java/com/enioka/scanner/service/ScannerService.java
+++ b/enioka_scan/src/main/java/com/enioka/scanner/service/ScannerService.java
@@ -77,7 +77,7 @@ public class ScannerService extends Service implements ScannerConnectionHandler,
private Set symbologySelection = defaultSymbology();
public static Set defaultSymbology() {
- return new HashSet<>(Arrays.asList(BarcodeType.EAN13, BarcodeType.CODE128));
+ return new HashSet<>(Arrays.asList(BarcodeType.CODE128, BarcodeType.CODE39, BarcodeType.DIS25, BarcodeType.INT25, BarcodeType.EAN13, BarcodeType.QRCODE, BarcodeType.AZTEC));
}
public static Set defaultSymbologyByName() {
diff --git a/enioka_scan/src/main/res/drawable-anydpi-v24/ic_bell.xml b/enioka_scan/src/main/res/drawable-anydpi-v24/ic_bell.xml
deleted file mode 100644
index 8d7abdf1..00000000
--- a/enioka_scan/src/main/res/drawable-anydpi-v24/ic_bell.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
diff --git a/enioka_scan/src/main/res/drawable-hdpi/ic_arrow_down_drop_circle_grey600_24dp.png b/enioka_scan/src/main/res/drawable-hdpi/ic_arrow_down_drop_circle_grey600_24dp.png
deleted file mode 100644
index 0495abfd..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/ic_arrow_down_drop_circle_grey600_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/ic_bell.png b/enioka_scan/src/main/res/drawable-hdpi/ic_bell.png
deleted file mode 100644
index 80c574cc..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/ic_bell.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/ic_done_black_24dp.png b/enioka_scan/src/main/res/drawable-hdpi/ic_done_black_24dp.png
deleted file mode 100644
index d4c06072..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/ic_done_black_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/ic_photo.png b/enioka_scan/src/main/res/drawable-hdpi/ic_photo.png
deleted file mode 100644
index adfe2df8..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/ic_photo.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/icn_flash_off.png b/enioka_scan/src/main/res/drawable-hdpi/icn_flash_off.png
deleted file mode 100644
index 5deb311c..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/icn_flash_off.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/icn_flash_off_on.png b/enioka_scan/src/main/res/drawable-hdpi/icn_flash_off_on.png
deleted file mode 100644
index 16e8efbf..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/icn_flash_off_on.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/icn_keyboard.png b/enioka_scan/src/main/res/drawable-hdpi/icn_keyboard.png
deleted file mode 100644
index 4269326c..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/icn_keyboard.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/scan_active.png b/enioka_scan/src/main/res/drawable-hdpi/scan_active.png
deleted file mode 100644
index 8fa03fef..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/scan_active.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/scan_failure.png b/enioka_scan/src/main/res/drawable-hdpi/scan_failure.png
deleted file mode 100644
index 282544d3..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/scan_failure.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/scan_inactive.png b/enioka_scan/src/main/res/drawable-hdpi/scan_inactive.png
deleted file mode 100644
index 3f241bb4..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/scan_inactive.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-hdpi/scan_success.png b/enioka_scan/src/main/res/drawable-hdpi/scan_success.png
deleted file mode 100644
index 00bc68dd..00000000
Binary files a/enioka_scan/src/main/res/drawable-hdpi/scan_success.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/ic_arrow_down_drop_circle_grey600_24dp.png b/enioka_scan/src/main/res/drawable-mdpi/ic_arrow_down_drop_circle_grey600_24dp.png
deleted file mode 100644
index 79896874..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/ic_arrow_down_drop_circle_grey600_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/ic_bell.png b/enioka_scan/src/main/res/drawable-mdpi/ic_bell.png
deleted file mode 100644
index aeaa9e38..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/ic_bell.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/ic_done_black_24dp.png b/enioka_scan/src/main/res/drawable-mdpi/ic_done_black_24dp.png
deleted file mode 100644
index 5e5e7cf2..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/ic_done_black_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/ic_photo.png b/enioka_scan/src/main/res/drawable-mdpi/ic_photo.png
deleted file mode 100644
index d06760a3..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/ic_photo.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/icn_flash_off.png b/enioka_scan/src/main/res/drawable-mdpi/icn_flash_off.png
deleted file mode 100644
index d7d7a29d..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/icn_flash_off.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/icn_flash_off_on.png b/enioka_scan/src/main/res/drawable-mdpi/icn_flash_off_on.png
deleted file mode 100644
index 65425e23..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/icn_flash_off_on.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/scan_active.png b/enioka_scan/src/main/res/drawable-mdpi/scan_active.png
deleted file mode 100644
index 77211f59..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/scan_active.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/scan_failure.png b/enioka_scan/src/main/res/drawable-mdpi/scan_failure.png
deleted file mode 100644
index 795c1439..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/scan_failure.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/scan_inactive.png b/enioka_scan/src/main/res/drawable-mdpi/scan_inactive.png
deleted file mode 100644
index 3cbde625..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/scan_inactive.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-mdpi/scan_success.png b/enioka_scan/src/main/res/drawable-mdpi/scan_success.png
deleted file mode 100644
index caeb4293..00000000
Binary files a/enioka_scan/src/main/res/drawable-mdpi/scan_success.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/ic_arrow_down_drop_circle_grey600_24dp.png b/enioka_scan/src/main/res/drawable-xhdpi/ic_arrow_down_drop_circle_grey600_24dp.png
deleted file mode 100644
index e1cef8d4..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/ic_arrow_down_drop_circle_grey600_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/ic_bell.png b/enioka_scan/src/main/res/drawable-xhdpi/ic_bell.png
deleted file mode 100644
index 2e5a2143..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/ic_bell.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/ic_done_black_24dp.png b/enioka_scan/src/main/res/drawable-xhdpi/ic_done_black_24dp.png
deleted file mode 100644
index 64a4944f..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/ic_done_black_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/ic_photo.png b/enioka_scan/src/main/res/drawable-xhdpi/ic_photo.png
deleted file mode 100644
index 7f663495..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/ic_photo.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/icn_flash_off.png b/enioka_scan/src/main/res/drawable-xhdpi/icn_flash_off.png
deleted file mode 100644
index 6188229a..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/icn_flash_off.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/icn_flash_off_on.png b/enioka_scan/src/main/res/drawable-xhdpi/icn_flash_off_on.png
deleted file mode 100644
index 1dc83b55..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/icn_flash_off_on.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/icn_keyboard.png b/enioka_scan/src/main/res/drawable-xhdpi/icn_keyboard.png
deleted file mode 100644
index 5a146e6e..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/icn_keyboard.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/scan_active.png b/enioka_scan/src/main/res/drawable-xhdpi/scan_active.png
deleted file mode 100644
index c19691e2..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/scan_active.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/scan_failure.png b/enioka_scan/src/main/res/drawable-xhdpi/scan_failure.png
deleted file mode 100644
index b888c473..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/scan_failure.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/scan_inactive.png b/enioka_scan/src/main/res/drawable-xhdpi/scan_inactive.png
deleted file mode 100644
index 666b2f0d..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/scan_inactive.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xhdpi/scan_success.png b/enioka_scan/src/main/res/drawable-xhdpi/scan_success.png
deleted file mode 100644
index 0c6a7973..00000000
Binary files a/enioka_scan/src/main/res/drawable-xhdpi/scan_success.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/ic_arrow_down_drop_circle_grey600_24dp.png b/enioka_scan/src/main/res/drawable-xxhdpi/ic_arrow_down_drop_circle_grey600_24dp.png
deleted file mode 100644
index a34c58dc..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/ic_arrow_down_drop_circle_grey600_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/ic_bell.png b/enioka_scan/src/main/res/drawable-xxhdpi/ic_bell.png
deleted file mode 100644
index 25fcbe8c..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/ic_bell.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/ic_done_black_24dp.png b/enioka_scan/src/main/res/drawable-xxhdpi/ic_done_black_24dp.png
deleted file mode 100644
index c9c01741..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/ic_done_black_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/ic_photo.png b/enioka_scan/src/main/res/drawable-xxhdpi/ic_photo.png
deleted file mode 100644
index bff2437b..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/ic_photo.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/icn_flash_off.png b/enioka_scan/src/main/res/drawable-xxhdpi/icn_flash_off.png
deleted file mode 100644
index 1c693070..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/icn_flash_off.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/icn_flash_off_on.png b/enioka_scan/src/main/res/drawable-xxhdpi/icn_flash_off_on.png
deleted file mode 100644
index 0c465e3b..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/icn_flash_off_on.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/icn_keyboard.png b/enioka_scan/src/main/res/drawable-xxhdpi/icn_keyboard.png
deleted file mode 100644
index 080d1607..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/icn_keyboard.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/scan_active.png b/enioka_scan/src/main/res/drawable-xxhdpi/scan_active.png
deleted file mode 100644
index 01022553..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/scan_active.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/scan_failure.png b/enioka_scan/src/main/res/drawable-xxhdpi/scan_failure.png
deleted file mode 100644
index 83c6abae..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/scan_failure.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/scan_inactive.png b/enioka_scan/src/main/res/drawable-xxhdpi/scan_inactive.png
deleted file mode 100644
index 3682b95e..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/scan_inactive.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxhdpi/scan_success.png b/enioka_scan/src/main/res/drawable-xxhdpi/scan_success.png
deleted file mode 100644
index cf88ecf2..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxhdpi/scan_success.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/ic_arrow_down_drop_circle_grey600_24dp.png b/enioka_scan/src/main/res/drawable-xxxhdpi/ic_arrow_down_drop_circle_grey600_24dp.png
deleted file mode 100644
index 974e7f93..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/ic_arrow_down_drop_circle_grey600_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/ic_done_black_24dp.png b/enioka_scan/src/main/res/drawable-xxxhdpi/ic_done_black_24dp.png
deleted file mode 100644
index 2f6d6386..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/ic_done_black_24dp.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/icn_flash_off.png b/enioka_scan/src/main/res/drawable-xxxhdpi/icn_flash_off.png
deleted file mode 100644
index fa7c035c..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/icn_flash_off.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/icn_flash_off_on.png b/enioka_scan/src/main/res/drawable-xxxhdpi/icn_flash_off_on.png
deleted file mode 100644
index 8ba9be2b..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/icn_flash_off_on.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/icn_keyboard.png b/enioka_scan/src/main/res/drawable-xxxhdpi/icn_keyboard.png
deleted file mode 100644
index 43e987d2..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/icn_keyboard.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/scan_active.png b/enioka_scan/src/main/res/drawable-xxxhdpi/scan_active.png
deleted file mode 100644
index d82f02f8..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/scan_active.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/scan_failure.png b/enioka_scan/src/main/res/drawable-xxxhdpi/scan_failure.png
deleted file mode 100644
index e723b051..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/scan_failure.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/scan_inactive.png b/enioka_scan/src/main/res/drawable-xxxhdpi/scan_inactive.png
deleted file mode 100644
index 8699ff49..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/scan_inactive.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable-xxxhdpi/scan_success.png b/enioka_scan/src/main/res/drawable-xxxhdpi/scan_success.png
deleted file mode 100644
index 1e0873f4..00000000
Binary files a/enioka_scan/src/main/res/drawable-xxxhdpi/scan_success.png and /dev/null differ
diff --git a/enioka_scan/src/main/res/drawable/bell.xml b/enioka_scan/src/main/res/drawable/bell.xml
new file mode 100644
index 00000000..181398cd
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/bell.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/bell_slash.xml b/enioka_scan/src/main/res/drawable/bell_slash.xml
new file mode 100644
index 00000000..328e1c71
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/bell_slash.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/bug.xml b/enioka_scan/src/main/res/drawable/bug.xml
new file mode 100644
index 00000000..b9d33dac
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/bug.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/camera2.xml b/enioka_scan/src/main/res/drawable/camera2.xml
new file mode 100644
index 00000000..e0d28c8a
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/camera2.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/camera_fill.xml b/enioka_scan/src/main/res/drawable/camera_fill.xml
new file mode 100644
index 00000000..c27c379a
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/camera_fill.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/done.xml b/enioka_scan/src/main/res/drawable/done.xml
new file mode 100644
index 00000000..0ccd6c27
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/done.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/flash.xml b/enioka_scan/src/main/res/drawable/flash.xml
new file mode 100644
index 00000000..762ecc52
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/flash.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/flash_off.xml b/enioka_scan/src/main/res/drawable/flash_off.xml
new file mode 100644
index 00000000..120fa31a
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/flash_off.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/flashlight.xml b/enioka_scan/src/main/res/drawable/flashlight.xml
new file mode 100644
index 00000000..81833b7d
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/flashlight.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/flashlight_off.xml b/enioka_scan/src/main/res/drawable/flashlight_off.xml
new file mode 100644
index 00000000..6fa0f8dc
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/flashlight_off.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/info.xml b/enioka_scan/src/main/res/drawable/info.xml
new file mode 100644
index 00000000..fcbcba41
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/info.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/keyboard_fill.xml b/enioka_scan/src/main/res/drawable/keyboard_fill.xml
new file mode 100644
index 00000000..56369d19
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/keyboard_fill.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/lightbulb.xml b/enioka_scan/src/main/res/drawable/lightbulb.xml
new file mode 100644
index 00000000..60d17bc9
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/lightbulb.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/lightbulb_off.xml b/enioka_scan/src/main/res/drawable/lightbulb_off.xml
new file mode 100644
index 00000000..ce901f6c
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/lightbulb_off.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/open_link.xml b/enioka_scan/src/main/res/drawable/open_link.xml
new file mode 100644
index 00000000..735fe72d
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/open_link.xml
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/pause_fill.xml b/enioka_scan/src/main/res/drawable/pause_fill.xml
new file mode 100644
index 00000000..5b856b7f
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/pause_fill.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/upc.xml b/enioka_scan/src/main/res/drawable/upc.xml
new file mode 100644
index 00000000..9a6caba5
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/upc.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/drawable/upc_scan.xml b/enioka_scan/src/main/res/drawable/upc_scan.xml
new file mode 100644
index 00000000..530c2e9f
--- /dev/null
+++ b/enioka_scan/src/main/res/drawable/upc_scan.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/enioka_scan/src/main/res/layout/activity_main.xml b/enioka_scan/src/main/res/layout/activity_main.xml
index 01bb416d..897e1fad 100644
--- a/enioka_scan/src/main/res/layout/activity_main.xml
+++ b/enioka_scan/src/main/res/layout/activity_main.xml
@@ -2,113 +2,186 @@
-
+ android:layout_height="55dp"
+ android:layout_marginTop="10dp"
+ android:layout_marginStart="12dp"
+ android:layout_marginEnd="12dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:cardBackgroundColor="@color/cardBackgroundColor"
+ app:cardCornerRadius="12dp">
+
+
+
+
+ app:layout_constraintBottom_toTopOf="@+id/bottom_layout"
+ app:layout_constraintTop_toBottomOf="@+id/scanner_card_last_scan"/>
-
+ android:gravity="center"
+ app:cardBackgroundColor="@color/cardBackgroundDone"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/scanner_provider_text">
-
+
-
+
-
+
+
+
+
+
+
+
+ app:icon="@drawable/open_link"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/scanner_card_last_scan" />
-
+ app:layout_constraintTop_toBottomOf="@id/open_link"
+ app:thumbIcon="@drawable/upc" />
-
-
+
+
+ app:layout_constraintTop_toBottomOf="@id/scanner_flashlight"
+ app:tint="@android:color/black"
+ android:contentDescription="@string/fab_scanner_bell" />
+
diff --git a/enioka_scan/src/main/res/layout/dropdown_item.xml b/enioka_scan/src/main/res/layout/dropdown_item.xml
index d20f0145..11d8813b 100644
--- a/enioka_scan/src/main/res/layout/dropdown_item.xml
+++ b/enioka_scan/src/main/res/layout/dropdown_item.xml
@@ -1,5 +1,6 @@
@@ -22,7 +23,7 @@
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
- android:src="@drawable/ic_done_black_24dp"/>
+ app:srcCompat="@drawable/done"/>
-
+ style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu">
+
+
+
+
+
+
-
-
-
Veuillez vérifier qu\'aucune autre application n\'utilise la caméra (comme ScanWedge, DataWedge…). Vérifiez aussi que la caméra fnction dans l\'application idoine.
Impossible de se connecter à la caméra
+ Scanner status
10AL9271B2I8
Initialisation du scanner non commencée
EniokaScan
@@ -33,6 +34,23 @@
Saisie manuelle
Aucun scanner compatible n\'est disponible sur cet appareil
Service d\'assistance à la gestion des scanners
- ZXing
+ Zbar / ZXing
+ Utilisation du lecteur ZXing !
+ Utilisation du lecteur ZBar !
Pause
+ Camera
+ Logs
+ Logs des scanneurs
+ Fermer
+ Activer le scan
+ Ouvrir le lien
+ Dernier scan copié avec succès dans le presse-papiers !
+ Signaler un bug
+
+
+ lumiere flash
+ logs des scanneurs disponibles
+ activation de la lumiere du scanneur
+ activation de la cloche
+ activation de la lumiere rouge du scanneur
\ No newline at end of file
diff --git a/enioka_scan/src/main/res/values/colors.xml b/enioka_scan/src/main/res/values/colors.xml
index b5605e7d..acfad3c2 100644
--- a/enioka_scan/src/main/res/values/colors.xml
+++ b/enioka_scan/src/main/res/values/colors.xml
@@ -3,8 +3,11 @@
#3F51B5
#303F9F
#FF4081
- #ffe100
+ #C6D118
#00b41b
+ #A8FFB5
#808080
#FF0000
+ #373737
+ #EADDFF
diff --git a/enioka_scan/src/main/res/values/dimen.xml b/enioka_scan/src/main/res/values/dimen.xml
new file mode 100644
index 00000000..108f6d88
--- /dev/null
+++ b/enioka_scan/src/main/res/values/dimen.xml
@@ -0,0 +1,5 @@
+
+
+ 12dp
+ 10sp
+
\ No newline at end of file
diff --git a/enioka_scan/src/main/res/values/strings.xml b/enioka_scan/src/main/res/values/strings.xml
index 4e03314f..f342d95f 100644
--- a/enioka_scan/src/main/res/values/strings.xml
+++ b/enioka_scan/src/main/res/values/strings.xml
@@ -30,16 +30,34 @@
No fallback camera available on device. Please plugin your laser barcode scanner and restart application. Application will now crash.
+ Scanner state
10AL9271B2I8
Scanner initialization not started
Using Bluetooth scanner or keyboard
There are no compatible scanners on this device
- ZXing
+ Zbar / ZXing
+ Using ZXing camera reader !
+ Using ZBar camera reader !
Pause
+ Camera
+ Last scan successfully copied to clipboard !
Manual input
Please enter the barcode value, then select one item among the results
0000000000
Send
+ Logs
+ Provider logs
+ Close
+ enable scan
+ Open link
+ Report bug
+
+
+ flash light
+ available provider logs
+ scanner flashlight activation
+ scanner bell activation
+ scanner red light activation
diff --git a/enioka_scan/src/main/res/values/styles.xml b/enioka_scan/src/main/res/values/styles.xml
new file mode 100644
index 00000000..c98be290
--- /dev/null
+++ b/enioka_scan/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/enioka_scan_athesi_rd50te/build.gradle b/enioka_scan_athesi_rd50te/build.gradle
index e47cbe25..9ac03a5b 100644
--- a/enioka_scan_athesi_rd50te/build.gradle
+++ b/enioka_scan_athesi_rd50te/build.gradle
@@ -9,6 +9,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_athesi_spa43lte/build.gradle b/enioka_scan_athesi_spa43lte/build.gradle
index b1e30b49..7492ba48 100644
--- a/enioka_scan_athesi_spa43lte/build.gradle
+++ b/enioka_scan_athesi_spa43lte/build.gradle
@@ -9,6 +9,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_bluebird/build.gradle b/enioka_scan_bluebird/build.gradle
index 98e3dd77..6c280f68 100644
--- a/enioka_scan_bluebird/build.gradle
+++ b/enioka_scan_bluebird/build.gradle
@@ -9,6 +9,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_camera/build.gradle b/enioka_scan_camera/build.gradle
index a35a6872..8c450332 100644
--- a/enioka_scan_camera/build.gradle
+++ b/enioka_scan_camera/build.gradle
@@ -8,6 +8,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
@@ -31,6 +32,7 @@ dependencies {
implementation project(':enioka_scan')
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
+ implementation 'com.google.android.material:material:1.12.0'
// ZBAR & ZXING (Zebra Crossing) = camera. From Maven Central.
api('me.dm7.barcodescanner:zbar:1.9.8') {
diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanView.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanView.java
index 5f88600f..728f2f8d 100644
--- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanView.java
+++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanView.java
@@ -124,6 +124,13 @@ public interface ResultHandler {
void handleScanResult(String result, BarcodeType type);
}
+ /**
+ * Set the camera preview ratio mode.
+ */
+ public void setPreviewRatioMode(int mode) {
+ this.proxiedView.setPreviewRatioMode(mode);
+ }
+
public void setReaderMode(CameraReader readerMode) {
this.proxiedView.setReaderMode(readerMode);
}
@@ -185,6 +192,15 @@ public void resetTargetPosition() {
this.proxiedView.resetTargetPosition();
}
+ /**
+ * Some scanner devices get trouble with the camera when the orientation changes.
+ * This method should be called when the orientation changes.
+ * Mainly used for devices that are using CameraBarcodeScanViewV1 API.
+ */
+ public void orientationChanged() {
+ this.proxiedView.orientationChanged();
+ }
+
/**
* Get the JPEG data of the image used in the latest successful scan.
*
diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewBase.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewBase.java
index a87e0344..e84a635f 100644
--- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewBase.java
+++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewBase.java
@@ -66,6 +66,7 @@ abstract class CameraBarcodeScanViewBase extends FrameLayout implements Scann
protected SurfaceView camPreviewSurfaceView;
protected TargetView targetView;
protected final TypedArray styledAttributes;
+ protected int aspectRatioMode;
public CameraBarcodeScanViewBase(@NonNull Context context) {
@@ -97,6 +98,7 @@ public CameraBarcodeScanViewBase(@NonNull Context context, @Nullable AttributeSe
this.resolution.minResolutionY = styledAttributes.getInteger(R.styleable.CameraBarcodeScanView_minResolutionY, 720);
this.resolution.maxResolutionY = styledAttributes.getInteger(R.styleable.CameraBarcodeScanView_maxResolutionY, 1080);
this.resolution.maxDistortionRatio = styledAttributes.getFloat(R.styleable.CameraBarcodeScanView_maxDistortionRatio, 0.3f);
+ this.aspectRatioMode = styledAttributes.getInt(R.styleable.CameraBarcodeScanView_previewRatioMode, 0);
initLayout();
}
@@ -134,6 +136,20 @@ protected void initializeFrameAnalyzerIfNeeded() {
// Public API, various setters
////////////////////////////////////////////////////////////////////////////////////////////////
+ public void setPreviewRatioMode(int mode) {
+ // If preview ratio mode is not defined, use the default value
+ if (mode == -1) {
+ return;
+ }
+
+ if (this.camPreviewSurfaceView == null) {
+ aspectRatioMode = mode;
+ return;
+ }
+
+ ((CameraPreviewSurfaceView) this.camPreviewSurfaceView).setPreviewRatioMode(mode);
+ }
+
public void setReaderMode(CameraReader readerMode) {
this.readerMode = readerMode;
reinitialiseFrameAnalyser();
@@ -171,6 +187,8 @@ public void setTorch(boolean value) {
public abstract void resumeCamera();
+ public abstract void orientationChanged();
+
/**
* Indicate if the torch mode is handled or not
*
@@ -230,7 +248,7 @@ protected void initLayout() {
// The view holding the preview. This will in turn (camHolder.addCallback) call setUpCamera.
if (this.camPreviewSurfaceView == null) {
- camPreviewSurfaceView = new CameraPreviewSurfaceView(getContext(), styledAttributes, this);
+ camPreviewSurfaceView = new CameraPreviewSurfaceView(getContext(), aspectRatioMode, this);
FrameLayout.LayoutParams prms = this.generateDefaultLayoutParams();
prms.gravity = Gravity.CENTER;
camPreviewSurfaceView.setLayoutParams(prms);
@@ -355,14 +373,16 @@ protected void addTargetView() {
}
public void resetTargetPosition() {
- final boolean saveAllowTargetDrag = allowTargetDrag;
- allowTargetDrag = false;
- computeCropRectangle();
- allowTargetDrag = saveAllowTargetDrag;
-
- final FrameLayout.LayoutParams prms = (LayoutParams) targetView.getLayoutParams();
- prms.topMargin = cropRect.top;
- targetView.setLayoutParams(prms);
+ if (targetView != null) {
+ final boolean saveAllowTargetDrag = allowTargetDrag;
+ allowTargetDrag = false;
+ computeCropRectangle();
+ allowTargetDrag = saveAllowTargetDrag;
+
+ final FrameLayout.LayoutParams prms = (LayoutParams) targetView.getLayoutParams();
+ prms.topMargin = cropRect.top;
+ targetView.setLayoutParams(prms);
+ }
}
/**
diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewV1.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewV1.java
index 53523ac9..7a0d3c0d 100644
--- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewV1.java
+++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewV1.java
@@ -421,6 +421,21 @@ void setTorchInternal(boolean value) {
setCameraParameters(prms);
}
+ /**
+ * Some scanner devices get trouble with the camera when the orientation changes.
+ * This method should be called when the orientation changes.
+ * Mainly used for devices that are using CameraBarcodeScanViewV1 API.
+ */
+ @Override
+ public void orientationChanged() {
+ if (this.cam == null) {
+ Log.w(VIEW_LOG_TAG, "orientationChanged: No camera instance, make sure camera was properly initialized and `cleanup()` or `closeCamera()` were not called previously");
+ return;
+ }
+
+ this.cam.setDisplayOrientation(getCameraDisplayOrientation());
+ }
+
// torch
////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewV2.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewV2.java
index dd097aff..7cc15986 100644
--- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewV2.java
+++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewV2.java
@@ -515,6 +515,16 @@ void setTorchInternal(boolean value) {
}
}
+ /**
+ * Some scanner devices get trouble with the camera when the orientation changes.
+ * This method should be called when the orientation changes.
+ * Mainly used for devices that are using CameraBarcodeScanViewV1 API.
+ */
+ @Override
+ public void orientationChanged() {
+ // Do nothing;
+ }
+
///////////////////////////////////////////////////////////////////////////
// Background thread for handling camera-related events
///////////////////////////////////////////////////////////////////////////
diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraPreviewSurfaceView.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraPreviewSurfaceView.java
index 65bb8e4e..577400f2 100644
--- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraPreviewSurfaceView.java
+++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraPreviewSurfaceView.java
@@ -17,7 +17,7 @@
*/
class CameraPreviewSurfaceView extends SurfaceView {
private final Callback parent;
- private final boolean respectCameraRatio;
+ private boolean respectCameraRatio;
interface Callback extends SurfaceHolder.Callback {
Point getCurrentCameraResolution();
@@ -25,14 +25,19 @@ interface Callback extends SurfaceHolder.Callback {
int getCameraOrientationRelativeToDeviceNaturalOrientation();
int getDeviceOrientationRelativeToDeviceNaturalOrientation();
+
+ void resetTargetPosition();
}
- public CameraPreviewSurfaceView(Context context, TypedArray styledAttributes, Callback parent) {
+ public CameraPreviewSurfaceView(Context context, int aspectRatioMode, Callback parent) {
super(context);
this.parent = parent;
- int rm = styledAttributes.getInt(R.styleable.CameraBarcodeScanView_previewRatioMode, 0);
- respectCameraRatio = rm == 1;
+ respectCameraRatio = aspectRatioMode == 1;
+ }
+
+ protected void setPreviewRatioMode(int respectCameraRatio) {
+ this.respectCameraRatio = respectCameraRatio == 1;
}
@Override
@@ -62,5 +67,6 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension((int) (parentImposedHeightPx * dataRatio), parentImposedHeightPx);
}
}
+ parent.resetTargetPosition();
}
}
diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraProvider.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraProvider.java
index 9e8757b6..3d27a4db 100644
--- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraProvider.java
+++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraProvider.java
@@ -6,6 +6,7 @@
import com.enioka.scanner.api.proxies.ScannerStatusCallbackProxy;
import com.enioka.scanner.data.BarcodeType;
+import java.util.HashMap;
import java.util.Set;
/**
@@ -18,23 +19,18 @@ public class CameraProvider implements CameraScannerProvider {
protected CameraBarcodeScanViewScanner cameraScanner;
@Override
- public int getCameraViewId() {
- return R.id.camera_scan_view;
- }
-
- @Override
- public int getLayoutIdCamera() {
- return R.layout.activity_main_alt;
- }
-
- @Override
- public int getScannerToggleViewId() {
- return R.id.scanner_switch_zxing;
- }
-
- @Override
- public int getScannerTogglePauseId() {
- return R.id.scanner_switch_pause;
+ public HashMap getIdResources() {
+ HashMap idResources = new HashMap<>();
+ idResources.put("camera_view_id", R.id.camera_scan_view);
+ idResources.put("layout_id_camera", R.layout.activity_camera);
+ idResources.put("scanner_toggle_view_id", R.id.scanner_switch_zxing);
+ idResources.put("scanner_toggle_pause_id", R.id.scanner_switch_pause);
+ idResources.put("card_last_scan_id", R.id.card_camera_last_scan);
+ idResources.put("constraint_layout_id", R.id.constraint_layout_main_activity);
+ idResources.put("scanner_flashlight_id", R.id.scanner_flashlight);
+ idResources.put("scanner_bt_provider_logs", R.id.scanner_bt_provider_logs);
+
+ return idResources;
}
@Override
@@ -90,6 +86,15 @@ public boolean isIlluminationOn() {
return this.cameraScanner.isIlluminationOn();
}
+ @Override
+ public void setPreviewRatioMode(View cameraView, int previewRatioMode) {
+ if (cameraView instanceof CameraBarcodeScanView) {
+ ((CameraBarcodeScanView) cameraView).setPreviewRatioMode(previewRatioMode);
+ } else {
+ throw new IllegalArgumentException("cameraView must be an instance of CameraBarcodeScanView");
+ }
+ }
+
@Override
public void setReaderMode(View cameraView, boolean readerMode) {
if (cameraView instanceof CameraBarcodeScanView) {
@@ -98,4 +103,13 @@ public void setReaderMode(View cameraView, boolean readerMode) {
throw new IllegalArgumentException("cameraView must be an instance of CameraBarcodeScanView");
}
}
+
+ @Override
+ public void orientationChanged(View cameraView) {
+ if (cameraView instanceof CameraBarcodeScanView) {
+ ((CameraBarcodeScanView) cameraView).orientationChanged();
+ } else {
+ throw new IllegalArgumentException("cameraView must be an instance of CameraBarcodeScanView");
+ }
+ }
}
diff --git a/enioka_scan_camera/src/main/res/drawable/text_background.xml b/enioka_scan_camera/src/main/res/drawable/text_background.xml
new file mode 100644
index 00000000..bd4d6e76
--- /dev/null
+++ b/enioka_scan_camera/src/main/res/drawable/text_background.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/enioka_scan_camera/src/main/res/layout/activity_camera.xml b/enioka_scan_camera/src/main/res/layout/activity_camera.xml
new file mode 100644
index 00000000..e4e5f774
--- /dev/null
+++ b/enioka_scan_camera/src/main/res/layout/activity_camera.xml
@@ -0,0 +1,201 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/enioka_scan_camera/src/main/res/layout/activity_main_alt.xml b/enioka_scan_camera/src/main/res/layout/activity_main_alt.xml
deleted file mode 100644
index 80161096..00000000
--- a/enioka_scan_camera/src/main/res/layout/activity_main_alt.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/enioka_scan_generalscan/build.gradle b/enioka_scan_generalscan/build.gradle
index 61246f1e..978db4e6 100644
--- a/enioka_scan_generalscan/build.gradle
+++ b/enioka_scan_generalscan/build.gradle
@@ -9,6 +9,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_honeywelloss_integrated/build.gradle b/enioka_scan_honeywelloss_integrated/build.gradle
index c703131f..a601d4f0 100644
--- a/enioka_scan_honeywelloss_integrated/build.gradle
+++ b/enioka_scan_honeywelloss_integrated/build.gradle
@@ -9,6 +9,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_honeywelloss_spp/build.gradle b/enioka_scan_honeywelloss_spp/build.gradle
index dbdd2075..2c86347d 100644
--- a/enioka_scan_honeywelloss_spp/build.gradle
+++ b/enioka_scan_honeywelloss_spp/build.gradle
@@ -9,6 +9,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_mock/build.gradle b/enioka_scan_mock/build.gradle
index 5837c3af..ab1a65ec 100644
--- a/enioka_scan_mock/build.gradle
+++ b/enioka_scan_mock/build.gradle
@@ -6,6 +6,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_postech/build.gradle b/enioka_scan_postech/build.gradle
index 882ad998..6152101e 100644
--- a/enioka_scan_postech/build.gradle
+++ b/enioka_scan_postech/build.gradle
@@ -8,6 +8,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_proglove/build.gradle b/enioka_scan_proglove/build.gradle
index dfd446ef..0423dfca 100644
--- a/enioka_scan_proglove/build.gradle
+++ b/enioka_scan_proglove/build.gradle
@@ -9,6 +9,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_zebra_dw/build.gradle b/enioka_scan_zebra_dw/build.gradle
index b194ce8f..025082d3 100644
--- a/enioka_scan_zebra_dw/build.gradle
+++ b/enioka_scan_zebra_dw/build.gradle
@@ -8,6 +8,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {
diff --git a/enioka_scan_zebraoss/build.gradle b/enioka_scan_zebraoss/build.gradle
index f44fc458..446637c2 100644
--- a/enioka_scan_zebraoss/build.gradle
+++ b/enioka_scan_zebraoss/build.gradle
@@ -8,6 +8,7 @@ android {
minSdkVersion 19
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ multiDexEnabled true
}
buildTypes {
release {