In this post I'll demonstrate how to programatically open Google Translate from another Android application and pass text to translate.
As an example I'll use a screen which displays some text and provides a "translate" button:
Here is the source code:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
TranslateTestTheme {
MainScreen(
title = "Dog",
body = dogDescription,
onTranslateClick = { openGoogleTranslate(dogDescription) },
)
}
}
}
}
@Composable
private fun MainScreen(
title: String,
body: String,
onTranslateClick: () -> Unit,
) {
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = title) },
actions = {
IconButton(onClick = onTranslateClick) {
Icon(Icons.Default.GTranslate, contentDescription = "Translate")
}
}
)
},
content = {
Text(
text = body,
style = MaterialTheme.typography.body2,
modifier = Modifier.padding(16.dp),
)
},
)
}
The key part is following callback: onTranslateClick = { openGoogleTranslate(dogDescription) }
.
Launching Google Translate with Intent.ACTION_PROCESS_TEXT
Let's take a look at the openGoogleTranslate
method:
fun Context.openGoogleTranslate(text: String) {
val intent = Intent()
.setAction(Intent.ACTION_PROCESS_TEXT)
.setType("text/plain")
.putExtra(Intent.EXTRA_PROCESS_TEXT, text)
.putExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, true)
startActivity(intent)
}
It opens any Activity
which is registered with Intent.ACTION_PROCESS_TEXT
intent filter. As Google Translate app provides such Activity
, it is one of the candidates to be opened when mentioned method is called.
It is important to remember, however, that some users have no Google Translate application installed. Some users also have on their devices more applications that handle Intent.ACTION_PROCESS_TEXT
.
In the second case, Android prompts the following dialog:
In case of no application to handle the intent installed, ActivityNotFoundException
will be thrown on startActivity
invocation. This case can be handled by try/catch
block:
try {
startActivity(intent)
} catch (e: ActivityNotFoundException) {
// TODO: Show error
}
Checking if Google Translate is installed
It would be nice to display the "translate" button only if Google Translate is installed. Following code can be use to check its existence:
fun Context.queryProcessTextActivities(): List<ResolveInfo> {
val intent = Intent()
.setAction(Intent.ACTION_PROCESS_TEXT)
.setType("text/plain")
return packageManager.queryIntentActivities(intent, 0)
}
fun Context.isGoogleTranslateInstalled() = queryProcessTextActivities()
.any { it.activityInfo.packageName == "com.google.android.apps.translate" }
In order to make queryIntentActivities
work correctly on all Android versions, the following fragment should be added to AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<application ...>
...
</application>
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
</queries>
</manifest>
Launching Google Translate directly
We can also make sure that - if it is installed - Google Translate will be launched, regardless if there are other applications to handle intent or not.
To do so, the following code can be used:
fun Context.queryProcessTextActivities(): List<ResolveInfo> {
val intent = Intent()
.setAction(Intent.ACTION_PROCESS_TEXT)
.setType("text/plain")
return packageManager.queryIntentActivities(intent, 0)
}
fun Context.googleTranslateActivityInfo() = queryProcessTextActivities()
.firstOrNull { it.activityInfo.packageName == "com.google.android.apps.translate" }
?.activityInfo
fun Context.openGoogleTranslate(activity: ActivityInfo, text: String) {
val intent = Intent()
.setAction(Intent.ACTION_PROCESS_TEXT)
.setType("text/plain")
.putExtra(Intent.EXTRA_PROCESS_TEXT, text)
.putExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, true)
// Following line makes sure only Google Translate app will be launched
.setClassName(activity.packageName, activity.name)
try {
startActivity(intent)
} catch (e: ActivityNotFoundException) {
// TODO: Show error
}
}
You can find complete Kotlin code under this link: https://gist.github.com/pchmielowski/d236f06f168c05efa3f5b26f1e2f0af9
Top comments (0)