Skip to content

Update Translate showcase app to use custom executors #62

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions android/translate-showcase/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ dependencies {
implementation "androidx.camera:camera-view:1.0.0-alpha12"

// Add ML Kit dependencies
implementation 'com.google.android.gms:play-services-mlkit-text-recognition:16.0.0'
implementation 'com.google.mlkit:language-id:16.0.0'
implementation 'com.google.mlkit:translate:16.0.0'
implementation 'com.google.android.gms:play-services-mlkit-text-recognition:16.1.0'
implementation 'com.google.mlkit:language-id:16.1.0'
implementation 'com.google.mlkit:translate:16.1.0'
}
apply plugin: 'com.google.android.gms.strict-version-matcher-plugin'
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import com.google.mlkit.showcase.translate.util.ImageUtils
import com.google.mlkit.vision.common.InputImage
import com.google.mlkit.vision.text.Text
import com.google.mlkit.vision.text.TextRecognition
import java.lang.Exception
import com.google.mlkit.vision.text.TextRecognizerOptions
import java.util.concurrent.Executor

/**
* Analyzes the frames passed in from the camera and returns any detected text within the requested
Expand All @@ -40,10 +41,12 @@ import java.lang.Exception
class TextAnalyzer(
private val context: Context,
lifecycle: Lifecycle,
executor: Executor,
private val result: MutableLiveData<String>,
private val imageCropPercentages: MutableLiveData<Pair<Int, Int>>
) : ImageAnalysis.Analyzer {
private val detector = TextRecognition.getClient()
private val detector =
TextRecognition.getClient(TextRecognizerOptions.Builder().setExecutor(executor).build())

init {
lifecycle.addObserver(detector)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import com.google.mlkit.showcase.translate.analyzer.TextAnalyzer
import com.google.mlkit.showcase.translate.util.Language
import com.google.mlkit.showcase.translate.util.ScopedExecutor
import kotlinx.android.synthetic.main.main_fragment.*
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import kotlin.math.abs
Expand Down Expand Up @@ -108,9 +107,11 @@ class MainFragment : Fragment() {
viewFinder = container.findViewById(R.id.viewfinder)

// Initialize our background executor
cameraExecutor = Executors.newSingleThreadExecutor()
cameraExecutor = Executors.newCachedThreadPool()
scopedExecutor = ScopedExecutor(cameraExecutor)

viewModel.executor = cameraExecutor

// Request camera permissions
if (allPermissionsGranted()) {
// Wait for the views to be properly laid out
Expand Down Expand Up @@ -178,8 +179,7 @@ class MainFragment : Fragment() {
) {
}

override fun surfaceDestroyed(holder: SurfaceHolder?) {
}
override fun surfaceDestroyed(holder: SurfaceHolder?) {}

override fun surfaceCreated(holder: SurfaceHolder?) {
holder?.let {
Expand Down Expand Up @@ -239,6 +239,7 @@ class MainFragment : Fragment() {
scopedExecutor, TextAnalyzer(
requireContext(),
lifecycle,
cameraExecutor,
viewModel.sourceText,
viewModel.imageCropPercentages
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,38 @@ import android.util.LruCache
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import com.google.mlkit.showcase.translate.util.Language
import com.google.mlkit.showcase.translate.util.ResultOrError
import com.google.mlkit.showcase.translate.util.SmoothedMutableLiveData
import com.google.mlkit.nl.languageid.LanguageIdentification
import com.google.mlkit.nl.languageid.LanguageIdentificationOptions
import com.google.mlkit.nl.translate.TranslateLanguage
import com.google.mlkit.nl.translate.Translation
import com.google.mlkit.nl.translate.Translator
import com.google.mlkit.nl.translate.TranslatorOptions
import com.google.mlkit.showcase.translate.main.MainFragment.Companion.DESIRED_HEIGHT_CROP_PERCENT
import com.google.mlkit.showcase.translate.main.MainFragment.Companion.DESIRED_WIDTH_CROP_PERCENT
import com.google.mlkit.showcase.translate.util.Language
import com.google.mlkit.showcase.translate.util.ResultOrError
import com.google.mlkit.showcase.translate.util.SmoothedMutableLiveData
import java.util.concurrent.Executor

class MainViewModel(application: Application) : AndroidViewModel(application) {
private val languageIdentification = LanguageIdentification.getClient()
override fun onCleared() {
languageIdentification.close()
translators.evictAll()
}

lateinit var executor: Executor
private val languageIdentification by lazy {
LanguageIdentification.getClient(
LanguageIdentificationOptions.Builder().setExecutor(executor).build()
)
}

val targetLang = MutableLiveData<Language>()
val sourceText = SmoothedMutableLiveData<String>(SMOOTHING_DURATION)

// We set desired crop percentages to avoid having the analyze the whole image from the live
// camera feed. However, we are not guaranteed what aspect ratio we will get from the camera, so
// we use the first frame we get back from the camera to update these crop percentages based on
Expand Down Expand Up @@ -75,34 +83,23 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
}
}

val sourceLang = Transformations.switchMap(sourceText) { text ->
val result = MutableLiveData<Language>()
languageIdentification.identifyLanguage(text)
.addOnSuccessListener {
if (it != "und")
result.value = Language(it)
}
result
}
val sourceLang = MediatorLiveData<Language>()

private fun translate(): Task<String> {
val text = sourceText.value
val source = sourceLang.value
val target = targetLang.value
if (modelDownloading.value != false || translating.value != false) {
return Tasks.forCanceled()
}
if (source == null || target == null || text == null || text.isEmpty()) {
return Tasks.forResult("")
}
val sourceLangCode = TranslateLanguage.fromLanguageTag(source.code)
val targetLangCode = TranslateLanguage.fromLanguageTag(target.code)
if (sourceLangCode == null || targetLangCode == null) {
return Tasks.forCanceled()
}
val text = sourceText.value ?: return Tasks.forResult("")
val source = sourceLang.value ?: return Tasks.forResult("")
val target = targetLang.value ?: return Tasks.forResult("")
val sourceLangCode =
TranslateLanguage.fromLanguageTag(source.code) ?: return Tasks.forCanceled()
val targetLangCode =
TranslateLanguage.fromLanguageTag(target.code) ?: return Tasks.forCanceled()
val options = TranslatorOptions.Builder()
.setSourceLanguage(sourceLangCode)
.setTargetLanguage(targetLangCode)
.setExecutor(executor)
.build()
val translator = translators[options]
modelDownloading.setValue(true)
Expand All @@ -127,6 +124,15 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
init {
modelDownloading.setValue(false)
translating.value = false

sourceLang.addSource(sourceText) { text ->
languageIdentification.identifyLanguage(text)
.addOnSuccessListener {
if (it != "und")
sourceLang.value = Language(it)
}
}

// Create a translation result or error object.
val processTranslation =
OnCompleteListener<String> { task ->
Expand Down
2 changes: 1 addition & 1 deletion android/translate-showcase/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
*/

include ':app'
rootProject.name='ML Kit Translate Codelab'
rootProject.name='ML Kit Translate Showcase'