mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-09 23:40:26 -04:00
Fixed, Unable to upload APK on play store for new apps.
* We have implemented Play Asset Delivery to include the ZIM file within the Android App Bundle (AAB). * To achieve this, we've created Gradle tasks to automatically download the ZIM file and place it inside the assets folder. * In order to utilize this asset file, we've refactored our custom application code. * We haven't removed the functionality of uploading the APK, as this approach remains static for now. Thus, we are retaining both codebases.
This commit is contained in:
parent
3a47ae601a
commit
4c951de69e
@ -100,6 +100,14 @@ class Transaction(
|
|||||||
).execute().prettyPrint()
|
).execute().prettyPrint()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun uploadBundle(file: File) {
|
||||||
|
publisher.edits().apks().upload(
|
||||||
|
packageName,
|
||||||
|
editId,
|
||||||
|
FileContent("application/octet-stream", file)
|
||||||
|
).execute().prettyPrint()
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
fun addToTrackInDraft(apkVariants: List<ApkVariantOutput>): Track =
|
fun addToTrackInDraft(apkVariants: List<ApkVariantOutput>): Track =
|
||||||
publisher.edits().tracks().update(packageName, editId, "internal", Track().apply {
|
publisher.edits().tracks().update(packageName, editId, "internal", Track().apply {
|
||||||
@ -110,6 +118,17 @@ class Transaction(
|
|||||||
})
|
})
|
||||||
track = "internal"
|
track = "internal"
|
||||||
}).execute().prettyPrint()
|
}).execute().prettyPrint()
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
fun addBundleToTrackInDraft(versionCode: Int, versionName: String?): Track =
|
||||||
|
publisher.edits().tracks().update(packageName, editId, "internal", Track().apply {
|
||||||
|
releases = listOf(TrackRelease().apply {
|
||||||
|
status = "draft"
|
||||||
|
name = versionName
|
||||||
|
versionCodes = listOf(versionCode.toLong())
|
||||||
|
})
|
||||||
|
track = "internal"
|
||||||
|
}).execute().prettyPrint()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AndroidPublisher.transactionWithCommit(packageName: String, func: Transaction.() -> Unit) {
|
fun AndroidPublisher.transactionWithCommit(packageName: String, func: Transaction.() -> Unit) {
|
||||||
|
@ -13,6 +13,7 @@ import java.io.FileOutputStream
|
|||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
|
import java.io.FileNotFoundException
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
android
|
android
|
||||||
@ -33,8 +34,13 @@ android {
|
|||||||
createDownloadTask(it)
|
createDownloadTask(it)
|
||||||
createPublishApkWithExpansionTask(it, applicationVariants)
|
createPublishApkWithExpansionTask(it, applicationVariants)
|
||||||
}
|
}
|
||||||
|
File("$projectDir/../install_time_asset_for_dwds/src/main/assets", "$name.zim").let {
|
||||||
|
createDownloadTaskForPlayAssetDelivery(it)
|
||||||
|
createPublishBundleWithAssetPlayDelivery(applicationVariants)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bundle {
|
bundle {
|
||||||
language {
|
language {
|
||||||
// This is for testing the bundle file for the play store
|
// This is for testing the bundle file for the play store
|
||||||
@ -42,6 +48,12 @@ android {
|
|||||||
enableSplit = false
|
enableSplit = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
splits {
|
||||||
|
abi {
|
||||||
|
isUniversalApk = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assetPacks += ":install_time_asset_for_dwds"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ProductFlavor.createDownloadTask(file: File): Task {
|
fun ProductFlavor.createDownloadTask(file: File): Task {
|
||||||
@ -105,6 +117,38 @@ fun writeZimFileData(responseBody: ResponseBody, file: File) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ProductFlavor.createDownloadTaskForPlayAssetDelivery(
|
||||||
|
file: File
|
||||||
|
): Task {
|
||||||
|
return tasks.create(
|
||||||
|
"download${
|
||||||
|
name.replaceFirstChar {
|
||||||
|
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it"
|
||||||
|
}
|
||||||
|
}ZimAndPutInAssetFolder"
|
||||||
|
) {
|
||||||
|
group = "Downloading"
|
||||||
|
doLast {
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.createNewFile()
|
||||||
|
|
||||||
|
OkHttpClient().newCall(fetchRequest()).execute().use { response ->
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
response.body?.let { responseBody ->
|
||||||
|
writeZimFileData(responseBody, file)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw RuntimeException(
|
||||||
|
"Download Failed. Error: ${response.message}\n" +
|
||||||
|
" Status Code: ${response.code}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val String.decodeUrl: String
|
val String.decodeUrl: String
|
||||||
get() = URLDecoder.decode(this, "UTF-8")
|
get() = URLDecoder.decode(this, "UTF-8")
|
||||||
val String.isAuthenticationUrl: Boolean
|
val String.isAuthenticationUrl: Boolean
|
||||||
@ -149,6 +193,37 @@ fun DomainObjectSet<ApplicationVariant>.releaseVariantsFor(productFlavor: Produc
|
|||||||
find { it.name.equals("${productFlavor.name}Release", true) }!!
|
find { it.name.equals("${productFlavor.name}Release", true) }!!
|
||||||
.outputs.filterIsInstance<ApkVariantOutput>().sortedBy { it.versionCodeOverride }
|
.outputs.filterIsInstance<ApkVariantOutput>().sortedBy { it.versionCodeOverride }
|
||||||
|
|
||||||
|
fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(
|
||||||
|
applicationVariants: DomainObjectSet<ApplicationVariant>
|
||||||
|
): Task {
|
||||||
|
val capitalizedName =
|
||||||
|
name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" }
|
||||||
|
return tasks.create("publish${capitalizedName}ReleaseBundleWithPlayAssetDelivery") {
|
||||||
|
group = "publishing"
|
||||||
|
description = "Uploads $capitalizedName to the Play Console with an Expansion file"
|
||||||
|
doLast {
|
||||||
|
val packageName = "org.kiwix$applicationIdSuffix"
|
||||||
|
println("packageName $packageName")
|
||||||
|
createPublisher(File(rootDir, "playstore.json"))
|
||||||
|
.transactionWithCommit(packageName) {
|
||||||
|
val variants =
|
||||||
|
applicationVariants.releaseVariantsFor(this@createPublishBundleWithAssetPlayDelivery)
|
||||||
|
val generatedBundleFile =
|
||||||
|
File(
|
||||||
|
"$buildDir/outputs/bundle/${capitalizedName.lowercase(Locale.getDefault())}" +
|
||||||
|
"Release/custom-${capitalizedName.lowercase(Locale.getDefault())}-release.aab"
|
||||||
|
)
|
||||||
|
if (generatedBundleFile.exists()) {
|
||||||
|
uploadBundle(generatedBundleFile)
|
||||||
|
addBundleToTrackInDraft(variants[0].versionCode, versionName)
|
||||||
|
} else {
|
||||||
|
throw FileNotFoundException("Unable to find generated aab file")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
tasks.filter { it.name.contains("ReleaseApkWithExpansionFile") }.forEach {
|
tasks.filter { it.name.contains("ReleaseApkWithExpansionFile") }.forEach {
|
||||||
val flavorName =
|
val flavorName =
|
||||||
@ -156,4 +231,10 @@ afterEvaluate {
|
|||||||
it.dependsOn.add(tasks.getByName("download${flavorName}Zim"))
|
it.dependsOn.add(tasks.getByName("download${flavorName}Zim"))
|
||||||
it.dependsOn.add(tasks.getByName("assemble${flavorName}Release"))
|
it.dependsOn.add(tasks.getByName("assemble${flavorName}Release"))
|
||||||
}
|
}
|
||||||
|
tasks.filter { it.name.contains("ReleaseBundleWithPlayAssetDelivery") }.forEach {
|
||||||
|
val flavorName =
|
||||||
|
it.name.substringAfter("publish").substringBefore("ReleaseBundleWithPlayAssetDelivery")
|
||||||
|
it.dependsOn.add(tasks.getByName("download${flavorName}ZimAndPutInAssetFolder"))
|
||||||
|
it.dependsOn.add(tasks.getByName("bundle${flavorName}Release"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,15 @@
|
|||||||
package org.kiwix.kiwixmobile.custom.main
|
package org.kiwix.kiwixmobile.custom.main
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.util.Log
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import org.kiwix.kiwixmobile.custom.main.ValidationState.HasBothFiles
|
import org.kiwix.kiwixmobile.custom.main.ValidationState.HasBothFiles
|
||||||
import org.kiwix.kiwixmobile.custom.main.ValidationState.HasFile
|
import org.kiwix.kiwixmobile.custom.main.ValidationState.HasFile
|
||||||
import org.kiwix.kiwixmobile.custom.main.ValidationState.HasNothing
|
import org.kiwix.kiwixmobile.custom.main.ValidationState.HasNothing
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class CustomFileValidator @Inject constructor(private val context: Context) {
|
class CustomFileValidator @Inject constructor(private val context: Context) {
|
||||||
@ -37,16 +41,48 @@ class CustomFileValidator @Inject constructor(private val context: Context) {
|
|||||||
|
|
||||||
private fun detectInstallationState(
|
private fun detectInstallationState(
|
||||||
obbFiles: List<File> = obbFiles(),
|
obbFiles: List<File> = obbFiles(),
|
||||||
zimFiles: List<File> = zimFiles()
|
zimFiles: List<File> = zimFiles(),
|
||||||
|
assetFile: File? = getFileFromPlayAssetDelivery()
|
||||||
): ValidationState {
|
): ValidationState {
|
||||||
return when {
|
return when {
|
||||||
obbFiles.isNotEmpty() && zimFiles().isNotEmpty() -> HasBothFiles(obbFiles[0], zimFiles[0])
|
obbFiles.isNotEmpty() && zimFiles().isNotEmpty() -> HasBothFiles(obbFiles[0], zimFiles[0])
|
||||||
obbFiles.isNotEmpty() -> HasFile(obbFiles[0])
|
obbFiles.isNotEmpty() -> HasFile(obbFiles[0])
|
||||||
zimFiles.isNotEmpty() -> HasFile(zimFiles[0])
|
zimFiles.isNotEmpty() -> HasFile(zimFiles[0])
|
||||||
|
assetFile != null -> HasFile(assetFile)
|
||||||
else -> HasNothing
|
else -> HasNothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("NestedBlockDepth", "MagicNumber")
|
||||||
|
private fun getFileFromPlayAssetDelivery(): File? {
|
||||||
|
var zimFile: File? = null
|
||||||
|
try {
|
||||||
|
val context = context.createPackageContext(context.packageName, 0)
|
||||||
|
val assetManager = context.assets
|
||||||
|
val inputStream = assetManager.open("dwds_de_dictionary_nopic_2023-09-12.zim")
|
||||||
|
val filePath = ContextCompat.getExternalFilesDirs(context, null)[0]
|
||||||
|
zimFile = File(filePath, "dwds_de_dictionary_nopic_2023-09-12.zim")
|
||||||
|
FileOutputStream(zimFile).use { outputSteam ->
|
||||||
|
inputStream.use { inputStream ->
|
||||||
|
val buffer = ByteArray(1024)
|
||||||
|
var length: Int
|
||||||
|
while (inputStream.read(buffer).also { length = it } > 0) {
|
||||||
|
outputSteam.write(buffer, 0, length)
|
||||||
|
}
|
||||||
|
outputSteam.flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (packageNameNotFoundException: PackageManager.NameNotFoundException) {
|
||||||
|
Log.w(
|
||||||
|
"ASSET_PACKAGE_DELIVERY",
|
||||||
|
"Asset package is not found ${packageNameNotFoundException.message}"
|
||||||
|
)
|
||||||
|
} catch (ioException: IOException) {
|
||||||
|
Log.w("ASSET_PACKAGE_DELIVERY", "Unable to copy the content of asset ${ioException.message}")
|
||||||
|
}
|
||||||
|
return zimFile
|
||||||
|
}
|
||||||
|
|
||||||
private fun obbFiles() = scanDirs(ContextCompat.getObbDirs(context), "obb")
|
private fun obbFiles() = scanDirs(ContextCompat.getObbDirs(context), "obb")
|
||||||
|
|
||||||
private fun zimFiles(): List<File> {
|
private fun zimFiles(): List<File> {
|
||||||
|
8
install_time_asset_for_dwds/build.gradle
Normal file
8
install_time_asset_for_dwds/build.gradle
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
apply plugin: 'com.android.asset-pack'
|
||||||
|
|
||||||
|
assetPack {
|
||||||
|
packName = "install_time_asset_for_dwds" // Directory name for the asset pack
|
||||||
|
dynamicDelivery {
|
||||||
|
deliveryType = "install-time" // delivery mode
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
include(
|
include(
|
||||||
":core",
|
":core",
|
||||||
":app",
|
":app",
|
||||||
":custom"
|
":custom",
|
||||||
|
":install_time_asset_for_dwds"
|
||||||
)
|
)
|
||||||
rootProject.name = "kiwix-android"
|
rootProject.name = "kiwix-android"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user