Full Code of getbouncer/cardscan-android for AI

master bf490afe479e cached
272 files
1.1 MB
295.7k tokens
48 symbols
1 requests
Download .txt
Showing preview only (1,250K chars total). Download the full file or copy to clipboard to get everything.
Repository: getbouncer/cardscan-android
Branch: master
Commit: bf490afe479e
Files: 272
Total size: 1.1 MB

Directory structure:
gitextract_79p3qz5m/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── android_test.yml
│       ├── lint.yml
│       ├── release.yml
│       └── unit_test.yml
├── .github_changelog_generator
├── .gitignore
├── CHANGELOG.md
├── CODEOWNERS
├── Contributor License Agreement
├── HISTORY.md
├── LICENSE
├── README.md
├── build.gradle
├── cardscan-demo/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── cardscan/
│       │                   └── demo/
│       │                       └── ExampleInstrumentedTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── getbouncer/
│       │   │           └── cardscan/
│       │   │               └── demo/
│       │   │                   ├── LaunchActivity.java
│       │   │                   └── SingleActivityDemo.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   ├── activity_launch.xml
│       │       │   └── activity_single_demo.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── cardscan/
│                           └── demo/
│                               └── ExampleUnitTest.kt
├── cardscan-ui/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── cardscan/
│       │                   └── ui/
│       │                       └── ExampleInstrumentedTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── getbouncer/
│       │   │           └── cardscan/
│       │   │               └── ui/
│       │   │                   ├── CardScanActivity.kt
│       │   │                   ├── CardScanBaseActivity.kt
│       │   │                   ├── CardScanFlow.kt
│       │   │                   ├── CardScanSheet.kt
│       │   │                   ├── analyzer/
│       │   │                   │   ├── CompletionLoopAnalyzer.kt
│       │   │                   │   └── MainLoopAnalyzer.kt
│       │   │                   ├── exception/
│       │   │                   │   ├── StripeNetworkException.kt
│       │   │                   │   └── UnknownScanException.kt
│       │   │                   └── result/
│       │   │                       ├── CompletionLoopAggregator.kt
│       │   │                       ├── MainLoopAggregator.kt
│       │   │                       └── MainLoopStateMachine.kt
│       │   └── res/
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── dimensions.xml
│       │           └── strings.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── cardscan/
│                           └── ui/
│                               └── result/
│                                   └── MainLoopStateMachineTest.kt
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── scan-camera/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── camera/
│                               ├── Camera1Adapter.kt
│                               ├── CameraAdapter.kt
│                               └── CameraSelector.kt
├── scan-camera2/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── camera/
│       │                       └── extension/
│       │                           └── UtilInstrumentationTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── camera/
│       │                       └── extension/
│       │                           ├── CameraAdapterImpl.kt
│       │                           ├── CameraDetails.kt
│       │                           └── Util.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── camera/
│                               └── extension/
│                                   └── UtilTest.kt
├── scan-camerax/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── camera/
│                               └── extension/
│                                   ├── CameraAdapterImpl.kt
│                                   ├── Image.kt
│                                   └── Util.kt
├── scan-framework/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   ├── assets/
│       │   │   └── sample_resource.tflite
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── framework/
│       │                       ├── FetcherTest.kt
│       │                       ├── LoaderTest.kt
│       │                       ├── StorageTest.kt
│       │                       ├── api/
│       │                       │   └── BouncerApiTest.kt
│       │                       ├── image/
│       │                       │   └── BitmapExtensionsTest.kt
│       │                       ├── layout/
│       │                       │   └── LayoutTest.kt
│       │                       └── util/
│       │                           └── AppDetailsTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── framework/
│       │                       ├── Analyzer.kt
│       │                       ├── Config.kt
│       │                       ├── Fetcher.kt
│       │                       ├── Loader.kt
│       │                       ├── Loop.kt
│       │                       ├── MachineState.kt
│       │                       ├── Result.kt
│       │                       ├── Scan.kt
│       │                       ├── Stat.kt
│       │                       ├── Storage.kt
│       │                       ├── TrackedImage.kt
│       │                       ├── api/
│       │                       │   ├── BouncerApi.kt
│       │                       │   ├── Network.kt
│       │                       │   ├── NetworkResult.kt
│       │                       │   └── dto/
│       │                       │       ├── AppInfo.kt
│       │                       │       ├── BouncerErrorResponse.kt
│       │                       │       ├── ClientDevice.kt
│       │                       │       ├── ClientStats.kt
│       │                       │       ├── ModelDetails.kt
│       │                       │       ├── ModelSignedUrlResponse.kt
│       │                       │       └── ValidateApiKeyResponse.kt
│       │                       ├── exception/
│       │                       │   ├── ImageTypeNotSupportedException.kt
│       │                       │   └── InvalidBouncerApiKeyException.kt
│       │                       ├── image/
│       │                       │   ├── BitmapExtensions.kt
│       │                       │   ├── ImageExtensions.kt
│       │                       │   ├── MLImage.kt
│       │                       │   ├── NV21Image.kt
│       │                       │   └── YuvImageExtensions.kt
│       │                       ├── interop/
│       │                       │   ├── BlockingAnalyzer.kt
│       │                       │   ├── BlockingResult.kt
│       │                       │   └── JavaContinuation.kt
│       │                       ├── ml/
│       │                       │   ├── ModelVersionTracker.kt
│       │                       │   ├── NonMaximumSuppression.kt
│       │                       │   ├── TensorFlowLiteAnalyzer.kt
│       │                       │   └── ssd/
│       │                       │       ├── ClassifierScores.kt
│       │                       │       ├── RectForm.kt
│       │                       │       └── SizeAndCenter.kt
│       │                       ├── time/
│       │                       │   ├── Clock.kt
│       │                       │   ├── Coroutine.kt
│       │                       │   ├── Duration.kt
│       │                       │   ├── Rate.kt
│       │                       │   └── Timer.kt
│       │                       └── util/
│       │                           ├── AppDetails.kt
│       │                           ├── ArrayExtensions.kt
│       │                           ├── Device.kt
│       │                           ├── File.kt
│       │                           ├── FrameRateTracker.kt
│       │                           ├── FrameSaver.kt
│       │                           ├── ItemCounter.kt
│       │                           ├── Layout.kt
│       │                           ├── Memoize.kt
│       │                           └── Retry.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── framework/
│                               ├── AnalyzerTest.kt
│                               ├── LoopTest.kt
│                               ├── interop/
│                               │   ├── BlockingAnalyzerTest.java
│                               │   └── BlockingResultTest.java
│                               ├── time/
│                               │   └── DurationTest.kt
│                               └── util/
│                                   ├── ArrayExtensionsTest.kt
│                                   ├── FrameSaverTest.kt
│                                   ├── ItemCounterTest.kt
│                                   ├── MemoizeTest.kt
│                                   └── RetryTest.kt
├── scan-payment/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── payment/
│       │                       ├── ImageTest.kt
│       │                       ├── PaymentCardAndroidTest.kt
│       │                       └── ml/
│       │                           ├── CardDetectTest.kt
│       │                           ├── ExpiryDetectTest.kt
│       │                           ├── SSDOcrTest.kt
│       │                           ├── TextDetectTest.kt
│       │                           └── ssd/
│       │                               └── SSDTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── payment/
│       │                       ├── FrameDetails.kt
│       │                       ├── Image.kt
│       │                       ├── ModelManager.kt
│       │                       ├── TextDetectModelManager.kt
│       │                       ├── analyzer/
│       │                       │   └── NameAndExpiryAnalyzer.kt
│       │                       ├── card/
│       │                       │   ├── CardExpiry.kt
│       │                       │   ├── CardIssuer.kt
│       │                       │   ├── CardType.kt
│       │                       │   ├── PanFormatter.kt
│       │                       │   ├── PanValidator.kt
│       │                       │   ├── PaymentCard.kt
│       │                       │   ├── PaymentCardUtils.kt
│       │                       │   └── RequiresMatchingCard.kt
│       │                       └── ml/
│       │                           ├── AlphabetDetect.kt
│       │                           ├── AlphabetDetectModelManager.kt
│       │                           ├── CardDetect.kt
│       │                           ├── CardDetectModelManager.kt
│       │                           ├── ExpiryDetect.kt
│       │                           ├── ExpiryDetectModelManager.kt
│       │                           ├── SSDOcr.kt
│       │                           ├── SSDOcrModelManager.kt
│       │                           ├── TextDetect.kt
│       │                           ├── ssd/
│       │                           │   ├── DetectionBox.kt
│       │                           │   ├── OcrPriorsGenerator.kt
│       │                           │   └── SSD.kt
│       │                           └── yolo/
│       │                               └── Yolo.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── payment/
│                               └── card/
│                                   └── PaymentCardTest.kt
├── scan-payment-full/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── payment/
│       │                       └── ml/
│       │                           ├── CardDetectTest.kt
│       │                           └── SSDOcrTest.kt
│       └── main/
│           ├── AndroidManifest.xml
│           └── assets/
│               ├── darknite_1_1_1_16.tflite
│               └── ux_0_5_23_16.tflite
├── scan-payment-minimal/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── payment/
│       │                       └── ml/
│       │                           ├── CardDetectTest.kt
│       │                           └── SSDOcrTest.kt
│       └── main/
│           ├── AndroidManifest.xml
│           └── assets/
│               ├── UX.0.25.106.8.tflite
│               └── mb2_brex_metal_synthetic_svhnextra_epoch_3_5_98_8.tflite
├── scan-ui/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── getbouncer/
│       │   │           └── scan/
│       │   │               └── ui/
│       │   │                   ├── DebugOverlayTest.kt
│       │   │                   └── util/
│       │   │                       └── ViewExtensionsTest.kt
│       │   └── res/
│       │       └── values/
│       │           └── colors.xml
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── getbouncer/
│       │   │           └── scan/
│       │   │               └── ui/
│       │   │                   ├── DebugOverlay.kt
│       │   │                   ├── ScanActivity.kt
│       │   │                   ├── ScanFlow.kt
│       │   │                   ├── SimpleScanActivity.kt
│       │   │                   ├── ViewFinderBackground.kt
│       │   │                   └── util/
│       │   │                       └── ViewExtensions.kt
│       │   └── res/
│       │       ├── drawable/
│       │       │   ├── bouncer_camera_swap_dark.xml
│       │       │   ├── bouncer_camera_swap_light.xml
│       │       │   ├── bouncer_card_background_correct.xml
│       │       │   ├── bouncer_card_background_found.xml
│       │       │   ├── bouncer_card_background_not_found.xml
│       │       │   ├── bouncer_card_background_wrong.xml
│       │       │   ├── bouncer_card_border_correct.xml
│       │       │   ├── bouncer_card_border_found.xml
│       │       │   ├── bouncer_card_border_found_long.xml
│       │       │   ├── bouncer_card_border_not_found.xml
│       │       │   ├── bouncer_card_border_wrong.xml
│       │       │   ├── bouncer_close_button_dark.xml
│       │       │   ├── bouncer_close_button_light.xml
│       │       │   ├── bouncer_flash_off_dark.xml
│       │       │   ├── bouncer_flash_off_light.xml
│       │       │   ├── bouncer_flash_on_dark.xml
│       │       │   ├── bouncer_flash_on_light.xml
│       │       │   ├── bouncer_lock_dark.xml
│       │       │   ├── bouncer_lock_light.xml
│       │       │   ├── bouncer_logo_dark_background.xml
│       │       │   └── bouncer_logo_light_background.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── dimensions.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── ui/
│                               └── ExampleUnitTest.kt
├── settings/
│   └── checkstyle.xml
├── settings.gradle
├── tensorflow-lite/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── tensorflow-lite-all-models.aar
└── tensorflow-lite-arm-only/
    ├── .gitignore
    ├── build.gradle
    ├── deploy.gradle
    └── tensorflow-lite-all-models-arm-only.aar

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: gradle
  directory: "/"
  schedule:
    interval: daily
  open-pull-requests-limit: 10
  ignore:
  - dependency-name: androidx.camera:camera-lifecycle
    versions:
    - 1.1.0-alpha04
  - dependency-name: androidx.camera:camera-camera2
    versions:
    - 1.1.0-alpha04
  - dependency-name: androidx.camera:camera-view
    versions:
    - 1.0.0-alpha24
  - dependency-name: androidx.camera:camera-core
    versions:
    - 1.1.0-alpha04
  - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-android
    versions:
    - 1.4.3-native-mt
  - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core
    versions:
    - 1.4.3-native-mt
  - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-test
    versions:
    - 1.4.3-native-mt
  - dependency-name: org.jetbrains.kotlin:kotlin-test
    versions:
    - 1.4.31
  - dependency-name: org.jetbrains.kotlin.plugin.serialization
    versions:
    - 1.4.30
    - 1.4.31
  - dependency-name: org.jetbrains.kotlin:kotlin-gradle-plugin
    versions:
    - 1.4.30
    - 1.4.31


================================================
FILE: .github/workflows/android_test.yml
================================================
name: Instrumentation Tests

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  instrumentation-test:

    runs-on: macOS-latest

    steps:
      - name: checkout
        uses: actions/checkout@v2

      - name: test
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: 29
          script: ./gradlew connectedCheck

      - name: upload-artifacts
        uses: actions/upload-artifact@v2
        if: failure()
        with:
          name: test-report
          path: ${{ github.workspace }}/*/build/reports/


================================================
FILE: .github/workflows/lint.yml
================================================
name: Lint

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  lint:

    runs-on: ubuntu-latest

    steps:
      - name: checkout
        uses: actions/checkout@v2

      - name: set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: lint
        run: ./gradlew ktlint

      - name: CheckStyle
        run: ./gradlew checkJavaStyle


================================================
FILE: .github/workflows/release.yml
================================================
name: Release

on:
  release:
    types: [published]

jobs:
  run_final_checks:
    name: Run final checks
    runs-on: ubuntu-latest

    steps:
      - name: checkout
        uses: actions/checkout@v2
        with:
          ref: ${{ github.event.release.target_commitish }}
          token: ${{secrets.SERVICE_PERSONAL_ACCESS_TOKEN}}
          submodules: recursive

      - name: set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: lint
        run: ./gradlew ktlint

      - name: CheckStyle
        run: ./gradlew checkJavaStyle

      - name: test
        run: ./gradlew test

  finalize_release:
    needs: run_final_checks
    name: Finalize Release
    runs-on: ubuntu-latest

    steps:
      - name: checkout
        uses: actions/checkout@v2
        with:
          ref: ${{ github.event.release.target_commitish }}
          token: ${{secrets.SERVICE_PERSONAL_ACCESS_TOKEN}}
          submodules: recursive

      - name: get current tag
        id: get_tag
        run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}

      - name: update version
        env:
          TAG_VERSION: ${{ steps.get_tag.outputs.VERSION }}
        run: |
          truncate -s $(( $(stat -c "%s" gradle.properties) - $(tail -n 1 gradle.properties | wc -c) )) gradle.properties
          echo "version=$TAG_VERSION" >> gradle.properties
          cat gradle.properties

      - name: generate changelog
        uses: heinrichreimer/github-changelog-generator-action@v2.1.1
        with:
          user: "getbouncer"
          project: "cardscan-android"
          repo: "getbouncer/cardscan-android"
          token: ${{ secrets.SERVICE_PERSONAL_ACCESS_TOKEN }}
          sinceTag: "1.0.5151"
          pullRequests: "true"
          prWoLabels: "true"
          issues: "true"
          issuesWoLabels: "true"
          author: "true"
          base: "HISTORY.md"
          unreleased: "true"
          breakingLabels: "Versioning - BREAKING"
          enhancementLabels: "Type - Enhancement, Type - Feature"
          bugLabels: "Type - Fix, Bug - Fixed"
          deprecatedLabels: "Type - Deprecated"
          removedLabels: "Type - Removal"
          securityLabels: "Security Fix"
          excludeLabels: "Skip-Changelog"

      - name: create commit
        id: commit
        uses: stefanzweifel/git-auto-commit-action@v4
        with:
          branch: ${{ github.event.release.target_commitish }}
          commit_message: "Automatic changelog update"
          file_pattern: "gradle.properties CHANGELOG.md"

  publish:
    needs: finalize_release
    name: Publish to MavenCentral
    runs-on: ubuntu-latest

    steps:
      - name: checkout
        uses: actions/checkout@v2
        with:
          ref: ${{ github.event.release.target_commitish }}
          token: ${{secrets.SERVICE_PERSONAL_ACCESS_TOKEN}}
          submodules: recursive

      - name: set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      # Base64 decodes and pipes the GPG key content into the secret file
      - name: Prepare environment
        env:
          GPG_KEY_CONTENTS: ${{ secrets.GPG_KEY }}
          SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }}
        run: |
          git fetch --unshallow
          sudo bash -c "echo '$GPG_KEY_CONTENTS' | base64 -d > '$SIGNING_SECRET_KEY_RING_FILE'"

      - name: Build release
        run: ./gradlew assembleRelease

      - name: Source jar and dokka
        run: ./gradlew androidSourcesJar javadocJar

      - name: Publish to MavenCentral
        env:
          OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
          OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
          SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
          SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
          SIGNING_SECRET_KEY_RING_FILE: ${{ secrets.SIGNING_SECRET_KEY_RING_FILE }}
          SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }}
        run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository


================================================
FILE: .github/workflows/unit_test.yml
================================================
name: Unit Tests

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  test:

    runs-on: ubuntu-latest

    steps:
      - name: checkout
        uses: actions/checkout@v2

      - name: set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: test
        run: ./gradlew test

      - name: upload-artifacts
        uses: actions/upload-artifact@v2
        if: failure()
        with:
          name: test-report
          path: ${{ github.workspace }}/*/build/reports/


================================================
FILE: .github_changelog_generator
================================================
since-tag=2.0.0015


================================================
FILE: .gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/compiler.xml
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/.idea/encodings.xml
/.idea/gradle.xml
/.idea/misc.xml
/.idea/runConfigurations.xml
/.idea/vcs.xml
/.idea/dictionaries
/.idea/codeStyles/Project.xml
/.idea/codeStyles/codeStyleConfig.xml
/.idea/.name
/.idea/checkstyle-idea.xml
/.idea/jarRepositories.xml
.DS_Store
/build
/captures
.externalNativeBuild
langapiconfig.json
*.cxx
github_token


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## [2.2.0003](https://github.com/getbouncer/cardscan-android/tree/2.2.0003) (2022-06-15)

**Closed issues:**

- Crash when intent is null in parseResult callback [\#506](https://github.com/getbouncer/cardscan-android/issues/506)

**Merged pull requests:**

- Add deprecation notice to cardscan-android [\#523](https://github.com/getbouncer/cardscan-android/pull/523) ([awush-stripe](https://github.com/awush-stripe))
- Remove references to bouncer emails [\#508](https://github.com/getbouncer/cardscan-android/pull/508) ([awush-stripe](https://github.com/awush-stripe))

## [2.2.0002](https://github.com/getbouncer/cardscan-android/tree/2.2.0002) (2022-04-11)

**Closed issues:**

- failed to build in android studio bumblebee [\#494](https://github.com/getbouncer/cardscan-android/issues/494)

**Merged pull requests:**

- Prevent crash on null result intent [\#507](https://github.com/getbouncer/cardscan-android/pull/507) ([awush-stripe](https://github.com/awush-stripe))

## [2.2.0001](https://github.com/getbouncer/cardscan-android/tree/2.2.0001) (2022-03-28)

**Closed issues:**

- The new CardScanSheet API is not testable [\#493](https://github.com/getbouncer/cardscan-android/issues/493)
- The new CardScanSheet API is not testable [\#492](https://github.com/getbouncer/cardscan-android/issues/492)
- The new CardScanSheet API doesn't deliver result when starter activity is destroyed [\#491](https://github.com/getbouncer/cardscan-android/issues/491)
- Getbouncer console not accessible. [\#487](https://github.com/getbouncer/cardscan-android/issues/487)

**Merged pull requests:**

- Update the interface so reference to the callback is not lost on activity killed [\#499](https://github.com/getbouncer/cardscan-android/pull/499) ([awush-stripe](https://github.com/awush-stripe))
- Make the activity result registry testable [\#498](https://github.com/getbouncer/cardscan-android/pull/498) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0023](https://github.com/getbouncer/cardscan-android/tree/2.1.0023) (2022-01-18)

## [2.1.0022](https://github.com/getbouncer/cardscan-android/tree/2.1.0022) (2022-01-17)

## [2.1.0021](https://github.com/getbouncer/cardscan-android/tree/2.1.0021) (2022-01-06)

**Merged pull requests:**

- Simplify the API interface for CardScan [\#482](https://github.com/getbouncer/cardscan-android/pull/482) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0020](https://github.com/getbouncer/cardscan-android/tree/2.1.0020) (2021-12-21)

**Merged pull requests:**

- Correctly report final stats [\#475](https://github.com/getbouncer/cardscan-android/pull/475) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0019](https://github.com/getbouncer/cardscan-android/tree/2.1.0019) (2021-12-09)

## [2.1.0018](https://github.com/getbouncer/cardscan-android/tree/2.1.0018) (2021-10-20)

## [2.1.0017](https://github.com/getbouncer/cardscan-android/tree/2.1.0017) (2021-10-20)

**Merged pull requests:**

- Revert model storage file name [\#461](https://github.com/getbouncer/cardscan-android/pull/461) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0016](https://github.com/getbouncer/cardscan-android/tree/2.1.0016) (2021-10-04)

## [2.1.0015](https://github.com/getbouncer/cardscan-android/tree/2.1.0015) (2021-10-04)

**Merged pull requests:**

- Make prepareScan more accessible by using a callback [\#458](https://github.com/getbouncer/cardscan-android/pull/458) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0014](https://github.com/getbouncer/cardscan-android/tree/2.1.0014) (2021-09-24)

**Merged pull requests:**

- Fix memory leak and double camera unbind [\#456](https://github.com/getbouncer/cardscan-android/pull/456) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0014-alpha02](https://github.com/getbouncer/cardscan-android/tree/2.1.0014-alpha02) (2021-09-23)

## [2.1.0014-alpha01](https://github.com/getbouncer/cardscan-android/tree/2.1.0014-alpha01) (2021-09-17)

## [2.1.0014-downgrade-core-ktx01](https://github.com/getbouncer/cardscan-android/tree/2.1.0014-downgrade-core-ktx01) (2021-09-17)

## [2.1.0013](https://github.com/getbouncer/cardscan-android/tree/2.1.0013) (2021-09-17)

**Closed issues:**

- java.lang.RuntimeException: getParameters failed \(empty parameters\) [\#448](https://github.com/getbouncer/cardscan-android/issues/448)

**Merged pull requests:**

- Add stat tracking fetcher [\#451](https://github.com/getbouncer/cardscan-android/pull/451) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0012](https://github.com/getbouncer/cardscan-android/tree/2.1.0012) (2021-09-15)

**Merged pull requests:**

- Fix crash for Redmi Note 9 when camera closes prematurely [\#449](https://github.com/getbouncer/cardscan-android/pull/449) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0011](https://github.com/getbouncer/cardscan-android/tree/2.1.0011) (2021-09-08)

**Merged pull requests:**

- Destory created renderscript types [\#447](https://github.com/getbouncer/cardscan-android/pull/447) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0010](https://github.com/getbouncer/cardscan-android/tree/2.1.0010) (2021-09-01)

**Merged pull requests:**

- Allow ranges of dependencies [\#442](https://github.com/getbouncer/cardscan-android/pull/442) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0009](https://github.com/getbouncer/cardscan-android/tree/2.1.0009) (2021-07-29)

**Closed issues:**

- "Cannot add a null child view to a ViewGroup" Exception on Camera1Adapter [\#435](https://github.com/getbouncer/cardscan-android/issues/435)
- CardScanActivity vs CardScanFlow warmUp/prepareScan [\#434](https://github.com/getbouncer/cardscan-android/issues/434)
- Are Tensorflow/lite vulnerabilities a concern? [\#427](https://github.com/getbouncer/cardscan-android/issues/427)
- Expiry date overlay doesn't show [\#406](https://github.com/getbouncer/cardscan-android/issues/406)

**Merged pull requests:**

- Fix camera preview null crash and restrict CardScanFlow to library access [\#436](https://github.com/getbouncer/cardscan-android/pull/436) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0008](https://github.com/getbouncer/cardscan-android/tree/2.1.0008) (2021-07-19)

**Merged pull requests:**

- Simplify onScanReady [\#426](https://github.com/getbouncer/cardscan-android/pull/426) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0007](https://github.com/getbouncer/cardscan-android/tree/2.1.0007) (2021-07-15)

**Merged pull requests:**

- Downgrade kotlin gradle plugin [\#422](https://github.com/getbouncer/cardscan-android/pull/422) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0006](https://github.com/getbouncer/cardscan-android/tree/2.1.0006) (2021-07-15)

**Merged pull requests:**

- Downgrade kotlin methods in loop [\#421](https://github.com/getbouncer/cardscan-android/pull/421) ([awush-stripe](https://github.com/awush-stripe))
- Downgrade kotlin libraries to 1.4.3 [\#420](https://github.com/getbouncer/cardscan-android/pull/420) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0005-ktx1.4.3](https://github.com/getbouncer/cardscan-android/tree/2.1.0005-ktx1.4.3) (2021-07-15)

## [2.1.0005](https://github.com/getbouncer/cardscan-android/tree/2.1.0005) (2021-07-14)

**Merged pull requests:**

- Update dependencies [\#419](https://github.com/getbouncer/cardscan-android/pull/419) ([awush-stripe](https://github.com/awush-stripe))
- Update coroutines [\#418](https://github.com/getbouncer/cardscan-android/pull/418) ([awush-stripe](https://github.com/awush-stripe))
- Bump kotlin-test from 1.5.10 to 1.5.21 [\#417](https://github.com/getbouncer/cardscan-android/pull/417) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump org.jetbrains.kotlin.plugin.serialization from 1.5.10 to 1.5.21 [\#416](https://github.com/getbouncer/cardscan-android/pull/416) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump kotlin-gradle-plugin from 1.5.10 to 1.5.21 [\#415](https://github.com/getbouncer/cardscan-android/pull/415) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump junit from 1.1.2 to 1.1.3 [\#413](https://github.com/getbouncer/cardscan-android/pull/413) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump org.jetbrains.dokka from 1.4.32 to 1.5.0 [\#411](https://github.com/getbouncer/cardscan-android/pull/411) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump kotlinx-serialization-json from 1.2.1 to 1.2.2 [\#409](https://github.com/getbouncer/cardscan-android/pull/409) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump camera-view from 1.0.0-alpha25 to 1.0.0-alpha26 [\#405](https://github.com/getbouncer/cardscan-android/pull/405) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump espresso-core from 3.3.0 to 3.4.0 [\#404](https://github.com/getbouncer/cardscan-android/pull/404) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump runner from 1.3.0 to 1.4.0 [\#403](https://github.com/getbouncer/cardscan-android/pull/403) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump core from 1.3.0 to 1.4.0 [\#402](https://github.com/getbouncer/cardscan-android/pull/402) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump gradle from 4.2.1 to 4.2.2 [\#401](https://github.com/getbouncer/cardscan-android/pull/401) ([dependabot[bot]](https://github.com/apps/dependabot))

## [2.1.0004](https://github.com/getbouncer/cardscan-android/tree/2.1.0004) (2021-07-12)

**Closed issues:**

- Missing dependency on Maven Central updating to 2.1.0003 [\#407](https://github.com/getbouncer/cardscan-android/issues/407)

**Merged pull requests:**

- Fix deployment names for scan-payment-full and scan-payment-minimal. [\#408](https://github.com/getbouncer/cardscan-android/pull/408) ([awush-stripe](https://github.com/awush-stripe))
- Bump core-ktx from 1.5.0 to 1.6.0 [\#400](https://github.com/getbouncer/cardscan-android/pull/400) ([dependabot[bot]](https://github.com/apps/dependabot))
- Update card images used for testing [\#396](https://github.com/getbouncer/cardscan-android/pull/396) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0003](https://github.com/getbouncer/cardscan-android/tree/2.1.0003) (2021-06-18)

**Merged pull requests:**

- Cycle beta versions faster [\#395](https://github.com/getbouncer/cardscan-android/pull/395) ([awush-stripe](https://github.com/awush-stripe))
- Bump fragment-ktx from 1.3.4 to 1.3.5 [\#394](https://github.com/getbouncer/cardscan-android/pull/394) ([dependabot[bot]](https://github.com/apps/dependabot))

## [2.1.0002](https://github.com/getbouncer/cardscan-android/tree/2.1.0002) (2021-06-11)

**Closed issues:**

- Some card scans reversed [\#388](https://github.com/getbouncer/cardscan-android/issues/388)

**Merged pull requests:**

- Make scan ready checks JVM static [\#393](https://github.com/getbouncer/cardscan-android/pull/393) ([awush-stripe](https://github.com/awush-stripe))

## [2.1.0001](https://github.com/getbouncer/cardscan-android/tree/2.1.0001) (2021-06-11)

**Merged pull requests:**

- Add QR false positive detection check [\#392](https://github.com/getbouncer/cardscan-android/pull/392) ([awush-stripe](https://github.com/awush-stripe))
- Add check to determine if the scan is ready [\#391](https://github.com/getbouncer/cardscan-android/pull/391) ([awush-stripe](https://github.com/awush-stripe))
- Default to download OCR / UX models [\#390](https://github.com/getbouncer/cardscan-android/pull/390) ([awush-stripe](https://github.com/awush-stripe))
- Upgrade dependencies [\#389](https://github.com/getbouncer/cardscan-android/pull/389) ([awush-stripe](https://github.com/awush-stripe))

## [2.0.0090](https://github.com/getbouncer/cardscan-android/tree/2.0.0090) (2021-05-24)

## [2.0.0089](https://github.com/getbouncer/cardscan-android/tree/2.0.0089) (2021-05-24)

**Merged pull requests:**

- Use button margin dimensions [\#381](https://github.com/getbouncer/cardscan-android/pull/381) ([awush-stripe](https://github.com/awush-stripe))
- Bump appcompat from 1.2.0 to 1.3.0 [\#380](https://github.com/getbouncer/cardscan-android/pull/380) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump core-ktx from 1.3.2 to 1.5.0 [\#379](https://github.com/getbouncer/cardscan-android/pull/379) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump fragment-ktx from 1.3.3 to 1.3.4 [\#378](https://github.com/getbouncer/cardscan-android/pull/378) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump kotlinx-serialization-json from 1.2.0 to 1.2.1 [\#372](https://github.com/getbouncer/cardscan-android/pull/372) ([dependabot[bot]](https://github.com/apps/dependabot))

## [2.0.0088](https://github.com/getbouncer/cardscan-android/tree/2.0.0088) (2021-05-18)

**Merged pull requests:**

- Improve error handling around cache calculation [\#377](https://github.com/getbouncer/cardscan-android/pull/377) ([awushensky](https://github.com/awushensky))

## [2.0.0087](https://github.com/getbouncer/cardscan-android/tree/2.0.0087) (2021-05-13)

## [2.0.0086](https://github.com/getbouncer/cardscan-android/tree/2.0.0086) (2021-05-13)

**Merged pull requests:**

- Remove jcenter [\#370](https://github.com/getbouncer/cardscan-android/pull/370) ([awushensky](https://github.com/awushensky))

## [2.0.0085](https://github.com/getbouncer/cardscan-android/tree/2.0.0085) (2021-05-12)

**Closed issues:**

- Feature request: scan a vertical/portrait card [\#346](https://github.com/getbouncer/cardscan-android/issues/346)
- name and year extraction not working [\#336](https://github.com/getbouncer/cardscan-android/issues/336)

**Merged pull requests:**

- Bump gradle from 4.2.0 to 4.2.1 [\#371](https://github.com/getbouncer/cardscan-android/pull/371) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump activity-ktx from 1.2.2 to 1.2.3 [\#369](https://github.com/getbouncer/cardscan-android/pull/369) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump gradle from 4.1.3 to 4.2.0 [\#368](https://github.com/getbouncer/cardscan-android/pull/368) ([dependabot[bot]](https://github.com/apps/dependabot))
- Remove compile dependency on camerax [\#367](https://github.com/getbouncer/cardscan-android/pull/367) ([awushensky](https://github.com/awushensky))
- Support multiple cameras and add swap camera string [\#362](https://github.com/getbouncer/cardscan-android/pull/362) ([awushensky](https://github.com/awushensky))
- Upgrade to GitHub-native Dependabot [\#361](https://github.com/getbouncer/cardscan-android/pull/361) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlinx-serialization-json from 1.1.0 to 1.2.0 [\#360](https://github.com/getbouncer/cardscan-android/pull/360) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlin-test from 1.4.32 to 1.5.0 [\#359](https://github.com/getbouncer/cardscan-android/pull/359) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlin-gradle-plugin from 1.4.32 to 1.5.0 [\#358](https://github.com/getbouncer/cardscan-android/pull/358) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump org.jetbrains.kotlin.plugin.serialization from 1.4.32 to 1.5.0 [\#357](https://github.com/getbouncer/cardscan-android/pull/357) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump org.jetbrains.dokka from 1.4.30 to 1.4.32 [\#356](https://github.com/getbouncer/cardscan-android/pull/356) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump io.github.gradle-nexus.publish-plugin from 1.0.0 to 1.1.0 [\#354](https://github.com/getbouncer/cardscan-android/pull/354) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump fragment-ktx from 1.3.2 to 1.3.3 [\#351](https://github.com/getbouncer/cardscan-android/pull/351) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0084](https://github.com/getbouncer/cardscan-android/tree/2.0.0084) (2021-04-20)

**Closed issues:**

- Fatal exception due to wrong coroutine context [\#348](https://github.com/getbouncer/cardscan-android/issues/348)

**Merged pull requests:**

- Use camera2 APIs [\#347](https://github.com/getbouncer/cardscan-android/pull/347) ([awushensky](https://github.com/awushensky))

## [2.0.0083](https://github.com/getbouncer/cardscan-android/tree/2.0.0083) (2021-04-12)

**Merged pull requests:**

- Ensure camera error handler runs on main thread [\#349](https://github.com/getbouncer/cardscan-android/pull/349) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-serialization-json from 1.0.1 to 1.1.0 [\#340](https://github.com/getbouncer/cardscan-android/pull/340) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0082](https://github.com/getbouncer/cardscan-android/tree/2.0.0082) (2021-03-30)

## [2.0.0081](https://github.com/getbouncer/cardscan-android/tree/2.0.0081) (2021-03-30)

**Merged pull requests:**

- Correctly name the artifact for scan-payment-base [\#345](https://github.com/getbouncer/cardscan-android/pull/345) ([awushensky](https://github.com/awushensky))

## [2.0.0080](https://github.com/getbouncer/cardscan-android/tree/2.0.0080) (2021-03-30)

**Merged pull requests:**

- Update kotlin versions [\#344](https://github.com/getbouncer/cardscan-android/pull/344) ([awushensky](https://github.com/awushensky))
- Update release names [\#339](https://github.com/getbouncer/cardscan-android/pull/339) ([awushensky](https://github.com/awushensky))

## [2.0.0079](https://github.com/getbouncer/cardscan-android/tree/2.0.0079) (2021-03-27)

**Merged pull requests:**

- Swap to maven central [\#338](https://github.com/getbouncer/cardscan-android/pull/338) ([awushensky](https://github.com/awushensky))

## [2.0.0078](https://github.com/getbouncer/cardscan-android/tree/2.0.0078) (2021-03-26)

**Closed issues:**

- Require specifying ML models through dependencies [\#332](https://github.com/getbouncer/cardscan-android/issues/332)

**Merged pull requests:**

- Fix name and expiry extraction [\#337](https://github.com/getbouncer/cardscan-android/pull/337) ([awushensky](https://github.com/awushensky))
- Bump kotlin-test from 1.4.31 to 1.4.32 [\#335](https://github.com/getbouncer/cardscan-android/pull/335) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump org.jetbrains.kotlin.plugin.serialization from 1.4.31 to 1.4.32 [\#334](https://github.com/getbouncer/cardscan-android/pull/334) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlin-gradle-plugin from 1.4.31 to 1.4.32 [\#333](https://github.com/getbouncer/cardscan-android/pull/333) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Support minimal ML models [\#331](https://github.com/getbouncer/cardscan-android/pull/331) ([awushensky](https://github.com/awushensky))
- Bump gradle from 4.1.2 to 4.1.3 [\#330](https://github.com/getbouncer/cardscan-android/pull/330) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0077](https://github.com/getbouncer/cardscan-android/tree/2.0.0077) (2021-03-23)

**Merged pull requests:**

- Reduce sdk size [\#328](https://github.com/getbouncer/cardscan-android/pull/328) ([awushensky](https://github.com/awushensky))

## [2.0.0076](https://github.com/getbouncer/cardscan-android/tree/2.0.0076) (2021-03-09)

## [2.0.0075](https://github.com/getbouncer/cardscan-android/tree/2.0.0075) (2021-03-06)

**Merged pull requests:**

- Add version code [\#326](https://github.com/getbouncer/cardscan-android/pull/326) ([awushensky](https://github.com/awushensky))
- Upgrade gradle and kotlin [\#325](https://github.com/getbouncer/cardscan-android/pull/325) ([awushensky](https://github.com/awushensky))

## [2.0.0074](https://github.com/getbouncer/cardscan-android/tree/2.0.0074) (2021-02-18)

## [2.0.0073](https://github.com/getbouncer/cardscan-android/tree/2.0.0073) (2021-02-18)

**Closed issues:**

- java.lang.NoClassDefFoundError: Failed resolution of: Lorg/tensorflow/lite/Interpreter$Options in 2.0.0072 [\#319](https://github.com/getbouncer/cardscan-android/issues/319)
- Card scan crash on release [\#316](https://github.com/getbouncer/cardscan-android/issues/316)

**Merged pull requests:**

- Bump ktlint from 0.40.0 to 0.41.0 [\#329](https://github.com/getbouncer/cardscan-android/pull/329) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Allow configuring no model downloads [\#327](https://github.com/getbouncer/cardscan-android/pull/327) ([awushensky](https://github.com/awushensky))
- Make card number display optional [\#321](https://github.com/getbouncer/cardscan-android/pull/321) ([awushensky](https://github.com/awushensky))
- Bump junit from 4.13.1 to 4.13.2 [\#320](https://github.com/getbouncer/cardscan-android/pull/320) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Upgrade kotlin dependencies [\#318](https://github.com/getbouncer/cardscan-android/pull/318) ([awushensky](https://github.com/awushensky))
- Bump kotlin-test from 1.4.21 to 1.4.30 [\#315](https://github.com/getbouncer/cardscan-android/pull/315) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0072](https://github.com/getbouncer/cardscan-android/tree/2.0.0072) (2021-02-04)

**Closed issues:**

- Crash on animation [\#299](https://github.com/getbouncer/cardscan-android/issues/299)

**Merged pull requests:**

- Fix crash on fade animations when minifying resources [\#317](https://github.com/getbouncer/cardscan-android/pull/317) ([awushensky](https://github.com/awushensky))

## [2.0.0071](https://github.com/getbouncer/cardscan-android/tree/2.0.0071) (2021-02-01)

**Merged pull requests:**

- Custom tensorflow lite library [\#312](https://github.com/getbouncer/cardscan-android/pull/312) ([awushensky](https://github.com/awushensky))

## [2.0.0070](https://github.com/getbouncer/cardscan-android/tree/2.0.0070) (2021-01-29)

**Merged pull requests:**

- Separate ocr ux models [\#311](https://github.com/getbouncer/cardscan-android/pull/311) ([awushensky](https://github.com/awushensky))
- Do not expire old models [\#310](https://github.com/getbouncer/cardscan-android/pull/310) ([awushensky](https://github.com/awushensky))

## [2.0.0069](https://github.com/getbouncer/cardscan-android/tree/2.0.0069) (2021-01-27)

**Merged pull requests:**

- Add cardscan local [\#309](https://github.com/getbouncer/cardscan-android/pull/309) ([awushensky](https://github.com/awushensky))
- Bump gradle from 4.1.1 to 4.1.2 [\#308](https://github.com/getbouncer/cardscan-android/pull/308) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0068](https://github.com/getbouncer/cardscan-android/tree/2.0.0068) (2021-01-13)

**Merged pull requests:**

- Relocate payment card [\#307](https://github.com/getbouncer/cardscan-android/pull/307) ([awushensky](https://github.com/awushensky))

## [2.0.0067](https://github.com/getbouncer/cardscan-android/tree/2.0.0067) (2021-01-11)

## [2.0.0066](https://github.com/getbouncer/cardscan-android/tree/2.0.0066) (2021-01-09)

## [2.0.0065](https://github.com/getbouncer/cardscan-android/tree/2.0.0065) (2021-01-09)

**Merged pull requests:**

- Fix memoization race condition [\#306](https://github.com/getbouncer/cardscan-android/pull/306) ([awushensky](https://github.com/awushensky))

## [2.0.0064](https://github.com/getbouncer/cardscan-android/tree/2.0.0064) (2021-01-09)

**Merged pull requests:**

- Allow optional fetchers [\#305](https://github.com/getbouncer/cardscan-android/pull/305) ([awushensky](https://github.com/awushensky))

## [2.0.0063](https://github.com/getbouncer/cardscan-android/tree/2.0.0063) (2021-01-04)

## [2.0.0062](https://github.com/getbouncer/cardscan-android/tree/2.0.0062) (2020-12-31)

## [2.0.0061](https://github.com/getbouncer/cardscan-android/tree/2.0.0061) (2020-12-31)

**Merged pull requests:**

- Improve analyzer performance [\#301](https://github.com/getbouncer/cardscan-android/pull/301) ([awushensky](https://github.com/awushensky))

## [2.0.0060](https://github.com/getbouncer/cardscan-android/tree/2.0.0060) (2020-12-22)

## [2.0.0059](https://github.com/getbouncer/cardscan-android/tree/2.0.0059) (2020-12-21)

**Merged pull requests:**

- Improve low-end performance [\#300](https://github.com/getbouncer/cardscan-android/pull/300) ([awushensky](https://github.com/awushensky))
- Update kotlin test [\#298](https://github.com/getbouncer/cardscan-android/pull/298) ([awushensky](https://github.com/awushensky))
- Make normalizeCardNumber public [\#297](https://github.com/getbouncer/cardscan-android/pull/297) ([awushensky](https://github.com/awushensky))
- Bump tensorflow-lite from 2.3.0 to 2.4.0 [\#296](https://github.com/getbouncer/cardscan-android/pull/296) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0058](https://github.com/getbouncer/cardscan-android/tree/2.0.0058) (2020-12-15)

**Merged pull requests:**

- Fix clearing stats prematurely [\#295](https://github.com/getbouncer/cardscan-android/pull/295) ([awushensky](https://github.com/awushensky))

## [2.0.0057](https://github.com/getbouncer/cardscan-android/tree/2.0.0057) (2020-12-14)

**Closed issues:**

- Mention new introduced strings in changelog and docs. [\#291](https://github.com/getbouncer/cardscan-android/issues/291)

**Merged pull requests:**

- Use app context for network [\#294](https://github.com/getbouncer/cardscan-android/pull/294) ([awushensky](https://github.com/awushensky))
- Update serializer [\#293](https://github.com/getbouncer/cardscan-android/pull/293) ([awushensky](https://github.com/awushensky))
- Upgrade kotlin [\#292](https://github.com/getbouncer/cardscan-android/pull/292) ([awushensky](https://github.com/awushensky))
- Bump kotlin-test from 1.4.20 to 1.4.21 [\#290](https://github.com/getbouncer/cardscan-android/pull/290) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump org.jetbrains.kotlin.plugin.serialization from 1.4.20 to 1.4.21 [\#289](https://github.com/getbouncer/cardscan-android/pull/289) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlin-gradle-plugin from 1.4.20 to 1.4.21 [\#288](https://github.com/getbouncer/cardscan-android/pull/288) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump ktlint from 0.39.0 to 0.40.0 [\#287](https://github.com/getbouncer/cardscan-android/pull/287) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0056](https://github.com/getbouncer/cardscan-android/tree/2.0.0056) (2020-12-03)

**Closed issues:**

- Integration of the library shows this. [\#256](https://github.com/getbouncer/cardscan-android/issues/256)

**Merged pull requests:**

- Support expirys up to 100 years in the future [\#286](https://github.com/getbouncer/cardscan-android/pull/286) ([awushensky](https://github.com/awushensky))
- Support 3-digit CVC for amex [\#285](https://github.com/getbouncer/cardscan-android/pull/285) ([awushensky](https://github.com/awushensky))
- Upgrade dependencies [\#278](https://github.com/getbouncer/cardscan-android/pull/278) ([awushensky](https://github.com/awushensky))

## [2.0.0055](https://github.com/getbouncer/cardscan-android/tree/2.0.0055) (2020-11-25)

**Merged pull requests:**

- Support beta model opt-in [\#277](https://github.com/getbouncer/cardscan-android/pull/277) ([awushensky](https://github.com/awushensky))

## [2.0.0054](https://github.com/getbouncer/cardscan-android/tree/2.0.0054) (2020-11-19)

**Merged pull requests:**

- Use network stack for model downloads [\#270](https://github.com/getbouncer/cardscan-android/pull/270) ([awushensky](https://github.com/awushensky))
- Bump gradle from 4.1.0 to 4.1.1 [\#267](https://github.com/getbouncer/cardscan-android/pull/267) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump constraintlayout from 2.0.2 to 2.0.4 [\#262](https://github.com/getbouncer/cardscan-android/pull/262) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0053](https://github.com/getbouncer/cardscan-android/tree/2.0.0053) (2020-11-13)

**Merged pull requests:**

- Make permissions requests make more sense [\#269](https://github.com/getbouncer/cardscan-android/pull/269) ([awushensky](https://github.com/awushensky))

## [2.0.0052](https://github.com/getbouncer/cardscan-android/tree/2.0.0052) (2020-11-13)

**Merged pull requests:**

- Reset stats at scan start [\#268](https://github.com/getbouncer/cardscan-android/pull/268) ([awushensky](https://github.com/awushensky))

## [2.0.0051](https://github.com/getbouncer/cardscan-android/tree/2.0.0051) (2020-11-10)

**Merged pull requests:**

- Do not use Date.toString due to crashes [\#266](https://github.com/getbouncer/cardscan-android/pull/266) ([awushensky](https://github.com/awushensky))

## [2.0.0050](https://github.com/getbouncer/cardscan-android/tree/2.0.0050) (2020-10-26)

**Merged pull requests:**

- Upgrade gradle to 4.1.0 [\#257](https://github.com/getbouncer/cardscan-android/pull/257) ([awushensky](https://github.com/awushensky))
- Send model hash with info request [\#250](https://github.com/getbouncer/cardscan-android/pull/250) ([awushensky](https://github.com/awushensky))

## [2.0.0049](https://github.com/getbouncer/cardscan-android/tree/2.0.0049) (2020-10-21)

**Merged pull requests:**

- Name and expiry in completion loop [\#255](https://github.com/getbouncer/cardscan-android/pull/255) ([awushensky](https://github.com/awushensky))

## [2.0.0048](https://github.com/getbouncer/cardscan-android/tree/2.0.0048) (2020-10-19)

**Merged pull requests:**

- Use latest version in loader [\#254](https://github.com/getbouncer/cardscan-android/pull/254) ([awushensky](https://github.com/awushensky))
- Fix stats concurrent modification [\#253](https://github.com/getbouncer/cardscan-android/pull/253) ([awushensky](https://github.com/awushensky))
- Enable delay analysis [\#252](https://github.com/getbouncer/cardscan-android/pull/252) ([awushensky](https://github.com/awushensky))

## [2.0.0047](https://github.com/getbouncer/cardscan-android/tree/2.0.0047) (2020-10-15)

**Merged pull requests:**

- Remove autofocus feature requirement [\#251](https://github.com/getbouncer/cardscan-android/pull/251) ([awushensky](https://github.com/awushensky))

## [1.0.5155](https://github.com/getbouncer/cardscan-android/tree/1.0.5155) (2020-10-15)

## [2.0.0046](https://github.com/getbouncer/cardscan-android/tree/2.0.0046) (2020-10-14)

## [2.0.0045](https://github.com/getbouncer/cardscan-android/tree/2.0.0045) (2020-10-12)

**Merged pull requests:**

- Upgrade gradle [\#248](https://github.com/getbouncer/cardscan-android/pull/248) ([awushensky](https://github.com/awushensky))
- Force model download if no cache [\#247](https://github.com/getbouncer/cardscan-android/pull/247) ([awushensky](https://github.com/awushensky))
- Bump junit from 4.13 to 4.13.1 [\#246](https://github.com/getbouncer/cardscan-android/pull/246) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump constraintlayout from 2.0.1 to 2.0.2 [\#241](https://github.com/getbouncer/cardscan-android/pull/241) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [1.0.5153](https://github.com/getbouncer/cardscan-android/tree/1.0.5153) (2020-10-09)

## [1.0.5154](https://github.com/getbouncer/cardscan-android/tree/1.0.5154) (2020-10-09)

**Merged pull requests:**

- Fix zoom image [\#245](https://github.com/getbouncer/cardscan-android/pull/245) ([awushensky](https://github.com/awushensky))
- Support zoomed model [\#236](https://github.com/getbouncer/cardscan-android/pull/236) ([awushensky](https://github.com/awushensky))

## [2.0.0044](https://github.com/getbouncer/cardscan-android/tree/2.0.0044) (2020-10-09)

**Merged pull requests:**

- Parallelize model downloads [\#244](https://github.com/getbouncer/cardscan-android/pull/244) ([awushensky](https://github.com/awushensky))
- Clean up some OCR [\#243](https://github.com/getbouncer/cardscan-android/pull/243) ([awushensky](https://github.com/awushensky))
- Improve fetcher logging [\#242](https://github.com/getbouncer/cardscan-android/pull/242) ([awushensky](https://github.com/awushensky))
- Target android 30 [\#240](https://github.com/getbouncer/cardscan-android/pull/240) ([awushensky](https://github.com/awushensky))

## [2.0.0043](https://github.com/getbouncer/cardscan-android/tree/2.0.0043) (2020-10-06)

**Merged pull requests:**

- Fix autofocus more [\#239](https://github.com/getbouncer/cardscan-android/pull/239) ([awushensky](https://github.com/awushensky))
- Remove camera1 autofocus repeater [\#238](https://github.com/getbouncer/cardscan-android/pull/238) ([awushensky](https://github.com/awushensky))
- Clean up image utils [\#237](https://github.com/getbouncer/cardscan-android/pull/237) ([awushensky](https://github.com/awushensky))

## [1.0.5152](https://github.com/getbouncer/cardscan-android/tree/1.0.5152) (2020-10-05)

**Merged pull requests:**

- Upgrade ocr model [\#235](https://github.com/getbouncer/cardscan-android/pull/235) ([awushensky](https://github.com/awushensky))

## [2.0.0042](https://github.com/getbouncer/cardscan-android/tree/2.0.0042) (2020-10-02)

**Merged pull requests:**

- Support model upgrade delay [\#234](https://github.com/getbouncer/cardscan-android/pull/234) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.3.1 to 1.3.2 [\#233](https://github.com/getbouncer/cardscan-android/pull/233) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0041](https://github.com/getbouncer/cardscan-android/tree/2.0.0041) (2020-10-02)

## [2.0.0040](https://github.com/getbouncer/cardscan-android/tree/2.0.0040) (2020-10-01)

**Merged pull requests:**

- Fix cancelation memory leak [\#232](https://github.com/getbouncer/cardscan-android/pull/232) ([awushensky](https://github.com/awushensky))
- Fix frame saver memory leak [\#231](https://github.com/getbouncer/cardscan-android/pull/231) ([awushensky](https://github.com/awushensky))

## [2.0.0039](https://github.com/getbouncer/cardscan-android/tree/2.0.0039) (2020-09-30)

**Merged pull requests:**

- Tune the name & expiry extraction analyzers [\#230](https://github.com/getbouncer/cardscan-android/pull/230) ([awushensky](https://github.com/awushensky))
- Split main loop [\#229](https://github.com/getbouncer/cardscan-android/pull/229) ([awushensky](https://github.com/awushensky))
- Calculate and adapt to device speed [\#228](https://github.com/getbouncer/cardscan-android/pull/228) ([awushensky](https://github.com/awushensky))
- Prevent duplicate final results [\#227](https://github.com/getbouncer/cardscan-android/pull/227) ([awushensky](https://github.com/awushensky))

## [2.0.0038](https://github.com/getbouncer/cardscan-android/tree/2.0.0038) (2020-09-25)

**Merged pull requests:**

- Clean up resources [\#226](https://github.com/getbouncer/cardscan-android/pull/226) ([awushensky](https://github.com/awushensky))

## [2.0.0037](https://github.com/getbouncer/cardscan-android/tree/2.0.0037) (2020-09-25)

**Closed issues:**

- Demo app crashed [\#223](https://github.com/getbouncer/cardscan-android/issues/223)

## [2.0.0036](https://github.com/getbouncer/cardscan-android/tree/2.0.0036) (2020-09-24)

**Merged pull requests:**

- Clean up single activity demo [\#225](https://github.com/getbouncer/cardscan-android/pull/225) ([awushensky](https://github.com/awushensky))

## [2.0.0035](https://github.com/getbouncer/cardscan-android/tree/2.0.0035) (2020-09-24)

**Merged pull requests:**

- Fix crash on single activity demo [\#224](https://github.com/getbouncer/cardscan-android/pull/224) ([awushensky](https://github.com/awushensky))
- Clean up UI changes [\#222](https://github.com/getbouncer/cardscan-android/pull/222) ([awushensky](https://github.com/awushensky))
- Add java continuation support [\#221](https://github.com/getbouncer/cardscan-android/pull/221) ([awushensky](https://github.com/awushensky))
- Create programmatic UI [\#217](https://github.com/getbouncer/cardscan-android/pull/217) ([awushensky](https://github.com/awushensky))

## [2.0.0034](https://github.com/getbouncer/cardscan-android/tree/2.0.0034) (2020-09-22)

**Merged pull requests:**

- Allow manual camera pause [\#216](https://github.com/getbouncer/cardscan-android/pull/216) ([awushensky](https://github.com/awushensky))
- Bump kotlin-stdlib-jdk7 from 1.4.0 to 1.4.10 [\#215](https://github.com/getbouncer/cardscan-android/pull/215) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlin-test from 1.4.0 to 1.4.10 [\#214](https://github.com/getbouncer/cardscan-android/pull/214) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump ktlint from 0.38.1 to 0.39.0 [\#213](https://github.com/getbouncer/cardscan-android/pull/213) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0033](https://github.com/getbouncer/cardscan-android/tree/2.0.0033) (2020-09-17)

## [2.0.0032](https://github.com/getbouncer/cardscan-android/tree/2.0.0032) (2020-09-11)

**Merged pull requests:**

- Fix a camera crash on revvl2 devices [\#212](https://github.com/getbouncer/cardscan-android/pull/212) ([awushensky](https://github.com/awushensky))
- Support better camera autofocus [\#211](https://github.com/getbouncer/cardscan-android/pull/211) ([awushensky](https://github.com/awushensky))
- Update state machine tests [\#210](https://github.com/getbouncer/cardscan-android/pull/210) ([awushensky](https://github.com/awushensky))
- Bump kotlin-gradle-plugin from 1.4.0 to 1.4.10 [\#209](https://github.com/getbouncer/cardscan-android/pull/209) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump org.jetbrains.kotlin.plugin.serialization from 1.4.0 to 1.4.10 [\#208](https://github.com/getbouncer/cardscan-android/pull/208) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0031](https://github.com/getbouncer/cardscan-android/tree/2.0.0031) (2020-09-11)

**Merged pull requests:**

- fixes the bitmap test [\#207](https://github.com/getbouncer/cardscan-android/pull/207) ([dxaen](https://github.com/dxaen))

## [2.0.0030](https://github.com/getbouncer/cardscan-android/tree/2.0.0030) (2020-09-08)

**Closed issues:**

- Analyzer failure with DexGuard enabled [\#202](https://github.com/getbouncer/cardscan-android/issues/202)

**Merged pull requests:**

- Add unit tests for cardscan state machine [\#206](https://github.com/getbouncer/cardscan-android/pull/206) ([awushensky](https://github.com/awushensky))
- Quick read support for android [\#203](https://github.com/getbouncer/cardscan-android/pull/203) ([dxaen](https://github.com/dxaen))

## [2.0.0029](https://github.com/getbouncer/cardscan-android/tree/2.0.0029) (2020-09-08)

**Merged pull requests:**

- Add proguard rules for tensorflow [\#205](https://github.com/getbouncer/cardscan-android/pull/205) ([awushensky](https://github.com/awushensky))
- Standardize expiry to strings [\#204](https://github.com/getbouncer/cardscan-android/pull/204) ([awushensky](https://github.com/awushensky))

## [2.0.0028](https://github.com/getbouncer/cardscan-android/tree/2.0.0028) (2020-09-03)

**Merged pull requests:**

- Open up the UI [\#201](https://github.com/getbouncer/cardscan-android/pull/201) ([awushensky](https://github.com/awushensky))
- Add card payment type data [\#198](https://github.com/getbouncer/cardscan-android/pull/198) ([awushensky](https://github.com/awushensky))

## [2.0.0027](https://github.com/getbouncer/cardscan-android/tree/2.0.0027) (2020-09-01)

**Merged pull requests:**

- Clean up state machine [\#199](https://github.com/getbouncer/cardscan-android/pull/199) ([awushensky](https://github.com/awushensky))

## [2.0.0026](https://github.com/getbouncer/cardscan-android/tree/2.0.0026) (2020-08-27)

**Merged pull requests:**

- Bump junit from 1.1.1 to 1.1.2 [\#197](https://github.com/getbouncer/cardscan-android/pull/197) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump espresso-core from 3.2.0 to 3.3.0 [\#196](https://github.com/getbouncer/cardscan-android/pull/196) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump runner from 1.2.0 to 1.3.0 [\#195](https://github.com/getbouncer/cardscan-android/pull/195) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump core from 1.2.0 to 1.3.0 [\#194](https://github.com/getbouncer/cardscan-android/pull/194) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump constraintlayout from 2.0.0 to 2.0.1 [\#193](https://github.com/getbouncer/cardscan-android/pull/193) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0025](https://github.com/getbouncer/cardscan-android/tree/2.0.0025) (2020-08-24)

**Merged pull requests:**

- Bump constraintlayout from 1.1.3 to 2.0.0 [\#192](https://github.com/getbouncer/cardscan-android/pull/192) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0024](https://github.com/getbouncer/cardscan-android/tree/2.0.0024) (2020-08-21)

## [2.0.0023](https://github.com/getbouncer/cardscan-android/tree/2.0.0023) (2020-08-21)

**Merged pull requests:**

- Enable minification on cardscan demo [\#191](https://github.com/getbouncer/cardscan-android/pull/191) ([awushensky](https://github.com/awushensky))
- Relocate ktlint [\#190](https://github.com/getbouncer/cardscan-android/pull/190) ([awushensky](https://github.com/awushensky))
- Fix accessibility descriptions [\#189](https://github.com/getbouncer/cardscan-android/pull/189) ([awushensky](https://github.com/awushensky))

## [2.0.0022](https://github.com/getbouncer/cardscan-android/tree/2.0.0022) (2020-08-18)

## [2.0.0021](https://github.com/getbouncer/cardscan-android/tree/2.0.0021) (2020-08-18)

**Closed issues:**

- How to scan other types of cards? [\#150](https://github.com/getbouncer/cardscan-android/issues/150)

**Merged pull requests:**

- Chang custom card issuer [\#185](https://github.com/getbouncer/cardscan-android/pull/185) ([smkuhne](https://github.com/smkuhne))
- Bump kotlinx-serialization-runtime from 1.0-M1-1.4.0-rc to 1.0-M1-1.4.0-rc-218 [\#184](https://github.com/getbouncer/cardscan-android/pull/184) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add custom pans [\#183](https://github.com/getbouncer/cardscan-android/pull/183) ([smkuhne](https://github.com/smkuhne))
- Update dependencies [\#182](https://github.com/getbouncer/cardscan-android/pull/182) ([awushensky](https://github.com/awushensky))
- Local rules [\#181](https://github.com/getbouncer/cardscan-android/pull/181) ([awushensky](https://github.com/awushensky))

## [2.0.0020](https://github.com/getbouncer/cardscan-android/tree/2.0.0020) (2020-08-13)

**Closed issues:**

- Crash on android 5 Lenovo [\#89](https://github.com/getbouncer/cardscan-android/issues/89)

**Merged pull requests:**

- Add aspect ratio method [\#173](https://github.com/getbouncer/cardscan-android/pull/173) ([smkuhne](https://github.com/smkuhne))
- Prevent crash on bad model download [\#172](https://github.com/getbouncer/cardscan-android/pull/172) ([awushensky](https://github.com/awushensky))

## [2.0.0019](https://github.com/getbouncer/cardscan-android/tree/2.0.0019) (2020-08-12)

**Merged pull requests:**

- Fix display bug [\#171](https://github.com/getbouncer/cardscan-android/pull/171) ([awushensky](https://github.com/awushensky))
- Support extracting iin and last4 from utils [\#170](https://github.com/getbouncer/cardscan-android/pull/170) ([awushensky](https://github.com/awushensky))
- Add check result [\#169](https://github.com/getbouncer/cardscan-android/pull/169) ([awushensky](https://github.com/awushensky))
- Bump appcompat from 1.1.0 to 1.2.0 [\#168](https://github.com/getbouncer/cardscan-android/pull/168) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add zoomOffset method [\#167](https://github.com/getbouncer/cardscan-android/pull/167) ([smkuhne](https://github.com/smkuhne))
- Use key without permissions for test [\#166](https://github.com/getbouncer/cardscan-android/pull/166) ([awushensky](https://github.com/awushensky))
- Update expiry timeout, handle new permissions [\#165](https://github.com/getbouncer/cardscan-android/pull/165) ([xsl](https://github.com/xsl))
- Add documentation [\#164](https://github.com/getbouncer/cardscan-android/pull/164) ([awushensky](https://github.com/awushensky))
- Bump tensorflow-lite from 2.2.0 to 2.3.0 [\#163](https://github.com/getbouncer/cardscan-android/pull/163) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump core-ktx from 1.3.0 to 1.3.1 [\#159](https://github.com/getbouncer/cardscan-android/pull/159) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0018](https://github.com/getbouncer/cardscan-android/tree/2.0.0018) (2020-07-28)

**Closed issues:**

- name and expiry date [\#82](https://github.com/getbouncer/cardscan-android/issues/82)

**Merged pull requests:**

- Clean up counters [\#162](https://github.com/getbouncer/cardscan-android/pull/162) ([awushensky](https://github.com/awushensky))
- Clean up state machine logic [\#161](https://github.com/getbouncer/cardscan-android/pull/161) ([awushensky](https://github.com/awushensky))
- Clean up state machine [\#160](https://github.com/getbouncer/cardscan-android/pull/160) ([awushensky](https://github.com/awushensky))
- Main loop state machine [\#158](https://github.com/getbouncer/cardscan-android/pull/158) ([awushensky](https://github.com/awushensky))

## [2.0.0017](https://github.com/getbouncer/cardscan-android/tree/2.0.0017) (2020-07-22)

**Merged pull requests:**

- Update api key validation check [\#156](https://github.com/getbouncer/cardscan-android/pull/156) ([awushensky](https://github.com/awushensky))
- Update changelog [\#155](https://github.com/getbouncer/cardscan-android/pull/155) ([smkuhne](https://github.com/smkuhne))

## [2.0.0016](https://github.com/getbouncer/cardscan-android/tree/2.0.0016) (2020-07-20)

**Merged pull requests:**

- Bump version to 2.0.0016 [\#154](https://github.com/getbouncer/cardscan-android/pull/154) ([smkuhne](https://github.com/smkuhne))
- Add readmes [\#153](https://github.com/getbouncer/cardscan-android/pull/153) ([awushensky](https://github.com/awushensky))
- Rename demo module [\#152](https://github.com/getbouncer/cardscan-android/pull/152) ([awushensky](https://github.com/awushensky))

## [2.0.0015](https://github.com/getbouncer/cardscan-android/tree/2.0.0015) (2020-07-18)

**Merged pull requests:**

- Restructure 2.0 [\#151](https://github.com/getbouncer/cardscan-android/pull/151) ([awushensky](https://github.com/awushensky))

## [2.0.0014](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0014) (2020-07-14)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0013...2.0.0014)

**Merged pull requests:**

- Image fragmentation [\#53](https://github.com/getbouncer/scan-framework-android/pull/53) ([smkuhne](https://github.com/smkuhne))
- Standardize models [\#35](https://github.com/getbouncer/scan-payment-android/pull/35) ([awushensky](https://github.com/awushensky))
- Image fragmentation [\#33](https://github.com/getbouncer/scan-payment-android/pull/33) ([smkuhne](https://github.com/smkuhne))
- Allow extending uploadstats [\#30](https://github.com/getbouncer/scan-ui-android/pull/30) ([awushensky](https://github.com/awushensky))
- Image fragmentation [\#28](https://github.com/getbouncer/scan-ui-android/pull/28) ([smkuhne](https://github.com/smkuhne))

## [2.0.0013](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0013) (2020-07-08)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0012...2.0.0013)

**Merged pull requests:**

- Bump ktlint from 0.37.0 to 0.37.2 [\#59](https://github.com/getbouncer/cardscan-demo-android/pull/59) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Use new warmup initializer [\#58](https://github.com/getbouncer/cardscan-demo-android/pull/58) ([xsl](https://github.com/xsl))
- Update UI [\#57](https://github.com/getbouncer/cardscan-demo-android/pull/57) ([awushensky](https://github.com/awushensky))
- Update for expiry extraction + new text detector [\#56](https://github.com/getbouncer/cardscan-demo-android/pull/56) ([xsl](https://github.com/xsl))
- Add more java interoperability [\#57](https://github.com/getbouncer/scan-framework-android/pull/57) ([awushensky](https://github.com/awushensky))
- Relocate loop state to result [\#56](https://github.com/getbouncer/scan-framework-android/pull/56) ([awushensky](https://github.com/awushensky))
- Add more memoize functions [\#55](https://github.com/getbouncer/scan-framework-android/pull/55) ([awushensky](https://github.com/awushensky))
- Separate error listeners [\#54](https://github.com/getbouncer/scan-framework-android/pull/54) ([awushensky](https://github.com/awushensky))
- Fix work leak [\#52](https://github.com/getbouncer/scan-framework-android/pull/52) ([awushensky](https://github.com/awushensky))
- Test duration [\#51](https://github.com/getbouncer/scan-framework-android/pull/51) ([awushensky](https://github.com/awushensky))
- Clean up network responses [\#49](https://github.com/getbouncer/scan-framework-android/pull/49) ([awushensky](https://github.com/awushensky))
- Add exceptions to retry [\#48](https://github.com/getbouncer/scan-framework-android/pull/48) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.37.0 to 0.37.2 [\#46](https://github.com/getbouncer/scan-framework-android/pull/46) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add device identifier to network requests [\#45](https://github.com/getbouncer/scan-framework-android/pull/45) ([awushensky](https://github.com/awushensky))
- Standardize local file name [\#44](https://github.com/getbouncer/scan-framework-android/pull/44) ([awushensky](https://github.com/awushensky))
- Add some convenience functions [\#43](https://github.com/getbouncer/scan-framework-android/pull/43) ([xsl](https://github.com/xsl))
- Launch the camera on IO dispatcher [\#32](https://github.com/getbouncer/scan-camera-android/pull/32) ([awushensky](https://github.com/awushensky))
- Relocate analyzers [\#34](https://github.com/getbouncer/scan-payment-android/pull/34) ([awushensky](https://github.com/awushensky))
- Support multiple MM/YYs on cards [\#32](https://github.com/getbouncer/scan-payment-android/pull/32) ([xsl](https://github.com/xsl))
- Bump ktlint from 0.37.0 to 0.37.2 [\#31](https://github.com/getbouncer/scan-payment-android/pull/31) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Expiry extraction + new text detector [\#30](https://github.com/getbouncer/scan-payment-android/pull/30) ([xsl](https://github.com/xsl))
- Update submodule [\#29](https://github.com/getbouncer/scan-ui-android/pull/29) ([awushensky](https://github.com/awushensky))
- Separate scan stats [\#27](https://github.com/getbouncer/scan-ui-android/pull/27) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.37.0 to 0.37.2 [\#26](https://github.com/getbouncer/scan-ui-android/pull/26) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add initialization error strings [\#25](https://github.com/getbouncer/scan-ui-android/pull/25) ([xsl](https://github.com/xsl))
- Update UI [\#24](https://github.com/getbouncer/scan-ui-android/pull/24) ([awushensky](https://github.com/awushensky))
- Update scan-framework-android submodule [\#23](https://github.com/getbouncer/scan-ui-android/pull/23) ([xsl](https://github.com/xsl))
- Shut down analyzer context on quit [\#38](https://github.com/getbouncer/cardscan-ui-android/pull/38) ([awushensky](https://github.com/awushensky))
- Separate loop logic [\#37](https://github.com/getbouncer/cardscan-ui-android/pull/37) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.37.0 to 0.37.2 [\#35](https://github.com/getbouncer/cardscan-ui-android/pull/35) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update ui [\#34](https://github.com/getbouncer/cardscan-ui-android/pull/34) ([awushensky](https://github.com/awushensky))
- Warmup name and expiry [\#33](https://github.com/getbouncer/cardscan-ui-android/pull/33) ([xsl](https://github.com/xsl))
- Expiry extraction + new text detector [\#32](https://github.com/getbouncer/cardscan-ui-android/pull/32) ([xsl](https://github.com/xsl))

## [2.0.0012](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0012) (2020-06-15)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0011...2.0.0012)

**Merged pull requests:**

- Rename warm up [\#55](https://github.com/getbouncer/cardscan-demo-android/pull/55) ([awushensky](https://github.com/awushensky))
- Use flows instead of channels [\#42](https://github.com/getbouncer/scan-framework-android/pull/42) ([awushensky](https://github.com/awushensky))
- Use channels better [\#41](https://github.com/getbouncer/scan-framework-android/pull/41) ([awushensky](https://github.com/awushensky))
- Fix framerate average calculation [\#40](https://github.com/getbouncer/scan-framework-android/pull/40) ([awushensky](https://github.com/awushensky))
- Make result handlers listen to a lifecycle [\#39](https://github.com/getbouncer/scan-framework-android/pull/39) ([awushensky](https://github.com/awushensky))
- Move images out of framework [\#38](https://github.com/getbouncer/scan-framework-android/pull/38) ([awushensky](https://github.com/awushensky))
- Support java interop [\#37](https://github.com/getbouncer/scan-framework-android/pull/37) ([awushensky](https://github.com/awushensky))
- Fix camera crash on flash not supported [\#30](https://github.com/getbouncer/scan-camera-android/pull/30) ([awushensky](https://github.com/awushensky))
- Increase the channel buffer size to 2 [\#29](https://github.com/getbouncer/scan-camera-android/pull/29) ([awushensky](https://github.com/awushensky))
- Reintroduce camera2 [\#28](https://github.com/getbouncer/scan-camera-android/pull/28) ([awushensky](https://github.com/awushensky))
- Centralize the channel logic [\#27](https://github.com/getbouncer/scan-camera-android/pull/27) ([awushensky](https://github.com/awushensky))
- Remove framework submodule [\#26](https://github.com/getbouncer/scan-camera-android/pull/26) ([awushensky](https://github.com/awushensky))
- Add timing to ssdocr input [\#29](https://github.com/getbouncer/scan-payment-android/pull/29) ([awushensky](https://github.com/awushensky))
- Relocate test resources [\#28](https://github.com/getbouncer/scan-payment-android/pull/28) ([awushensky](https://github.com/awushensky))
- Relocate image manipulation utilities [\#27](https://github.com/getbouncer/scan-payment-android/pull/27) ([awushensky](https://github.com/awushensky))
- Use flows [\#22](https://github.com/getbouncer/scan-ui-android/pull/22) ([awushensky](https://github.com/awushensky))
- Relocate scan process [\#21](https://github.com/getbouncer/scan-ui-android/pull/21) ([awushensky](https://github.com/awushensky))
- Separate framework from camera [\#20](https://github.com/getbouncer/scan-ui-android/pull/20) ([awushensky](https://github.com/awushensky))
- Handle devices without cameras [\#19](https://github.com/getbouncer/scan-ui-android/pull/19) ([awushensky](https://github.com/awushensky))
- Reduce jitter in name display [\#31](https://github.com/getbouncer/cardscan-ui-android/pull/31) ([awushensky](https://github.com/awushensky))
- Fix analyzer pool memory leak [\#30](https://github.com/getbouncer/cardscan-ui-android/pull/30) ([awushensky](https://github.com/awushensky))
- Actually reset the result aggregator [\#29](https://github.com/getbouncer/cardscan-ui-android/pull/29) ([awushensky](https://github.com/awushensky))
- Relocate scan logic [\#28](https://github.com/getbouncer/cardscan-ui-android/pull/28) ([awushensky](https://github.com/awushensky))
- Relocate scan flow to implementation [\#27](https://github.com/getbouncer/cardscan-ui-android/pull/27) ([awushensky](https://github.com/awushensky))
- Separate camera and loops [\#26](https://github.com/getbouncer/cardscan-ui-android/pull/26) ([awushensky](https://github.com/awushensky))

## [2.0.0011](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0011) (2020-06-08)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0009...2.0.0011)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0010...2.0.0011)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0010...2.0.0011)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0010...2.0.0011)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0010...2.0.0011)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0009...2.0.0011)

**Merged pull requests:**

- Support separate name extraction parameters [\#54](https://github.com/getbouncer/cardscan-demo-android/pull/54) ([awushensky](https://github.com/awushensky))
- Add docs and buttons for name extraction [\#53](https://github.com/getbouncer/cardscan-demo-android/pull/53) ([xsl](https://github.com/xsl))
- Reduce name extraction settings [\#52](https://github.com/getbouncer/cardscan-demo-android/pull/52) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#51](https://github.com/getbouncer/cardscan-demo-android/pull/51) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update for name extraction [\#50](https://github.com/getbouncer/cardscan-demo-android/pull/50) ([xsl](https://github.com/xsl))
- Bump gradle from 3.6.3 to 4.0.0 [\#47](https://github.com/getbouncer/cardscan-demo-android/pull/47) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update coroutine interoperability [\#36](https://github.com/getbouncer/scan-framework-android/pull/36) ([awushensky](https://github.com/awushensky))
- Standardize result counter [\#35](https://github.com/getbouncer/scan-framework-android/pull/35) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#34](https://github.com/getbouncer/scan-framework-android/pull/34) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add memoization functions [\#33](https://github.com/getbouncer/scan-framework-android/pull/33) ([awushensky](https://github.com/awushensky))
- Don't retry on FileNotFoundExceptions [\#32](https://github.com/getbouncer/scan-framework-android/pull/32) ([xsl](https://github.com/xsl))
- Update image utilities [\#31](https://github.com/getbouncer/scan-framework-android/pull/31) ([awushensky](https://github.com/awushensky))
- Use default dispatcher for camera [\#25](https://github.com/getbouncer/scan-camera-android/pull/25) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#24](https://github.com/getbouncer/scan-camera-android/pull/24) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update submodule [\#23](https://github.com/getbouncer/scan-camera-android/pull/23) ([xsl](https://github.com/xsl))
- Update image utils [\#22](https://github.com/getbouncer/scan-camera-android/pull/22) ([awushensky](https://github.com/awushensky))
- Remove threadsafe flag [\#26](https://github.com/getbouncer/scan-payment-android/pull/26) ([awushensky](https://github.com/awushensky))
- Minor tuning for name extraction [\#25](https://github.com/getbouncer/scan-payment-android/pull/25) ([xsl](https://github.com/xsl))
- Relocate object detect test [\#24](https://github.com/getbouncer/scan-payment-android/pull/24) ([awushensky](https://github.com/awushensky))
- Remove debug log [\#23](https://github.com/getbouncer/scan-payment-android/pull/23) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#22](https://github.com/getbouncer/scan-payment-android/pull/22) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update image utils [\#21](https://github.com/getbouncer/scan-payment-android/pull/21) ([awushensky](https://github.com/awushensky))
- Add NameDetectAnalyzer and move object detector over \(for now at least\) [\#20](https://github.com/getbouncer/scan-payment-android/pull/20) ([xsl](https://github.com/xsl))
- Remove unnecessary manifest entries [\#18](https://github.com/getbouncer/scan-ui-android/pull/18) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#17](https://github.com/getbouncer/scan-ui-android/pull/17) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Introduce fadeIn duration config and update card border animation duration [\#16](https://github.com/getbouncer/scan-ui-android/pull/16) ([xsl](https://github.com/xsl))
- Support java interoperability [\#25](https://github.com/getbouncer/cardscan-ui-android/pull/25) ([awushensky](https://github.com/awushensky))
- Enable disabling name extraction on start [\#24](https://github.com/getbouncer/cardscan-ui-android/pull/24) ([awushensky](https://github.com/awushensky))
- Update scan payments submodule [\#23](https://github.com/getbouncer/cardscan-ui-android/pull/23) ([xsl](https://github.com/xsl))
- Use default dispatchers [\#22](https://github.com/getbouncer/cardscan-ui-android/pull/22) ([awushensky](https://github.com/awushensky))
- Reduce settings for name extractor [\#21](https://github.com/getbouncer/cardscan-ui-android/pull/21) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#20](https://github.com/getbouncer/cardscan-ui-android/pull/20) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update image utils [\#19](https://github.com/getbouncer/cardscan-ui-android/pull/19) ([awushensky](https://github.com/awushensky))
- Name extraction v1 w/ old object detector [\#18](https://github.com/getbouncer/cardscan-ui-android/pull/18) ([xsl](https://github.com/xsl))
- Bump gradle from 3.6.3 to 4.0.0 [\#17](https://github.com/getbouncer/cardscan-ui-android/pull/17) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0010](https://github.com/getbouncer/scan-framework-android/tree/2.0.0010) (2020-05-30)

[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0009...2.0.0010)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0009...2.0.0010)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0009...2.0.0010)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0009...2.0.0010)

**Merged pull requests:**

- Terminate a finite loop that has no data [\#30](https://github.com/getbouncer/scan-framework-android/pull/30) ([awushensky](https://github.com/awushensky))
- Bump gradle from 3.6.3 to 4.0.0 [\#29](https://github.com/getbouncer/scan-framework-android/pull/29) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Better support camera flash [\#21](https://github.com/getbouncer/scan-camera-android/pull/21) ([awushensky](https://github.com/awushensky))
- Bump gradle from 3.6.3 to 4.0.0 [\#20](https://github.com/getbouncer/scan-camera-android/pull/20) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump gradle from 3.6.3 to 4.0.0 [\#19](https://github.com/getbouncer/scan-payment-android/pull/19) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump gradle from 3.6.3 to 4.0.0 [\#15](https://github.com/getbouncer/scan-ui-android/pull/15) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0009](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0009) (2020-05-29)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0008...2.0.0009)

**Merged pull requests:**

- Bump core-ktx from 1.2.0 to 1.3.0 [\#46](https://github.com/getbouncer/cardscan-demo-android/pull/46) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Remove required card number [\#45](https://github.com/getbouncer/cardscan-demo-android/pull/45) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#28](https://github.com/getbouncer/scan-framework-android/pull/28) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Start aggregation timer on valid result [\#27](https://github.com/getbouncer/scan-framework-android/pull/27) ([awushensky](https://github.com/awushensky))
- Stop ignoring scan timeout [\#26](https://github.com/getbouncer/scan-framework-android/pull/26) ([awushensky](https://github.com/awushensky))
- Simplify results [\#25](https://github.com/getbouncer/scan-framework-android/pull/25) ([awushensky](https://github.com/awushensky))
- Add logging to stats [\#24](https://github.com/getbouncer/scan-framework-android/pull/24) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#19](https://github.com/getbouncer/scan-camera-android/pull/19) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Use random focus variance [\#18](https://github.com/getbouncer/scan-camera-android/pull/18) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#18](https://github.com/getbouncer/scan-payment-android/pull/18) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Relocate aggregator [\#17](https://github.com/getbouncer/scan-payment-android/pull/17) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#14](https://github.com/getbouncer/scan-ui-android/pull/14) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Keep the screen on while scanning [\#13](https://github.com/getbouncer/scan-ui-android/pull/13) ([awushensky](https://github.com/awushensky))
- Reset previously valid result [\#16](https://github.com/getbouncer/cardscan-ui-android/pull/16) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#15](https://github.com/getbouncer/cardscan-ui-android/pull/15) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Remove isValidPan [\#14](https://github.com/getbouncer/cardscan-ui-android/pull/14) ([awushensky](https://github.com/awushensky))
- Start result aggregation on valid result [\#13](https://github.com/getbouncer/cardscan-ui-android/pull/13) ([awushensky](https://github.com/awushensky))
- Simplify results [\#12](https://github.com/getbouncer/cardscan-ui-android/pull/12) ([awushensky](https://github.com/awushensky))

## [2.0.0008](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0008) (2020-05-21)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0007...2.0.0008)

**Merged pull requests:**

- Bump kotlinx-coroutines-core from 1.3.6 to 1.3.7 [\#43](https://github.com/getbouncer/cardscan-demo-android/pull/43) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#42](https://github.com/getbouncer/cardscan-demo-android/pull/42) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#41](https://github.com/getbouncer/cardscan-demo-android/pull/41) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Make dependencies explicit [\#39](https://github.com/getbouncer/cardscan-demo-android/pull/39) ([awushensky](https://github.com/awushensky))
- Display card pan always [\#38](https://github.com/getbouncer/cardscan-demo-android/pull/38) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-android from 1.3.6 to 1.3.7 [\#19](https://github.com/getbouncer/scan-framework-android/pull/19) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlinx-coroutines-test from 1.3.6 to 1.3.7 [\#18](https://github.com/getbouncer/scan-framework-android/pull/18) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Use invalid api key for test [\#14](https://github.com/getbouncer/scan-framework-android/pull/14) ([awushensky](https://github.com/awushensky))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#13](https://github.com/getbouncer/scan-framework-android/pull/13) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump tensorflow-lite from 1.15.0 to 2.2.0 [\#12](https://github.com/getbouncer/scan-framework-android/pull/12) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#11](https://github.com/getbouncer/scan-framework-android/pull/11) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add more tests [\#8](https://github.com/getbouncer/scan-framework-android/pull/8) ([awushensky](https://github.com/awushensky))
- Add android test github action [\#7](https://github.com/getbouncer/scan-framework-android/pull/7) ([awushensky](https://github.com/awushensky))
- Ensure results are not duplicated [\#6](https://github.com/getbouncer/scan-framework-android/pull/6) ([awushensky](https://github.com/awushensky))
- Optimize some image utilities [\#5](https://github.com/getbouncer/scan-framework-android/pull/5) ([awushensky](https://github.com/awushensky))
- Refocus camera [\#15](https://github.com/getbouncer/scan-camera-android/pull/15) ([awushensky](https://github.com/awushensky))
- Simplify camera start [\#14](https://github.com/getbouncer/scan-camera-android/pull/14) ([awushensky](https://github.com/awushensky))
- Ignore camera config change failures [\#13](https://github.com/getbouncer/scan-camera-android/pull/13) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-core from 1.3.6 to 1.3.7 [\#12](https://github.com/getbouncer/scan-camera-android/pull/12) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlinx-coroutines-test from 1.3.6 to 1.3.7 [\#11](https://github.com/getbouncer/scan-camera-android/pull/11) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#8](https://github.com/getbouncer/scan-camera-android/pull/8) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#7](https://github.com/getbouncer/scan-camera-android/pull/7) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add tests to camera [\#5](https://github.com/getbouncer/scan-camera-android/pull/5) ([awushensky](https://github.com/awushensky))
- Remove camerax and camera2 [\#4](https://github.com/getbouncer/scan-camera-android/pull/4) ([awushensky](https://github.com/awushensky))
- Add camera1 and camerax [\#3](https://github.com/getbouncer/scan-camera-android/pull/3) ([awushensky](https://github.com/awushensky))
- Use better coroutine testing [\#13](https://github.com/getbouncer/scan-payment-android/pull/13) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-core from 1.3.6 to 1.3.7 [\#12](https://github.com/getbouncer/scan-payment-android/pull/12) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlinx-coroutines-android from 1.3.6 to 1.3.7 [\#11](https://github.com/getbouncer/scan-payment-android/pull/11) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#10](https://github.com/getbouncer/scan-payment-android/pull/10) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#7](https://github.com/getbouncer/scan-payment-android/pull/7) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add tests [\#5](https://github.com/getbouncer/scan-payment-android/pull/5) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-core from 1.3.3 to 1.3.7 [\#11](https://github.com/getbouncer/scan-ui-android/pull/11) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add tests [\#10](https://github.com/getbouncer/scan-ui-android/pull/10) ([awushensky](https://github.com/awushensky))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#8](https://github.com/getbouncer/scan-ui-android/pull/8) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#7](https://github.com/getbouncer/scan-ui-android/pull/7) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update default user interface [\#6](https://github.com/getbouncer/scan-ui-android/pull/6) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-core from 1.3.6 to 1.3.7 [\#10](https://github.com/getbouncer/cardscan-ui-android/pull/10) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#8](https://github.com/getbouncer/cardscan-ui-android/pull/8) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#7](https://github.com/getbouncer/cardscan-ui-android/pull/7) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add integration tests to CI [\#6](https://github.com/getbouncer/cardscan-ui-android/pull/6) ([awushensky](https://github.com/awushensky))
- Update user interface [\#5](https://github.com/getbouncer/cardscan-ui-android/pull/5) ([awushensky](https://github.com/awushensky))

## [2.0.0007](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0007) (2020-05-12)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0005...2.0.0007)

**Merged pull requests:**

- Update documentation [\#37](https://github.com/getbouncer/cardscan-demo-android/pull/37) ([awushensky](https://github.com/awushensky))
- Fix crash on network failure [\#4](https://github.com/getbouncer/scan-framework-android/pull/4) ([awushensky](https://github.com/awushensky))
- Fix crash on camera open failure [\#2](https://github.com/getbouncer/scan-camera-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update submodules [\#4](https://github.com/getbouncer/scan-payment-android/pull/4) ([awushensky](https://github.com/awushensky))
- Update version [\#5](https://github.com/getbouncer/scan-ui-android/pull/5) ([awushensky](https://github.com/awushensky))
- Update submodules [\#4](https://github.com/getbouncer/cardscan-ui-android/pull/4) ([awushensky](https://github.com/awushensky))
- Set api key on warmup [\#3](https://github.com/getbouncer/cardscan-ui-android/pull/3) ([awushensky](https://github.com/awushensky))

## [2.0.0006](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0006) (2020-05-09)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0005...2.0.0006)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0005...2.0.0006)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0005...2.0.0006)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0005...2.0.0006)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.005...2.0.0006)

**Merged pull requests:**

- Update version [\#36](https://github.com/getbouncer/cardscan-demo-android/pull/36) ([awushensky](https://github.com/awushensky))
- Fix signedUrl failure crash [\#3](https://github.com/getbouncer/scan-framework-android/pull/3) ([awushensky](https://github.com/awushensky))
- update version [\#3](https://github.com/getbouncer/scan-payment-android/pull/3) ([awushensky](https://github.com/awushensky))
- Allow invalid api key error [\#4](https://github.com/getbouncer/scan-ui-android/pull/4) ([awushensky](https://github.com/awushensky))

## [2.0.0005](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0005) (2020-05-08)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0004...2.0.0005)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/e0e5089a945c8b6b6ed47f3838d3d61997c1afe4...2.0.0005)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/70e9702f2bb0a99ef89e1477064eb541b661170f...2.0.0005)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/d19502708ef72c01d522e2d18e7a8bfbb81ec0b2...2.0.0005)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/0904ef185c19491c25b73c61eb8a22bed1eecb75...2.0.005)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/ebb299b0e1b799ec7c12aff1f535d0278d9107c1...2.0.0005)

**Merged pull requests:**

- Update submodules [\#35](https://github.com/getbouncer/cardscan-demo-android/pull/35) ([awushensky](https://github.com/awushensky))
- Replace libraries [\#34](https://github.com/getbouncer/cardscan-demo-android/pull/34) ([awushensky](https://github.com/awushensky))
- Remove build from git [\#2](https://github.com/getbouncer/scan-framework-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update documentation [\#1](https://github.com/getbouncer/scan-framework-android/pull/1) ([awushensky](https://github.com/awushensky))
- Update documentation [\#1](https://github.com/getbouncer/scan-camera-android/pull/1) ([awushensky](https://github.com/awushensky))
- Add results [\#2](https://github.com/getbouncer/scan-payment-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update documentation [\#1](https://github.com/getbouncer/scan-payment-android/pull/1) ([awushensky](https://github.com/awushensky))
- Rename module in docs [\#3](https://github.com/getbouncer/scan-ui-android/pull/3) ([awushensky](https://github.com/awushensky))
- Rename module [\#2](https://github.com/getbouncer/scan-ui-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update docs [\#1](https://github.com/getbouncer/scan-ui-android/pull/1) ([awushensky](https://github.com/awushensky))
- Update submodules [\#2](https://github.com/getbouncer/cardscan-ui-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update documentation [\#1](https://github.com/getbouncer/cardscan-ui-android/pull/1) ([awushensky](https://github.com/awushensky))

## [2.0.0004](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0004) (2020-05-06)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0003...2.0.0004)

**Merged pull requests:**

- Update version [\#33](https://github.com/getbouncer/cardscan-demo-android/pull/33) ([awushensky](https://github.com/awushensky))

## [2.0.0003](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0003) (2020-04-29)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/a0e3c8e303b7f72e2b08701e01781d9558b07e2c...2.0.0003)

**Implemented enhancements:**

- Update github checks [\#5](https://github.com/getbouncer/cardscan-demo-android/pull/5) ([awushensky](https://github.com/awushensky))

**Merged pull requests:**

- Update thread handling [\#32](https://github.com/getbouncer/cardscan-demo-android/pull/32) ([awushensky](https://github.com/awushensky))
- Update documentation [\#31](https://github.com/getbouncer/cardscan-demo-android/pull/31) ([awushensky](https://github.com/awushensky))
- Extract common ui [\#30](https://github.com/getbouncer/cardscan-demo-android/pull/30) ([awushensky](https://github.com/awushensky))
- Update submodules [\#29](https://github.com/getbouncer/cardscan-demo-android/pull/29) ([awushensky](https://github.com/awushensky))
- Update submodules [\#28](https://github.com/getbouncer/cardscan-demo-android/pull/28) ([awushensky](https://github.com/awushensky))
- Update submodules [\#27](https://github.com/getbouncer/cardscan-demo-android/pull/27) ([awushensky](https://github.com/awushensky))
- Update submodules [\#26](https://github.com/getbouncer/cardscan-demo-android/pull/26) ([awushensky](https://github.com/awushensky))
- Update submodules [\#25](https://github.com/getbouncer/cardscan-demo-android/pull/25) ([awushensky](https://github.com/awushensky))
- Update submodules [\#24](https://github.com/getbouncer/cardscan-demo-android/pull/24) ([awushensky](https://github.com/awushensky))
- Update submodules [\#23](https://github.com/getbouncer/cardscan-demo-android/pull/23) ([awushensky](https://github.com/awushensky))
- Prevent screenshots [\#22](https://github.com/getbouncer/cardscan-demo-android/pull/22) ([awushensky](https://github.com/awushensky))
- Add api key check [\#21](https://github.com/getbouncer/cardscan-demo-android/pull/21) ([awushensky](https://github.com/awushensky))
- Update license [\#20](https://github.com/getbouncer/cardscan-demo-android/pull/20) ([awushensky](https://github.com/awushensky))
- Update documentation [\#19](https://github.com/getbouncer/cardscan-demo-android/pull/19) ([awushensky](https://github.com/awushensky))
- Update submodules [\#18](https://github.com/getbouncer/cardscan-demo-android/pull/18) ([awushensky](https://github.com/awushensky))
- Add documentation [\#17](https://github.com/getbouncer/cardscan-demo-android/pull/17) ([awushensky](https://github.com/awushensky))
- Make logo optional [\#16](https://github.com/getbouncer/cardscan-demo-android/pull/16) ([awushensky](https://github.com/awushensky))
- Update submodules [\#15](https://github.com/getbouncer/cardscan-demo-android/pull/15) ([awushensky](https://github.com/awushensky))
- Update submodules [\#14](https://github.com/getbouncer/cardscan-demo-android/pull/14) ([awushensky](https://github.com/awushensky))
- Rename app to demo [\#13](https://github.com/getbouncer/cardscan-demo-android/pull/13) ([awushensky](https://github.com/awushensky))
- Support state in loops [\#12](https://github.com/getbouncer/cardscan-demo-android/pull/12) ([awushensky](https://github.com/awushensky))
- Remove camera 1 api [\#11](https://github.com/getbouncer/cardscan-demo-android/pull/11) ([awushensky](https://github.com/awushensky))
- Scope tests to the app itself [\#10](https://github.com/getbouncer/cardscan-demo-android/pull/10) ([awushensky](https://github.com/awushensky))
- Update submodules [\#9](https://github.com/getbouncer/cardscan-demo-android/pull/9) ([awushensky](https://github.com/awushensky))
- Update submodules [\#8](https://github.com/getbouncer/cardscan-demo-android/pull/8) ([awushensky](https://github.com/awushensky))
- Use submodules [\#7](https://github.com/getbouncer/cardscan-demo-android/pull/7) ([awushensky](https://github.com/awushensky))
- Show the card pan when scanninng [\#6](https://github.com/getbouncer/cardscan-demo-android/pull/6) ([awushensky](https://github.com/awushensky))
- Update dependencies [\#4](https://github.com/getbouncer/cardscan-demo-android/pull/4) ([awushensky](https://github.com/awushensky))
- Require API key [\#3](https://github.com/getbouncer/cardscan-demo-android/pull/3) ([awushensky](https://github.com/awushensky))
- Add code owners [\#2](https://github.com/getbouncer/cardscan-demo-android/pull/2) ([awushensky](https://github.com/awushensky))
- Support camera1 APIs [\#1](https://github.com/getbouncer/cardscan-demo-android/pull/1) ([awushensky](https://github.com/awushensky))



\* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)*


================================================
FILE: CODEOWNERS
================================================
# This is a comment.
# Each line is a file pattern followed by one or more owners.

# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
# @global-owner1 and @global-owner2 will be requested for
# review when someone opens a pull request.
*       @awushensky @xsl @kingst @dxaen @awushensky-stripe

# Order is important; the last matching pattern takes the most
# precedence. When someone opens a pull request that only
# modifies JS files, only @js-owner and not the global
# owner(s) will be requested for a review.
# *.js    @js-owner

# You can also use email addresses if you prefer. They'll be
# used to look up users just like we do for commit author
# emails.
# *.go docs@example.com

# In this example, @doctocat owns any files in the build/logs
# directory at the root of the repository and any of its
# subdirectories.
# /build/logs/ @doctocat

# The `docs/*` pattern will match files like
# `docs/getting-started.md` but not further nested files like
# `docs/build-app/troubleshooting.md`.
# docs/*  docs@example.com

# In this example, @octocat owns any file in an apps directory
# anywhere in your repository.
# apps/ @octocat

# In this example, @doctocat owns any file in the `/docs`
# directory in the root of your repository.
# /docs/ @doctocat


================================================
FILE: Contributor License Agreement
================================================
Bouncer
Individual and Entity Contributor License Agreement

Thank you for your interest in contributing to software projects managed by Bouncer Technologies,
Inc. (“We”, “Us” or “Our”). This Contributor License Agreement (“Agreement”) documents the rights
granted by contributors to Us. This Agreement is for your protection as a contributor as well as for
our protection; it does not change your rights to use your own Contributions for any other purpose.
To make this document effective, please read the Agreement carefully and then (i) sign it and send
it to Us by email (PDF) at bouncer-support@stripe.com or (ii) submit it to us electronically, in either
case by following the instructions at [insert hyperlink]. By signing this Agreement (including by
clicking “I agree” and submitting it to us electronically), You are creating a legally binding
contract. If You are less than eighteen years old, please have Your parents or guardian sign the
Agreement. This Agreement covers all future Contributions from You, and may cover more than one
software project managed by Us.

1. Definitions
--------------
“Affiliates” means other Legal Entities that control, are controlled by, or under common control
with that Legal Entity. For the purposes of this definition, “control” means (i) the power, direct
or indirect, to cause the direction or management of such Legal Entity, whether by contract or
otherwise, (ii) ownership of fifty percent (50%) or more of the outstanding shares or securities
which vote to elect the management or other persons who direct such Legal Entity or (iii) beneficial
ownership of such entity.

“Contribution” means any work of authorship that is Submitted by You to Us in which You own or
assert ownership of the Copyright. By Submitting any Contribution, you represent that You own the
Copyright in the entire work of authorship, or that you otherwise are legally entitled to Submit the
Contribution and to grant the licenses in this Agreement.

“Copyright” means all rights protecting works of authorship owned or controlled by You or your
Affiliates (as may be applicable), including copyright, moral and related (or neighboring) rights,
as appropriate, for the full term of their existence, including any extensions by You.

“Effective Date” means the date You execute this Agreement or the date You first Submit a
Contribution to Us, whichever is earlier.

“Legal Entity” means an entity which is not a natural person.

“Material” means the work of authorship which is made available by Us to third parties. When this
Agreement covers more than one software project, the Material means the work of authorship to which
the Contribution was Submitted. After You Submit the Contribution, it may be included in the
Material.

“Media” means any portion of a Contribution which is not software.

“Submit” means any form of electronic, verbal, or written communication sent to Us or our
representatives at a destination (including websites) that we own or control or that is otherwise
registered to us, including but not limited to electronic mailing lists, source code control
systems, instant messages or similar communications, and issue tracking systems that are managed by,
or on behalf of, Us for the purpose of discussing and improving the Material, but excluding any
communication that is conspicuously marked or otherwise designated in writing by You as “Not a
Contribution.”

“Submission Date” means the date on which You Submit a Contribution to Us.

“You” (entity). If You are an individual acting on your own behalf, then “You” means the individual
who Submits a Contribution to Us.

“You” (individual). If You are Submitting any Contribution on behalf of any entity, then “You” means
the Legal Entity on behalf of whom you Submit a Contribution to Us.


2. Grant of Rights
------------------
2.1 Copyright License
(a) Except for the license granted to Us in this Agreement, You reserve all right, title, and
interest in and to Your Contributions. That means that you can keep doing whatever you want with
your Contribution, and you can license it to anyone you want under any terms you want.

(b) To the maximum extent permitted by the relevant law, You grant to Us a perpetual, worldwide,
non-exclusive, transferable, no charge and royalty-free, irrevocable license under the Copyright
covering the Contribution, with the right to sublicense such rights through multiple tiers of
sublicensees, to reproduce, modify, display, perform, sublicense and distribute the Contribution as
part of the Material; provided that this license is subject to Section 2.3.

2.2 Patent License
For patent claims including, without limitation, method, process, and apparatus claims which You (or
your Affiliates, as may be applicable) own, control or have the right to grant, now or in the
future, You grant to Us a perpetual, worldwide, non-exclusive, transferable, no charge and royalty-
free, irrevocable patent license, with the right to sublicense these rights to multiple tiers of
sublicensees, to make, have made, use, sell, offer for sale, import and otherwise transfer the
Contribution (and the Contribution in combination with the Material, and portions of such
combination). This license is granted only to the extent that the exercise of the licensed rights
infringes such patent claims; and is subject to Section 2.3. If any person institutes patent
litigation against Contributor or any other entity (including a cross-claim or counterclaim in a
lawsuit) alleging that the Contributions, or the Project to which the Contributions were submitted,
constitutes direct or contributory patent infringement, then any patent licenses granted under this
Agreement for that Contribution to the person or entity instituting the litigation, or the Project
to which the Contributions were submitted, shall terminate as of the date such litigation is filed.

2.3 Outbound License
Based on the grant of rights in Sections 2.1 (meaning, no matter what, you can keep licensing your
Contribution to others however you want) and 2.2, if We include Your Contribution in any Material,
and if We determine that it is appropriate for the purpose of commercializing any Material or any
project under Our control, we may license the Contribution under any license, including copyleft,
permissive, commercial, or proprietary licenses.

2.4 Moral Rights.
We agree to comply with applicable laws regarding your Contribution, including copyright laws and
law related to moral rights. If moral rights apply to the Contribution, to the maximum extent
permitted by law, You waive and agree not to assert such moral rights against Us or our successors
in interest, or any of our licensees, either direct or indirect.

2.5 Our Rights.
You acknowledge that We are not obligated to use Your Contribution as part of any Material, and that
we and may decide to include any Contribution We consider appropriate.

2.6 Reservation of Rights.
Any rights in Your Contribution not expressly licensed under this Agreement are expressly reserved
by You.

3. Agreement.
-------------
You confirm that:

(a) You have the legal authority to enter into this Agreement. If your employer(s) has rights to
intellectual property that you create that includes your Contributions, you represent that you have
received permission to make Contributions on behalf of that employer, and that your employer has
waived such rights for your Contributions to Us.

(b) You (or your Affiliates, as may be applicable) own or otherwise have the legal right to license
the Copyright and patent claims covering the Contribution which are required to grant the rights
under Section 2.

(c) The grant of rights under Section 2 does not violate any grant of rights which You (or your
Affiliates, as may be applicable) have made to third parties, including Your employer.

(d)  You represent that each of Your Contributions is Your original work. You represent that Your
Contribution submissions include complete details of any third-party license or other restriction
(including, but not limited to, related patents and trademarks) of which you are personally aware
and which are associated with any part of Your Contributions.

(e) You agree to notify Us of any facts or circumstances of which you become aware that would make
these representations inaccurate in any respect.

4. Disclaimer
-------------
EXCEPT FOR THE EXPRESS WARRANTIES IN SECTION 3, THE CONTRIBUTION IS PROVIDED "AS IS". YOU EXPRESSLY
DISCLAIM ALL EXPRESS OR IMPLIED WARRANTIES INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTY OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. TO THE EXTENT THAT ANY SUCH
WARRANTIES CANNOT BE DISCLAIMED, SUCH WARRANTY IS LIMITED IN DURATION TO THE MINIMUM PERIOD
PERMITTED BY LAW.

5. Consequential Damage Waiver
------------------------------
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT WILL YOU OR WE BE LIABLE FOR ANY LOSS
OF PROFITS, LOSS OF ANTICIPATED SAVINGS, LOSS OF DATA, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL
AND EXEMPLARY DAMAGES ARISING OUT OF THIS AGREEMENT REGARDLESS OF THE LEGAL OR EQUITABLE THEORY
(CONTRACT, TORT OR OTHERWISE) UPON WHICH THE CLAIM IS BASED.

6. Miscellaneous
----------------
6.1 This Agreement will be governed by and construed in accordance with the laws of the State of
California, without regard to conflicts of law provisions. The sole venue for all disputes relating
to this Agreement shall be in Alameda County, California. The rights and obligations of the parties
under this Agreement shall not be governed by the 1980 U.N. Convention on Contracts for the
International Sale of Goods.

6.2 This Agreement may be amended only by a written document signed by the party against whom
enforcement is sought.

6.3 The failure of either party to require performance by the other party of any provision of this
Agreement in one situation shall not affect the right of a party to require such performance at any
time in the future. A waiver of performance under a provision in one situation shall not be
considered a waiver of the performance of the provision in the future or a waiver of the provision
in its entirety.

6.4 If any provision of this Agreement is found void and unenforceable, such provision will be
replaced to the extent possible with a provision that comes closest to the meaning of the original
provision and which is enforceable. The terms and conditions set forth in this Agreement shall apply
notwithstanding any failure of essential purpose of this Agreement or any limited remedy to the
maximum extent possible under law.

This Agreement contains the entire understanding of the parties regarding the subject matter of this
Agreement and supersedes all prior and contemporaneous negotiations and agreements, whether written
or oral, between the parties with respect to the subject matter of this Agreement.

By signing below, Contributor accepts and agrees to the preceding terms and conditions for
Contributor’s present and future Contributions submitted to Us.


________________________________________
Signature

________________________________________
Contributor Name

________________________________________
Legal Entity Name (if applicable)

________________________________________
Contributor Address

________________________________________
Title

________________________________________
Contributor Address

________________________________________
Email

________________________________________
Telephone

________________________________________
Date


================================================
FILE: HISTORY.md
================================================
## [2.0.0014](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0014) (2020-07-14)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0013...2.0.0014)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0013...2.0.0014)

**Merged pull requests:**

- Image fragmentation [\#53](https://github.com/getbouncer/scan-framework-android/pull/53) ([smkuhne](https://github.com/smkuhne))
- Standardize models [\#35](https://github.com/getbouncer/scan-payment-android/pull/35) ([awushensky](https://github.com/awushensky))
- Image fragmentation [\#33](https://github.com/getbouncer/scan-payment-android/pull/33) ([smkuhne](https://github.com/smkuhne))
- Allow extending uploadstats [\#30](https://github.com/getbouncer/scan-ui-android/pull/30) ([awushensky](https://github.com/awushensky))
- Image fragmentation [\#28](https://github.com/getbouncer/scan-ui-android/pull/28) ([smkuhne](https://github.com/smkuhne))

## [2.0.0013](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0013) (2020-07-08)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0012...2.0.0013)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0012...2.0.0013)

**Merged pull requests:**

- Bump ktlint from 0.37.0 to 0.37.2 [\#59](https://github.com/getbouncer/cardscan-demo-android/pull/59) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Use new warmup initializer [\#58](https://github.com/getbouncer/cardscan-demo-android/pull/58) ([xsl](https://github.com/xsl))
- Update UI [\#57](https://github.com/getbouncer/cardscan-demo-android/pull/57) ([awushensky](https://github.com/awushensky))
- Update for expiry extraction + new text detector [\#56](https://github.com/getbouncer/cardscan-demo-android/pull/56) ([xsl](https://github.com/xsl))
- Add more java interoperability [\#57](https://github.com/getbouncer/scan-framework-android/pull/57) ([awushensky](https://github.com/awushensky))
- Relocate loop state to result [\#56](https://github.com/getbouncer/scan-framework-android/pull/56) ([awushensky](https://github.com/awushensky))
- Add more memoize functions [\#55](https://github.com/getbouncer/scan-framework-android/pull/55) ([awushensky](https://github.com/awushensky))
- Separate error listeners [\#54](https://github.com/getbouncer/scan-framework-android/pull/54) ([awushensky](https://github.com/awushensky))
- Fix work leak [\#52](https://github.com/getbouncer/scan-framework-android/pull/52) ([awushensky](https://github.com/awushensky))
- Test duration [\#51](https://github.com/getbouncer/scan-framework-android/pull/51) ([awushensky](https://github.com/awushensky))
- Clean up network responses [\#49](https://github.com/getbouncer/scan-framework-android/pull/49) ([awushensky](https://github.com/awushensky))
- Add exceptions to retry [\#48](https://github.com/getbouncer/scan-framework-android/pull/48) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.37.0 to 0.37.2 [\#46](https://github.com/getbouncer/scan-framework-android/pull/46) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add device identifier to network requests [\#45](https://github.com/getbouncer/scan-framework-android/pull/45) ([awushensky](https://github.com/awushensky))
- Standardize local file name [\#44](https://github.com/getbouncer/scan-framework-android/pull/44) ([awushensky](https://github.com/awushensky))
- Add some convenience functions [\#43](https://github.com/getbouncer/scan-framework-android/pull/43) ([xsl](https://github.com/xsl))
- Launch the camera on IO dispatcher [\#32](https://github.com/getbouncer/scan-camera-android/pull/32) ([awushensky](https://github.com/awushensky))
- Relocate analyzers [\#34](https://github.com/getbouncer/scan-payment-android/pull/34) ([awushensky](https://github.com/awushensky))
- Support multiple MM/YYs on cards [\#32](https://github.com/getbouncer/scan-payment-android/pull/32) ([xsl](https://github.com/xsl))
- Bump ktlint from 0.37.0 to 0.37.2 [\#31](https://github.com/getbouncer/scan-payment-android/pull/31) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Expiry extraction + new text detector [\#30](https://github.com/getbouncer/scan-payment-android/pull/30) ([xsl](https://github.com/xsl))
- Update submodule [\#29](https://github.com/getbouncer/scan-ui-android/pull/29) ([awushensky](https://github.com/awushensky))
- Separate scan stats [\#27](https://github.com/getbouncer/scan-ui-android/pull/27) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.37.0 to 0.37.2 [\#26](https://github.com/getbouncer/scan-ui-android/pull/26) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add initialization error strings [\#25](https://github.com/getbouncer/scan-ui-android/pull/25) ([xsl](https://github.com/xsl))
- Update UI [\#24](https://github.com/getbouncer/scan-ui-android/pull/24) ([awushensky](https://github.com/awushensky))
- Update scan-framework-android submodule [\#23](https://github.com/getbouncer/scan-ui-android/pull/23) ([xsl](https://github.com/xsl))
- Shut down analyzer context on quit [\#38](https://github.com/getbouncer/cardscan-ui-android/pull/38) ([awushensky](https://github.com/awushensky))
- Separate loop logic [\#37](https://github.com/getbouncer/cardscan-ui-android/pull/37) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.37.0 to 0.37.2 [\#35](https://github.com/getbouncer/cardscan-ui-android/pull/35) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update ui [\#34](https://github.com/getbouncer/cardscan-ui-android/pull/34) ([awushensky](https://github.com/awushensky))
- Warmup name and expiry [\#33](https://github.com/getbouncer/cardscan-ui-android/pull/33) ([xsl](https://github.com/xsl))
- Expiry extraction + new text detector [\#32](https://github.com/getbouncer/cardscan-ui-android/pull/32) ([xsl](https://github.com/xsl))

## [2.0.0012](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0012) (2020-06-15)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0011...2.0.0012)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0011...2.0.0012)

**Merged pull requests:**

- Rename warm up [\#55](https://github.com/getbouncer/cardscan-demo-android/pull/55) ([awushensky](https://github.com/awushensky))
- Use flows instead of channels [\#42](https://github.com/getbouncer/scan-framework-android/pull/42) ([awushensky](https://github.com/awushensky))
- Use channels better [\#41](https://github.com/getbouncer/scan-framework-android/pull/41) ([awushensky](https://github.com/awushensky))
- Fix framerate average calculation [\#40](https://github.com/getbouncer/scan-framework-android/pull/40) ([awushensky](https://github.com/awushensky))
- Make result handlers listen to a lifecycle [\#39](https://github.com/getbouncer/scan-framework-android/pull/39) ([awushensky](https://github.com/awushensky))
- Move images out of framework [\#38](https://github.com/getbouncer/scan-framework-android/pull/38) ([awushensky](https://github.com/awushensky))
- Support java interop [\#37](https://github.com/getbouncer/scan-framework-android/pull/37) ([awushensky](https://github.com/awushensky))
- Fix camera crash on flash not supported [\#30](https://github.com/getbouncer/scan-camera-android/pull/30) ([awushensky](https://github.com/awushensky))
- Increase the channel buffer size to 2 [\#29](https://github.com/getbouncer/scan-camera-android/pull/29) ([awushensky](https://github.com/awushensky))
- Reintroduce camera2 [\#28](https://github.com/getbouncer/scan-camera-android/pull/28) ([awushensky](https://github.com/awushensky))
- Centralize the channel logic [\#27](https://github.com/getbouncer/scan-camera-android/pull/27) ([awushensky](https://github.com/awushensky))
- Remove framework submodule [\#26](https://github.com/getbouncer/scan-camera-android/pull/26) ([awushensky](https://github.com/awushensky))
- Add timing to ssdocr input [\#29](https://github.com/getbouncer/scan-payment-android/pull/29) ([awushensky](https://github.com/awushensky))
- Relocate test resources [\#28](https://github.com/getbouncer/scan-payment-android/pull/28) ([awushensky](https://github.com/awushensky))
- Relocate image manipulation utilities [\#27](https://github.com/getbouncer/scan-payment-android/pull/27) ([awushensky](https://github.com/awushensky))
- Use flows [\#22](https://github.com/getbouncer/scan-ui-android/pull/22) ([awushensky](https://github.com/awushensky))
- Relocate scan process [\#21](https://github.com/getbouncer/scan-ui-android/pull/21) ([awushensky](https://github.com/awushensky))
- Separate framework from camera [\#20](https://github.com/getbouncer/scan-ui-android/pull/20) ([awushensky](https://github.com/awushensky))
- Handle devices without cameras [\#19](https://github.com/getbouncer/scan-ui-android/pull/19) ([awushensky](https://github.com/awushensky))
- Reduce jitter in name display [\#31](https://github.com/getbouncer/cardscan-ui-android/pull/31) ([awushensky](https://github.com/awushensky))
- Fix analyzer pool memory leak [\#30](https://github.com/getbouncer/cardscan-ui-android/pull/30) ([awushensky](https://github.com/awushensky))
- Actually reset the result aggregator [\#29](https://github.com/getbouncer/cardscan-ui-android/pull/29) ([awushensky](https://github.com/awushensky))
- Relocate scan logic [\#28](https://github.com/getbouncer/cardscan-ui-android/pull/28) ([awushensky](https://github.com/awushensky))
- Relocate scan flow to implementation [\#27](https://github.com/getbouncer/cardscan-ui-android/pull/27) ([awushensky](https://github.com/awushensky))
- Separate camera and loops [\#26](https://github.com/getbouncer/cardscan-ui-android/pull/26) ([awushensky](https://github.com/awushensky))

## [2.0.0011](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0011) (2020-06-08)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0009...2.0.0011)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0010...2.0.0011)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0010...2.0.0011)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0010...2.0.0011)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0010...2.0.0011)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0009...2.0.0011)

**Merged pull requests:**

- Support separate name extraction parameters [\#54](https://github.com/getbouncer/cardscan-demo-android/pull/54) ([awushensky](https://github.com/awushensky))
- Add docs and buttons for name extraction [\#53](https://github.com/getbouncer/cardscan-demo-android/pull/53) ([xsl](https://github.com/xsl))
- Reduce name extraction settings [\#52](https://github.com/getbouncer/cardscan-demo-android/pull/52) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#51](https://github.com/getbouncer/cardscan-demo-android/pull/51) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update for name extraction [\#50](https://github.com/getbouncer/cardscan-demo-android/pull/50) ([xsl](https://github.com/xsl))
- Bump gradle from 3.6.3 to 4.0.0 [\#47](https://github.com/getbouncer/cardscan-demo-android/pull/47) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update coroutine interoperability [\#36](https://github.com/getbouncer/scan-framework-android/pull/36) ([awushensky](https://github.com/awushensky))
- Standardize result counter [\#35](https://github.com/getbouncer/scan-framework-android/pull/35) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#34](https://github.com/getbouncer/scan-framework-android/pull/34) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add memoization functions [\#33](https://github.com/getbouncer/scan-framework-android/pull/33) ([awushensky](https://github.com/awushensky))
- Don't retry on FileNotFoundExceptions [\#32](https://github.com/getbouncer/scan-framework-android/pull/32) ([xsl](https://github.com/xsl))
- Update image utilities [\#31](https://github.com/getbouncer/scan-framework-android/pull/31) ([awushensky](https://github.com/awushensky))
- Use default dispatcher for camera [\#25](https://github.com/getbouncer/scan-camera-android/pull/25) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#24](https://github.com/getbouncer/scan-camera-android/pull/24) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update submodule [\#23](https://github.com/getbouncer/scan-camera-android/pull/23) ([xsl](https://github.com/xsl))
- Update image utils [\#22](https://github.com/getbouncer/scan-camera-android/pull/22) ([awushensky](https://github.com/awushensky))
- Remove threadsafe flag [\#26](https://github.com/getbouncer/scan-payment-android/pull/26) ([awushensky](https://github.com/awushensky))
- Minor tuning for name extraction [\#25](https://github.com/getbouncer/scan-payment-android/pull/25) ([xsl](https://github.com/xsl))
- Relocate object detect test [\#24](https://github.com/getbouncer/scan-payment-android/pull/24) ([awushensky](https://github.com/awushensky))
- Remove debug log [\#23](https://github.com/getbouncer/scan-payment-android/pull/23) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#22](https://github.com/getbouncer/scan-payment-android/pull/22) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update image utils [\#21](https://github.com/getbouncer/scan-payment-android/pull/21) ([awushensky](https://github.com/awushensky))
- Add NameDetectAnalyzer and move object detector over \(for now at least\) [\#20](https://github.com/getbouncer/scan-payment-android/pull/20) ([xsl](https://github.com/xsl))
- Remove unnecessary manifest entries [\#18](https://github.com/getbouncer/scan-ui-android/pull/18) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#17](https://github.com/getbouncer/scan-ui-android/pull/17) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Introduce fadeIn duration config and update card border animation duration [\#16](https://github.com/getbouncer/scan-ui-android/pull/16) ([xsl](https://github.com/xsl))
- Support java interoperability [\#25](https://github.com/getbouncer/cardscan-ui-android/pull/25) ([awushensky](https://github.com/awushensky))
- Enable disabling name extraction on start [\#24](https://github.com/getbouncer/cardscan-ui-android/pull/24) ([awushensky](https://github.com/awushensky))
- Update scan payments submodule [\#23](https://github.com/getbouncer/cardscan-ui-android/pull/23) ([xsl](https://github.com/xsl))
- Use default dispatchers [\#22](https://github.com/getbouncer/cardscan-ui-android/pull/22) ([awushensky](https://github.com/awushensky))
- Reduce settings for name extractor [\#21](https://github.com/getbouncer/cardscan-ui-android/pull/21) ([awushensky](https://github.com/awushensky))
- Bump ktlint from 0.36.0 to 0.37.0 [\#20](https://github.com/getbouncer/cardscan-ui-android/pull/20) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update image utils [\#19](https://github.com/getbouncer/cardscan-ui-android/pull/19) ([awushensky](https://github.com/awushensky))
- Name extraction v1 w/ old object detector [\#18](https://github.com/getbouncer/cardscan-ui-android/pull/18) ([xsl](https://github.com/xsl))
- Bump gradle from 3.6.3 to 4.0.0 [\#17](https://github.com/getbouncer/cardscan-ui-android/pull/17) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0010](https://github.com/getbouncer/scan-framework-android/tree/2.0.0010) (2020-05-30)

[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0009...2.0.0010)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0009...2.0.0010)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0009...2.0.0010)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0009...2.0.0010)

**Merged pull requests:**

- Terminate a finite loop that has no data [\#30](https://github.com/getbouncer/scan-framework-android/pull/30) ([awushensky](https://github.com/awushensky))
- Bump gradle from 3.6.3 to 4.0.0 [\#29](https://github.com/getbouncer/scan-framework-android/pull/29) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Better support camera flash [\#21](https://github.com/getbouncer/scan-camera-android/pull/21) ([awushensky](https://github.com/awushensky))
- Bump gradle from 3.6.3 to 4.0.0 [\#20](https://github.com/getbouncer/scan-camera-android/pull/20) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump gradle from 3.6.3 to 4.0.0 [\#19](https://github.com/getbouncer/scan-payment-android/pull/19) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump gradle from 3.6.3 to 4.0.0 [\#15](https://github.com/getbouncer/scan-ui-android/pull/15) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))

## [2.0.0009](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0009) (2020-05-29)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0008...2.0.0009)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0008...2.0.0009)

**Merged pull requests:**

- Bump core-ktx from 1.2.0 to 1.3.0 [\#46](https://github.com/getbouncer/cardscan-demo-android/pull/46) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Remove required card number [\#45](https://github.com/getbouncer/cardscan-demo-android/pull/45) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#28](https://github.com/getbouncer/scan-framework-android/pull/28) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Start aggregation timer on valid result [\#27](https://github.com/getbouncer/scan-framework-android/pull/27) ([awushensky](https://github.com/awushensky))
- Stop ignoring scan timeout [\#26](https://github.com/getbouncer/scan-framework-android/pull/26) ([awushensky](https://github.com/awushensky))
- Simplify results [\#25](https://github.com/getbouncer/scan-framework-android/pull/25) ([awushensky](https://github.com/awushensky))
- Add logging to stats [\#24](https://github.com/getbouncer/scan-framework-android/pull/24) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#19](https://github.com/getbouncer/scan-camera-android/pull/19) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Use random focus variance [\#18](https://github.com/getbouncer/scan-camera-android/pull/18) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#18](https://github.com/getbouncer/scan-payment-android/pull/18) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Relocate aggregator [\#17](https://github.com/getbouncer/scan-payment-android/pull/17) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#14](https://github.com/getbouncer/scan-ui-android/pull/14) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Keep the screen on while scanning [\#13](https://github.com/getbouncer/scan-ui-android/pull/13) ([awushensky](https://github.com/awushensky))
- Reset previously valid result [\#16](https://github.com/getbouncer/cardscan-ui-android/pull/16) ([awushensky](https://github.com/awushensky))
- Bump core-ktx from 1.2.0 to 1.3.0 [\#15](https://github.com/getbouncer/cardscan-ui-android/pull/15) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Remove isValidPan [\#14](https://github.com/getbouncer/cardscan-ui-android/pull/14) ([awushensky](https://github.com/awushensky))
- Start result aggregation on valid result [\#13](https://github.com/getbouncer/cardscan-ui-android/pull/13) ([awushensky](https://github.com/awushensky))
- Simplify results [\#12](https://github.com/getbouncer/cardscan-ui-android/pull/12) ([awushensky](https://github.com/awushensky))

## [2.0.0008](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0008) (2020-05-21)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0007...2.0.0008)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0007...2.0.0008)

**Merged pull requests:**

- Bump kotlinx-coroutines-core from 1.3.6 to 1.3.7 [\#43](https://github.com/getbouncer/cardscan-demo-android/pull/43) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#42](https://github.com/getbouncer/cardscan-demo-android/pull/42) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#41](https://github.com/getbouncer/cardscan-demo-android/pull/41) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Make dependencies explicit [\#39](https://github.com/getbouncer/cardscan-demo-android/pull/39) ([awushensky](https://github.com/awushensky))
- Display card pan always [\#38](https://github.com/getbouncer/cardscan-demo-android/pull/38) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-android from 1.3.6 to 1.3.7 [\#19](https://github.com/getbouncer/scan-framework-android/pull/19) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlinx-coroutines-test from 1.3.6 to 1.3.7 [\#18](https://github.com/getbouncer/scan-framework-android/pull/18) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Use invalid api key for test [\#14](https://github.com/getbouncer/scan-framework-android/pull/14) ([awushensky](https://github.com/awushensky))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#13](https://github.com/getbouncer/scan-framework-android/pull/13) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump tensorflow-lite from 1.15.0 to 2.2.0 [\#12](https://github.com/getbouncer/scan-framework-android/pull/12) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#11](https://github.com/getbouncer/scan-framework-android/pull/11) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add more tests [\#8](https://github.com/getbouncer/scan-framework-android/pull/8) ([awushensky](https://github.com/awushensky))
- Add android test github action [\#7](https://github.com/getbouncer/scan-framework-android/pull/7) ([awushensky](https://github.com/awushensky))
- Ensure results are not duplicated [\#6](https://github.com/getbouncer/scan-framework-android/pull/6) ([awushensky](https://github.com/awushensky))
- Optimize some image utilities [\#5](https://github.com/getbouncer/scan-framework-android/pull/5) ([awushensky](https://github.com/awushensky))
- Refocus camera [\#15](https://github.com/getbouncer/scan-camera-android/pull/15) ([awushensky](https://github.com/awushensky))
- Simplify camera start [\#14](https://github.com/getbouncer/scan-camera-android/pull/14) ([awushensky](https://github.com/awushensky))
- Ignore camera config change failures [\#13](https://github.com/getbouncer/scan-camera-android/pull/13) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-core from 1.3.6 to 1.3.7 [\#12](https://github.com/getbouncer/scan-camera-android/pull/12) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlinx-coroutines-test from 1.3.6 to 1.3.7 [\#11](https://github.com/getbouncer/scan-camera-android/pull/11) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#8](https://github.com/getbouncer/scan-camera-android/pull/8) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#7](https://github.com/getbouncer/scan-camera-android/pull/7) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add tests to camera [\#5](https://github.com/getbouncer/scan-camera-android/pull/5) ([awushensky](https://github.com/awushensky))
- Remove camerax and camera2 [\#4](https://github.com/getbouncer/scan-camera-android/pull/4) ([awushensky](https://github.com/awushensky))
- Add camera1 and camerax [\#3](https://github.com/getbouncer/scan-camera-android/pull/3) ([awushensky](https://github.com/awushensky))
- Use better coroutine testing [\#13](https://github.com/getbouncer/scan-payment-android/pull/13) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-core from 1.3.6 to 1.3.7 [\#12](https://github.com/getbouncer/scan-payment-android/pull/12) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump kotlinx-coroutines-android from 1.3.6 to 1.3.7 [\#11](https://github.com/getbouncer/scan-payment-android/pull/11) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#10](https://github.com/getbouncer/scan-payment-android/pull/10) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#7](https://github.com/getbouncer/scan-payment-android/pull/7) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add tests [\#5](https://github.com/getbouncer/scan-payment-android/pull/5) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-core from 1.3.3 to 1.3.7 [\#11](https://github.com/getbouncer/scan-ui-android/pull/11) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add tests [\#10](https://github.com/getbouncer/scan-ui-android/pull/10) ([awushensky](https://github.com/awushensky))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#8](https://github.com/getbouncer/scan-ui-android/pull/8) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#7](https://github.com/getbouncer/scan-ui-android/pull/7) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Update default user interface [\#6](https://github.com/getbouncer/scan-ui-android/pull/6) ([awushensky](https://github.com/awushensky))
- Bump kotlinx-coroutines-core from 1.3.6 to 1.3.7 [\#10](https://github.com/getbouncer/cardscan-ui-android/pull/10) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.jfrog.bintray from 1.7.3 to 1.8.5 [\#8](https://github.com/getbouncer/cardscan-ui-android/pull/8) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Bump com.github.dcendents.android-maven from 2.0 to 2.1 [\#7](https://github.com/getbouncer/cardscan-ui-android/pull/7) ([dependabot-preview[bot]](https://github.com/apps/dependabot-preview))
- Add integration tests to CI [\#6](https://github.com/getbouncer/cardscan-ui-android/pull/6) ([awushensky](https://github.com/awushensky))
- Update user interface [\#5](https://github.com/getbouncer/cardscan-ui-android/pull/5) ([awushensky](https://github.com/awushensky))

## [2.0.0007](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0007) (2020-05-12)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.0006...2.0.0007)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/2.0.0005...2.0.0007)

**Merged pull requests:**

- Update documentation [\#37](https://github.com/getbouncer/cardscan-demo-android/pull/37) ([awushensky](https://github.com/awushensky))
- Fix crash on network failure [\#4](https://github.com/getbouncer/scan-framework-android/pull/4) ([awushensky](https://github.com/awushensky))
- Fix crash on camera open failure [\#2](https://github.com/getbouncer/scan-camera-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update submodules [\#4](https://github.com/getbouncer/scan-payment-android/pull/4) ([awushensky](https://github.com/awushensky))
- Update version [\#5](https://github.com/getbouncer/scan-ui-android/pull/5) ([awushensky](https://github.com/awushensky))
- Update submodules [\#4](https://github.com/getbouncer/cardscan-ui-android/pull/4) ([awushensky](https://github.com/awushensky))
- Set api key on warmup [\#3](https://github.com/getbouncer/cardscan-ui-android/pull/3) ([awushensky](https://github.com/awushensky))

## [2.0.0006](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0006) (2020-05-09)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0005...2.0.0006)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/2.0.0005...2.0.0006)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/2.0.0005...2.0.0006)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/2.0.0005...2.0.0006)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/2.0.005...2.0.0006)

**Merged pull requests:**

- Update version [\#36](https://github.com/getbouncer/cardscan-demo-android/pull/36) ([awushensky](https://github.com/awushensky))
- Fix signedUrl failure crash [\#3](https://github.com/getbouncer/scan-framework-android/pull/3) ([awushensky](https://github.com/awushensky))
- update version [\#3](https://github.com/getbouncer/scan-payment-android/pull/3) ([awushensky](https://github.com/awushensky))
- Allow invalid api key error [\#4](https://github.com/getbouncer/scan-ui-android/pull/4) ([awushensky](https://github.com/awushensky))

## [2.0.0005](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0005) (2020-05-08)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0004...2.0.0005)
[Full Changelog](https://github.com/getbouncer/scan-framework-android/compare/e0e5089a945c8b6b6ed47f3838d3d61997c1afe4...2.0.0005)
[Full Changelog](https://github.com/getbouncer/scan-camera-android/compare/70e9702f2bb0a99ef89e1477064eb541b661170f...2.0.0005)
[Full Changelog](https://github.com/getbouncer/scan-payment-android/compare/d19502708ef72c01d522e2d18e7a8bfbb81ec0b2...2.0.0005)
[Full Changelog](https://github.com/getbouncer/scan-ui-android/compare/0904ef185c19491c25b73c61eb8a22bed1eecb75...2.0.005)
[Full Changelog](https://github.com/getbouncer/cardscan-ui-android/compare/ebb299b0e1b799ec7c12aff1f535d0278d9107c1...2.0.0005)

**Merged pull requests:**

- Update submodules [\#35](https://github.com/getbouncer/cardscan-demo-android/pull/35) ([awushensky](https://github.com/awushensky))
- Replace libraries [\#34](https://github.com/getbouncer/cardscan-demo-android/pull/34) ([awushensky](https://github.com/awushensky))
- Remove build from git [\#2](https://github.com/getbouncer/scan-framework-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update documentation [\#1](https://github.com/getbouncer/scan-framework-android/pull/1) ([awushensky](https://github.com/awushensky))
- Update documentation [\#1](https://github.com/getbouncer/scan-camera-android/pull/1) ([awushensky](https://github.com/awushensky))
- Add results [\#2](https://github.com/getbouncer/scan-payment-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update documentation [\#1](https://github.com/getbouncer/scan-payment-android/pull/1) ([awushensky](https://github.com/awushensky))
- Rename module in docs [\#3](https://github.com/getbouncer/scan-ui-android/pull/3) ([awushensky](https://github.com/awushensky))
- Rename module [\#2](https://github.com/getbouncer/scan-ui-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update docs [\#1](https://github.com/getbouncer/scan-ui-android/pull/1) ([awushensky](https://github.com/awushensky))
- Update submodules [\#2](https://github.com/getbouncer/cardscan-ui-android/pull/2) ([awushensky](https://github.com/awushensky))
- Update documentation [\#1](https://github.com/getbouncer/cardscan-ui-android/pull/1) ([awushensky](https://github.com/awushensky))

## [2.0.0004](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0004) (2020-05-06)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/2.0.0003...2.0.0004)

**Merged pull requests:**

- Update version [\#33](https://github.com/getbouncer/cardscan-demo-android/pull/33) ([awushensky](https://github.com/awushensky))

## [2.0.0003](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0003) (2020-04-29)

[Full Changelog](https://github.com/getbouncer/cardscan-demo-android/compare/a0e3c8e303b7f72e2b08701e01781d9558b07e2c...2.0.0003)

**Implemented enhancements:**

- Update github checks [\#5](https://github.com/getbouncer/cardscan-demo-android/pull/5) ([awushensky](https://github.com/awushensky))

**Merged pull requests:**

- Update thread handling [\#32](https://github.com/getbouncer/cardscan-demo-android/pull/32) ([awushensky](https://github.com/awushensky))
- Update documentation [\#31](https://github.com/getbouncer/cardscan-demo-android/pull/31) ([awushensky](https://github.com/awushensky))
- Extract common ui [\#30](https://github.com/getbouncer/cardscan-demo-android/pull/30) ([awushensky](https://github.com/awushensky))
- Update submodules [\#29](https://github.com/getbouncer/cardscan-demo-android/pull/29) ([awushensky](https://github.com/awushensky))
- Update submodules [\#28](https://github.com/getbouncer/cardscan-demo-android/pull/28) ([awushensky](https://github.com/awushensky))
- Update submodules [\#27](https://github.com/getbouncer/cardscan-demo-android/pull/27) ([awushensky](https://github.com/awushensky))
- Update submodules [\#26](https://github.com/getbouncer/cardscan-demo-android/pull/26) ([awushensky](https://github.com/awushensky))
- Update submodules [\#25](https://github.com/getbouncer/cardscan-demo-android/pull/25) ([awushensky](https://github.com/awushensky))
- Update submodules [\#24](https://github.com/getbouncer/cardscan-demo-android/pull/24) ([awushensky](https://github.com/awushensky))
- Update submodules [\#23](https://github.com/getbouncer/cardscan-demo-android/pull/23) ([awushensky](https://github.com/awushensky))
- Prevent screenshots [\#22](https://github.com/getbouncer/cardscan-demo-android/pull/22) ([awushensky](https://github.com/awushensky))
- Add api key check [\#21](https://github.com/getbouncer/cardscan-demo-android/pull/21) ([awushensky](https://github.com/awushensky))
- Update license [\#20](https://github.com/getbouncer/cardscan-demo-android/pull/20) ([awushensky](https://github.com/awushensky))
- Update documentation [\#19](https://github.com/getbouncer/cardscan-demo-android/pull/19) ([awushensky](https://github.com/awushensky))
- Update submodules [\#18](https://github.com/getbouncer/cardscan-demo-android/pull/18) ([awushensky](https://github.com/awushensky))
- Add documentation [\#17](https://github.com/getbouncer/cardscan-demo-android/pull/17) ([awushensky](https://github.com/awushensky))
- Make logo optional [\#16](https://github.com/getbouncer/cardscan-demo-android/pull/16) ([awushensky](https://github.com/awushensky))
- Update submodules [\#15](https://github.com/getbouncer/cardscan-demo-android/pull/15) ([awushensky](https://github.com/awushensky))
- Update submodules [\#14](https://github.com/getbouncer/cardscan-demo-android/pull/14) ([awushensky](https://github.com/awushensky))
- Rename app to demo [\#13](https://github.com/getbouncer/cardscan-demo-android/pull/13) ([awushensky](https://github.com/awushensky))
- Support state in loops [\#12](https://github.com/getbouncer/cardscan-demo-android/pull/12) ([awushensky](https://github.com/awushensky))
- Remove camera 1 api [\#11](https://github.com/getbouncer/cardscan-demo-android/pull/11) ([awushensky](https://github.com/awushensky))
- Scope tests to the app itself [\#10](https://github.com/getbouncer/cardscan-demo-android/pull/10) ([awushensky](https://github.com/awushensky))
- Update submodules [\#9](https://github.com/getbouncer/cardscan-demo-android/pull/9) ([awushensky](https://github.com/awushensky))
- Update submodules [\#8](https://github.com/getbouncer/cardscan-demo-android/pull/8) ([awushensky](https://github.com/awushensky))
- Use submodules [\#7](https://github.com/getbouncer/cardscan-demo-android/pull/7) ([awushensky](https://github.com/awushensky))
- Show the card pan when scanninng [\#6](https://github.com/getbouncer/cardscan-demo-android/pull/6) ([awushensky](https://github.com/awushensky))
- Update dependencies [\#4](https://github.com/getbouncer/cardscan-demo-android/pull/4) ([awushensky](https://github.com/awushensky))
- Require API key [\#3](https://github.com/getbouncer/cardscan-demo-android/pull/3) ([awushensky](https://github.com/awushensky))
- Add code owners [\#2](https://github.com/getbouncer/cardscan-demo-android/pull/2) ([awushensky](https://github.com/awushensky))
- Support camera1 APIs [\#1](https://github.com/getbouncer/cardscan-demo-android/pull/1) ([awushensky](https://github.com/awushensky))



================================================
FILE: LICENSE
================================================
The MIT License

Copyright (c) 2011- Stripe, Inc. (https://stripe.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
# Deprecation Notice
Hello from the Stripe (formerly Bouncer) team!

We're excited to provide an update on the state and future of the [Card Scan OCR](https://github.com/stripe/stripe-android/tree/master/stripecardscan) product! As we continue to build into Stripe's ecosystem, we'll be supporting the mission to continuously improve the end customer experience in many of Stripe's core checkout products.

This SDK has been [migrated to Stripe](https://github.com/stripe/stripe-android/tree/master/stripecardscan) and is now free for use under the MIT license!

If you are not currently a Stripe user, and interested in learning more about improving checkout experience through Stripe, please let us know and we can connect you with the team.

If you are not currently a Stripe user, and want to continue using the existing SDK, you can do so free of charge. Starting January 1, 2022, we will no longer be charging for use of the existing Bouncer Card Scan OCR SDK. For product support on [Android](https://github.com/stripe/stripe-android/issues) and [iOS](https://github.com/stripe/stripe-ios/issues). For billing support, please email [bouncer-support@stripe.com](mailto:bouncer-support@stripe.com).

For the new product, please visit the [stripe github repository](https://github.com/stripe/stripe-android/tree/master/stripecardscan).

# Overview
This repository contains the legacy, deprecated open source code for [Bouncer](https://www.getbouncer.com) products (e.g. CardScan). See the individual sub modules for more information on each.

[CardScan](https://getbouncer.com/scan) is a relatively small library that provides fast and accurate payment card scanning.

CardScan is the foundation for CardVerify enterprise libraries, which validate the authenticity of payment cards as they are scanned.

![Lint](https://github.com/getbouncer/cardscan-android/workflows/Lint/badge.svg)
![Instrumentation Tests](https://github.com/getbouncer/cardscan-android/workflows/Instrumentation%20Tests/badge.svg)
![Unit Tests](https://github.com/getbouncer/cardscan-android/workflows/Unit%20Tests/badge.svg)
![Release](https://github.com/getbouncer/cardscan-android/workflows/Release/badge.svg)
[![GitHub release](https://img.shields.io/github/release/getbouncer/cardscan-android.svg?maxAge=60)](https://github.com/getbouncer/cardscan-android/releases)

![demo](docs/images/demo.gif)

## Contents
* [Requirements](#requirements)
* [Demo](#demo)
* [Integration](#integration)
* [Customizing](#customizing)
* [Developing](#developing)
* [Authors](#authors)
* [License](#license)

## Requirements
* Android API level 21 or higher
* AndroidX compatibility
* Kotlin coroutine compatibility

Note: Your app does not have to be written in kotlin to integrate this library, but must be able to depend on kotlin functionality.

## Demo
This repository contains a demonstration app for the CardScan product. To build and run the demo app, follow the instructions in the [demo documentation](https://docs.getbouncer.com/card-scan/android-integration-guide#demo).

## Integration
See the [integration documentation](https://docs.getbouncer.com/card-scan/android-integration-guide) in the Bouncer Docs.

### Provisioning an API key
CardScan requires a valid API key to run. To provision an API key, visit the [Bouncer API console](https://api.getbouncer.com/console).

### Name and expiration extraction support (BETA)
To test name and/or expiration extraction, please first provision an API key, then reach out to [bouncer-support@stripe.com](mailto:bouncer-support@stripe.com) with details about your use case and estimated volumes.

Before launching the CardScan flow, make sure to call the ```CardScanActivity.warmup()``` function with your API key and set ```initializeNameAndExpiryExtraction``` to ```true```

```kotlin
CardScanActivity.warmup(this, API_KEY, true)
```

## Customizing
CardScan is built to be customized to fit your UI.

### Basic modifications
To modify text, colors, or padding of the default UI, see the [customization](https://docs.getbouncer.com/card-scan/android-integration-guide/customization-guide) documentation.

### Extensive modifications
To modify arrangement or UI functionality, CardScan can be used as a library for your custom implementation. See the [example single-activity demo app](demo/src/main/java/com/getbouncer/cardscan/demo/SingleActivityDemo.java).

## Developing
See the [development docs](https://docs.getbouncer.com/card-scan/android-integration-guide/development-guide) for details on developing for CardScan.

## Authors
Adam Wushensky, Sam King, and Zain ul Abi Din

## License
This library is available under the MIT license. See the [LICENSE](LICENSE) file for the full license text.


================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
        google()
        maven { url "https://plugins.gradle.org/m2/" }
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:4.2.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31"
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

plugins {
    id 'org.jetbrains.kotlin.plugin.serialization' version "1.5.31"
    id 'org.jetbrains.dokka' version '1.5.0'
    id "io.github.gradle-nexus.publish-plugin" version "1.1.0"
}

allprojects {
    apply plugin: 'checkstyle'

    checkstyle {
        toolVersion '8.29'
    }

    configurations {
        javadocDeps
        kotlinlint
    }

    dependencies {
        kotlinlint("com.pinterest:ktlint:0.41.0") {
            attributes {
                attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, Bundling.EXTERNAL))
            }
        }
    }

    repositories {
        mavenLocal()
        mavenCentral()
        google()
        maven { url "https://plugins.gradle.org/m2/" }
    }

    task checkJavaStyle(type: Checkstyle) {
        showViolations = true
        configFile file("../settings/checkstyle.xml")
        source 'src/main/java'
        include '**/*.java'
        exclude '**/gen/**'
        exclude '**/R.java'
        exclude '**/BuildConfig.java'

        // empty classpath
        classpath = files()
    }

    task ktlint(type: JavaExec, group: "verification") {
        description = "Check Kotlin code style."
        main = "com.pinterest.ktlint.Main"
        classpath = configurations.kotlinlint
        args "src/**/*.kt"
        // to generate report in checkstyle format prepend following args:
        // "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/ktlint.xml"
        // see https://github.com/pinterest/ktlint#usage for more
    }

    task ktlintFormat(type: JavaExec, group: "formatting") {
        description = "Fix Kotlin code style deviations."
        main = "com.pinterest.ktlint.Main"
        classpath = configurations.kotlinlint
        args "-F", "src/**/*.kt"
    }
}

ext {
    publishGroupId = 'com.getbouncer'
}

File secretPropsFile = project.rootProject.file('local.properties')
if (secretPropsFile.exists()) {
    Properties p = new Properties()
    new FileInputStream(secretPropsFile).withCloseable { is ->
        p.load(is)
    }
    p.each { name, value ->
        ext[name] = value
    }
} else {
    ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID')
    ext["signing.password"] = System.getenv('SIGNING_PASSWORD')
    ext["signing.secretKeyRingFile"] = System.getenv('SIGNING_SECRET_KEY_RING_FILE')

    ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME')
    ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD')

    ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID')
}

nexusPublishing {
    repositories {
        sonatype {
            nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
            snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
            packageGroup = publishGroupId
            stagingProfileId = sonatypeStagingProfileId
            username = ossrhUsername
            password = ossrhPassword
        }
    }
}


================================================
FILE: cardscan-demo/.gitignore
================================================
/build


================================================
FILE: cardscan-demo/README.md
================================================
# Deprecation Notice
Hello from the Stripe (formerly Bouncer) team!

We're excited to provide an update on the state and future of the [Card Scan OCR](https://github.com/stripe/stripe-android/tree/master/stripecardscan) product! As we continue to build into Stripe's ecosystem, we'll be supporting the mission to continuously improve the end customer experience in many of Stripe's core checkout products.

This SDK has been [migrated to Stripe](https://github.com/stripe/stripe-android/tree/master/stripecardscan) and is now free for use under the MIT license!

If you are not currently a Stripe user, and interested in learning more about improving checkout experience through Stripe, please let us know and we can connect you with the team.

If you are not currently a Stripe user, and want to continue using the existing SDK, you can do so free of charge. Starting January 1, 2022, we will no longer be charging for use of the existing Bouncer Card Scan OCR SDK. For product support on [Android](https://github.com/stripe/stripe-android/issues) and [iOS](https://github.com/stripe/stripe-ios/issues). For billing support, please email [bouncer-support@stripe.com](mailto:bouncer-support@stripe.com).

For the new product, please visit the [stripe github repository](https://github.com/stripe/stripe-android/tree/master/stripecardscan).

# Overview
This repository serves as a legacy, deprecated open source demonstration for the CardScan library. [CardScan](https://cardscan.io/) is a relatively small library that provides fast and accurate payment card scanning.

CardScan is the foundation for CardVerify enterprise libraries, which validate the authenticity of payment cards as they are scanned.

![demo](../docs/images/demo.gif)

## Contents
* [Requirements](#requirements)
* [Demo](#demo)
* [Integration](#integration)
* [Customizing](#customizing)
* [Developing](#developing)
* [Authors](#authors)
* [License](#license)

## Requirements
* Android API level 21 or higher
* AndroidX compatibility
* Kotlin coroutine compatibility

Note: Your app does not have to be written in kotlin to integrate this library, but must be able to depend on kotlin functionality.

## Demo
This repository contains a demonstration app for the CardScan product. To build and install this library follow the following steps:

1. Clone the repository from github
    ```bash
    git clone --recursive https://github.com/getbouncer/cardscan-demo-android
    ```
    
2. Build the library using gradle or [android studio](https://developer.android.com/studio).
    a. Using android studio, open the directory `cardscan-demo-android`. Install the app on your device or an emulator by clicking the play button in the top right of android studio.
    
    ![build_android_studio](../docs/images/build_android_studio.png)
    
    b. Using gradle, build the demo app by executing the following command:
    
    ```bash
    ./gradlew demo:assembleRelease
    ```
    This will create a release APK in the `cardscan-demo/build/outputs/apk` directory. Copy this file to your device and install it.

## Integration
See the [integration documentation](https://docs.getbouncer.com/card-scan/android-integration-guide/android-development-guide) in the Bouncer Docs.

### Provisioning an API key
CardScan requires a valid API key to run. To provision an API key, visit the [Bouncer API console](https://api.getbouncer.com/console).

### Name and expiration extraction support (BETA)
To test name and/or expiration extraction, please first provision an API key, then reach out to [bouncer-support@stripe.com](mailto:bouncer-support@stripe.com) with details about your use case and estimated volumes.

Before launching the CardScan flow, make sure to call the ```CardScanActivity.warmup()``` function with your API key and set ```initializeNameAndExpiryExtraction``` to ```true```

```kotlin
CardScanActivity.warmup(this, API_KEY, true)
```

## Customizing
CardScan is built to be customized to fit your UI.

### Basic modifications
To modify text, colors, or padding of the default UI, see the [customization](https://docs.getbouncer.com/card-scan/android-integration-guide/android-customization-guide) documentation.

### Extensive modifications
To modify arrangement or UI functionality, CardScan can be used as a library for your custom implementation. See the [example single-activity demo app](demo/src/main/java/com/getbouncer/cardscan/demo/SingleActivityDemo.java).

## Developing
See the [development docs](https://docs.getbouncer.com/card-scan/android-integration-guide/android-development-guide) for details on developing for CardScan.

## Authors
Adam Wushensky, Sam King, and Zain ul Abi Din

## License
This library is available under the MIT license. See the [LICENSE](../LICENSE) file for the full license text.


================================================
FILE: cardscan-demo/build.gradle
================================================
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 30
    buildToolsVersion '30.0.3'

    defaultConfig {
        applicationId "com.getbouncer.cardscan.demo"
        minSdkVersion 21
        targetSdkVersion 30
        versionCode 1

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }

    lintOptions {
        enable "Interoperability"
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation project(":scan-camerax")
    implementation project(':scan-payment-full')
    implementation project(":cardscan-ui")

    implementation "androidx.appcompat:appcompat:1.3.1"
    implementation "androidx.core:core-ktx:1.6.0"
    implementation "androidx.constraintlayout:constraintlayout:2.1.0"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1"
}

dependencies {
    testImplementation "androidx.test:core:1.4.0"
    testImplementation "androidx.test:runner:1.4.0"
    testImplementation "junit:junit:4.13.2"
    testImplementation "org.jetbrains.kotlin:kotlin-test:1.5.30"

    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
}

dependencies {
    androidTestImplementation "androidx.test.ext:junit:1.1.3"
    androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
    androidTestImplementation "org.jetbrains.kotlin:kotlin-test:1.5.30"
}


================================================
FILE: cardscan-demo/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile


================================================
FILE: cardscan-demo/src/androidTest/java/com/getbouncer/cardscan/demo/ExampleInstrumentedTest.kt
================================================
package com.getbouncer.cardscan.demo

import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Test
import kotlin.test.assertEquals

/**
 * Instrumented test, which will execute on an Android device.
 *
 * See [testing documentation](http://d.android.com/tools/testing).
 */
class ExampleInstrumentedTest {
    @Test
    fun useAppContext() {
        // Context of the app under test.
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        assertEquals("com.getbouncer.cardscan.demo", appContext.packageName)
    }
}


================================================
FILE: cardscan-demo/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.getbouncer.cardscan.demo">

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.FLASHLIGHT"/>
    <uses-permission android:name="android.permission.INTERNET" />

    <uses-feature android:name="android.hardware.camera" android:required="false" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />

    <application
        android:label="@string/app_name"
        android:allowBackup="false"
        android:supportsRtl="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:icon="@mipmap/ic_launcher">

        <activity
            android:name=".LaunchActivity"
            android:screenOrientation="fullSensor"
            android:theme="@style/AppTheme">

            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>

        <activity android:name=".SingleActivityDemo"
            android:screenOrientation="nosensor"
            android:theme="@style/AppTheme" />

    </application>

</manifest>


================================================
FILE: cardscan-demo/src/main/java/com/getbouncer/cardscan/demo/LaunchActivity.java
================================================
package com.getbouncer.cardscan.demo;

import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.getbouncer.cardscan.ui.CardScanSheet;
import com.getbouncer.cardscan.ui.CardScanSheetResult;
import com.getbouncer.cardscan.ui.ScannedCard;
import com.getbouncer.scan.framework.Config;
import com.getbouncer.scan.framework.Scan;
import com.getbouncer.scan.ui.CancellationReason;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import kotlin.Unit;

public class LaunchActivity extends AppCompatActivity {

    private static final String API_KEY = "qOJ_fF-WLDMbG05iBq5wvwiTNTmM2qIn";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_launch);

        final CardScanSheet sheet = CardScanSheet.create(this, API_KEY, this::handleScanResult);

        // Because this activity displays card numbers, disallow screenshots.
        getWindow().setFlags(
            WindowManager.LayoutParams.FLAG_SECURE,
            WindowManager.LayoutParams.FLAG_SECURE
        );

        ((CheckBox) findViewById(R.id.enableDebugCheckbox))
                .setOnCheckedChangeListener((buttonView, isChecked) -> Config.setDebug(isChecked));

        findViewById(R.id.scanCardButton).setOnClickListener(v -> {
            final boolean enableNameExtraction =
                ((CheckBox) findViewById(R.id.enableNameExtractionCheckbox)).isChecked();
            final boolean enableExpiryExtraction =
                ((CheckBox) findViewById(R.id.enableExpiryExtractionCheckbox)).isChecked();
            final boolean enableEnterCardManually =
                ((CheckBox) findViewById(R.id.enableEnterCardManuallyCheckbox)).isChecked();

            sheet.present(
                /* enableEnterCardManually */ enableEnterCardManually,
                /* enableExpiryExtraction */ enableExpiryExtraction,
                /* enableNameExtraction */ enableNameExtraction
            );
        });

        if (Scan.INSTANCE.isDeviceArchitectureArm()) {
            ((TextView) findViewById(R.id.deviceArchitectureText))
                .setText(getString(
                    R.string.deviceArchitecture,
                    "arm: " + Scan.INSTANCE.getDeviceArchitecture()
                ));
        } else {
            ((TextView) findViewById(R.id.deviceArchitectureText))
                .setText(getString(
                    R.string.deviceArchitecture,
                    "NOT arm" + Scan.INSTANCE.getDeviceArchitecture()
                ));
        }

        findViewById(R.id.singleActivityDemo).setOnClickListener(v ->
                startActivity(new Intent(this, SingleActivityDemo.class))
        );

        CardScanSheet.prepareScan(this, API_KEY, true, () -> null);
    }

    private Unit handleScanResult(final CardScanSheetResult result) {
        if (result instanceof CardScanSheetResult.Completed) {
            cardScanned(((CardScanSheetResult.Completed) result).getScannedCard());
        } else if (result instanceof CardScanSheetResult.Canceled) {
            userCanceled(((CardScanSheetResult.Canceled) result).getReason());
        } else if (result instanceof CardScanSheetResult.Failed) {
            analyzerFailure(((CardScanSheetResult.Failed) result).getError());
        }

        return Unit.INSTANCE;
    }

    private void cardScanned(@NotNull final ScannedCard scanResult) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        StringBuilder message = new StringBuilder();
        message.append(scanResult.getPan());
        if (scanResult.getCardholderName() != null) {
            message.append("\nName: ");
            message.append(scanResult.getCardholderName());
        }
        if (scanResult.getExpiryMonth() != null && scanResult.getExpiryYear() != null) {
            message.append(
                    String.format("\nExpiry: %s/%s",
                    scanResult.getExpiryMonth(),
                    scanResult.getExpiryYear())
            );
        }
        if (scanResult.getErrorString() != null) {
            message.append("\nError: ");
            message.append(scanResult.getErrorString());
        }
        builder.setMessage(message);
        builder.show();
    }

    private void userCanceled(@NotNull final CancellationReason reason) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        if (reason instanceof CancellationReason.Back) {
            builder.setMessage(R.string.user_pressed_back);
        } else if (reason instanceof CancellationReason.Closed) {
            builder.setMessage(R.string.scan_canceled);
        } else if (reason instanceof CancellationReason.CameraPermissionDenied) {
            builder.setMessage(R.string.permission_denied);
        } else if (reason instanceof CancellationReason.UserCannotScan) {
            builder.setMessage(R.string.enter_manually);
        }
        builder.show();
    }

    private void analyzerFailure(@NotNull final Throwable reason) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(reason.getMessage());
        builder.show();
    }
}


================================================
FILE: cardscan-demo/src/main/java/com/getbouncer/cardscan/demo/SingleActivityDemo.java
================================================
package com.getbouncer.cardscan.demo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.util.Size;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.getbouncer.cardscan.ui.CardScanFlow;
import com.getbouncer.cardscan.ui.SavedFrame;
import com.getbouncer.cardscan.ui.analyzer.CompletionLoopAnalyzer;
import com.getbouncer.cardscan.ui.result.CompletionLoopListener;
import com.getbouncer.cardscan.ui.result.CompletionLoopResult;
import com.getbouncer.cardscan.ui.result.MainLoopAggregator;
import com.getbouncer.cardscan.ui.result.MainLoopState;
import com.getbouncer.scan.camera.CameraAdapter;
import com.getbouncer.scan.camera.CameraErrorListener;
import com.getbouncer.scan.camera.CameraPreviewImage;
import com.getbouncer.scan.camera.CameraSelectorKt;
import com.getbouncer.scan.framework.AggregateResultListener;
import com.getbouncer.scan.framework.AnalyzerLoopErrorListener;
import com.getbouncer.scan.framework.Config;
import com.getbouncer.scan.framework.Stats;
import com.getbouncer.scan.framework.api.BouncerApi;
import com.getbouncer.scan.framework.api.dto.ScanStatistics;
import com.getbouncer.scan.framework.interop.BlockingAggregateResultListener;
import com.getbouncer.scan.framework.util.AppDetails;
import com.getbouncer.scan.framework.util.Device;
import com.getbouncer.scan.payment.card.CardExpiryKt;
import com.getbouncer.scan.payment.card.PanFormatterKt;
import com.getbouncer.scan.payment.card.PaymentCardUtils;
import com.getbouncer.scan.ui.ViewFinderBackground;
import com.getbouncer.scan.ui.util.ViewExtensionsKt;

import java.util.Locale;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import kotlin.Unit;
import kotlin.coroutines.CoroutineContext;
import kotlinx.coroutines.CoroutineScope;
import kotlinx.coroutines.Dispatchers;

public class SingleActivityDemo extends AppCompatActivity implements CameraErrorListener,
        AnalyzerLoopErrorListener, CoroutineScope {

    private enum State {
        NOT_FOUND,
        FOUND,
        CORRECT
    }

    private static final int PERMISSION_REQUEST_CODE = 1200;
    private static final Size MINIMUM_RESOLUTION = new Size(1280, 720);

    private Button scanCardButton;
    private View scanView;

    private FrameLayout cameraPreview;

    private FrameLayout viewFinderWindow;
    private ViewFinderBackground viewFinderBackground;
    private ImageView viewFinderBorder;
    private View processingOverlay;

    private ImageView flashButtonView;

    private TextView cardPanTextView;

    private CameraAdapter<CameraPreviewImage<Bitmap>> cameraAdapter;

    private CardScanFlow cardScanFlow;

    private State scanState = State.NOT_FOUND;

    private String pan = null;

    /**
     * CardScan uses kotlin coroutines to run multiple analyzers in parallel for maximum image
     * throughput. This coroutine context binds the coroutines to this activity, so that if this
     * activity is terminated, all coroutines are terminated and there is no work leak.
     *
     * Additionally, this specifies which threads the coroutines will run on. Normally, the default
     * dispatchers should be used so that coroutines run on threads bound by the number of CPU
     * cores.
     */
    @NotNull
    @Override
    public CoroutineContext getCoroutineContext() {
        return Dispatchers.getDefault();
    }

    @Override
    @SuppressLint("ClickableViewAccessibility")
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single_demo);

        scanCardButton = findViewById(R.id.scanCardButton);
        scanView = findViewById(R.id.scanView);

        scanCardButton.setOnClickListener(v -> {
            scanCardButton.setVisibility(View.GONE);
            scanView.setVisibility(View.VISIBLE);

            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) !=
                    PackageManager.PERMISSION_GRANTED) {
                requestCameraPermission();
            } else {
                startScan();
            }
        });

        cameraPreview = findViewById(R.id.cameraPreviewHolder);
        viewFinderWindow = findViewById(R.id.viewFinderWindow);
        viewFinderBackground = findViewById(R.id.viewFinderBackground);
        viewFinderBorder = findViewById(R.id.viewFinderBorder);
        processingOverlay = findViewById(R.id.processing_overlay);

        flashButtonView = findViewById(R.id.flashButtonView);
        ImageView closeButtonView = findViewById(R.id.closeButtonView);

        cardPanTextView = findViewById(R.id.cardPanTextView);

        closeButtonView.setOnClickListener(v -> userCancelScan());
        flashButtonView.setOnClickListener(v -> setFlashlightState(!cameraAdapter.isTorchOn()));

        // Allow the user to set the focus of the camera by tapping on the view finder.
        viewFinderWindow.setOnTouchListener((v, event) -> {
            cameraAdapter.setFocus(new PointF(
                event.getX() + viewFinderWindow.getLeft(), 
                event.getY() + viewFinderWindow.getTop())
            );
            return true;
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (cardScanFlow != null) {
            cardScanFlow.cancelFlow();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        setFlashlightState(false);
    }

    @Override
    protected void onResume() {
        super.onResume();
        setStateNotFound();
    }

    /**
     * Request permission to use the camera.
     */
    private void requestCameraPermission() {
        ActivityCompat.requestPermissions(
            this,
            new String[] { Manifest.permission.CAMERA },
            PERMISSION_REQUEST_CODE
        );
    }

    /**
     * Handle permission status changes. If the camera permission has been granted, start it. If
     * not, show a dialog.
     */
    @Override
    public void onRequestPermissionsResult(
        int requestCode,
        @NotNull String[] permissions,
        @NotNull int[] grantResults
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == PERMISSION_REQUEST_CODE && grantResults.length > 0) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startScan();
            } else {
                showPermissionDeniedDialog();
            }
        }
    }

    /**
     * Show an explanation dialog for why we are requesting camera permissions.
     */
    private void showPermissionDeniedDialog() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(R.string.bouncer_camera_permission_denied_message)
            .setPositiveButton(
                R.string.bouncer_camera_permission_denied_ok,
                (dialog, which) -> requestCameraPermission()
            )
            .setNegativeButton(
                R.string.bouncer_camera_permission_denied_cancel,
                (dialog, which) -> startScan()
            )
            .show();
    }

    /**
     * Start the scanning flow.
     */
    private void startScan() {
        // ensure the cameraPreview view has rendered.
        cameraPreview.post(() -> {
            // Track scan statistics for health check
            Stats.INSTANCE.startScan();

            // Tell the background where to draw a hole for the viewfinder window
            viewFinderBackground.setViewFinderRect(ViewExtensionsKt.asRect(viewFinderWindow));

            // Create a camera adapter and bind it to this activity.
            cameraAdapter = CameraSelectorKt.getCameraAdapter(
                this,
                cameraPreview,
                MINIMUM_RESOLUTION,
                this
            );
            cameraAdapter.bindToLifecycle(this);
            cameraAdapter.withFlashSupport(supported -> {
                flashButtonView.setVisibility(supported ? View.VISIBLE : View.INVISIBLE);
                return Unit.INSTANCE;
            });

            // Create and start a CardScanFlow which will handle the business logic of the scan
            cardScanFlow = new CardScanFlow(
                true,
                true,
                aggregateResultListener,
                this
            );
            cardScanFlow.startFlow(
                this,
                cameraAdapter.getImageStream(),
                ViewExtensionsKt.asRect(viewFinderWindow),
                this,
                this
            );
        });
    }

    /**
     * Turn the flashlight on or off.
     */
    private void setFlashlightState(boolean on) {
        if (cameraAdapter != null) {
            cameraAdapter.setTorchState(on);

            if (cameraAdapter.isTorchOn()) {
                flashButtonView.setImageResource(R.drawable.bouncer_flash_on_dark);
            } else {
                flashButtonView.setImageResource(R.drawable.bouncer_flash_off_dark);
            }
        }
    }

    /**
     * Cancel scanning due to analyzer failure
     */
    private void analyzerFailureCancelScan(@Nullable final Throwable cause) {
        Log.e(Config.getLogTag(), "Canceling scan due to analyzer error", cause);
        new AlertDialog.Builder(this)
            .setMessage("Analyzer failure")
            .show();
        closeScanner();
    }

    /**
     * Cancel scanning due to a camera error.
     */
    private void cameraErrorCancelScan(@Nullable final Throwable cause) {
        Log.e(Config.getLogTag(), "Canceling scan due to camera error", cause);
        new AlertDialog.Builder(this)
            .setMessage("Camera error")
            .show();
        closeScanner();
    }

    /**
     * The scan has been cancelled by the user.
     */
    private void userCancelScan() {
        new AlertDialog.Builder(this)
            .setMessage("Scan Canceled by user")
            .show();
        closeScanner();
    }

    /**
     * Show the completed scan results
     */
    private void completeScan(
        @Nullable String expiryMonth,
        @Nullable String expiryYear,
        @Nullable String cardNumber,
        @Nullable String issuer,
        @Nullable String name,
        @Nullable String error
    ) {
        new AlertDialog.Builder(this)
            .setMessage(String.format(
                Locale.getDefault(),
                "%s\n%s\n%s/%s\n%s\n%s",
                cardNumber,
                issuer,
                expiryMonth,
                expiryYear,
                name,
                error
            ))
            .show();
        closeScanner();
    }

    /**
     * Close the scanner.
     */
    private void closeScanner() {
        setFlashlightState(false);
        scanCardButton.setVisibility(View.VISIBLE);
        scanView.setVisibility(View.GONE);
        setStateNotFound();
        cameraAdapter.unbindFromLifecycle(this);
        if (cardScanFlow != null) {
            cardScanFlow.cancelFlow();
        }
        BouncerApi.uploadScanStats(
            this,
            Stats.INSTANCE.getInstanceId(),
            Stats.INSTANCE.getScanId(),
            Device.fromContext(this),
            AppDetails.fromContext(this),
            ScanStatistics.fromStats()
        );
    }

    @Override
    public void onCameraOpenError(@Nullable Throwable cause) {
        cameraErrorCancelScan(cause);
    }

    @Override
    public void onCameraAccessError(@Nullable Throwable cause) {
        cameraErrorCancelScan(cause);
    }

    @Override
    public void onCameraUnsupportedError(@Nullable Throwable cause) {
        cameraErrorCancelScan(cause);
    }

    @Override
    public boolean onAnalyzerFailure(@NotNull Throwable t) {
        analyzerFailureCancelScan(t);
        return true;
    }

    @Override
    public boolean onResultFailure(@NotNull Throwable t) {
        analyzerFailureCancelScan(t);
        return true;
    }

    private final CompletionLoopListener completionLoopListener = new CompletionLoopListener() {
        @Override
        public void onCompletionLoopFrameProcessed(
                @NotNull CompletionLoopAnalyzer.Prediction result,
                @NotNull SavedFrame frame
        ) {
            // display debug information if so desired
        }

        @Override
        public void onCompletionLoopDone(@NotNull CompletionLoopResult result) {
            @Nullable final String expiryMonth;
            @Nullable final String expiryYear;
            if (result.getExpiryMonth() != null &&
                result.getExpiryYear() != null &&
                CardExpiryKt.isValidExpiry(
                    null,
                    result.getExpiryMonth(),
                    result.getExpiryYear()
                )
            ) {
                expiryMonth = result.getExpiryMonth();
                expiryYear = result.getExpiryYear();
            } else {
                expiryMonth = null;
                expiryYear = null;
            }

            new Handler(getMainLooper()).post(() -> {
                // Only show the expiry dates that are not expired
                completeScan(
                    expiryMonth,
                    expiryYear,
                    SingleActivityDemo.this.pan,
                    PaymentCardUtils.getCardIssuer(SingleActivityDemo.this.pan).getDisplayName(),
                    result.getName(),
                    result.getErrorString()
                );
            });
        }
    };

    private final AggregateResultListener<
            MainLoopAggregator.InterimResult,
            MainLoopAggregator.FinalResult> aggregateResultListener =
            new BlockingAggregateResultListener<
                MainLoopAggregator.InterimResult,
                MainLoopAggregator.FinalResult>() {

        /**
         * An interim result has been received from the scan, the scan is still running. Update your
         * UI as necessary here to display the progress of the scan.
         */
        @Override
        public void onInterimResultBlocking(MainLoopAggregator.InterimResult interimResult) {
            new Handler(getMainLooper()).post(() -> {
                final MainLoopState mainLoopState = interimResult.getState();

                if (mainLoopState instanceof MainLoopState.Initial) {
                    // In initial state, show no card found
                    setStateNotFound();

                } else if (mainLoopState instanceof MainLoopState.PanFound) {
                    // If OCR is running and a valid card number is visible, display it
                    final MainLoopState.PanFound state = (MainLoopState.PanFound) mainLoopState;
                    final String pan = state.getMostLikelyPan();
                    if (pan != null) {
                        cardPanTextView.setText(PanFormatterKt.formatPan(pan));
                        ViewExtensionsKt.show(cardPanTextView);
                    }
                    setStateFound();

                } else if (mainLoopState instanceof MainLoopState.CardSatisfied) {
                    // If OCR is running and a valid card number is visible, display it
                    final MainLoopState.CardSatisfied state =
                            (MainLoopState.CardSatisfied) mainLoopState;
                    final String pan = state.getMostLikelyPan();
                    if (pan != null) {
                        cardPanTextView.setText(PanFormatterKt.formatPan(pan));
                        ViewExtensionsKt.show(cardPanTextView);
                    }

                    setStateFound();

                } else if (mainLoopState instanceof MainLoopState.PanSatisfied) {
                    // If OCR is running and a valid card number is visible, display it
                    final MainLoopState.PanSatisfied state =
                            (MainLoopState.PanSatisfied) mainLoopState;
                    final String pan = state.getPan();
                    if (pan != null) {
                        cardPanTextView.setText(PanFormatterKt.formatPan(pan));
                        ViewExtensionsKt.show(cardPanTextView);
                    }

                    setStateFound();

                } else if (mainLoopState instanceof MainLoopState.Finished) {
                    // Once the main loop has finished, the camera can stop
                    cameraAdapter.unbindFromLifecycle(SingleActivityDemo.this);
                    setStateCorrect();

                }
            });
        }

        /**
         * The scan has completed and the final result is available. Close the scanner and make use
         * of the final result.
         */
        @Override
        public void onResultBlocking(MainLoopAggregator.FinalResult result) {
            SingleActivityDemo.this.pan = result.getPan();
            cardScanFlow.launchCompletionLoop(
                SingleActivityDemo.this,
                completionLoopListener,
                cardScanFlow.selectCompletionLoopFrames(
                    result.getAverageFrameRate(),
                    result.getSavedFrames()
                ),
                result.getAverageFrameRate().compareTo(Config.getSlowDeviceFrameRate()) > 0,
                SingleActivityDemo.this
            );
        }

        /**
         * The scan was reset (usually because the activity was backgrounded). Reset the UI.
         */
        @Override
        public void onResetBlocking() {
            new Handler(getMainLooper()).post(() -> setStateNotFound());
        }
    };

    /**
     * Display a blue border tracing the outline of the card to indicate that the card is identified
     * and scanning is running.
     */
    private void setStateFound() {
        if (scanState == State.FOUND) return;
        ViewExtensionsKt.startAnimation(viewFinderBorder,
            R.drawable.bouncer_card_border_found_long);
        ViewExtensionsKt.hide(processingOverlay);
        scanState = State.FOUND;
    }

    /**
     * Return the view to its initial state, where no card has been detected.
     */
    private void setStateNotFound() {
        if (scanState == State.NOT_FOUND) return;
        ViewExtensionsKt.startAnimation(viewFinderBorder, R.drawable.bouncer_card_border_not_found);
        ViewExtensionsKt.hide(cardPanTextView);
        ViewExtensionsKt.hide(processingOverlay);
        scanState = State.NOT_FOUND;
    }

    /**
     * Flash the border around the card green to indicate that scanning was successful.
     */
    private void setStateCorrect() {
        if (scanState == State.CORRECT) return;
        ViewExtensionsKt.startAnimation(viewFinderBorder, R.drawable.bouncer_card_border_correct);
        ViewExtensionsKt.show(processingOverlay);
        scanState = State.CORRECT;
    }
}


================================================
FILE: cardscan-demo/src/main/res/drawable/ic_launcher_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#008577"
        android:pathData="M0,0h108v108h-108z" />
    <path
        android:fillColor="#00000000"
        android:pathData="M9,0L9,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,0L19,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M29,0L29,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M39,0L39,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M49,0L49,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M59,0L59,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M69,0L69,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M79,0L79,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M89,0L89,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M99,0L99,108"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,9L108,9"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,19L108,19"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,29L108,29"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,39L108,39"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,49L108,49"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,59L108,59"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,69L108,69"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,79L108,79"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,89L108,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M0,99L108,99"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,29L89,29"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,39L89,39"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,49L89,49"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,59L89,59"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,69L89,69"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M19,79L89,79"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M29,19L29,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M39,19L39,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M49,19L49,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M59,19L59,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M69,19L69,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
    <path
        android:fillColor="#00000000"
        android:pathData="M79,19L79,89"
        android:strokeWidth="0.8"
        android:strokeColor="#33FFFFFF" />
</vector>


================================================
FILE: cardscan-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillType="evenOdd"
        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
        android:strokeWidth="1"
        android:strokeColor="#00000000">
        <aapt:attr name="android:fillColor">
            <gradient
                android:endX="78.5885"
                android:endY="90.9159"
                android:startX="48.7653"
                android:startY="61.0927"
                android:type="linear">
                <item
                    android:color="#44000000"
                    android:offset="0.0" />
                <item
                    android:color="#00000000"
                    android:offset="1.0" />
            </gradient>
        </aapt:attr>
    </path>
    <path
        android:fillColor="#FFFFFF"
        an
Download .txt
gitextract_79p3qz5m/

├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── android_test.yml
│       ├── lint.yml
│       ├── release.yml
│       └── unit_test.yml
├── .github_changelog_generator
├── .gitignore
├── CHANGELOG.md
├── CODEOWNERS
├── Contributor License Agreement
├── HISTORY.md
├── LICENSE
├── README.md
├── build.gradle
├── cardscan-demo/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── cardscan/
│       │                   └── demo/
│       │                       └── ExampleInstrumentedTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── getbouncer/
│       │   │           └── cardscan/
│       │   │               └── demo/
│       │   │                   ├── LaunchActivity.java
│       │   │                   └── SingleActivityDemo.java
│       │   └── res/
│       │       ├── drawable/
│       │       │   └── ic_launcher_background.xml
│       │       ├── drawable-v24/
│       │       │   └── ic_launcher_foreground.xml
│       │       ├── layout/
│       │       │   ├── activity_launch.xml
│       │       │   └── activity_single_demo.xml
│       │       ├── mipmap-anydpi-v26/
│       │       │   ├── ic_launcher.xml
│       │       │   └── ic_launcher_round.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── cardscan/
│                           └── demo/
│                               └── ExampleUnitTest.kt
├── cardscan-ui/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── cardscan/
│       │                   └── ui/
│       │                       └── ExampleInstrumentedTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── getbouncer/
│       │   │           └── cardscan/
│       │   │               └── ui/
│       │   │                   ├── CardScanActivity.kt
│       │   │                   ├── CardScanBaseActivity.kt
│       │   │                   ├── CardScanFlow.kt
│       │   │                   ├── CardScanSheet.kt
│       │   │                   ├── analyzer/
│       │   │                   │   ├── CompletionLoopAnalyzer.kt
│       │   │                   │   └── MainLoopAnalyzer.kt
│       │   │                   ├── exception/
│       │   │                   │   ├── StripeNetworkException.kt
│       │   │                   │   └── UnknownScanException.kt
│       │   │                   └── result/
│       │   │                       ├── CompletionLoopAggregator.kt
│       │   │                       ├── MainLoopAggregator.kt
│       │   │                       └── MainLoopStateMachine.kt
│       │   └── res/
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── dimensions.xml
│       │           └── strings.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── cardscan/
│                           └── ui/
│                               └── result/
│                                   └── MainLoopStateMachineTest.kt
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── scan-camera/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── camera/
│                               ├── Camera1Adapter.kt
│                               ├── CameraAdapter.kt
│                               └── CameraSelector.kt
├── scan-camera2/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── camera/
│       │                       └── extension/
│       │                           └── UtilInstrumentationTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── camera/
│       │                       └── extension/
│       │                           ├── CameraAdapterImpl.kt
│       │                           ├── CameraDetails.kt
│       │                           └── Util.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── camera/
│                               └── extension/
│                                   └── UtilTest.kt
├── scan-camerax/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── camera/
│                               └── extension/
│                                   ├── CameraAdapterImpl.kt
│                                   ├── Image.kt
│                                   └── Util.kt
├── scan-framework/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   ├── assets/
│       │   │   └── sample_resource.tflite
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── framework/
│       │                       ├── FetcherTest.kt
│       │                       ├── LoaderTest.kt
│       │                       ├── StorageTest.kt
│       │                       ├── api/
│       │                       │   └── BouncerApiTest.kt
│       │                       ├── image/
│       │                       │   └── BitmapExtensionsTest.kt
│       │                       ├── layout/
│       │                       │   └── LayoutTest.kt
│       │                       └── util/
│       │                           └── AppDetailsTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── framework/
│       │                       ├── Analyzer.kt
│       │                       ├── Config.kt
│       │                       ├── Fetcher.kt
│       │                       ├── Loader.kt
│       │                       ├── Loop.kt
│       │                       ├── MachineState.kt
│       │                       ├── Result.kt
│       │                       ├── Scan.kt
│       │                       ├── Stat.kt
│       │                       ├── Storage.kt
│       │                       ├── TrackedImage.kt
│       │                       ├── api/
│       │                       │   ├── BouncerApi.kt
│       │                       │   ├── Network.kt
│       │                       │   ├── NetworkResult.kt
│       │                       │   └── dto/
│       │                       │       ├── AppInfo.kt
│       │                       │       ├── BouncerErrorResponse.kt
│       │                       │       ├── ClientDevice.kt
│       │                       │       ├── ClientStats.kt
│       │                       │       ├── ModelDetails.kt
│       │                       │       ├── ModelSignedUrlResponse.kt
│       │                       │       └── ValidateApiKeyResponse.kt
│       │                       ├── exception/
│       │                       │   ├── ImageTypeNotSupportedException.kt
│       │                       │   └── InvalidBouncerApiKeyException.kt
│       │                       ├── image/
│       │                       │   ├── BitmapExtensions.kt
│       │                       │   ├── ImageExtensions.kt
│       │                       │   ├── MLImage.kt
│       │                       │   ├── NV21Image.kt
│       │                       │   └── YuvImageExtensions.kt
│       │                       ├── interop/
│       │                       │   ├── BlockingAnalyzer.kt
│       │                       │   ├── BlockingResult.kt
│       │                       │   └── JavaContinuation.kt
│       │                       ├── ml/
│       │                       │   ├── ModelVersionTracker.kt
│       │                       │   ├── NonMaximumSuppression.kt
│       │                       │   ├── TensorFlowLiteAnalyzer.kt
│       │                       │   └── ssd/
│       │                       │       ├── ClassifierScores.kt
│       │                       │       ├── RectForm.kt
│       │                       │       └── SizeAndCenter.kt
│       │                       ├── time/
│       │                       │   ├── Clock.kt
│       │                       │   ├── Coroutine.kt
│       │                       │   ├── Duration.kt
│       │                       │   ├── Rate.kt
│       │                       │   └── Timer.kt
│       │                       └── util/
│       │                           ├── AppDetails.kt
│       │                           ├── ArrayExtensions.kt
│       │                           ├── Device.kt
│       │                           ├── File.kt
│       │                           ├── FrameRateTracker.kt
│       │                           ├── FrameSaver.kt
│       │                           ├── ItemCounter.kt
│       │                           ├── Layout.kt
│       │                           ├── Memoize.kt
│       │                           └── Retry.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── framework/
│                               ├── AnalyzerTest.kt
│                               ├── LoopTest.kt
│                               ├── interop/
│                               │   ├── BlockingAnalyzerTest.java
│                               │   └── BlockingResultTest.java
│                               ├── time/
│                               │   └── DurationTest.kt
│                               └── util/
│                                   ├── ArrayExtensionsTest.kt
│                                   ├── FrameSaverTest.kt
│                                   ├── ItemCounterTest.kt
│                                   ├── MemoizeTest.kt
│                                   └── RetryTest.kt
├── scan-payment/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── payment/
│       │                       ├── ImageTest.kt
│       │                       ├── PaymentCardAndroidTest.kt
│       │                       └── ml/
│       │                           ├── CardDetectTest.kt
│       │                           ├── ExpiryDetectTest.kt
│       │                           ├── SSDOcrTest.kt
│       │                           ├── TextDetectTest.kt
│       │                           └── ssd/
│       │                               └── SSDTest.kt
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── payment/
│       │                       ├── FrameDetails.kt
│       │                       ├── Image.kt
│       │                       ├── ModelManager.kt
│       │                       ├── TextDetectModelManager.kt
│       │                       ├── analyzer/
│       │                       │   └── NameAndExpiryAnalyzer.kt
│       │                       ├── card/
│       │                       │   ├── CardExpiry.kt
│       │                       │   ├── CardIssuer.kt
│       │                       │   ├── CardType.kt
│       │                       │   ├── PanFormatter.kt
│       │                       │   ├── PanValidator.kt
│       │                       │   ├── PaymentCard.kt
│       │                       │   ├── PaymentCardUtils.kt
│       │                       │   └── RequiresMatchingCard.kt
│       │                       └── ml/
│       │                           ├── AlphabetDetect.kt
│       │                           ├── AlphabetDetectModelManager.kt
│       │                           ├── CardDetect.kt
│       │                           ├── CardDetectModelManager.kt
│       │                           ├── ExpiryDetect.kt
│       │                           ├── ExpiryDetectModelManager.kt
│       │                           ├── SSDOcr.kt
│       │                           ├── SSDOcrModelManager.kt
│       │                           ├── TextDetect.kt
│       │                           ├── ssd/
│       │                           │   ├── DetectionBox.kt
│       │                           │   ├── OcrPriorsGenerator.kt
│       │                           │   └── SSD.kt
│       │                           └── yolo/
│       │                               └── Yolo.kt
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── payment/
│                               └── card/
│                                   └── PaymentCardTest.kt
├── scan-payment-full/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── payment/
│       │                       └── ml/
│       │                           ├── CardDetectTest.kt
│       │                           └── SSDOcrTest.kt
│       └── main/
│           ├── AndroidManifest.xml
│           └── assets/
│               ├── darknite_1_1_1_16.tflite
│               └── ux_0_5_23_16.tflite
├── scan-payment-minimal/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── getbouncer/
│       │               └── scan/
│       │                   └── payment/
│       │                       └── ml/
│       │                           ├── CardDetectTest.kt
│       │                           └── SSDOcrTest.kt
│       └── main/
│           ├── AndroidManifest.xml
│           └── assets/
│               ├── UX.0.25.106.8.tflite
│               └── mb2_brex_metal_synthetic_svhnextra_epoch_3_5_98_8.tflite
├── scan-ui/
│   ├── .gitignore
│   ├── README.md
│   ├── build.gradle
│   ├── consumer-rules.pro
│   ├── deploy.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── getbouncer/
│       │   │           └── scan/
│       │   │               └── ui/
│       │   │                   ├── DebugOverlayTest.kt
│       │   │                   └── util/
│       │   │                       └── ViewExtensionsTest.kt
│       │   └── res/
│       │       └── values/
│       │           └── colors.xml
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── getbouncer/
│       │   │           └── scan/
│       │   │               └── ui/
│       │   │                   ├── DebugOverlay.kt
│       │   │                   ├── ScanActivity.kt
│       │   │                   ├── ScanFlow.kt
│       │   │                   ├── SimpleScanActivity.kt
│       │   │                   ├── ViewFinderBackground.kt
│       │   │                   └── util/
│       │   │                       └── ViewExtensions.kt
│       │   └── res/
│       │       ├── drawable/
│       │       │   ├── bouncer_camera_swap_dark.xml
│       │       │   ├── bouncer_camera_swap_light.xml
│       │       │   ├── bouncer_card_background_correct.xml
│       │       │   ├── bouncer_card_background_found.xml
│       │       │   ├── bouncer_card_background_not_found.xml
│       │       │   ├── bouncer_card_background_wrong.xml
│       │       │   ├── bouncer_card_border_correct.xml
│       │       │   ├── bouncer_card_border_found.xml
│       │       │   ├── bouncer_card_border_found_long.xml
│       │       │   ├── bouncer_card_border_not_found.xml
│       │       │   ├── bouncer_card_border_wrong.xml
│       │       │   ├── bouncer_close_button_dark.xml
│       │       │   ├── bouncer_close_button_light.xml
│       │       │   ├── bouncer_flash_off_dark.xml
│       │       │   ├── bouncer_flash_off_light.xml
│       │       │   ├── bouncer_flash_on_dark.xml
│       │       │   ├── bouncer_flash_on_light.xml
│       │       │   ├── bouncer_lock_dark.xml
│       │       │   ├── bouncer_lock_light.xml
│       │       │   ├── bouncer_logo_dark_background.xml
│       │       │   └── bouncer_logo_light_background.xml
│       │       └── values/
│       │           ├── colors.xml
│       │           ├── dimensions.xml
│       │           ├── strings.xml
│       │           └── styles.xml
│       └── test/
│           └── java/
│               └── com/
│                   └── getbouncer/
│                       └── scan/
│                           └── ui/
│                               └── ExampleUnitTest.kt
├── settings/
│   └── checkstyle.xml
├── settings.gradle
├── tensorflow-lite/
│   ├── .gitignore
│   ├── build.gradle
│   ├── deploy.gradle
│   └── tensorflow-lite-all-models.aar
└── tensorflow-lite-arm-only/
    ├── .gitignore
    ├── build.gradle
    ├── deploy.gradle
    └── tensorflow-lite-all-models-arm-only.aar
Download .txt
SYMBOL INDEX (48 symbols across 4 files)

FILE: cardscan-demo/src/main/java/com/getbouncer/cardscan/demo/LaunchActivity.java
  class LaunchActivity (line 24) | public class LaunchActivity extends AppCompatActivity {
    method onCreate (line 28) | @Override
    method handleScanResult (line 80) | private Unit handleScanResult(final CardScanSheetResult result) {
    method cardScanned (line 92) | private void cardScanned(@NotNull final ScannedCard scanResult) {
    method userCanceled (line 115) | private void userCanceled(@NotNull final CancellationReason reason) {
    method analyzerFailure (line 129) | private void analyzerFailure(@NotNull final Throwable reason) {

FILE: cardscan-demo/src/main/java/com/getbouncer/cardscan/demo/SingleActivityDemo.java
  class SingleActivityDemo (line 59) | public class SingleActivityDemo extends AppCompatActivity implements Cam...
    type State (line 62) | private enum State {
    method getCoroutineContext (line 102) | @NotNull
    method onCreate (line 108) | @Override
    method onDestroy (line 153) | @Override
    method onPause (line 161) | @Override
    method onResume (line 167) | @Override
    method requestCameraPermission (line 176) | private void requestCameraPermission() {
    method onRequestPermissionsResult (line 188) | @Override
    method showPermissionDeniedDialog (line 208) | private void showPermissionDeniedDialog() {
    method startScan (line 225) | private void startScan() {
    method setFlashlightState (line 267) | private void setFlashlightState(boolean on) {
    method analyzerFailureCancelScan (line 282) | private void analyzerFailureCancelScan(@Nullable final Throwable cause) {
    method cameraErrorCancelScan (line 293) | private void cameraErrorCancelScan(@Nullable final Throwable cause) {
    method userCancelScan (line 304) | private void userCancelScan() {
    method completeScan (line 314) | private void completeScan(
    method closeScanner (line 340) | private void closeScanner() {
    method onCameraOpenError (line 359) | @Override
    method onCameraAccessError (line 364) | @Override
    method onCameraUnsupportedError (line 369) | @Override
    method onAnalyzerFailure (line 374) | @Override
    method onResultFailure (line 380) | @Override
    method onCompletionLoopFrameProcessed (line 387) | @Override
    method onCompletionLoopDone (line 395) | @Override
    method onInterimResultBlocking (line 439) | @Override
    method onResultBlocking (line 495) | @Override
    method onResetBlocking (line 513) | @Override
    method setStateFound (line 523) | private void setStateFound() {
    method setStateNotFound (line 534) | private void setStateNotFound() {
    method setStateCorrect (line 545) | private void setStateCorrect() {

FILE: scan-framework/src/test/java/com/getbouncer/scan/framework/interop/BlockingAnalyzerTest.java
  class BlockingAnalyzerTest (line 22) | public class BlockingAnalyzerTest {
    method blockingAnalyzer_works (line 24) | @Test(timeout = 1000)
    method blockingAnalyzerFactory_works (line 53) | @Test(timeout = 1000)
    method blockingAnalyzerPoolFactory_works (line 96) | @Test

FILE: scan-framework/src/test/java/com/getbouncer/scan/framework/interop/BlockingResultTest.java
  class BlockingResultTest (line 28) | public class BlockingResultTest {
    class TerminatingTestResult (line 30) | private static class TerminatingTestResult {
    class AggregateTestResult (line 36) | private static class AggregateTestResult {
    method blockingResultHandler_works (line 42) | @Test(timeout = 1000)
    method blockingStatefulResultHandler_works (line 72) | @Test(timeout = 1000)
    method blockingTerminatingResultHandler_works (line 102) | @Test(timeout = 1000)
    method blockingAggregateResultListener_works (line 172) | @Test(timeout = 1000L)
    method blockingResultAggregator_works (line 242) | @Test(timeout = 1000L)
Condensed preview — 272 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,244K chars).
[
  {
    "path": ".github/dependabot.yml",
    "chars": 1077,
    "preview": "version: 2\nupdates:\n- package-ecosystem: gradle\n  directory: \"/\"\n  schedule:\n    interval: daily\n  open-pull-requests-li"
  },
  {
    "path": ".github/workflows/android_test.yml",
    "chars": 585,
    "preview": "name: Instrumentation Tests\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  inst"
  },
  {
    "path": ".github/workflows/lint.yml",
    "chars": 424,
    "preview": "name: Lint\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  lint:\n\n    runs-on: u"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 4109,
    "preview": "name: Release\n\non:\n  release:\n    types: [published]\n\njobs:\n  run_final_checks:\n    name: Run final checks\n    runs-on: "
  },
  {
    "path": ".github/workflows/unit_test.yml",
    "chars": 558,
    "preview": "name: Unit Tests\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  test:\n\n    runs"
  },
  {
    "path": ".github_changelog_generator",
    "chars": 19,
    "preview": "since-tag=2.0.0015\n"
  },
  {
    "path": ".gitignore",
    "chars": 515,
    "preview": "*.iml\n.gradle\n/local.properties\n/.idea/caches\n/.idea/compiler.xml\n/.idea/libraries\n/.idea/modules.xml\n/.idea/workspace.x"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 86791,
    "preview": "# Changelog\n\n## [2.2.0003](https://github.com/getbouncer/cardscan-android/tree/2.2.0003) (2022-06-15)\n\n**Closed issues:*"
  },
  {
    "path": "CODEOWNERS",
    "chars": 1321,
    "preview": "# This is a comment.\n# Each line is a file pattern followed by one or more owners.\n\n# These owners will be the default o"
  },
  {
    "path": "Contributor License Agreement",
    "chars": 11557,
    "preview": "Bouncer\nIndividual and Entity Contributor License Agreement\n\nThank you for your interest in contributing to software pro"
  },
  {
    "path": "HISTORY.md",
    "chars": 39597,
    "preview": "## [2.0.0014](https://github.com/getbouncer/cardscan-demo-android/tree/2.0.0014) (2020-07-14)\n\n[Full Changelog](https://"
  },
  {
    "path": "LICENSE",
    "chars": 1095,
    "preview": "The MIT License\n\nCopyright (c) 2011- Stripe, Inc. (https://stripe.com)\n\nPermission is hereby granted, free of charge, to"
  },
  {
    "path": "README.md",
    "chars": 4723,
    "preview": "# Deprecation Notice\nHello from the Stripe (formerly Bouncer) team!\n\nWe're excited to provide an update on the state and"
  },
  {
    "path": "build.gradle",
    "chars": 3498,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    r"
  },
  {
    "path": "cardscan-demo/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "cardscan-demo/README.md",
    "chars": 4801,
    "preview": "# Deprecation Notice\nHello from the Stripe (formerly Bouncer) team!\n\nWe're excited to provide an update on the state and"
  },
  {
    "path": "cardscan-demo/build.gradle",
    "chars": 1828,
    "preview": "apply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\n\nandroid {\n    compileSdkVersion 30\n    buildTool"
  },
  {
    "path": "cardscan-demo/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "cardscan-demo/src/androidTest/java/com/getbouncer/cardscan/demo/ExampleInstrumentedTest.kt",
    "chars": 572,
    "preview": "package com.getbouncer.cardscan.demo\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport org.junit.Test\nim"
  },
  {
    "path": "cardscan-demo/src/main/AndroidManifest.xml",
    "chars": 1360,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.getbouncer.cardscan.demo\">\n\n    <u"
  },
  {
    "path": "cardscan-demo/src/main/java/com/getbouncer/cardscan/demo/LaunchActivity.java",
    "chars": 5413,
    "preview": "package com.getbouncer.cardscan.demo;\n\nimport android.app.AlertDialog;\nimport android.content.Intent;\nimport android.os."
  },
  {
    "path": "cardscan-demo/src/main/java/com/getbouncer/cardscan/demo/SingleActivityDemo.java",
    "chars": 19338,
    "preview": "package com.getbouncer.cardscan.demo;\n\nimport android.Manifest;\nimport android.annotation.SuppressLint;\nimport android.c"
  },
  {
    "path": "cardscan-demo/src/main/res/drawable/ic_launcher_background.xml",
    "chars": 5606,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:wi"
  },
  {
    "path": "cardscan-demo/src/main/res/drawable-v24/ic_launcher_foreground.xml",
    "chars": 1880,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:aapt=\"http://schemas.android.com/aapt\"\n    "
  },
  {
    "path": "cardscan-demo/src/main/res/layout/activity_launch.xml",
    "chars": 3971,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ScrollView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xm"
  },
  {
    "path": "cardscan-demo/src/main/res/layout/activity_single_demo.xml",
    "chars": 9276,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<merge\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:a"
  },
  {
    "path": "cardscan-demo/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "cardscan-demo/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "chars": 272,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <b"
  },
  {
    "path": "cardscan-demo/src/main/res/values/colors.xml",
    "chars": 208,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#008577</color>\n    <color name=\"color"
  },
  {
    "path": "cardscan-demo/src/main/res/values/strings.xml",
    "chars": 800,
    "preview": "<resources>\n    <string name=\"app_name\">CardScan Demo</string>\n\n    <string name=\"scan_card\">Scan Card</string>\n\n    <st"
  },
  {
    "path": "cardscan-demo/src/main/res/values/styles.xml",
    "chars": 383,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "cardscan-demo/src/test/java/com/getbouncer/cardscan/demo/ExampleUnitTest.kt",
    "chars": 358,
    "preview": "package com.getbouncer.cardscan.demo\n\nimport org.junit.Test\nimport kotlin.test.assertEquals\n\n/**\n * Example local unit t"
  },
  {
    "path": "cardscan-ui/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "cardscan-ui/README.md",
    "chars": 4127,
    "preview": "# Deprecation Notice\nHello from the Stripe (formerly Bouncer) team!\n\nWe're excited to provide an update on the state and"
  },
  {
    "path": "cardscan-ui/build.gradle",
    "chars": 2047,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-parcelize'\n\nandroid {\n    compi"
  },
  {
    "path": "cardscan-ui/consumer-rules.pro",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "cardscan-ui/deploy.gradle",
    "chars": 5178,
    "preview": "apply plugin: 'maven-publish'\napply plugin: 'org.jetbrains.dokka'\napply plugin: 'signing'\n\ntask androidSourcesJar(type: "
  },
  {
    "path": "cardscan-ui/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "cardscan-ui/src/androidTest/java/com/getbouncer/cardscan/ui/ExampleInstrumentedTest.kt",
    "chars": 431,
    "preview": "package com.getbouncer.cardscan.ui\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport org.junit.Test\nimpo"
  },
  {
    "path": "cardscan-ui/src/main/AndroidManifest.xml",
    "chars": 358,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.getbouncer.cardscan.ui\">\n\n    <app"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/CardScanActivity.kt",
    "chars": 10990,
    "preview": "package com.getbouncer.cardscan.ui\n\nimport android.app.Activity\nimport android.content.Intent\nimport android.os.Bundle\ni"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/CardScanBaseActivity.kt",
    "chars": 9256,
    "preview": "package com.getbouncer.cardscan.ui\n\nimport android.annotation.SuppressLint\nimport android.os.Bundle\nimport android.util."
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/CardScanFlow.kt",
    "chars": 14733,
    "preview": "package com.getbouncer.cardscan.ui\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.graphic"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/CardScanSheet.kt",
    "chars": 7388,
    "preview": "package com.getbouncer.cardscan.ui\n\nimport android.content.Context\nimport android.content.Intent\nimport android.os.Parce"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/analyzer/CompletionLoopAnalyzer.kt",
    "chars": 2234,
    "preview": "package com.getbouncer.cardscan.ui.analyzer\n\nimport com.getbouncer.cardscan.ui.SavedFrame\nimport com.getbouncer.scan.fra"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/analyzer/MainLoopAnalyzer.kt",
    "chars": 2765,
    "preview": "package com.getbouncer.cardscan.ui.analyzer\n\nimport android.graphics.Bitmap\nimport android.graphics.Rect\nimport com.getb"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/exception/StripeNetworkException.kt",
    "chars": 268,
    "preview": "package com.getbouncer.cardscan.ui.exception\n\nimport java.lang.Exception\n\n@Deprecated(message = \"Replaced by stripe card"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/exception/UnknownScanException.kt",
    "chars": 246,
    "preview": "package com.getbouncer.cardscan.ui.exception\n\n@Deprecated(message = \"Replaced by stripe card scan. See https://github.co"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/result/CompletionLoopAggregator.kt",
    "chars": 4028,
    "preview": "package com.getbouncer.cardscan.ui.result\n\nimport com.getbouncer.cardscan.ui.SavedFrame\nimport com.getbouncer.cardscan.u"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/result/MainLoopAggregator.kt",
    "chars": 4936,
    "preview": "package com.getbouncer.cardscan.ui.result\n\nimport android.util.Log\nimport androidx.annotation.Keep\nimport com.getbouncer"
  },
  {
    "path": "cardscan-ui/src/main/java/com/getbouncer/cardscan/ui/result/MainLoopStateMachine.kt",
    "chars": 5432,
    "preview": "package com.getbouncer.cardscan.ui.result\n\nimport androidx.annotation.VisibleForTesting\nimport com.getbouncer.cardscan.u"
  },
  {
    "path": "cardscan-ui/src/main/res/values/colors.xml",
    "chars": 622,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"bouncerProcessingBackground\">#AA000000</color>\n    <"
  },
  {
    "path": "cardscan-ui/src/main/res/values/dimensions.xml",
    "chars": 495,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"bouncerProcessingTextSize\">24sp</dimen>\n\n    <dimen "
  },
  {
    "path": "cardscan-ui/src/main/res/values/strings.xml",
    "chars": 325,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"bouncer_processing_card\">Processing, please wait</s"
  },
  {
    "path": "cardscan-ui/src/test/java/com/getbouncer/cardscan/ui/result/MainLoopStateMachineTest.kt",
    "chars": 12346,
    "preview": "package com.getbouncer.cardscan.ui.result\n\nimport androidx.test.filters.LargeTest\nimport com.getbouncer.cardscan.ui.anal"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 232,
    "preview": "#Fri Feb 26 15:43:08 PST 2021\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradle.properties",
    "chars": 1180,
    "preview": "# Project-wide Gradle settings.\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will ov"
  },
  {
    "path": "gradlew",
    "chars": 5296,
    "preview": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up"
  },
  {
    "path": "gradlew.bat",
    "chars": 2260,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "scan-camera/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "scan-camera/README.md",
    "chars": 3486,
    "preview": "# Deprecation Notice\nHello from the Stripe (formerly Bouncer) team!\n\nWe're excited to provide an update on the state and"
  },
  {
    "path": "scan-camera/build.gradle",
    "chars": 1688,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\n\nandroid {\n    compileSdkVersion 30\n    buildToolsVer"
  },
  {
    "path": "scan-camera/consumer-rules.pro",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "scan-camera/deploy.gradle",
    "chars": 5173,
    "preview": "apply plugin: 'maven-publish'\napply plugin: 'org.jetbrains.dokka'\napply plugin: 'signing'\n\ntask androidSourcesJar(type: "
  },
  {
    "path": "scan-camera/proguard-rules.pro",
    "chars": 751,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "scan-camera/src/main/AndroidManifest.xml",
    "chars": 441,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.getbouncer.scan.camera\" >\n\n    <us"
  },
  {
    "path": "scan-camera/src/main/java/com/getbouncer/scan/camera/Camera1Adapter.kt",
    "chars": 15738,
    "preview": "@file:Suppress(\"deprecation\")\npackage com.getbouncer.scan.camera\n\nimport android.annotation.SuppressLint\nimport android."
  },
  {
    "path": "scan-camera/src/main/java/com/getbouncer/scan/camera/CameraAdapter.kt",
    "chars": 5688,
    "preview": "package com.getbouncer.scan.camera\n\nimport android.content.Context\nimport android.content.pm.PackageManager\nimport andro"
  },
  {
    "path": "scan-camera/src/main/java/com/getbouncer/scan/camera/CameraSelector.kt",
    "chars": 2212,
    "preview": "package com.getbouncer.scan.camera\n\nimport android.app.Activity\nimport android.graphics.Bitmap\nimport android.os.Build\ni"
  },
  {
    "path": "scan-camera2/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "scan-camera2/build.gradle",
    "chars": 1573,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\n\nandroid {\n    compileSdkVersion 30\n    buildToolsVer"
  },
  {
    "path": "scan-camera2/deploy.gradle",
    "chars": 5174,
    "preview": "apply plugin: 'maven-publish'\napply plugin: 'org.jetbrains.dokka'\napply plugin: 'signing'\n\ntask androidSourcesJar(type: "
  },
  {
    "path": "scan-camera2/src/androidTest/java/com/getbouncer/scan/camera/extension/UtilInstrumentationTest.kt",
    "chars": 2687,
    "preview": "package com.getbouncer.scan.camera.extension\n\nimport android.util.Size\nimport android.view.Surface\nimport androidx.test."
  },
  {
    "path": "scan-camera2/src/main/AndroidManifest.xml",
    "chars": 451,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.getbouncer.scan.camera.extension\" "
  },
  {
    "path": "scan-camera2/src/main/java/com/getbouncer/scan/camera/extension/CameraAdapterImpl.kt",
    "chars": 25268,
    "preview": "/*\n * Copyright 2014 The Android Open Source Project\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "scan-camera2/src/main/java/com/getbouncer/scan/camera/extension/CameraDetails.kt",
    "chars": 379,
    "preview": "package com.getbouncer.scan.camera.extension\n\nimport android.hardware.camera2.params.StreamConfigurationMap\n\n/**\n * Deta"
  },
  {
    "path": "scan-camera2/src/main/java/com/getbouncer/scan/camera/extension/Util.kt",
    "chars": 3611,
    "preview": "package com.getbouncer.scan.camera.extension\n\nimport android.util.Size\nimport android.util.SizeF\nimport android.view.Sur"
  },
  {
    "path": "scan-camera2/src/test/java/com/getbouncer/scan/camera/extension/UtilTest.kt",
    "chars": 2158,
    "preview": "package com.getbouncer.scan.camera.extension\n\nimport android.view.Surface\nimport androidx.test.filters.SmallTest\nimport "
  },
  {
    "path": "scan-camerax/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "scan-camerax/build.gradle",
    "chars": 1931,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\n\nandroid {\n    compileSdkVersion 30\n    buildToolsVer"
  },
  {
    "path": "scan-camerax/deploy.gradle",
    "chars": 5174,
    "preview": "apply plugin: 'maven-publish'\napply plugin: 'org.jetbrains.dokka'\napply plugin: 'signing'\n\ntask androidSourcesJar(type: "
  },
  {
    "path": "scan-camerax/src/main/AndroidManifest.xml",
    "chars": 451,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.getbouncer.scan.camera.extension\" "
  },
  {
    "path": "scan-camerax/src/main/java/com/getbouncer/scan/camera/extension/CameraAdapterImpl.kt",
    "chars": 9975,
    "preview": "package com.getbouncer.scan.camera.extension\n\nimport android.app.Activity\nimport android.graphics.Bitmap\nimport android."
  },
  {
    "path": "scan-camerax/src/main/java/com/getbouncer/scan/camera/extension/Image.kt",
    "chars": 1186,
    "preview": "package com.getbouncer.scan.camera.extension\n\nimport android.graphics.ImageFormat\nimport android.renderscript.RenderScri"
  },
  {
    "path": "scan-camerax/src/main/java/com/getbouncer/scan/camera/extension/Util.kt",
    "chars": 548,
    "preview": "package com.getbouncer.scan.camera.extension\n\nimport android.util.Size\nimport kotlin.math.max\nimport kotlin.math.min\n\n/*"
  },
  {
    "path": "scan-framework/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "scan-framework/README.md",
    "chars": 8264,
    "preview": "# Deprecation Notice\nHello from the Stripe (formerly Bouncer) team!\n\nWe're excited to provide an update on the state and"
  },
  {
    "path": "scan-framework/build.gradle",
    "chars": 2362,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'kotlinx-serialization'\n\nandroid {\n    "
  },
  {
    "path": "scan-framework/consumer-rules.pro",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "scan-framework/deploy.gradle",
    "chars": 5173,
    "preview": "apply plugin: 'maven-publish'\napply plugin: 'org.jetbrains.dokka'\napply plugin: 'signing'\n\ntask androidSourcesJar(type: "
  },
  {
    "path": "scan-framework/proguard-rules.pro",
    "chars": 803,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "scan-framework/src/androidTest/assets/sample_resource.tflite",
    "chars": 14,
    "preview": "ABC123\nDEF456\n"
  },
  {
    "path": "scan-framework/src/androidTest/java/com/getbouncer/scan/framework/FetcherTest.kt",
    "chars": 12600,
    "preview": "package com.getbouncer.scan.framework\n\nimport androidx.test.filters.LargeTest\nimport androidx.test.filters.SmallTest\nimp"
  },
  {
    "path": "scan-framework/src/androidTest/java/com/getbouncer/scan/framework/LoaderTest.kt",
    "chars": 3086,
    "preview": "package com.getbouncer.scan.framework\n\nimport androidx.test.filters.SmallTest\nimport androidx.test.platform.app.Instrume"
  },
  {
    "path": "scan-framework/src/androidTest/java/com/getbouncer/scan/framework/StorageTest.kt",
    "chars": 4312,
    "preview": "package com.getbouncer.scan.framework\n\nimport androidx.test.filters.SmallTest\nimport androidx.test.platform.app.Instrume"
  },
  {
    "path": "scan-framework/src/androidTest/java/com/getbouncer/scan/framework/api/BouncerApiTest.kt",
    "chars": 4155,
    "preview": "package com.getbouncer.scan.framework.api\n\nimport androidx.test.filters.LargeTest\nimport androidx.test.platform.app.Inst"
  },
  {
    "path": "scan-framework/src/androidTest/java/com/getbouncer/scan/framework/image/BitmapExtensionsTest.kt",
    "chars": 3123,
    "preview": "package com.getbouncer.scan.framework.image\n\nimport android.graphics.Rect\nimport android.util.Size\nimport androidx.core."
  },
  {
    "path": "scan-framework/src/androidTest/java/com/getbouncer/scan/framework/layout/LayoutTest.kt",
    "chars": 7028,
    "preview": "package com.getbouncer.scan.framework.layout\n\nimport android.graphics.Rect\nimport android.util.Size\nimport androidx.test"
  },
  {
    "path": "scan-framework/src/androidTest/java/com/getbouncer/scan/framework/util/AppDetailsTest.kt",
    "chars": 844,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport androidx.test.platform.app.InstrumentationRegistry\nimport org.junit.T"
  },
  {
    "path": "scan-framework/src/main/AndroidManifest.xml",
    "chars": 196,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.getbouncer.scan.framework\" >\n\n    "
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Analyzer.kt",
    "chars": 2425,
    "preview": "package com.getbouncer.scan.framework\n\nimport java.io.Closeable\n\n/**\n * The default number of analyzers to run in parall"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Config.kt",
    "chars": 5038,
    "preview": "package com.getbouncer.scan.framework\n\nimport com.getbouncer.scan.framework.exception.InvalidBouncerApiKeyException\nimpo"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Fetcher.kt",
    "chars": 30471,
    "preview": "package com.getbouncer.scan.framework\n\nimport android.content.Context\nimport android.util.Log\nimport com.getbouncer.scan"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Loader.kt",
    "chars": 4543,
    "preview": "package com.getbouncer.scan.framework\n\nimport android.content.Context\nimport android.util.Log\nimport com.getbouncer.scan"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Loop.kt",
    "chars": 11997,
    "preview": "package com.getbouncer.scan.framework\n\nimport com.getbouncer.scan.framework.time.Clock\nimport com.getbouncer.scan.framew"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/MachineState.kt",
    "chars": 683,
    "preview": "package com.getbouncer.scan.framework\n\nimport android.util.Log\nimport com.getbouncer.scan.framework.time.Clock\nimport co"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Result.kt",
    "chars": 6529,
    "preview": "package com.getbouncer.scan.framework\n\nimport androidx.lifecycle.Lifecycle\nimport androidx.lifecycle.LifecycleObserver\ni"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Scan.kt",
    "chars": 1747,
    "preview": "package com.getbouncer.scan.framework\n\nimport android.os.Build\n\n@Deprecated(message = \"Replaced by stripe card scan. See"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Stat.kt",
    "chars": 10511,
    "preview": "package com.getbouncer.scan.framework\n\nimport android.util.Log\nimport androidx.annotation.CheckResult\nimport com.getboun"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/Storage.kt",
    "chars": 9108,
    "preview": "package com.getbouncer.scan.framework\n\nimport android.content.Context\nimport android.content.SharedPreferences\nimport an"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/TrackedImage.kt",
    "chars": 301,
    "preview": "package com.getbouncer.scan.framework\n\n/**\n * An image with a stat tracker.\n */\n@Deprecated(message = \"Replaced by strip"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/BouncerApi.kt",
    "chars": 5134,
    "preview": "@file:JvmName(\"BouncerApi\")\npackage com.getbouncer.scan.framework.api\n\nimport android.content.Context\nimport com.getboun"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/Network.kt",
    "chars": 13226,
    "preview": "@file:JvmName(\"Network\")\npackage com.getbouncer.scan.framework.api\n\nimport android.content.Context\nimport android.util.B"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/NetworkResult.kt",
    "chars": 1284,
    "preview": "package com.getbouncer.scan.framework.api\n\n@Deprecated(\n    message = \"Replaced by stripe card scan. See https://github."
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/dto/AppInfo.kt",
    "chars": 1615,
    "preview": "package com.getbouncer.scan.framework.api.dto\n\nimport androidx.annotation.RestrictTo\nimport com.getbouncer.scan.framewor"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/dto/BouncerErrorResponse.kt",
    "chars": 579,
    "preview": "package com.getbouncer.scan.framework.api.dto\n\nimport kotlinx.serialization.SerialName\nimport kotlinx.serialization.Seri"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/dto/ClientDevice.kt",
    "chars": 2492,
    "preview": "package com.getbouncer.scan.framework.api.dto\n\nimport androidx.annotation.RestrictTo\nimport com.getbouncer.scan.framewor"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/dto/ClientStats.kt",
    "chars": 4954,
    "preview": "package com.getbouncer.scan.framework.api.dto\n\nimport com.getbouncer.scan.framework.RepeatingTaskStats\nimport com.getbou"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/dto/ModelDetails.kt",
    "chars": 1278,
    "preview": "package com.getbouncer.scan.framework.api.dto\n\nimport kotlinx.serialization.SerialName\nimport kotlinx.serialization.Seri"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/dto/ModelSignedUrlResponse.kt",
    "chars": 414,
    "preview": "package com.getbouncer.scan.framework.api.dto\n\nimport kotlinx.serialization.SerialName\nimport kotlinx.serialization.Seri"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/api/dto/ValidateApiKeyResponse.kt",
    "chars": 496,
    "preview": "package com.getbouncer.scan.framework.api.dto\n\nimport kotlinx.serialization.SerialName\nimport kotlinx.serialization.Seri"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/exception/ImageTypeNotSupportedException.kt",
    "chars": 331,
    "preview": "package com.getbouncer.scan.framework.exception\n\nimport java.lang.Exception\n\n@Deprecated(\n    message = \"Replaced by str"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/exception/InvalidBouncerApiKeyException.kt",
    "chars": 283,
    "preview": "package com.getbouncer.scan.framework.exception\n\n@Deprecated(\n    message = \"Replaced by stripe card scan. See https://g"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/image/BitmapExtensions.kt",
    "chars": 7282,
    "preview": "package com.getbouncer.scan.framework.image\n\nimport android.graphics.Bitmap\nimport android.graphics.Canvas\nimport androi"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/image/ImageExtensions.kt",
    "chars": 2365,
    "preview": "package com.getbouncer.scan.framework.image\n\nimport android.graphics.Bitmap\nimport android.graphics.BitmapFactory\nimport"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/image/MLImage.kt",
    "chars": 3435,
    "preview": "package com.getbouncer.scan.framework.image\n\nimport android.graphics.Bitmap\nimport java.nio.ByteBuffer\nimport java.nio.B"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/image/NV21Image.kt",
    "chars": 17718,
    "preview": "package com.getbouncer.scan.framework.image\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport androi"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/image/YuvImageExtensions.kt",
    "chars": 847,
    "preview": "package com.getbouncer.scan.framework.image\n\nimport android.graphics.Bitmap\nimport android.graphics.BitmapFactory\nimport"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/interop/BlockingAnalyzer.kt",
    "chars": 2344,
    "preview": "package com.getbouncer.scan.framework.interop\n\nimport com.getbouncer.scan.framework.Analyzer\nimport com.getbouncer.scan."
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/interop/BlockingResult.kt",
    "chars": 4074,
    "preview": "package com.getbouncer.scan.framework.interop\n\nimport com.getbouncer.scan.framework.AggregateResultListener\nimport com.g"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/interop/JavaContinuation.kt",
    "chars": 2433,
    "preview": "@file:JvmName(\"Coroutine\")\npackage com.getbouncer.scan.framework.interop\n\nimport android.util.Log\nimport com.getbouncer."
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/ml/ModelVersionTracker.kt",
    "chars": 1583,
    "preview": "package com.getbouncer.scan.framework.ml\n\nprivate val MODEL_MAP = mutableMapOf<String, MutableSet<Triple<String, Int, Bo"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/ml/NonMaximumSuppression.kt",
    "chars": 3629,
    "preview": "package com.getbouncer.scan.framework.ml\n\nimport com.getbouncer.scan.framework.ml.ssd.RectForm\nimport com.getbouncer.sca"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/ml/TensorFlowLiteAnalyzer.kt",
    "chars": 3441,
    "preview": "package com.getbouncer.scan.framework.ml\n\nimport android.content.Context\nimport android.util.Log\nimport com.getbouncer.s"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/ml/ssd/ClassifierScores.kt",
    "chars": 646,
    "preview": "package com.getbouncer.scan.framework.ml.ssd\n\nimport com.getbouncer.scan.framework.util.updateEach\nimport kotlin.math.ex"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/ml/ssd/RectForm.kt",
    "chars": 4719,
    "preview": "package com.getbouncer.scan.framework.ml.ssd\n\nimport android.graphics.RectF\nimport com.getbouncer.scan.framework.util.cl"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/ml/ssd/SizeAndCenter.kt",
    "chars": 5330,
    "preview": "package com.getbouncer.scan.framework.ml.ssd\n\nimport com.getbouncer.scan.framework.util.clamp\nimport kotlin.math.exp\n\n/*"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/time/Clock.kt",
    "chars": 5041,
    "preview": "package com.getbouncer.scan.framework.time\n\nimport androidx.annotation.CheckResult\n\n@Deprecated(\n    message = \"Replaced"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/time/Coroutine.kt",
    "chars": 418,
    "preview": "package com.getbouncer.scan.framework.time\n\nimport kotlin.math.roundToLong\n\n/**\n * Allow delaying for a specified durati"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/time/Duration.kt",
    "chars": 18260,
    "preview": "package com.getbouncer.scan.framework.time\n\nimport kotlin.math.round\nimport kotlin.math.roundToLong\n\n/**\n * Round a numb"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/time/Rate.kt",
    "chars": 469,
    "preview": "package com.getbouncer.scan.framework.time\n\n/**\n * A rate of execution.\n */\n@Deprecated(\n    message = \"Replaced by stri"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/time/Timer.kt",
    "chars": 2846,
    "preview": "package com.getbouncer.scan.framework.time\n\nimport android.util.Log\nimport com.getbouncer.scan.framework.Config\nimport k"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/AppDetails.kt",
    "chars": 2261,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport android.content.Context\nimport com.getbouncer.scan.framework.BuildCon"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/ArrayExtensions.kt",
    "chars": 7465,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport androidx.annotation.CheckResult\nimport java.nio.ByteBuffer\nimport kot"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/Device.kt",
    "chars": 4722,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport android.annotation.SuppressLint\nimport android.content.Context\nimport"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/File.kt",
    "chars": 2277,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport kotlinx.coroutines.Dispatchers\nimport kotlinx.coroutines.withContext\n"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/FrameRateTracker.kt",
    "chars": 4098,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport android.util.Log\nimport com.getbouncer.scan.framework.Config\nimport c"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/FrameSaver.kt",
    "chars": 2436,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport androidx.annotation.CheckResult\nimport kotlinx.coroutines.sync.Mutex\n"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/ItemCounter.kt",
    "chars": 3039,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport androidx.annotation.CheckResult\nimport kotlinx.coroutines.runBlocking"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/Layout.kt",
    "chars": 21974,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport android.graphics.Rect\nimport android.graphics.RectF\nimport android.ut"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/Memoize.kt",
    "chars": 36951,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport com.getbouncer.scan.framework.time.Clock\nimport com.getbouncer.scan.f"
  },
  {
    "path": "scan-framework/src/main/java/com/getbouncer/scan/framework/util/Retry.kt",
    "chars": 2785,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport com.getbouncer.scan.framework.time.Duration\nimport kotlinx.coroutines"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/AnalyzerTest.kt",
    "chars": 1560,
    "preview": "package com.getbouncer.scan.framework\n\nimport androidx.test.filters.SmallTest\nimport kotlinx.coroutines.ExperimentalCoro"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/LoopTest.kt",
    "chars": 10474,
    "preview": "package com.getbouncer.scan.framework\n\nimport androidx.test.filters.MediumTest\nimport androidx.test.filters.SmallTest\nim"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/interop/BlockingAnalyzerTest.java",
    "chars": 4566,
    "preview": "package com.getbouncer.scan.framework.interop;\n\nimport androidx.test.filters.MediumTest;\n\nimport com.getbouncer.scan.fra"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/interop/BlockingResultTest.java",
    "chars": 10825,
    "preview": "package com.getbouncer.scan.framework.interop;\n\nimport androidx.test.filters.MediumTest;\n\nimport com.getbouncer.scan.fra"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/time/DurationTest.kt",
    "chars": 8223,
    "preview": "package com.getbouncer.scan.framework.time\n\nimport androidx.test.filters.SmallTest\nimport org.junit.Test\nimport kotlin.m"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/util/ArrayExtensionsTest.kt",
    "chars": 3435,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport androidx.test.filters.SmallTest\nimport org.junit.Assert\nimport org.ju"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/util/FrameSaverTest.kt",
    "chars": 1600,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutine"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/util/ItemCounterTest.kt",
    "chars": 3670,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport kotlinx.coroutines.ExperimentalCoroutinesApi\nimport kotlinx.coroutine"
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/util/MemoizeTest.kt",
    "chars": 36279,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport androidx.test.filters.SmallTest\nimport com.getbouncer.scan.framework."
  },
  {
    "path": "scan-framework/src/test/java/com/getbouncer/scan/framework/util/RetryTest.kt",
    "chars": 1871,
    "preview": "package com.getbouncer.scan.framework.util\n\nimport androidx.test.filters.SmallTest\nimport com.getbouncer.scan.framework."
  },
  {
    "path": "scan-payment/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "scan-payment/README.md",
    "chars": 3507,
    "preview": "# Deprecation Notice\nHello from the Stripe (formerly Bouncer) team!\n\nWe're excited to provide an update on the state and"
  },
  {
    "path": "scan-payment/build.gradle",
    "chars": 2235,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'kotlin-android'\napply plugin: 'kotlinx-serialization'\napply plugin: '"
  },
  {
    "path": "scan-payment/consumer-rules.pro",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "scan-payment/deploy.gradle",
    "chars": 5189,
    "preview": "apply plugin: 'maven-publish'\napply plugin: 'org.jetbrains.dokka'\napply plugin: 'signing'\n\ntask androidSourcesJar(type: "
  },
  {
    "path": "scan-payment/proguard-rules.pro",
    "chars": 803,
    "preview": "# Add project specific ProGuard rules here.\n# You can control the set of applied configuration files using the\n# proguar"
  },
  {
    "path": "scan-payment/src/androidTest/java/com/getbouncer/scan/payment/ImageTest.kt",
    "chars": 8818,
    "preview": "package com.getbouncer.scan.payment\n\nimport android.graphics.Bitmap\nimport android.graphics.Canvas\nimport android.graphi"
  },
  {
    "path": "scan-payment/src/androidTest/java/com/getbouncer/scan/payment/PaymentCardAndroidTest.kt",
    "chars": 978,
    "preview": "package com.getbouncer.scan.payment\n\nimport androidx.test.filters.SmallTest\nimport androidx.test.platform.app.Instrument"
  },
  {
    "path": "scan-payment/src/androidTest/java/com/getbouncer/scan/payment/ml/CardDetectTest.kt",
    "chars": 5062,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport androidx.core.graphics.drawable.toBitmap\nimport androidx.test.filters.Med"
  },
  {
    "path": "scan-payment/src/androidTest/java/com/getbouncer/scan/payment/ml/ExpiryDetectTest.kt",
    "chars": 1403,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport androidx.test.filters.SmallTest\nimport androidx.test.platform.app.Instrum"
  },
  {
    "path": "scan-payment/src/androidTest/java/com/getbouncer/scan/payment/ml/SSDOcrTest.kt",
    "chars": 5414,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport androidx.core.graphics.drawable.toBitmap\nimport androidx.test.filters.Med"
  },
  {
    "path": "scan-payment/src/androidTest/java/com/getbouncer/scan/payment/ml/TextDetectTest.kt",
    "chars": 1397,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport androidx.test.filters.SmallTest\nimport androidx.test.platform.app.Instrum"
  },
  {
    "path": "scan-payment/src/androidTest/java/com/getbouncer/scan/payment/ml/ssd/SSDTest.kt",
    "chars": 11512,
    "preview": "package com.getbouncer.scan.payment.ml.ssd\n\nimport android.graphics.RectF\nimport com.getbouncer.scan.payment.ml.VERTICAL"
  },
  {
    "path": "scan-payment/src/main/AndroidManifest.xml",
    "chars": 114,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.getbouncer.scan.payment\" />\n"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/FrameDetails.kt",
    "chars": 414,
    "preview": "package com.getbouncer.scan.payment\n\nimport androidx.annotation.Keep\n\n@Keep\n@Deprecated(\n    message = \"Replaced by stri"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/Image.kt",
    "chars": 4990,
    "preview": "package com.getbouncer.scan.payment\n\nimport android.app.ActivityManager\nimport android.content.Context\nimport android.co"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ModelManager.kt",
    "chars": 1326,
    "preview": "package com.getbouncer.scan.payment\n\nimport android.content.Context\nimport androidx.annotation.VisibleForTesting\nimport "
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/TextDetectModelManager.kt",
    "chars": 492,
    "preview": "package com.getbouncer.scan.payment\n\nimport android.content.Context\nimport com.getbouncer.scan.framework.Fetcher\nimport "
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/analyzer/NameAndExpiryAnalyzer.kt",
    "chars": 14318,
    "preview": "package com.getbouncer.scan.payment.analyzer\n\nimport android.graphics.Bitmap\nimport android.graphics.Rect\nimport android"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/card/CardExpiry.kt",
    "chars": 4368,
    "preview": "package com.getbouncer.scan.payment.card\n\nimport java.util.Calendar\n\n/**\n * Determine if the given expiry is currently v"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/card/CardIssuer.kt",
    "chars": 3099,
    "preview": "package com.getbouncer.scan.payment.card\n\nimport android.os.Parcelable\nimport kotlinx.parcelize.Parcelize\n\n/**\n * A list"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/card/CardType.kt",
    "chars": 2644,
    "preview": "package com.getbouncer.scan.payment.card\n\nimport android.content.Context\nimport androidx.annotation.CheckResult\nimport a"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/card/PanFormatter.kt",
    "chars": 6615,
    "preview": "package com.getbouncer.scan.payment.card\n\n/*\n * The following are known PAN formats. The information in this table was t"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/card/PanValidator.kt",
    "chars": 2218,
    "preview": "package com.getbouncer.scan.payment.card\n\n/**\n * A class that provides a method to determine if a PAN is valid.\n */\n@Dep"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/card/PaymentCard.kt",
    "chars": 768,
    "preview": "package com.getbouncer.scan.payment.card\n\nimport android.os.Parcelable\nimport kotlinx.parcelize.Parcelize\n\n@Parcelize\n@D"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/card/PaymentCardUtils.kt",
    "chars": 18826,
    "preview": "@file:JvmName(\"PaymentCardUtils\")\npackage com.getbouncer.scan.payment.card\n\nimport android.content.Context\nimport androi"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/card/RequiresMatchingCard.kt",
    "chars": 1719,
    "preview": "package com.getbouncer.scan.payment.card\n\n/**\n * An interface for a class that requires a card to match. This provides t"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/AlphabetDetect.kt",
    "chars": 4892,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.uti"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/AlphabetDetectModelManager.kt",
    "chars": 502,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport com.getbouncer.scan.framework.Fetcher\nimpo"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/CardDetect.kt",
    "chars": 5090,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.gra"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/CardDetectModelManager.kt",
    "chars": 2889,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport android.util.Log\nimport com.getbouncer.sca"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/ExpiryDetect.kt",
    "chars": 8292,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.gra"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/ExpiryDetectModelManager.kt",
    "chars": 498,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport com.getbouncer.scan.framework.Fetcher\nimpo"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/SSDOcr.kt",
    "chars": 7935,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.gra"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/SSDOcrModelManager.kt",
    "chars": 2822,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport android.util.Log\nimport com.getbouncer.sca"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/TextDetect.kt",
    "chars": 16225,
    "preview": "package com.getbouncer.scan.payment.ml\n\nimport android.content.Context\nimport android.graphics.Bitmap\nimport android.gra"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/ssd/DetectionBox.kt",
    "chars": 636,
    "preview": "package com.getbouncer.scan.payment.ml.ssd\n\nimport android.graphics.RectF\nimport androidx.annotation.RestrictTo\n\n@Restri"
  },
  {
    "path": "scan-payment/src/main/java/com/getbouncer/scan/payment/ml/ssd/OcrPriorsGenerator.kt",
    "chars": 2441,
    "preview": "package com.getbouncer.scan.payment.ml.ssd\n\nimport android.util.Size\nimport com.getbouncer.scan.framework.ml.ssd.SizeAnd"
  }
]

// ... and 72 more files (download for full content)

About this extraction

This page contains the full source code of the getbouncer/cardscan-android GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 272 files (1.1 MB), approximately 295.7k tokens, and a symbol index with 48 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!