Skip to content

What Are the Alternatives to Google Play for Android App Distribution?

Purpose

I’ve been asked repeatedly about alternatives to Google Play for distributing Android apps. Whether you’re an independent developer tired of the 15-30% commission cut, building open-source software that needs a more permissive home, or working in markets where Google Play isn’t easily accessible, you have legitimate options. Android’s open nature means you’re not locked into Google’s ecosystem for app distribution. Let me walk through what’s available and how to actually use these alternatives.

The Problem with Google Play Dominance

Google Play’s near-monopoly position comes with real costs:

  • Revenue loss: Google takes 15-30% of all in-app purchases and app sales
  • Strict policies: Apps can be removed for vague policy violations with limited recourse
  • Review delays: Updates can take hours or days to approve
  • Data requirements: Google demands increasing access to user analytics
  • Geographic limitations: Some regions have limited payment options or access restrictions

When I built my first Android app, the Google Play Developer Console felt like the only option. But once I started exploring alternatives, I realized the ecosystem is far more diverse than it appears at first glance.

F-Droid: The Open Source Option

F-Droid is my go-to recommendation for open-source Android apps. It’s a repository of free and open-source software (FOSS) that anyone can contribute to. Here’s why I like it:

  • Zero fees: No commission on downloads or purchases
  • Transparent verification: Source code is required and verified
  • Community-driven: Decisions about inclusion are made publicly
  • Privacy-focused: No tracking required, no user data harvesting

Getting your app on F-Droid requires it to be fully open-source. You’ll need to:

  1. Host your source code publicly (GitLab, GitHub, etc.)
  2. Add a build manifest that F-Droid can use to compile your app
  3. Ensure all dependencies are also open-source

The build manifest is straightforward. Here’s a minimal example:

<?xml version='1.0' encoding='UTF-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application android:label="@string/app_name"
android:icon="@mipmap/ic_launcher">
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

F-Droid automatically builds your app from source, ensuring users get exactly what’s in your repository. This transparency builds trust with privacy-conscious users.

Direct APK Distribution

The simplest alternative is distributing your APK directly to users. This gives you complete control over distribution, updates, and monetization. Here’s how I do it:

Step 1: Prepare Your APK

Build a release-ready APK using Android Studio or Gradle:

Terminal window
./gradlew assembleRelease

This generates an APK in app/build/outputs/apk/release/. Make sure to sign it properly.

Step 2: Enable Install from Unknown Sources

Users need to allow installations from unknown sources. Here’s how to check this permission in your app and guide users:

private fun checkInstallPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val packageManager = packageManager
if (!packageManager.canRequestPackageInstalls()) {
// Prompt user to enable unknown sources
AlertDialog.Builder(this)
.setTitle("Enable Unknown Sources")
.setMessage("Please enable 'Install unknown apps' permission to continue")
.setPositiveButton("Settings") { _, _ ->
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
data = Uri.parse("package:$packageName")
}
startActivity(intent)
}
.setNegativeButton("Cancel", null)
.show()
}
}
}

Step 3: Host Your APK

Options for hosting:

  • GitHub Releases: Free and integrates with version control
  • Your own server: Complete control, custom domain
  • Cloud storage: AWS S3, Google Cloud Storage
  • Specialized platforms: Itch.io, Ko-fi for indie distribution

When I host APKs, I always include a hash so users can verify integrity:

Terminal window
sha256sum app-release.apk > app-release.apk.sha256

Step 4: Implement In-App Updates

Direct distribution means you handle updates yourself. Here’s a simple update checker:

private suspend fun checkForUpdates() {
try {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://your-server.com/version.json")
.build()
val response = client.newCall(request).execute()
val versionJson = response.body?.string()
val latestVersion = JSONObject(versionJson).getInt("versionCode")
val currentVersion = packageManager
.getPackageInfo(packageName, 0).versionCode
if (latestVersion > currentVersion) {
showUpdateDialog()
}
} catch (e: Exception) {
// Handle network errors gracefully
}
}

Third-Party App Stores

Several established app stores offer alternatives to Google Play. Each has different requirements and audiences. Here’s how they compare:

StoreCommissionSetup FeeKey MarketsDeveloper Tools
Amazon Appstore20%$99/yearUS, UK, Europe, JapanAmazon App Testing Service
Samsung Galaxy Store30%FreeSamsung devices (500M+ users)Galaxy Store Tester
Huawei AppGallery30%FreeChina, emerging marketsHMS Core integration
GetJar30%FreeEmerging marketsBasic analytics
Aptoide30%VariableGlobal, niche communitiesCustom store option

Amazon Appstore has been my experience with third-party stores. The setup process is similar to Google Play but with different review criteria. Amazon offers promotion opportunities through their Underground program and frequent promotional events.

Samsung Galaxy Store reaches a massive audience without a setup fee. Since Samsung devices ship with the store pre-installed, your app gets automatic exposure to hundreds of millions of potential users.

Huawei AppGallery is essential if you’re targeting Chinese markets. After Google’s services ban in China, Huawei’s store became the dominant alternative there. You’ll need to integrate Huawei Mobile Services (HMS) instead of Google Play Services.

Technical Setup

When distributing outside Google Play, your app needs proper configuration. Here’s the essential setup:

Android Manifest Configuration

<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<!-- Request storage permission for APK downloads -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- For Android 13+ scoped storage -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- Request install permissions for in-app updates -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.MyApp">
<activity
android:name=".MainActivity"
android:exported="true"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- File provider for sharing APKs -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

Create File Provider Configuration

Create res/xml/file_paths.xml:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="." />
<cache-path name="cache" path="." />
</paths>

Runtime Permission Handling

private const val REQUEST_CODE_INSTALL = 123
private fun checkAndRequestInstallPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!packageManager.canRequestPackageInstalls()) {
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
data = Uri.parse("package:$packageName")
}
startActivityForResult(intent, REQUEST_CODE_INSTALL)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE_INSTALL) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (packageManager.canRequestPackageInstalls()) {
// Permission granted, proceed with APK download and install
downloadAndInstallAPK()
} else {
Toast.makeText(this, "Install permission denied", Toast.LENGTH_SHORT).show()
}
}
}
}

APK Installation Code

private suspend fun downloadAndInstallAPK() {
try {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://your-server.com/app-release.apk")
.build()
val response = client.newCall(request).execute()
val apkFile = File(getExternalFilesDir(null), "update.apk")
response.body?.byteStream()?.use { input ->
FileOutputStream(apkFile).use { output ->
input.copyTo(output)
}
}
installAPK(apkFile)
} catch (e: Exception) {
Log.e("Update", "Download failed", e)
}
}
private fun installAPK(file: File) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val uri = FileProvider.getUriForFile(
this,
"$packageName.fileprovider",
file
)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "application/vnd.android.package-archive")
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
}
startActivity(intent)
} else {
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(
Uri.fromFile(file),
"application/vnd.android.package-archive"
)
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
startActivity(intent)
}
}

Regional Considerations

When choosing distribution channels, consider your target market:

China: Google Play is largely inaccessible. Huawei AppGallery dominates with other local players like Tencent MyApp and Baidu Mobile Assistant. You’ll need to integrate HMS and comply with local regulations.

India: Google Play dominates but Amazon Appstore has significant reach. Local payment integration like UPI is crucial for monetization.

Europe: Google Play is mandatory but competition is increasing. Samsung Galaxy Store and Amazon Appstore have decent market share. GDPR compliance is non-negotiable.

North America: Google Play and Apple App Store dominate, but Amazon’s Kindle ecosystem provides a significant alternative audience.

Emerging Markets: Direct APK distribution is common due to limited payment options and network constraints. Consider lightweight APKs (APK splits) and offline functionality.

Summary

You have real alternatives to Google Play for Android app distribution. Here’s my practical advice:

  • For open-source projects: F-Droid is your best option. The community and transparency benefits outweigh the limited audience.
  • For commercial apps with a direct audience: Consider Amazon Appstore or Samsung Galaxy Store alongside Google Play. The dual-listing strategy maximizes reach.
  • For China and emerging markets: Prioritize local app stores like Huawei AppGallery and implement regional payment methods.
  • For maximum control: Direct APK distribution gives you complete freedom but requires handling your own hosting, updates, and security.

The key is matching your distribution strategy to your audience and business model. Don’t limit yourself to Google Play by default. Explore these alternatives and choose what works for your specific situation.

Android’s open ecosystem is a feature, not a bug. Take advantage of it.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments