# android-media
A Rust-based Android media library that provides simple and easy-to-use audio recording and playback functionality.
## Features
- π€ **Audio Recording** - Support for microphone recording with asynchronous audio data reading
- π **Audio Playback** - Support for both streaming and static playback modes
- π― **Type Safety** - Enum-based constants provide type-safe APIs
- β‘ **Async Support** - Tokio-based async APIs to avoid blocking the main thread
- π **JNI Integration** - Seamless integration with native Android AudioRecord and AudioTrack
- π¦ **Zero Dependencies** - No third-party dependencies except required JNI and Tokio
## Quick Start
### Install Dependencies
First, install `cargo-apk2`, a tool for building Android APKs:
```bash
cargo install cargo-apk2
```
Then add `android-media` to your project:
```bash
cargo add android-media
```
### Run Example
```bash
cd example
cargo apk2 run
```
## Usage Examples
### Audio Recording
```rust
use android_media::{
AudioMicrophone,
AudioEncoding,
ChannelInConfig,
SampleRate,
};
// Create microphone instance
let mic = AudioMicrophone::new(
env,
&context,
SampleRate::Rate16000.value(), // Sample rate 16000Hz
ChannelInConfig::Mono.value(), // Mono channel
AudioEncoding::Pcm16bit.value(), // 16-bit PCM encoding
)?;
// Start recording
mic.start()?;
// Read 3 seconds of audio data
let audio_data = mic.read(3000).await?;
// Stop recording
mic.stop()?;
```
### Audio Playback
```rust
use android_media::{
AudioPlayer,
AudioEncoding,
ChannelOutConfig,
PlayerMode,
SampleRate,
};
// Create player instance
let player = AudioPlayer::new(
env,
&context,
SampleRate::Rate16000.value(), // Sample rate 16000Hz
ChannelOutConfig::Mono.value(), // Mono channel
AudioEncoding::Pcm16bit.value(), // 16-bit PCM encoding
PlayerMode::Stream.value(), // Stream playback mode
)?;
// Start playback
player.play()?;
// Write audio data
player.write(&audio_data).await?;
// Stop playback
player.stop()?;
```
### Record and Play
```rust
async fn record_and_play(env: JNIEnv, context: GlobalRef) -> anyhow::Result<()> {
use android_media::*;
// Create microphone
let mic = AudioMicrophone::new(
env,
&context,
SampleRate::Rate16000.value(),
ChannelInConfig::Mono.value(),
AudioEncoding::Pcm16bit.value(),
)?;
// Record 3 seconds of audio
mic.start()?;
let data = mic.read(3000).await?;
mic.stop()?;
// Play recorded audio
let player = AudioPlayer::new(
env,
&context,
SampleRate::Rate16000.value(),
ChannelOutConfig::Mono.value(),
AudioEncoding::Pcm16bit.value(),
PlayerMode::Stream.value(),
)?;
player.play()?;
player.write(&data).await?;
Ok(())
}
```
## API Documentation
### Audio Constants
#### SampleRate
Audio sample rate enumeration supporting standard sample rates:
- `Rate8000` - 8000 Hz, commonly used for speech recognition
- `Rate16000` - 16000 Hz, standard for voice applications
- `Rate22050` - 22050 Hz
- `Rate44100` - 44100 Hz, CD audio standard
- `Rate48000` - 48000 Hz, professional audio standard
```rust
use android_media::SampleRate;
let rate = SampleRate::Rate16000;
assert_eq!(rate.value(), 16000);
```
#### AudioEncoding
Audio encoding format enumeration:
- `Pcm8bit` - 8-bit PCM encoding
- `Pcm16bit` - 16-bit PCM encoding (most common)
- `PcmFloat` - 32-bit float PCM encoding
```rust
use android_media::AudioEncoding;
let encoding = AudioEncoding::Pcm16bit;
assert_eq!(encoding.value(), 2);
assert_eq!(encoding.bytes_per_sample(), 2);
```
#### ChannelInConfig / ChannelOutConfig
Audio channel configuration:
- `Mono` - Single channel (mono)
- `Stereo` - Two channels (stereo)
```rust
use android_media::ChannelInConfig;
let config = ChannelInConfig::Mono;
assert_eq!(config.value(), 16);
assert_eq!(config.channel_count(), 1);
```
#### AudioSource
Audio source type:
- `Default` - Default audio source
- `Mic` - Main microphone
- `Camcorder` - Camera audio
- `VoiceRecognition` - Voice recognition (with noise suppression)
- `VoiceCommunication` - Voice communication (with echo cancellation)
#### PlayerMode
Player mode:
- `Static` - Static mode, suitable for short audio clips
- `Stream` - Stream mode, suitable for long audio and real-time streams
### AudioMicrophone
Rust wrapper for microphone recording.
#### Methods
- `new()` - Create a new microphone instance
- `start()` - Start recording
- `stop()` - Stop recording
- `read(duration_ms)` - Asynchronously read audio data for a specified duration
- `release()` - Release resources
- `get_sample_rate()` - Get sample rate
- `get_channel_count()` - Get channel count
- `get_audio_format()` - Get audio format
- `get_buffer_size()` - Get buffer size
- `calculate_bytes_for_duration(duration_ms)` - Calculate bytes for a specified duration
### AudioPlayer
Rust wrapper for audio playback.
#### Methods
- `new()` - Create a new player instance
- `play()` - Start playback
- `stop()` - Stop playback
- `pause()` - Pause playback
- `flush()` - Flush buffer
- `release()` - Release resources
- `write(audio_data)` - Asynchronously write audio data
- `get_sample_rate()` - Get sample rate
- `get_channel_count()` - Get channel count
- `get_audio_format()` - Get audio format
- `get_mode()` - Get playback mode
- `get_buffer_size()` - Get buffer size
## Permissions
To use audio recording functionality, add microphone permission to `AndroidManifest.xml`:
```toml
[[package.metadata.android.uses_permission]]
name = "android.permission.RECORD_AUDIO"
```
For dynamic permission requests in your activity, see the example implementation in `example/src/MainActivity.java`.
## Platform Support
- Android API 23+ (Android 6.0 Marshmallow and above)
## Development Environment
- Rust 2024 Edition
- Android NDK
- cargo-apk2
## License
Apache License 2.0
## Author's Projects
- [Compo](https://github.com/mzdk100/compo) - Core declarative reactive component framework
- [Compo Platform Loop](https://github.com/mzdk100/compo-platform-loop) - Cross-platform event loop implementation
- [Compo Window](https://github.com/mzdk100/compo-window) - Compo window component
- [cargo-apk2](https://github.com/mzdk100/cargo-apk2) - Build Android applications with Cargo
## Contributing
Issues and Pull Requests are welcome!