是否可以从 base64String API 响应调用生成 APK 文件?
Is it possible to generate an APK file from a base64String API response call?
我目前正在研究如何以编程方式更新和安装 APK 文件的解决方案 - 与 this 问题非常相似。我的应用程序 不使用 Google 服务。
出于更新目的,具有升序版本的 APK 文件存储在内部服务器和 C# Web 服务上 returns 最新 版本的 APK 文件。
我用 Retrofit2 做这个:
@Streaming
@GET("/ws/webservice.svc/getUpdate")
fun getUpdate(
@Query("Programm") program: String,
@Query("version") version: String,
@Query("test") test: Boolean
): Single<String>
和实时数据:
override fun getUpdate() {
disposables += api.getUpdate(
program = context.getString(R.string.app_name),
version = context.getString(R.string.app_version),
test = isTest
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = {
liveData.value = GetUpdate(it)
},
onError = {
liveData.value = Error("Error getUpdate: " + it.message)
}
)
}
我面临的问题是 API 调用的响应(这意味着 - 最新的 APK 文件)具有如图所示的 base64String 表示在下图中 - 例如,当在浏览器中进行 API 调用时,这只是服务器响应的一部分。
是否有可能在下载后从这个字符串表示中生成一个 "real" APK 文件,这样我就可以在设备上安装它了?我知道这很奇怪,但客户希望我为此重新使用相同的 Web 服务。
我发现了一个类似的问题 here。这在 Kotlin 中如何完成?提前致谢。
是的,您需要将 base64
解码为 ByteArray
,然后将字节写入后缀为 .apk
的位置。您拥有的是 String
,其中 bytes
是 encoded
,使用 base64
编码方案。
自从您使用 kotlin
后,您可能需要查看此处的内容才能从 String
获取 ByteArray!
[1]。然后确保您写入的文件具有 .apk
扩展名。
[1] https://developer.android.com/reference/kotlin/java/util/Base64.Decoder#decode(kotlin.String)
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
带 LiveData 的 MVVM:
override fun getUpdate() {
disposables += api.getUpdate(
program = context.getString(R.string.app_name) + ".apk",
version = context.getString(R.string.app_version),
test = isTest
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(::decodeToAPK)
.subscribe({
liveData.value = GetUpdate
}, {
liveData.value = Error("Error getUpdate: " + it.message)
})
}
private fun decodeToAPK(base64String: String) {
val byteArrayAPK = Base64.decode(base64String, Base64.DEFAULT)
val file =
File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "yourApp.apk")
try {
val fileOutputStream = FileOutputStream(file)
fileOutputStream.write(byteArrayAPK)
fileOutputStream.flush()
fileOutputStream.close()
} catch (e: UnsupportedEncodingException) {
Log.d(null, "error writing APK")
e.printStackTrace()
}
}
sealed class SomeAction : Action {
data class Error(val message: String) : SomeAction()
object GetUpdate : SomeAction()
}
我目前正在研究如何以编程方式更新和安装 APK 文件的解决方案 - 与 this 问题非常相似。我的应用程序 不使用 Google 服务。
出于更新目的,具有升序版本的 APK 文件存储在内部服务器和 C# Web 服务上 returns 最新 版本的 APK 文件。
我用 Retrofit2 做这个:
@Streaming
@GET("/ws/webservice.svc/getUpdate")
fun getUpdate(
@Query("Programm") program: String,
@Query("version") version: String,
@Query("test") test: Boolean
): Single<String>
和实时数据:
override fun getUpdate() {
disposables += api.getUpdate(
program = context.getString(R.string.app_name),
version = context.getString(R.string.app_version),
test = isTest
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = {
liveData.value = GetUpdate(it)
},
onError = {
liveData.value = Error("Error getUpdate: " + it.message)
}
)
}
我面临的问题是 API 调用的响应(这意味着 - 最新的 APK 文件)具有如图所示的 base64String 表示在下图中 - 例如,当在浏览器中进行 API 调用时,这只是服务器响应的一部分。
是否有可能在下载后从这个字符串表示中生成一个 "real" APK 文件,这样我就可以在设备上安装它了?我知道这很奇怪,但客户希望我为此重新使用相同的 Web 服务。
我发现了一个类似的问题 here。这在 Kotlin 中如何完成?提前致谢。
是的,您需要将 base64
解码为 ByteArray
,然后将字节写入后缀为 .apk
的位置。您拥有的是 String
,其中 bytes
是 encoded
,使用 base64
编码方案。
自从您使用 kotlin
后,您可能需要查看此处的内容才能从 String
获取 ByteArray!
[1]。然后确保您写入的文件具有 .apk
扩展名。
[1] https://developer.android.com/reference/kotlin/java/util/Base64.Decoder#decode(kotlin.String)
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
带 LiveData 的 MVVM:
override fun getUpdate() {
disposables += api.getUpdate(
program = context.getString(R.string.app_name) + ".apk",
version = context.getString(R.string.app_version),
test = isTest
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(::decodeToAPK)
.subscribe({
liveData.value = GetUpdate
}, {
liveData.value = Error("Error getUpdate: " + it.message)
})
}
private fun decodeToAPK(base64String: String) {
val byteArrayAPK = Base64.decode(base64String, Base64.DEFAULT)
val file =
File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "yourApp.apk")
try {
val fileOutputStream = FileOutputStream(file)
fileOutputStream.write(byteArrayAPK)
fileOutputStream.flush()
fileOutputStream.close()
} catch (e: UnsupportedEncodingException) {
Log.d(null, "error writing APK")
e.printStackTrace()
}
}
sealed class SomeAction : Action {
data class Error(val message: String) : SomeAction()
object GetUpdate : SomeAction()
}