You can use the Android SDK v5 to track user behavior of the camera. The examples code below is based on Android's cameraX library. You can also check the implementation in our demo application on GitHub (also based on cameraX).

When using cameraX, the following functions can be tracked out of the box:

  • Change flash settings
  • Change camera (front / back)
  • Take picture
  • Open the latest picture

Any other function needs additional implementation work to be tracked.

Please note

  • Ensure that event parameters are configured accordingly in your account.
  • If you do not use cameraX tracking is possible as well of course, but you might need to adjust implementation.
//Access Camera:
   
view.findViewById<Button>(R.id.button).setOnClickListener {
            Navigation.findNavController(requireActivity(), R.id.fragment_container).navigate(
                  MainFragmentDirections.actionMainFragmentToPermissionsFragment()
            )
   
            //Tracking event is sent
            Webtrekk.getInstance().trackCustomEvent("access camera")
        }
   
//Take/Save image:
   
/** Define callback that will be triggered after a photo has been taken and saved to disk */
    private val imageSavedListener = object : ImageCapture.OnImageSavedCallback {
        override fun onError(imageCaptureError: Int, message: String, cause: Throwable?) {
            Log.e(TAG, "Photo capture failed: $message", cause)
        }
   
        override fun onImageSaved(photoFile: File) {
            Log.d(TAG, "Photo capture succeeded: ${photoFile.absolutePath}")
   
            // We can only change the foreground Drawable using API level 23+ API
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
   
                // Update the gallery thumbnail with latest picture taken
                setGalleryThumbnail(photoFile)
            }
   
            // Implicit broadcasts will be ignored for devices running API
            // level >= 24, so if you only target 24+ you can remove this statement
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                requireActivity().sendBroadcast(
                    Intent(android.hardware.Camera.ACTION_NEW_PICTURE, Uri.fromFile(photoFile))
                )
            }
   
            // If the folder selected is an external media directory, this is unnecessary
            // but otherwise other apps will not be able to access our images unless we
            // scan them using [MediaScannerConnection]
            val mimeType = MimeTypeMap.getSingleton()
                    .getMimeTypeFromExtension(photoFile.extension)
            MediaScannerConnection.scanFile(
                    context, arrayOf(photoFile.absolutePath), arrayOf(mimeType), null)
   
            //If there is no error, tracking event for taking/saving image is sent
            val params: LinkedHashMap<String, String> = LinkedHashMap()
            params.put("ck6", "take picture")
            Webtrekk.getInstance().trackCustomEvent("click.camera.button", params)
        }
   
    }
   
//Change flash settings:
   
/** Global variable to keep state of flash mode, default value set to off */
   
    private var flashMode = ImageCapture.FLASH_MODE_OFF
   
/** Listener for button used to change flash mode */
        controls.findViewById<ImageButton>(R.id.flash_mode_button).setOnClickListener {
            val flashResource: Int
            flashMode = if (flashMode == ImageCapture.FLASH_MODE_OFF){
                flashResource = R.drawable.ic_flash_auto_white_24dp;
                ImageCapture.FLASH_MODE_AUTO
            }
            else if (flashMode == ImageCapture.FLASH_MODE_AUTO){
                flashResource = R.drawable.ic_flash_on_white_24dp;
                ImageCapture.FLASH_MODE_ON
            }
            else {
                flashResource = R.drawable.ic_flash_off_white_24dp;
                ImageCapture.FLASH_MODE_OFF
            }
            val flashButtonImage = container.findViewById<ImageButton>(R.id.flash_mode_button)
   
            // Run the operations in the view's thread
            flashButtonImage.post {
   
                // Load thumbnail into circular button using Glide
                Glide.with(flashButtonImage)
                    .load(flashResource)
                    .apply(RequestOptions.circleCropTransform())
                    .into(flashButtonImage)
            }
   
            //Bind use cases
            bindCameraUseCases()
   
            //Tracking event is sent
            val params: LinkedHashMap<String, String> = LinkedHashMap()
            params.put("ck6", "change flash setting")
            Webtrekk.getInstance().trackCustomEvent("click.camera.button", params)
        }
   
//Change lens facing to front or back:
   
/** Global variable to keep state of chosen camera, default values set to back camera */
   
    private var lensFacing = CameraSelector.LENS_FACING_BACK
   
/** Listener for button used to switch cameras */
        controls.findViewById<ImageButton>(R.id.camera_switch_button).setOnClickListener {
            lensFacing = if (CameraSelector.LENS_FACING_FRONT == lensFacing) {
                CameraSelector.LENS_FACING_BACK
            } else {
                CameraSelector.LENS_FACING_FRONT
            }
   
            //Bind use cases
            bindCameraUseCases()
   
            //Tracking event is sent
            val params: LinkedHashMap<String, String> = LinkedHashMap()
            params.put("ck6", "change camera")
            Webtrekk.getInstance().trackCustomEvent("click.camera.button", params)
        }
JAVA
//Access Camera:
   
        view.findViewById(R.id.button).setOnClickListener(v -> {
            Navigation.findNavController(requireActivity(), R.id.fragment_container).navigate(
                MainFragmentDirections.actionMainFragmentToPermissionsFragment());
   
                //Tracking event is sent
                Webtrekk.getInstance().trackCustomEvent("access camera", Collections.emptyMap());
   
        });
   
//Take/Save image:
   
/** Define callback that will be triggered after a photo has been taken and saved to disk */
   
    private ImageCapture.OnImageSavedCallback imageSavedListener = new ImageCapture.OnImageSavedCallback() {
        @Override
        public void onError(int imageCaptureError, @NonNull String message, @Nullable Throwable cause) {
            Log.e(TAG, "Photo capture failed: " + message, cause);
        }
        @Override
        public void onImageSaved(@NonNull File file) {
            String msg = "Pic captured at " + file.getAbsolutePath();
            Log.d(TAG, "Photo capture succeeded: " + msg);
   
            // We can only change the foreground Drawable using API level 23+ API
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
   
                // Update the gallery thumbnail with latest picture taken
                setGalleryThumbnail(true);
            }
   
            //If there is no error, tracking event for taking/saving image is sent
            Map<String, String> params = new LinkedHashMap<>();
            params.put("ck6", "take picture");
            Webtrekk.getInstance().trackCustomEvent("click.camera.button", params);
        }
    };
   
//Change flash settings:
   
/** Global variable to keep state of flash mode, default value set to off */
   
    private int flashMode = FlashMode.OFF;
   
/** Listener for button used to change flash mode */
        view.findViewById(R.id.flash).setOnClickListener(v -> {
            if (flashMode == FlashMode.ON) {
                flashMode = FlashMode.OFF;
                flashResource = R.drawable.ic_flash_off_white_24dp;
            } else if (flashMode == FlashMode.OFF) {
                flashMode = FlashMode.AUTO;
                flashResource = R.drawable.ic_flash_auto_white_24dp;
            } else if (flashMode == FlashMode.AUTO) {
                flashMode = FlashMode.ON;
                flashResource = R.drawable.ic_flash_on_white_24dp;
            }
   
            Glide.with(flashButton)
                    .load(flashResource)
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .skipMemoryCache(true)
                    .apply(RequestOptions.circleCropTransform())
                    .into(flashButton);
            bindPreview(cameraProvider);
   
            //Tracking event is sent
            Map<String, String> params = new LinkedHashMap<>();
            params.put("ck6", "change flash setting");
            Webtrekk.getInstance().trackCustomEvent("click.camera.button", params);
        });
   
//Change lens facing to front or back:
   
/** Global variable to keep state of chosen camera, default values set to back camera */
    private int lensFacing = LensFacing.BACK;
   
/** Listener for button used to switch cameras */
view.findViewById(R.id.camera_switch_button).setOnClickListener(v -> {
            if (lensFacing == LensFacing.BACK)
                lensFacing = LensFacing.FRONT;
            else
                lensFacing = LensFacing.BACK;
            bindPreview(cameraProvider);
   
            //Tracking event is sent
            Map<String, String> params = new LinkedHashMap<>();
            params.put("ck6", "change camera");
            Webtrekk.getInstance().trackCustomEvent("click.camera.button", params);
        });
JAVA