Mobile Applications
Build voice-first mobile apps with Flutter, React Native, and Kotlin.
Mobile apps are the primary way users interact with technology in Ethiopia. Addis AI provides the low-latency infrastructure needed to build responsive Chat and Voice applications on mobile networks.
SDKs Coming Soon
Official SDKs for Flutter and React Native are in development.
Currently, we recommend using standard HTTP clients (http for Dart, fetch for JS, OkHttp for Kotlin) pointing to your backend proxy.
Security: APKs are Public
Mobile applications (APKs/IPAs) can be decompiled. If you hardcode your sk_ key in your Flutter or Android code, it will be stolen.
Pattern: Mobile App ➝ Your Backend (Secure) ➝ Addis AI API.
Integration Patterns
These examples demonstrate how to call the API (conceptually). In production, replace https://api.addisassistant.com with https://your-backend.com/api/proxy to secure your keys.
Flutter (Dart)
Flutter is the dominant framework in our ecosystem. Use the http package.
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<String> generateText(String prompt) async {
// 1. Define endpoint (Use your backend in production)
final url = Uri.parse('https://api.addisassistant.com/api/v1/chat_generate');
// 2. Prepare payload
final body = jsonEncode({
"model": "Addis-፩-አሌፍ",
"prompt": prompt,
"target_language": "am",
"generation_config": {"temperature": 0.7}
});
// 3. Send Request
try {
final response = await http.post(
url,
headers: {
"Content-Type": "application/json",
"X-API-Key": "sk_YOUR_KEY", // ⚠️ Move to Backend
},
body: body,
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data['response_text'];
} else {
throw Exception('Failed to load: ${response.statusCode}');
}
} catch (e) {
return "Error: $e";
}
}Playing Base64 audio in Flutter requires decoding to bytes.
Dependencies: audioplayers, path_provider
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';
import 'package:audioplayers/audioplayers.dart';
Future<void> playBase64Audio(String base64String) async {
// 1. Decode Base64
Uint8List bytes = base64Decode(base64String);
// 2. Save to temporary file
final dir = await getTemporaryDirectory();
final file = File('${dir.path}/speech.wav');
await file.writeAsBytes(bytes);
// 3. Play
final player = AudioPlayer();
await player.play(DeviceFileSource(file.path));
}React Native
Similar to the web, but ensure you handle network permissions on Android.
const chatWithAddis = async (userMessage) => {
try {
const response = await fetch('https://api.addisassistant.com/api/v1/chat_generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'sk_YOUR_KEY', // ⚠️ Move to Backend
},
body: JSON.stringify({
prompt: userMessage,
target_language: 'am'
}),
});
const json = await response.json();
console.log(json.response_text);
return json.response_text;
} catch (error) {
console.error(error);
}
};Android (Kotlin)
Using OkHttp for networking.
val client = OkHttpClient()
val JSON = "application/json; charset=utf-8".toMediaType()
fun chat(prompt: String) {
val jsonBody = """
{
"prompt": "$prompt",
"target_language": "am",
"model": "Addis-፩-አሌፍ"
}
""".trimIndent()
val body = RequestBody.create(JSON, jsonBody)
val request = Request.Builder()
.url("https://api.addisassistant.com/api/v1/chat_generate")
.addHeader("X-API-Key", "sk_YOUR_KEY") // ⚠️ Move to Backend
.post(body)
.build()
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
}
})
}Handling Audio (TTS)
Mobile apps often need to play audio generated by our TTS engine. The API returns a Base64 string, not a URL.
Strategy
Since you cannot stream Base64 directly into most native media players easily:
- Decode the Base64 string to a Byte Array.
- Write the bytes to a temporary file (
cachedirectory). - Play the file using the device's native player.
Caching
Mobile data in Ethiopia can be expensive. Always cache the audio file locally. Hash the input text to create a filename key. If the user requests the same text again, play the local file instead of calling the API.
Best Practices
- Permissions: If using Speech-to-Text, remember to request Microphone Permission (
android.permission.RECORD_AUDIO/NSMicrophoneUsageDescription) in your manifest/plist. - Timeouts: Mobile networks fluctuate. Set your connection timeouts to at least 30 seconds to avoid
SocketTimeoutExceptionsduring long generations. - Background Threading: Network requests (especially file uploads) should never run on the UI thread. Use
Isolatesin Flutter orCoroutinesin Kotlin to keep your UI responsive.