Building My First Android App
My experience creating SpeakOut, an early Android application, and navigating the nuances of the Google Play Store publishing ecosystem.
I have reached a long-awaited milestone: publishing my first Android application on the Google Play Store. The application is called SpeakOut, a text-to-speech utility. While it was never intended to compete with social giants or blockbuster mobile games, the journey from an initial concept to live distribution on real user devices provided an invaluable education in mobile software engineering.
Why I Built SpeakOut
Every software engineer needs a practical project to bridge theory and real-world deployment. When choosing my first mobile project, I aimed for specific criteria:
- Focused enough to complete without endless scope creep.
- Practical enough to provide immediate utility to users.
- Complex enough to explore native hardware APIs, activity lifecycles, and asynchronous threading.
- Capable of being tested on physical handsets with varied specifications.
The Development Setup
In 2014, Android development was in an interesting transition period. While Google was rolling out the early previews of Android Studio, the established standard remained Eclipse paired with the Android Development Tools (ADT) plugin.
My development stack included:
- Eclipse IDE with ADT: Reliable for compiling APKs.
- Android SDK: Targeting Android 4.4 KitKat while supporting devices back to Android 2.2 Froyo.
- Physical Test Device: A Samsung Galaxy S3 running Android 4.3.
- Genymotion: Fast x86 emulation for verifying varying screen densities and resolutions.
Engineering the Codebase
The core implementation centered on the Android TextToSpeech engine:
Code • javapackage com.ersindemirtas.speakphone; import android.app.Activity; import android.os.Bundle; import android.speech.tts.TextToSpeech; import android.view.View; import android.widget.Button; import android.widget.EditText; import java.util.Locale; public class MainActivity extends Activity implements TextToSpeech.OnInitListener { private TextToSpeech tts; private EditText inputText; private Button speakButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); inputText = (EditText) findViewById(R.id.inputText); speakButton = (Button) findViewById(R.id.speakButton); tts = new TextToSpeech(this, this); speakButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String text = inputText.getText().toString(); tts.speak(text, TextToSpeech.QUEUE_FLUSH, null); } }); } @Override public void onInit(int status) { if (status == TextToSpeech.SUCCESS) { tts.setLanguage(Locale.UK); } } @Override protected void onDestroy() { if (tts != null) { tts.stop(); tts.shutdown(); } super.onDestroy(); } }
Ensuring clean cleanup in onDestroy() was critical to prevent memory leaks and orphaned system audio threads when the user rotated the screen or exited the app.
Testing Across Device Fragmentation
Virtual emulators are helpful, but nothing substitutes for testing on physical hardware. Testing on an actual Samsung Galaxy S3 and a friend's HTC One immediately revealed critical edge cases:
- Different device manufacturers bundled completely different default text-to-speech voice engines.
- Some devices required users to manually download voice synthesis data packs before speech could initiate.
- Keyboard layouts and screen orientations varied dramatically between budget and flagship displays.
Handling these hardware discrepancies required defensive coding, permission checks, and helpful user prompts.
Publishing to the Google Play Store
The publishing workflow demanded as much attention to detail as the Java code:
- Manifest Configuration: Specifying minimum and target SDK versions with strict permissions:
Code • xml<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.ersindemirtas.speakphone" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" /> </manifest>
- Release Keystore Signing: Generating a cryptographically signed APK and safely archiving the release keystore.
- Asset Production: High-resolution launcher icons, feature graphics, and localization metadata for the store listing.
Key Takeaways
- Embrace Hardware Reality Early: Do not rely exclusively on emulators. Device fragmentation will expose edge cases that emulator logs never show.
- Respect the Activity Lifecycle: Failing to clean up background resources and audio engines during activity pauses will drain device batteries and trigger crash reports.
- Ship to Learn: Over-polishing an unreleased project in private will never teach you as much as shipping a minimal, reliable version to real users.
Ersin Demirtas
Software Engineer based in London, UK. Building web applications, APIs, and tools with Laravel, TypeScript, React, and Next.js.
Related Articles
Efficient AI: Local LoRA Training and Cloudflare Deployment
Feb 4, 2026 —Discover how to train custom AI models locally without breaking the bank using LoRA, and deploy them serverless with Cloudflare Workers AI.
Vector Databases vs Traditional Databases
Feb 4, 2026 —As artificial intelligence reshapes software architecture, explore the foundational differences between vector databases and traditional SQL/NoSQL storage engines.