Skip to content

Commit

Permalink
Merge pull request #3836 from kartikaysharma01/mlkit-scanner
Browse files Browse the repository at this point in the history
feat: Choice between classic and MLkit scanner with a system of dimensions to disable binary blobs for F-Droid
  • Loading branch information
VaiTon committed Mar 9, 2021
2 parents 7fc3fb9 + d80d87f commit 4594db1
Show file tree
Hide file tree
Showing 28 changed files with 2,993 additions and 12 deletions.
16 changes: 15 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ dependencies {

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.33")
implementation("com.google.dagger:dagger:2.33")
Expand Down Expand Up @@ -202,7 +206,7 @@ android {
dataBinding = true
}

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


defaultConfig {
Expand Down Expand Up @@ -275,6 +279,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 @@ -285,6 +290,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 @@ -295,6 +301,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 @@ -305,6 +312,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 @@ -476,6 +477,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 @@ -646,15 +651,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)
.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 @@ -699,11 +699,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 @@ -792,6 +793,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)
}
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()
}
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 @@ -588,7 +588,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) }

}

0 comments on commit 4594db1

Please sign in to comment.