Skip to content

Commit c5bb62d

Browse files
committed
Improved workflow when selecting high res srabilization to ensure that all parameters are set correctly for this mode (debounce, static resolution < 12MP)
1 parent 56009a7 commit c5bb62d

File tree

3 files changed

+249
-2
lines changed

3 files changed

+249
-2
lines changed

AI_MultiBarcodes_Capture/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ android {
1414
applicationId = "com.zebra.ai_multibarcodes_capture.dev"
1515
minSdk = 34
1616
targetSdk = 35
17-
versionCode = 42
18-
versionName = "1.42"
17+
versionCode = 43
18+
versionName = "1.43"
1919

2020
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2121

AI_MultiBarcodes_Capture/src/main/java/com/zebra/ai_multibarcodes_capture/settings/SettingsActivity.java

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import com.zebra.datawedgeprofileintents.DWScannerPluginEnable;
6363
import com.zebra.datawedgeprofileintentshelpers.CreateProfileHelper;
6464

65+
import androidx.appcompat.app.AlertDialog;
6566
import androidx.appcompat.app.AppCompatActivity;
6667
import androidx.appcompat.widget.Toolbar;
6768
import androidx.core.view.ViewCompat;
@@ -416,6 +417,9 @@ public void onClick(View v) {
416417
// Setup debounce listeners
417418
setupDebounceListeners();
418419

420+
// Setup high-res stabilization listener
421+
setupHighResStabilizationListener();
422+
419423
findViewById(R.id.btCancel).setOnClickListener(new View.OnClickListener() {
420424
@Override
421425
public void onClick(View view) {
@@ -1722,13 +1726,241 @@ private void loadHighResStabilization(SharedPreferences sharedPreferences) {
17221726
boolean highResStabilizationEnabled = sharedPreferences.getBoolean(
17231727
SHARED_PREFERENCES_HIGH_RES_STABILIZATION_ENABLED,
17241728
SHARED_PREFERENCES_HIGH_RES_STABILIZATION_ENABLED_DEFAULT);
1729+
1730+
// Temporarily remove listener to prevent dialog from showing during load
1731+
cbHighResStabilization.setOnCheckedChangeListener(null);
17251732
cbHighResStabilization.setChecked(highResStabilizationEnabled);
1733+
// Restore listener
1734+
setupHighResStabilizationListener();
1735+
1736+
// Update high resolution options state based on loaded setting
1737+
updateHighResolutionOptionsState(highResStabilizationEnabled);
17261738
}
17271739

17281740
private void saveHighResStabilization(SharedPreferences.Editor editor) {
17291741
editor.putBoolean(SHARED_PREFERENCES_HIGH_RES_STABILIZATION_ENABLED, cbHighResStabilization.isChecked());
17301742
}
17311743

1744+
private void setupHighResStabilizationListener() {
1745+
cbHighResStabilization.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
1746+
@Override
1747+
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1748+
if (isChecked) {
1749+
// Check if debounce is disabled
1750+
checkDebounceForHighResStabilization();
1751+
// Disable high resolutions (>8MP) when high-res stabilization is enabled
1752+
updateHighResolutionOptionsState(true);
1753+
} else {
1754+
// Re-enable high resolutions when high-res stabilization is disabled
1755+
updateHighResolutionOptionsState(false);
1756+
}
1757+
}
1758+
});
1759+
}
1760+
1761+
/**
1762+
* Updates the state of high resolution options (>8MP) based on high-res stabilization state.
1763+
* When high-res stabilization is enabled, resolutions above 8MP are disabled to ensure
1764+
* consistent coordinate mapping between preview and high-res capture.
1765+
*
1766+
* @param disableHighRes true to disable resolutions >8MP, false to re-enable them
1767+
*/
1768+
private void updateHighResolutionOptionsState(boolean disableHighRes) {
1769+
// Disable/enable dynamic resolution mode
1770+
// When high-res stabilization is enabled, only static resolution mode is available
1771+
if (spinnerResolutionMode != null) {
1772+
spinnerResolutionMode.setEnabled(!disableHighRes);
1773+
spinnerResolutionMode.setAlpha(disableHighRes ? 0.5f : 1.0f);
1774+
1775+
// If disabling dynamic mode and it's currently selected, switch to static
1776+
if (disableHighRes && spinnerResolutionMode.getSelectedItemPosition() == 1) {
1777+
spinnerResolutionMode.setSelection(0);
1778+
updateResolutionModeVisibility(0);
1779+
}
1780+
}
1781+
1782+
// Disable/enable 12MP and higher resolutions (only applicable in static mode)
1783+
if (rb12MPResolution != null) {
1784+
rb12MPResolution.setEnabled(!disableHighRes);
1785+
rb12MPResolution.setAlpha(disableHighRes ? 0.5f : 1.0f);
1786+
}
1787+
if (rb12_5MPResolution != null) {
1788+
rb12_5MPResolution.setEnabled(!disableHighRes);
1789+
rb12_5MPResolution.setAlpha(disableHighRes ? 0.5f : 1.0f);
1790+
}
1791+
if (rb12_6MPResolution != null) {
1792+
rb12_6MPResolution.setEnabled(!disableHighRes);
1793+
rb12_6MPResolution.setAlpha(disableHighRes ? 0.5f : 1.0f);
1794+
}
1795+
1796+
// If disabling and one of the high resolutions is currently selected, fall back to 8MP or lower
1797+
if (disableHighRes) {
1798+
boolean needsFallback = (rb12MPResolution != null && rb12MPResolution.isChecked()) ||
1799+
(rb12_5MPResolution != null && rb12_5MPResolution.isChecked()) ||
1800+
(rb12_6MPResolution != null && rb12_6MPResolution.isChecked());
1801+
1802+
if (needsFallback) {
1803+
// Select the highest available resolution <= 8MP
1804+
if (rb8MPResolution != null && rb8MPResolution.getVisibility() == View.VISIBLE) {
1805+
rb8MPResolution.setChecked(true);
1806+
} else if (rb4MPResolution != null && rb4MPResolution.getVisibility() == View.VISIBLE) {
1807+
rb4MPResolution.setChecked(true);
1808+
} else if (rb2MPResolution != null && rb2MPResolution.getVisibility() == View.VISIBLE) {
1809+
rb2MPResolution.setChecked(true);
1810+
} else if (rb1MPResolution != null && rb1MPResolution.getVisibility() == View.VISIBLE) {
1811+
rb1MPResolution.setChecked(true);
1812+
}
1813+
}
1814+
}
1815+
}
1816+
1817+
private void checkDebounceForHighResStabilization() {
1818+
if (!cbDebounceEnabled.isChecked()) {
1819+
// Show warning dialog for debounce
1820+
new AlertDialog.Builder(this)
1821+
.setTitle(getString(R.string.high_res_debounce_warning_title))
1822+
.setMessage(getString(R.string.high_res_debounce_warning_message))
1823+
.setNegativeButton(getString(R.string.cancel), (dialog, which) -> {
1824+
// Cancel - uncheck high-res stabilization
1825+
cbHighResStabilization.setOnCheckedChangeListener(null);
1826+
cbHighResStabilization.setChecked(false);
1827+
setupHighResStabilizationListener();
1828+
dialog.dismiss();
1829+
})
1830+
.setNeutralButton(getString(R.string.enable_debounce), (dialog, which) -> {
1831+
// Enable debounce with current settings
1832+
cbDebounceEnabled.setChecked(true);
1833+
updateDebounceUIState(true);
1834+
dialog.dismiss();
1835+
// Continue to check resolution mode
1836+
checkResolutionModeForHighResStabilization();
1837+
})
1838+
.setPositiveButton(getString(R.string.enable_debounce_recommended), (dialog, which) -> {
1839+
// Enable debounce with recommended settings
1840+
applyRecommendedDebounceSettings();
1841+
dialog.dismiss();
1842+
// Continue to check resolution mode
1843+
checkResolutionModeForHighResStabilization();
1844+
})
1845+
.setCancelable(false)
1846+
.show();
1847+
} else {
1848+
// Debounce is already enabled, check resolution mode
1849+
checkResolutionModeForHighResStabilization();
1850+
}
1851+
}
1852+
1853+
private void applyRecommendedDebounceSettings() {
1854+
// Enable debounce
1855+
cbDebounceEnabled.setChecked(true);
1856+
updateDebounceUIState(true);
1857+
1858+
// Set algorithm to IOU (index 1)
1859+
spinnerDebounceAlgorithm.setSelection(1);
1860+
updateDebounceAlgorithmVisibility(1);
1861+
1862+
// Set max frames to 30
1863+
sbDebounceMaxFrames.setProgress(30);
1864+
tvDebounceMaxFramesValue.setText(getString(R.string.debounce_max_frames_value, 30));
1865+
1866+
// Set IOU threshold to 20 (0.2)
1867+
sbDebounceIouThreshold.setProgress(20);
1868+
float iouValue = 20 / 100.0f;
1869+
tvDebounceIouThresholdValue.setText(String.format(getString(R.string.debounce_iou_threshold_value), iouValue));
1870+
}
1871+
1872+
private void checkResolutionModeForHighResStabilization() {
1873+
// Check if resolution mode is dynamic (position 1)
1874+
int modePosition = spinnerResolutionMode.getSelectedItemPosition();
1875+
if (modePosition == 1) {
1876+
// Show warning dialog for dynamic resolution
1877+
new AlertDialog.Builder(this)
1878+
.setTitle(getString(R.string.high_res_dynamic_warning_title))
1879+
.setMessage(getString(R.string.high_res_dynamic_warning_message))
1880+
.setNegativeButton(getString(R.string.cancel), (dialog, which) -> {
1881+
// Cancel - uncheck high-res stabilization
1882+
cbHighResStabilization.setOnCheckedChangeListener(null);
1883+
cbHighResStabilization.setChecked(false);
1884+
setupHighResStabilizationListener();
1885+
dialog.dismiss();
1886+
})
1887+
.setNeutralButton(getString(R.string.set_static_mode), (dialog, which) -> {
1888+
// Set to static mode with current resolution
1889+
spinnerResolutionMode.setSelection(0);
1890+
updateResolutionModeVisibility(0);
1891+
dialog.dismiss();
1892+
// Continue to check if static resolution is too high
1893+
checkStaticResolutionForHighResStabilization();
1894+
})
1895+
.setPositiveButton(getString(R.string.set_static_recommended), (dialog, which) -> {
1896+
// Set to static mode with recommended settings (4MP)
1897+
applyRecommendedResolutionSettings();
1898+
dialog.dismiss();
1899+
// No need to check resolution - already set to 4MP
1900+
})
1901+
.setCancelable(false)
1902+
.show();
1903+
} else {
1904+
// Static mode - check if resolution is too high
1905+
checkStaticResolutionForHighResStabilization();
1906+
}
1907+
}
1908+
1909+
private void checkStaticResolutionForHighResStabilization() {
1910+
// Check if a resolution higher than 8MP is selected
1911+
boolean isHighResSelected = (rb12MPResolution != null && rb12MPResolution.isChecked()) ||
1912+
(rb12_5MPResolution != null && rb12_5MPResolution.isChecked()) ||
1913+
(rb12_6MPResolution != null && rb12_6MPResolution.isChecked());
1914+
1915+
if (isHighResSelected) {
1916+
// Show warning dialog for high resolution
1917+
new AlertDialog.Builder(this)
1918+
.setTitle(getString(R.string.high_res_resolution_warning_title))
1919+
.setMessage(getString(R.string.high_res_resolution_warning_message))
1920+
.setNegativeButton(getString(R.string.cancel), (dialog, which) -> {
1921+
// Cancel - uncheck high-res stabilization
1922+
cbHighResStabilization.setOnCheckedChangeListener(null);
1923+
cbHighResStabilization.setChecked(false);
1924+
setupHighResStabilizationListener();
1925+
dialog.dismiss();
1926+
})
1927+
.setPositiveButton(getString(R.string.set_lower_resolution), (dialog, which) -> {
1928+
// Set to the highest available resolution <= 8MP
1929+
selectHighestAvailableResolutionUnder8MP();
1930+
dialog.dismiss();
1931+
})
1932+
.setCancelable(false)
1933+
.show();
1934+
}
1935+
}
1936+
1937+
private void selectHighestAvailableResolutionUnder8MP() {
1938+
// Select the highest available resolution <= 8MP
1939+
if (rb8MPResolution != null && rb8MPResolution.getVisibility() == View.VISIBLE) {
1940+
rb8MPResolution.setChecked(true);
1941+
} else if (rb4MPResolution != null && rb4MPResolution.getVisibility() == View.VISIBLE) {
1942+
rb4MPResolution.setChecked(true);
1943+
} else if (rb2MPResolution != null && rb2MPResolution.getVisibility() == View.VISIBLE) {
1944+
rb2MPResolution.setChecked(true);
1945+
} else if (rb1MPResolution != null && rb1MPResolution.getVisibility() == View.VISIBLE) {
1946+
rb1MPResolution.setChecked(true);
1947+
}
1948+
}
1949+
1950+
private void applyRecommendedResolutionSettings() {
1951+
// Set to static mode
1952+
spinnerResolutionMode.setSelection(0);
1953+
updateResolutionModeVisibility(0);
1954+
1955+
// Set to 4MP resolution
1956+
if (rb4MPResolution != null && rb4MPResolution.getVisibility() == View.VISIBLE) {
1957+
rb4MPResolution.setChecked(true);
1958+
} else if (rb2MPResolution != null && rb2MPResolution.getVisibility() == View.VISIBLE) {
1959+
// Fallback to 2MP if 4MP not available
1960+
rb2MPResolution.setChecked(true);
1961+
}
1962+
}
1963+
17321964
private void setupDebounceListeners() {
17331965
// Setup algorithm spinner
17341966
setupDebounceAlgorithmSpinner();

AI_MultiBarcodes_Capture/src/main/res/values/strings.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,21 @@
278278
<string name="force_continuous_autofocus_checkbox">Force continuous autofocus</string>
279279
<string name="enable_high_res_stabilization">Enable High-Res Capture Stabilization</string>
280280

281+
<!-- High-Res Stabilization Warning Dialogs -->
282+
<string name="high_res_debounce_warning_title">Debounce Required</string>
283+
<string name="high_res_debounce_warning_message">High-Res Capture Stabilization requires Debounce to be enabled for tracking barcode positions across frames.\n\nWould you like to enable Debounce?</string>
284+
<string name="enable_debounce">Enable Debounce</string>
285+
<string name="enable_debounce_recommended">Recommended Settings</string>
286+
287+
<string name="high_res_dynamic_warning_title">Static Resolution Recommended</string>
288+
<string name="high_res_dynamic_warning_message">High-Res Capture Stabilization works best with Static resolution mode for consistent coordinate mapping.\n\nWould you like to switch to Static mode?</string>
289+
<string name="set_static_mode">Set Static Mode</string>
290+
<string name="set_static_recommended">Recommended (4MP)</string>
291+
292+
<string name="high_res_resolution_warning_title">Resolution Too High</string>
293+
<string name="high_res_resolution_warning_message">High-Res Capture Stabilization requires a resolution of 8MP or lower for optimal performance.\n\nWould you like to set a lower resolution?</string>
294+
<string name="set_lower_resolution">Set Lower Resolution</string>
295+
281296
<!-- Dialog Messages (French -> English) -->
282297
<string name="rename">Rename</string>
283298
<string name="rename_file">Rename a file</string>

0 commit comments

Comments
 (0)