Loading _docs/help.html +4 −0 Original line number Diff line number Diff line Loading @@ -599,6 +599,10 @@ can also select UTC <a href="https://en.wikipedia.org/wiki/Coordinated_Universal For the latter option, a "Z" will be appended to the filename (e.g., "IMG_20160524_155116Z.jpg"). The Z (Zulu) suffix is a standard convention for identifying UTC timestamps.</p> <p><b>Allow vibration feedback</b> - Whether to allow haptic vibration feedback, for example when adjusting some controls. Note this also requires touch interactions to be enabled in your device's settings, this is usually under the "Sound and vibration" settings or similar.</p> <p><b>Show camera when locked</b> - If you have a lock screen on your device (e.g., PIN to unlock), if this option is enabled Open Camera will show above the lock screen - i.e., if locked, you won't have to enter the PIN to use Open Camera. The device still needs to be unlocked in order to go to the Settings or Gallery. If you would Loading _docs/history.html +3 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,9 @@ ADDED Support for UltraHDR on supported devices, under Settings/Photo settings (requires Android 14+ and Camera2 API). ADDED New "Auto source" mode for focus bracketing: in this mode, the source focus distance will be automatically set via continuous focus or touch to focus. ADDED Haptic/vibration feedback for adjusting some seekbars. Can be disabled under Settings/More camera controls/"Allow vibration feedback". Note this also requires touch interactions to be enabled in your device's settings. UPDATED Now requires Android 5+, Android 4.x no longer supported (sorry to anyone still on those devices - but latest AndroidX libraries now require Android 5+). UPDATED Improved performance for Camera2 API (on Android 12+) for taking photos with continuous Loading app/src/main/java/net/sourceforge/opencamera/MainActivity.java +54 −2 Original line number Diff line number Diff line Loading @@ -5805,6 +5805,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen zoomSeekBar.setMax(preview.getMaxZoom()); zoomSeekBar.setProgress(preview.getMaxZoom()-preview.getCameraController().getZoom()); zoomSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -5812,8 +5814,17 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen // note we zoom even if !fromUser, as various other UI controls (multitouch, volume key zoom, -/+ zoomcontrol) // indirectly set zoom via this method, from setting the zoom slider // if hasSmoothZoom()==true, then the preview already handled zooming to the current value if( !preview.hasSmoothZoom() ) preview.zoomTo(preview.getMaxZoom() - progress, false); if( !preview.hasSmoothZoom() ) { int new_zoom_factor = preview.getMaxZoom() - progress; if( fromUser && preview.getCameraController() != null ) { float old_zoom_ratio = preview.getZoomRatio(); float new_zoom_ratio = preview.getZoomRatio(new_zoom_factor); if( new_zoom_ratio != old_zoom_ratio ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } preview.zoomTo(new_zoom_factor, false); } } @Override Loading Loading @@ -5868,6 +5879,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen //setProgressSeekbarExponential(iso_seek_bar, preview.getMinimumISO(), preview.getMaximumISO(), preview.getCameraController().getISO()); manualSeekbars.setProgressSeekbarISO(iso_seek_bar, preview.getMinimumISO(), preview.getMaximumISO(), preview.getCameraController().getISO()); iso_seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -5888,6 +5901,9 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen // the ISO buttons rather than moving the slider directly, see MainUI.setupExposureUI()) preview.setISO( manualSeekbars.getISO(progress) ); mainUI.updateSelectedISOButton(); if( fromUser ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } @Override Loading @@ -5906,6 +5922,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen //setProgressSeekbarExponential(exposure_time_seek_bar, preview.getMinimumExposureTime(), preview.getMaximumExposureTime(), preview.getCameraController().getExposureTime()); manualSeekbars.setProgressSeekbarShutterSpeed(exposure_time_seek_bar, preview.getMinimumExposureTime(), preview.getMaximumExposureTime(), preview.getCameraController().getExposureTime()); exposure_time_seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -5917,6 +5935,9 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen long max_exposure_time = preview.getMaximumExposureTime(); long exposure_time = exponentialScaling(frac, min_exposure_time, max_exposure_time);*/ preview.setExposureTime( manualSeekbars.getExposureTime(progress) ); if( fromUser ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } @Override Loading Loading @@ -5971,6 +5992,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen exposure_seek_bar.setMax( exposure_seekbar_values.size()-1 ); exposure_seek_bar.setProgress( current_progress ); exposure_seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -5980,6 +6003,12 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen return; } int new_exposure = exposure_seekbar_values.get(progress); if( fromUser ) { // check if not scrolling past the repeated zeroes if( preview.getCurrentExposure() != new_exposure ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } preview.setExposure(new_exposure); } Loading Loading @@ -6054,6 +6083,24 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen } } public static long performHapticFeedback(SeekBar seekBar, long last_haptic_time) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(seekBar.getContext()); if( sharedPreferences.getBoolean(PreferenceKeys.AllowHapticFeedbackPreferenceKey, true) ) { long time_ms = System.currentTimeMillis(); if( time_ms > last_haptic_time + 16 ) { last_haptic_time = time_ms; // SEGMENT_TICK or SEGMENT_TICK doesn't work on Galaxy S24+ at least, even though on Android 14! /*if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE ) { seekBar.performHapticFeedback(HapticFeedbackConstants.SEGMENT_FREQUENT_TICK); } else*/ { seekBar.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); } } } return last_haptic_time; } public void setManualFocusSeekbarProgress(final boolean is_target_distance, float focus_distance) { final SeekBar focusSeekBar = findViewById(is_target_distance ? R.id.focus_bracketing_target_seekbar : R.id.focus_seekbar); ManualSeekbars.setProgressSeekbarScaled(focusSeekBar, 0.0, preview.getMinimumFocusDistance(), focus_distance); Loading Loading @@ -6159,6 +6206,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen */ manualSeekbars.setProgressSeekbarWhiteBalance(white_balance_seek_bar, minimum_temperature, maximum_temperature, preview.getCameraController().getWhiteBalanceTemperature()); white_balance_seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -6166,6 +6215,9 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen //int temperature = minimum_temperature + progress; //preview.setWhiteBalanceTemperature(temperature); preview.setWhiteBalanceTemperature( manualSeekbars.getWhiteBalanceTemperature(progress) ); if( fromUser ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } @Override Loading app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +2 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,8 @@ public class PreferenceKeys { public static final String DimWhenDisconnectedPreferenceKey = "preference_remote_disconnect_screen_dim"; public static final String AllowHapticFeedbackPreferenceKey = "preference_allow_haptic_feedback"; public static final String ShowWhenLockedPreferenceKey = "preference_show_when_locked"; public static final String AllowLongPressPreferenceKey = "preference_allow_long_press"; Loading app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java +6 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ import android.view.View; import android.widget.SeekBar; import android.widget.TextView; import net.sourceforge.opencamera.MainActivity; import net.sourceforge.opencamera.R; /** This contains a custom preference to display a seekbar in place of a ListPreference. Loading Loading @@ -78,10 +79,15 @@ public class ArraySeekBarPreference extends DialogPreference { seekbar.setProgress(index); } seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { String new_entry = entries[progress].toString(); textView.setText(new_entry); if( fromUser ) { last_haptic_time = MainActivity.performHapticFeedback(seekBar, last_haptic_time); } } @Override Loading Loading
_docs/help.html +4 −0 Original line number Diff line number Diff line Loading @@ -599,6 +599,10 @@ can also select UTC <a href="https://en.wikipedia.org/wiki/Coordinated_Universal For the latter option, a "Z" will be appended to the filename (e.g., "IMG_20160524_155116Z.jpg"). The Z (Zulu) suffix is a standard convention for identifying UTC timestamps.</p> <p><b>Allow vibration feedback</b> - Whether to allow haptic vibration feedback, for example when adjusting some controls. Note this also requires touch interactions to be enabled in your device's settings, this is usually under the "Sound and vibration" settings or similar.</p> <p><b>Show camera when locked</b> - If you have a lock screen on your device (e.g., PIN to unlock), if this option is enabled Open Camera will show above the lock screen - i.e., if locked, you won't have to enter the PIN to use Open Camera. The device still needs to be unlocked in order to go to the Settings or Gallery. If you would Loading
_docs/history.html +3 −0 Original line number Diff line number Diff line Loading @@ -77,6 +77,9 @@ ADDED Support for UltraHDR on supported devices, under Settings/Photo settings (requires Android 14+ and Camera2 API). ADDED New "Auto source" mode for focus bracketing: in this mode, the source focus distance will be automatically set via continuous focus or touch to focus. ADDED Haptic/vibration feedback for adjusting some seekbars. Can be disabled under Settings/More camera controls/"Allow vibration feedback". Note this also requires touch interactions to be enabled in your device's settings. UPDATED Now requires Android 5+, Android 4.x no longer supported (sorry to anyone still on those devices - but latest AndroidX libraries now require Android 5+). UPDATED Improved performance for Camera2 API (on Android 12+) for taking photos with continuous Loading
app/src/main/java/net/sourceforge/opencamera/MainActivity.java +54 −2 Original line number Diff line number Diff line Loading @@ -5805,6 +5805,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen zoomSeekBar.setMax(preview.getMaxZoom()); zoomSeekBar.setProgress(preview.getMaxZoom()-preview.getCameraController().getZoom()); zoomSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -5812,8 +5814,17 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen // note we zoom even if !fromUser, as various other UI controls (multitouch, volume key zoom, -/+ zoomcontrol) // indirectly set zoom via this method, from setting the zoom slider // if hasSmoothZoom()==true, then the preview already handled zooming to the current value if( !preview.hasSmoothZoom() ) preview.zoomTo(preview.getMaxZoom() - progress, false); if( !preview.hasSmoothZoom() ) { int new_zoom_factor = preview.getMaxZoom() - progress; if( fromUser && preview.getCameraController() != null ) { float old_zoom_ratio = preview.getZoomRatio(); float new_zoom_ratio = preview.getZoomRatio(new_zoom_factor); if( new_zoom_ratio != old_zoom_ratio ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } preview.zoomTo(new_zoom_factor, false); } } @Override Loading Loading @@ -5868,6 +5879,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen //setProgressSeekbarExponential(iso_seek_bar, preview.getMinimumISO(), preview.getMaximumISO(), preview.getCameraController().getISO()); manualSeekbars.setProgressSeekbarISO(iso_seek_bar, preview.getMinimumISO(), preview.getMaximumISO(), preview.getCameraController().getISO()); iso_seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -5888,6 +5901,9 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen // the ISO buttons rather than moving the slider directly, see MainUI.setupExposureUI()) preview.setISO( manualSeekbars.getISO(progress) ); mainUI.updateSelectedISOButton(); if( fromUser ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } @Override Loading @@ -5906,6 +5922,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen //setProgressSeekbarExponential(exposure_time_seek_bar, preview.getMinimumExposureTime(), preview.getMaximumExposureTime(), preview.getCameraController().getExposureTime()); manualSeekbars.setProgressSeekbarShutterSpeed(exposure_time_seek_bar, preview.getMinimumExposureTime(), preview.getMaximumExposureTime(), preview.getCameraController().getExposureTime()); exposure_time_seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -5917,6 +5935,9 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen long max_exposure_time = preview.getMaximumExposureTime(); long exposure_time = exponentialScaling(frac, min_exposure_time, max_exposure_time);*/ preview.setExposureTime( manualSeekbars.getExposureTime(progress) ); if( fromUser ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } @Override Loading Loading @@ -5971,6 +5992,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen exposure_seek_bar.setMax( exposure_seekbar_values.size()-1 ); exposure_seek_bar.setProgress( current_progress ); exposure_seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -5980,6 +6003,12 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen return; } int new_exposure = exposure_seekbar_values.get(progress); if( fromUser ) { // check if not scrolling past the repeated zeroes if( preview.getCurrentExposure() != new_exposure ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } preview.setExposure(new_exposure); } Loading Loading @@ -6054,6 +6083,24 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen } } public static long performHapticFeedback(SeekBar seekBar, long last_haptic_time) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(seekBar.getContext()); if( sharedPreferences.getBoolean(PreferenceKeys.AllowHapticFeedbackPreferenceKey, true) ) { long time_ms = System.currentTimeMillis(); if( time_ms > last_haptic_time + 16 ) { last_haptic_time = time_ms; // SEGMENT_TICK or SEGMENT_TICK doesn't work on Galaxy S24+ at least, even though on Android 14! /*if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE ) { seekBar.performHapticFeedback(HapticFeedbackConstants.SEGMENT_FREQUENT_TICK); } else*/ { seekBar.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); } } } return last_haptic_time; } public void setManualFocusSeekbarProgress(final boolean is_target_distance, float focus_distance) { final SeekBar focusSeekBar = findViewById(is_target_distance ? R.id.focus_bracketing_target_seekbar : R.id.focus_seekbar); ManualSeekbars.setProgressSeekbarScaled(focusSeekBar, 0.0, preview.getMinimumFocusDistance(), focus_distance); Loading Loading @@ -6159,6 +6206,8 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen */ manualSeekbars.setProgressSeekbarWhiteBalance(white_balance_seek_bar, minimum_temperature, maximum_temperature, preview.getCameraController().getWhiteBalanceTemperature()); white_balance_seek_bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if( MyDebug.LOG ) Loading @@ -6166,6 +6215,9 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen //int temperature = minimum_temperature + progress; //preview.setWhiteBalanceTemperature(temperature); preview.setWhiteBalanceTemperature( manualSeekbars.getWhiteBalanceTemperature(progress) ); if( fromUser ) { last_haptic_time = performHapticFeedback(seekBar, last_haptic_time); } } @Override Loading
app/src/main/java/net/sourceforge/opencamera/PreferenceKeys.java +2 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,8 @@ public class PreferenceKeys { public static final String DimWhenDisconnectedPreferenceKey = "preference_remote_disconnect_screen_dim"; public static final String AllowHapticFeedbackPreferenceKey = "preference_allow_haptic_feedback"; public static final String ShowWhenLockedPreferenceKey = "preference_show_when_locked"; public static final String AllowLongPressPreferenceKey = "preference_allow_long_press"; Loading
app/src/main/java/net/sourceforge/opencamera/ui/ArraySeekBarPreference.java +6 −0 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ import android.view.View; import android.widget.SeekBar; import android.widget.TextView; import net.sourceforge.opencamera.MainActivity; import net.sourceforge.opencamera.R; /** This contains a custom preference to display a seekbar in place of a ListPreference. Loading Loading @@ -78,10 +79,15 @@ public class ArraySeekBarPreference extends DialogPreference { seekbar.setProgress(index); } seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { private long last_haptic_time; @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { String new_entry = entries[progress].toString(); textView.setText(new_entry); if( fromUser ) { last_haptic_time = MainActivity.performHapticFeedback(seekBar, last_haptic_time); } } @Override Loading