Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Choice between classic and MLkit scanner with a system of dimensions to disable binary blobs for F-Droid #3836

Merged
merged 14 commits into from
Mar 9, 2021
Merged
16 changes: 15 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ dependencies {
implementation("androidx.work:work-rxjava2:2.4.0")
implementation("androidx.startup:startup-runtime:1.0.0")

// ML Kit barcode Scanner
implementation ("com.google.mlkit:barcode-scanning:16.1.1")

implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")

kapt("com.google.dagger:dagger-compiler:2.30.1")
implementation("com.google.dagger:dagger:2.30.1")
Expand Down Expand Up @@ -199,7 +203,7 @@ android {
dataBinding = true
}

flavorDimensions("versionCode")
flavorDimensions("versionCode", "platform")


defaultConfig {
Expand Down Expand Up @@ -272,6 +276,7 @@ android {
buildConfigField("String", "OFWEBSITE", "\"https://world.openfoodfacts.org/\"")
buildConfigField("String", "WIKIDATA", "\"https://www.wikidata.org/wiki/Special:EntityData/\"")
buildConfigField("String", "STATICURL", "\"https://static.openfoodfacts.org\"")
dimension = "versionCode"
}
create("obf") {
applicationId = "openfoodfacts.github.scrachx.openbeauty"
Expand All @@ -282,6 +287,7 @@ android {
buildConfigField("String", "OFWEBSITE", "\"https://world.openbeautyfacts.org/\"")
buildConfigField("String", "WIKIDATA", "\"https://www.wikidata.org/wiki/Special:EntityData/\"")
buildConfigField("String", "STATICURL", "\"https://static.openbeautyfacts.org\"")
dimension = "versionCode"
}
create("opff") {
applicationId = "org.openpetfoodfacts.scanner"
Expand All @@ -292,6 +298,7 @@ android {
buildConfigField("String", "OFWEBSITE", "\"https://world.openpetfoodfacts.org/\"")
buildConfigField("String", "WIKIDATA", "\"https://www.wikidata.org/wiki/Special:EntityData/\"")
buildConfigField("String", "STATICURL", "\"https://static.openpetfoodfacts.org\"")
dimension = "versionCode"
}
create("opf") {
applicationId = "org.openproductsfacts.scanner"
Expand All @@ -302,6 +309,13 @@ android {
buildConfigField("String", "OFWEBSITE", "\"https://world.openproductsfacts.org/\"")
buildConfigField("String", "WIKIDATA", "\"https://www.wikidata.org/wiki/Special:EntityData/\"")
buildConfigField("String", "STATICURL", "\"https://static.openproductsfacts.org\"")
dimension = "versionCode"
}
create("playstore") {
dimension = "platform"
}
create("fdroid") {
dimension = "platform"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ import java.util.*
import java.util.concurrent.TimeUnit

class ContinuousScanActivity : AppCompatActivity() {

private var _binding: ActivityContinuousScanBinding? = null
private val binding get() = _binding!!

Expand Down Expand Up @@ -477,6 +478,10 @@ class ContinuousScanActivity : AppCompatActivity() {
// Setup barcode scanner
binding.barcodeScanner.barcodeView.decoderFactory = DefaultDecoderFactory(BARCODE_FORMATS)
binding.barcodeScanner.setStatusText(null)
binding.barcodeScanner.setOnClickListener {
quickViewBehavior.state = BottomSheetBehavior.STATE_HIDDEN
binding.barcodeScanner.resume()
}
binding.barcodeScanner.barcodeView.cameraSettings.run {
requestedCameraId = cameraState
isAutoFocusEnabled = autoFocusActive
Expand Down Expand Up @@ -647,15 +652,10 @@ class ContinuousScanActivity : AppCompatActivity() {
R.id.troubleScanning -> {
hideAllViews()
hintBarcodeDisp?.dispose()

binding.quickView.setOnClickListener(null)
binding.quickViewSearchByBarcode.text = null
binding.quickViewSearchByBarcode.visibility = View.VISIBLE
binding.quickView.visibility = View.INVISIBLE
quickViewBehavior.state = BottomSheetBehavior.STATE_EXPANDED
commonDisp.add(Completable.timer(500, TimeUnit.MILLISECONDS)
VaiTon marked this conversation as resolved.
Show resolved Hide resolved
.doOnComplete { binding.quickView.visibility = View.VISIBLE }
.subscribeOn(AndroidSchedulers.mainThread()).subscribe())
quickViewBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
binding.quickViewSearchByBarcode.requestFocus()
}
R.id.toggleCamera -> toggleCamera()
Expand Down Expand Up @@ -700,11 +700,12 @@ class ContinuousScanActivity : AppCompatActivity() {
lastBarcode = null
binding.txtProductCallToAction.visibility = View.GONE
}
BottomSheetBehavior.STATE_COLLAPSED -> binding.barcodeScanner.resume()
BottomSheetBehavior.STATE_DRAGGING -> if (product == null) {
quickViewBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
else -> {
binding.barcodeScanner.pause()
}
}
}


if (binding.quickViewSearchByBarcode.visibility == View.VISIBLE) {
quickViewBehavior.peekHeight = peekSmall
bottomSheet.layoutParams.height = quickViewBehavior.peekHeight
Expand Down Expand Up @@ -793,6 +794,8 @@ class ContinuousScanActivity : AppCompatActivity() {
}

companion object {
val showSelectScannerPref = false

private const val LOGIN_ACTIVITY_REQUEST_CODE = 2
val BARCODE_FORMATS = listOf(
BarcodeFormat.UPC_A,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ object AppFlavors {
const val OPF = "opf"
const val OBF = "obf"
@JvmStatic
fun isFlavors(vararg flavors: String) = flavors.contains(BuildConfig.FLAVOR)
fun isFlavors(vararg flavors: String) = flavors.contains(BuildConfig.FLAVOR_versionCode)
VaiTon marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import openfoodfacts.github.scrachx.openfood.R
import openfoodfacts.github.scrachx.openfood.app.OFFApplication
import openfoodfacts.github.scrachx.openfood.customtabs.CustomTabActivityHelper
import openfoodfacts.github.scrachx.openfood.customtabs.WebViewFallback
import openfoodfacts.github.scrachx.openfood.features.scan.ContinuousScanActivity
import openfoodfacts.github.scrachx.openfood.jobs.LoadTaxonomiesWorker
import openfoodfacts.github.scrachx.openfood.jobs.OfflineProductWorker.Companion.scheduleSync
import openfoodfacts.github.scrachx.openfood.models.DaoSession
Expand Down Expand Up @@ -150,6 +151,37 @@ class PreferencesFragment : PreferenceFragmentCompat(), INavigationItem, OnShare
true
}

requirePreference<SwitchPreference>(getString(R.string.pref_scanner_type_key)).let {
it.isVisible = ContinuousScanActivity.showSelectScannerPref
it.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
if(newValue == true){
MaterialDialog.Builder(requireActivity()).run {
title(R.string.preference_choose_scanner_dialog_title)
content(R.string.preference_choose_scanner_dialog_body)
positiveText(R.string.proceed)
onPositive { _, _ ->
it.isChecked = true
settings.edit { putBoolean(getString(R.string.pref_scanner_type_key), newValue as Boolean) }
Toast.makeText(requireActivity(), getString(R.string.changes_saved), Toast.LENGTH_SHORT).show()
}
negativeText(R.string.dialog_cancel)
onNegative {
dialog, _ -> dialog.dismiss()
it.isChecked = false
settings.edit { putBoolean(getString(R.string.pref_scanner_type_key), false) }
}
show()
}
}
else{
it.isChecked = false
settings.edit { putBoolean(getString(R.string.pref_scanner_type_key), newValue as Boolean) }
Toast.makeText(requireActivity(), getString(R.string.changes_saved), Toast.LENGTH_SHORT).show()
VaiTon marked this conversation as resolved.
Show resolved Hide resolved
}
true
}
}

val countryLabels = mutableListOf<String>()
val countryTags = mutableListOf<String>()

Expand Down
9 changes: 9 additions & 0 deletions app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@

<color name="brown_100">#d7ccc8</color>

<!-- MLKit Scanner preview screen overlay-->
<color name="transparent">#00000000</color>
<color name="reticle_ripple">#9AFFFFFF</color>
<color name="object_reticle_outer_ring_fill">#1F000000</color>
<color name="object_reticle_outer_ring_stroke">#9AFFFFFF</color>
<color name="object_reticle_inner_ring">@color/white</color>
<color name="barcode_reticle_background">#99000000</color>
<color name="barcode_reticle_stroke">#40000000</color>

<color name="grey_50">#fafafa</color>
<color name="grey_100">#f5f5f5</color>
<color name="grey_200">#eeeeee</color>
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,14 @@
<!-- Override the navigation dimensions to be identical in both active and inactive states -->
<dimen name="design_bottom_navigation_text_size" tools:override="true">12sp</dimen>
<dimen name="design_bottom_navigation_active_text_size" tools:override="true">12sp</dimen>

<!-- preview graphic overlay -->
<dimen name="barcode_reticle_ripple_stroke_width">4dp</dimen>
<dimen name="barcode_reticle_ripple_size_offset">40dp</dimen>
<dimen name="barcode_reticle_stroke_width">4dp</dimen>
<dimen name="barcode_reticle_corner_radius">8dp</dimen>
<dimen name="bottom_prompt_chip_text_size">14sp</dimen>
<dimen name="bottom_prompt_chip_margin_bottom">28dp</dimen>
<dimen name="bottom_prompt_chip_corner_radius">8dp</dimen>

</resources>
5 changes: 5 additions & 0 deletions app/src/main/res/values/pref_keys.xml
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,9 @@
<string name="pref_crop_new_images_title">Crop new images</string>
<string name="pref_crop_new_images_summary">Enables crop action on new images</string>

<string name="pref_scanner_startup_title">Use MLKit Scanner</string>
<string name="pref_scanner_startup_summaryOff">Increases Scanning efficiency.</string>
<string name="pref_scanner_startup_summaryOn">Switch off to use Classic Barcode Scanner.</string>
<string name="pref_scanner_type_key" translatable="false">select_scanner</string>

</resources>
9 changes: 9 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,16 @@
<string name="device_on_mobile_data_warning_positive">Preferences</string>
<string name="device_on_mobile_data_warning_negative">Upload anyway</string>
<string name="changes_saved">Changes saved successfully</string>
<string name="proceed">Proceed</string>
<string name="preference_choose_language_dialog_title">Choose language</string>
<string name="preference_choose_scanner_dialog_title"><b>New: Enhanced “MLKit” scanner</b></string>
<string name="preference_choose_scanner_dialog_body">We have included a new option to more reliably scan barcodes. While this scanner works on your device, using machine learning,
please be aware that it is a proprietary component provided by Google, governed by this privacy policy, and that some limited telemetry might be sent back to Google’s servers
to improve their software. As noted in the MLKit terms, this won’t include any information about the products you scan and the telemetry is anonymized. Choosing MLKit scanner
implies that you accept those terms\n<b>Note: You can switch back at any time between the 2 scanners in the Settings.</b>
</string>
<string name="prompt_point_at_a_barcode">Point your camera at a barcode</string>
<string name="prompt_move_camera_closer">Move closer to detect</string>


<string name="please_check_your_connection">Please check your connection.</string>
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@
android:title="@string/pref_country_title"
app:summary="@string/pref_country_summary" />

<SwitchPreference
android:defaultValue="false"
android:key="@string/pref_scanner_type_key"
android:title="@string/pref_scanner_startup_title"
app:summaryOff="@string/pref_scanner_startup_summaryOff"
android:summaryOn="@string/pref_scanner_startup_summaryOn"/>

<SwitchPreference
android:defaultValue="false"
android:key="startScan"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package openfoodfacts.github.scrachx.openfood.camera

import android.animation.AnimatorSet
import android.animation.ValueAnimator
import androidx.interpolator.view.animation.FastOutSlowInInterpolator

/**
* Custom animator for the object or barcode reticle in live camera.
*/
class CameraReticleAnimator(graphicOverlay: GraphicOverlay) {

/** Returns the scale value of ripple alpha ranges in [0, 1]. */
var rippleAlphaScale = 0f
private set

/** Returns the scale value of ripple size ranges in [0, 1]. */
var rippleSizeScale = 0f
private set

/** Returns the scale value of ripple stroke width ranges in [0, 1]. */
var rippleStrokeWidthScale = 1f
private set

private val animatorSet: AnimatorSet

init {
val rippleFadeInAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(DURATION_RIPPLE_FADE_IN_MS).apply {
addUpdateListener { animation ->
rippleAlphaScale = animation.animatedValue as Float
graphicOverlay.postInvalidate()
}
}

val rippleFadeOutAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(DURATION_RIPPLE_FADE_OUT_MS).apply {
startDelay = START_DELAY_RIPPLE_FADE_OUT_MS
addUpdateListener { animation ->
rippleAlphaScale = animation.animatedValue as Float
graphicOverlay.postInvalidate()
}
}

val rippleExpandAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(DURATION_RIPPLE_EXPAND_MS).apply {
startDelay = START_DELAY_RIPPLE_EXPAND_MS
interpolator = FastOutSlowInInterpolator()
addUpdateListener { animation ->
rippleSizeScale = animation.animatedValue as Float
graphicOverlay.postInvalidate()
}
}

val rippleStrokeWidthShrinkAnimator = ValueAnimator.ofFloat(1f, 0.5f).setDuration(DURATION_RIPPLE_STROKE_WIDTH_SHRINK_MS).apply {
startDelay = START_DELAY_RIPPLE_STROKE_WIDTH_SHRINK_MS
interpolator = FastOutSlowInInterpolator()
addUpdateListener { animation ->
rippleStrokeWidthScale = animation.animatedValue as Float
graphicOverlay.postInvalidate()
}
}

val fakeAnimatorForRestartDelay = ValueAnimator.ofInt(0, 0).setDuration(DURATION_RESTART_DORMANCY_MS).apply {
startDelay = START_DELAY_RESTART_DORMANCY_MS
}

animatorSet = AnimatorSet().apply {
playTogether(
rippleFadeInAnimator,
rippleFadeOutAnimator,
rippleExpandAnimator,
rippleStrokeWidthShrinkAnimator,
fakeAnimatorForRestartDelay
)
}

}

fun start() {
if (!animatorSet.isRunning) animatorSet.start()
}

fun cancel() {
animatorSet.cancel()
rippleAlphaScale = 0f
rippleSizeScale = 0f
rippleStrokeWidthScale = 1f
}

companion object {

private const val DURATION_RIPPLE_FADE_IN_MS: Long = 333
private const val DURATION_RIPPLE_FADE_OUT_MS: Long = 500
private const val DURATION_RIPPLE_EXPAND_MS: Long = 833
private const val DURATION_RIPPLE_STROKE_WIDTH_SHRINK_MS: Long = 833
private const val DURATION_RESTART_DORMANCY_MS: Long = 1333
private const val START_DELAY_RIPPLE_FADE_OUT_MS: Long = 667
private const val START_DELAY_RIPPLE_EXPAND_MS: Long = 333
private const val START_DELAY_RIPPLE_STROKE_WIDTH_SHRINK_MS: Long = 333
private const val START_DELAY_RESTART_DORMANCY_MS: Long = 1167
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@file:Suppress("DEPRECATION")

package openfoodfacts.github.scrachx.openfood.camera

import android.hardware.Camera
import com.google.android.gms.common.images.Size

/**
* Stores a preview size and a corresponding same-aspect-ratio picture size. To avoid distorted
* preview images on some devices, the picture size must be set to a size that is the same aspect
* ratio as the preview size or the preview may end up being distorted. If the picture size is null,
* then there is no picture size with the same aspect ratio as the preview size.
*/

data class CameraSizePair(val previewSize: Camera.Size, val pictureSize: Camera.Size?) {

val preview: Size = Size(previewSize.width, previewSize.height)
val picture: Size? = pictureSize?.let { Size(it.width, it.height) }

}
Loading