# Build an on-device AI fitness tutor app on Android

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/)
- [Set up AI Plank Tutor](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/1-introduce-plank-tutor/)
- [Get pose landmarks from camera](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/2-camera-pose-landmarks/)
- [Add scoring logic for the plank pose](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/3-plank-score/)
- [Turn pose data into a prompt for the local LLM](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/4-data-to-prompt/)
- [Run the LLM locally with AI Chat](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/5-llm-ai-chat/)
- [Connect coaching corrections to Android text-to-speech](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/6-android-tts/)
- [Explore options for tuning and extending AI Plank Tutor](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/7-extend/)
- [Next Steps](https://learn.arm.com/learning-paths/mobile-graphics-and-gaming/ai-plank-tutor/_next-steps/)

## About this Learning Path

| Skill level:  | Introductory         |
|---------------|----------------------|
| Reading time: | 1 hr 30 min          |
| Last updated: | 04 Aug 2026          |

| Author:       | Ben Clark, Arm       |
|---------------|----------------------|
| Arm IP:       | [Cortex-A](https://support.arm.com/?tab=compute-ip&Product%20Type=Application%20Processors) |
| Tags:         | ML, Android, Android Studio, Kotlin, CameraX, MediaPipe, LLM, Neon, SVE2, SME2 |

### Who is this for?

This Learning Path is for Android developers who want to explore creating an ML or Generative AI pipeline, including camera input, local Large Language Model (LLM) inference, and speech.

### What will you learn?

Upon completion of this Learning Path, you will be able to:

- Detect human pose landmarks from live Android camera frames with MediaPipe.
- Structure data and build compact prompts that turn raw data into useful LLM input.
- Run a mobile-sized LLM on-device with Arm's AI Chat library.
- Generate output as speech with Text-To-Speech.

### Prerequisites

Before starting, you will need the following:

- A development machine with Android Studio installed.
- A recent Arm-powered Android phone in Developer Mode, with USB debugging enabled, a USB data cable, and at least 5 GB of free storage for the GGUF model import.
- Android Debug Bridge (`adb`), included with the Android SDK platform tools.
- Basic familiarity with Kotlin and Android app development.

### Summary

You’ll build AI Plank Tutor, an on-device Android app that evaluates a static plank pose and delivers spoken correction. You’ll configure CameraX and MediaPipe Pose Landmarker to extract landmarks from live camera frames, calculate joint angles, and compute a weighted score against an instructor reference. Then, you’ll turn the largest joint-angle differences into a compact prompt for a local LLM. Finally, you’ll integrate Arm AI Chat for GGUF inference and connect Android text-to-speech so the app speaks each correction. By the end, you’ll have a complete on-device pipeline from camera input to spoken feedback.

### Frequently asked questions

<details>
<summary>Where should I add the CameraX initialization code?</summary>
Open `ui/MainActivity.kt` and replace the `TODO` in `setUpCamera()` with the provided `ProcessCameraProvider` snippet. When the provider is ready, the callback stores it and calls `bindCameraUseCases()`.
</details>

<details>
<summary>What do I do if the camera doesn't detect pose landmarks?</summary>
After CameraX initializes and binds its use cases, MediaPipe Pose Landmarker should produce landmarks for each frame. If the camera preview appears but no pose landmarks are detected, make sure that you granted camera permission and that your full body is visible in the frame. Then, check Logcat for `PoseLandmarkerHelper` errors. If the preview doesn’t appear, confirm that `bindCameraUseCases()` runs after `ProcessCameraProvider` becomes available.
</details>

<details>
<summary>What defines the reference pose and weighting used to score the plank?</summary>
`data/PlankPoseData.kt` contains `referenceLandmarks` for the instructor pose and `angleWeights` that set the importance of each joint. The app uses these values to calculate joint angles and a weighted score.
</details>

<details>
<summary>How do I control which joint differences are sent to the LLM?</summary>
`ui/landmarker/PoseScoreHelper.kt` maps angles to names with `KEY_ANGLE_NAMES` and formats the largest differences in `angleDifference()`. Use the `filter` and `maxEntries` parameters to set a threshold and limit the entries included in the prompt.
</details>

<details>
<summary>Where do I add the AI Chat dependency and which model format should I use?</summary>
Add `implementation("com.arm:ai-chat:0.1.0")` to the `dependencies` block in `app/build.gradle`, then sync the project.
</details>
