Sample Code
Learn how to implement Lens in an Android application
Here are some examples of implementing Lens in an Android application.
Basic Setup
XML layout contains two views: LensCameraView
for preview and AppCompatButtton
to initiate image capture. Java
/Kotlin
containsbasic logic to enable camera and initiate capture.
<xml version="1.0" encoding="utf-8">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Camera View -->
<com.truepic.lenssdk.LensCameraView
android:id="@+id/lens_camera"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<!-- Capture Button -->
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/capture_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Take Picture"
android:layout_margin="15dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</xml>
public class CameraActivityExample extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
LensCameraView lensCamera = findViewById(R.id.lens_camera);
AppCompatButton captureButton = findViewById(R.id.capture_button);
lensCamera.setApiKey("api key here", new LensHandler() {
@Override
public void onError(LensError lensError) {
handleError(lensError);
}
@Override
public void enableCapture(boolean enabled) {
captureButton.setEnabled(enabled);
if(!enabled) {
// optional: notify user
}
}
}, false);
captureButton.setOnClickListener(view -> lensCamera.startCapture(new LensPhotoCaptureHandler() {
@Override
public void onTruepicCaptured(UUID uuid, Truepic truepic) {
// save C2PA image
}
@Override
public void onThumbnailCaptured(UUID uuid, Truepic truepic) {
// optional
// save thumbnail while C2PA image is being created
}
}));
}
private void handleError(LensError error) {
switch (error.errorType()) {
case Env_PlayStoreServices:
case Env_AirplaneMode:
case Env_DevMode:
case Env_Network:
case Permissions_Location:
case Permissions_Camera:
case Enrollment:
case Attestation:
case Camera:
case KeyGeneration:
case Native:
default:
Log.d("Camera", error.errorMessage())
}
}
}
class CameraActivityExample : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera)
val lensCamera: LensCameraView = findViewById(R.id.lens_camera)
val captureButton: AppCompatButton = findViewById(R.id.capture_button)
lensCamera.setApiKey("api key here", object : LensHandler {
override fun onError(error: LensError) {
handleError(error)
}
override fun enableCapture(enable: Boolean) {
captureButton.isEnabled = enabled
if(!enabled) {
// optional: notify user
}
}
})
captureButton.setOnClickLenstener {
lensCamera.startCapture(object : LensPhotoCaptureHandler {
override fun onTruepicCaptured(uuid: UUID, truepic: Truepic) {
// save C2PA image
}
override fun onThumbnailCaptured(uuid: UUID, truepic: Truepic) {
// optional
// save thumbnail while C2PA image is being created
}
})
}
}
private fun handleError(error: LensError) {
when (error.errorType()) {
ErrorType.Env_PlayStoreServices,
ErrorType.Env_AirplaneMode,
ErrorType.Env_DevMode,
ErrorType.Env_Network,
ErrorType.Permissions_Location,
ErrorType.Permissions_Camera,
ErrorType.Enrollment,
ErrorType.Attestation,
ErrorType.Camera,
ErrorType.KeyGeneration,
ErrorType.Native,
else ->
Log.d("Camera", error.errorMessage())
}
}
}
Touch listener for camera gestures
This is a sample implementation of pinch to zoom (scale) and tap to focus gestures that could be added to the camera preview by utilizing lensCameraView.setOnTouchListener
.
public class CameraTouchListener implements View.OnTouchListener, ScaleGestureDetector.OnScaleGestureListener {
private final ScaleGestureDetector gestureScale;
float scaleFactor = 1;
boolean isScaling = false;
LensCamera camera;
ImageView focusReticle;
public CameraTouchListener(Context context, LensCamera camera, ImageView focusReticle) {
this.camera = camera;
gestureScale = new ScaleGestureDetector(context, this);
this.focusReticle = focusReticle;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
// pinch to zoom
scaleFactor *= detector.getScaleFactor();
scaleFactor = scaleFactor = Math.max(scaleFactor, 1);
scaleFactor = ((float)((int)(scaleFactor * 100))) / 100;
camera.setZoomRatio(scaleFactor);
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
isScaling = true;
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
isScaling = false;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
gestureScale.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
if (!isScaling)
// focusing
focusReticle.setX(event.getX() - focusReticle.getWidth() / 2.0F);
focusReticle.setY(event.getY() - focusReticle.getHeight() / 2.0F);
focusReticle.setVisibility(View.VISIBLE);
camera.focusMeteringOnTap(event, LensCamera.MODE_AE | LensCamera.MODE_AF | LensCamera.MODE_AWB, () -> {
if ((focusReticle != null)&&(focusReticle.getVisibility() == View.VISIBLE)) {
focusReticle.setVisibility(View.INVISIBLE);
}
});
v.performClick();
return true;
default:
return false;
}
}
}
class CameraTouchListenerKt(context: Context, private var camera: LensCamera, private var focusReticle: ImageView) : View.OnTouchListener,
ScaleGestureDetector.OnScaleGestureListener {
private val gestureScale: ScaleGestureDetector = ScaleGestureDetector(context, this)
private var scaleFactor = 1f
private var isScaling = false
override fun onScale(detector: ScaleGestureDetector): Boolean {
// pinch to zoom
scaleFactor *= detector.scaleFactor
scaleFactor = scaleFactor.coerceAtLeast(1f)
scaleFactor = (scaleFactor * 100).toInt().toFloat() / 100
camera.setZoomRatio(scaleFactor)
return true
}
override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
isScaling = true
return true
}
override fun onScaleEnd(detector: ScaleGestureDetector) {
isScaling = false
}
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View, event: MotionEvent): Boolean {
gestureScale.onTouchEvent(event)
return when (event.action) {
MotionEvent.ACTION_DOWN -> true
MotionEvent.ACTION_UP -> {
if (!isScaling) {
// focusing
focusReticle.x = event.x - focusReticle.width / 2.0f
focusReticle.y = event.y - focusReticle.height / 2.0f
focusReticle.visibility = View.VISIBLE
camera.focusMeteringOnTap(event, LensCamera.MODE_AE or LensCamera.MODE_AF or LensCamera.MODE_AWB) {
if (focusReticle.visibility == View.VISIBLE) {
focusReticle.visibility = View.INVISIBLE
}
}
}
v.performClick()
true
}
else -> false
}
}
}
Updated 4 months ago