Quick Start — Tera Beauty SDK (15 minutes)
Integrate the on-device Beauty Editor into an existing app: one repository, one dependency, one Activity call. For the full reference see partner-guide.md.
Step 1 — Repository + credentials (the step people get wrong)
The dependency line is trivial; wiring the Artifactory repo with credentials is what trips most
consumers. In your settings.gradle.kts:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
maven {
url = uri("https://artifactory.apero.vn/artifactory/gradle-release/")
credentials {
username = providers.gradleProperty("artifactoryUser").orNull
?: System.getenv("ARTIFACTORY_USER")
password = providers.gradleProperty("artifactoryPassword").orNull
?: System.getenv("ARTIFACTORY_PASSWORD")
}
}
}
}
Put the credentials in ~/.gradle/gradle.properties (never commit them):
artifactoryUser=<your-user>
artifactoryPassword=<your-token>
Contact the Apero team for credentials.
Step 2 — One dependency
In your app module's build.gradle.kts:
dependencies {
implementation("apero-inhouse:tera-sdk-beauty:1.0.0")
}
That's the only apero-inhouse:* line you need — the 8 engine artifacts
(beauty-core, beauty-renderer, beauty-detection, beauty-face, beauty-body,
beauty-adjust, beauty-retouch, beauty-sdk) resolve transitively.
Requirements: minSdk 24, compileSdk 36, Java 11.
Step 3 — Launch the editor and read the result
The API mirrors ML Kit: getClient(options) → build an IntentSender → launch it with
StartIntentSenderForResult → parse the result.
class MainActivity : AppCompatActivity() {
// 1) Launcher that receives the edited image (null Intent = user cancelled).
private val editorLauncher =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
val edited = BeautyEditingResult.fromActivityResultIntent(result.data) ?: return@registerForActivityResult
// edited.imageUri / edited.imagePath — the saved result
binding.preview.setImageURI(edited.imageUri)
}
private fun launchEditor(inputUri: Uri) {
// 2) Configure
val options = BeautyEditorOptions.Builder()
.setEnabledTools(Tool.CROP, Tool.ADJUST, Tool.FACE_EDIT, Tool.BODY, Tool.MAKEUP, Tool.AUTO_RETOUCH)
.setOutputFormat(OutputFormat.JPEG)
.setOutputQuality(95)
.build()
// 3) Build the intent and launch
BeautyEditing.getClient(options)
.getStartEditingIntent(this, inputUri = inputUri)
.addOnSuccessListener { editorLauncher.launch(IntentSenderRequest.Builder(it).build()) }
.addOnFailureListener { e -> Log.e("Beauty", "Failed to build editor intent", e) }
}
}
Passing the input image safely
The editor is a separate Activity, so it must be able to read inputUri on its own:
file://or a plain path → always works.content://from another app (e.g. the system picker) → copy it into your cache first and pass afile://uri. The sample'sMainActivitydoes exactly this:
val file = File(cacheDir, "beauty_input_${System.currentTimeMillis()}.jpg")
contentResolver.openInputStream(pickedContentUri)?.use { input ->
file.outputStream().use { input.copyTo(it) }
}
launchEditor(Uri.fromFile(file))
Step 4 (optional) — Open straight into one tool
To wire a Home-screen "Makeup" button directly to the Makeup tool, keep all tools enabled and set the initial tool:
val options = BeautyEditorOptions.Builder()
.setInitialTool(Tool.MAKEUP) // opens on Makeup; closing it returns to the full tool bar
.build()
null (the default) opens on the full tool bar.
Done
You now have a working integration. Next:
- tools-guide.md — what each tool does and how to show a subset.
- theming-guide.md — rebrand the editor to your colors.
- troubleshooting.md — if the build or first launch fails.