Addis AI

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

Do not embed keys in your App

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:

  1. Decode the Base64 string to a Byte Array.
  2. Write the bytes to a temporary file (cache directory).
  3. 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 SocketTimeoutExceptions during long generations.
  • Background Threading: Network requests (especially file uploads) should never run on the UI thread. Use Isolates in Flutter or Coroutines in Kotlin to keep your UI responsive.

On this page