【问题标题】:Is it possible to generate an APK file from a base64String API response call?是否可以从 base64String API 响应调用生成 APK 文件?
【发布时间】:2020-05-12 23:49:14
【问题描述】:

我目前正在研究如何以编程方式更新和安装 APK 文件的解决方案 - 非常类似于 this 问题。我的应用不使用 Google 服务。

出于更新目的,具有升序版本的 APK 文件存储在内部服务器上,C# Web 服务返回 APK 文件的最新版本。

我用 Retrofit2 来做这个:

    @Streaming
    @GET("/ws/webservice.svc/getUpdate")
    fun getUpdate(
        @Query("Programm") program: String,
        @Query("version") version: String,
        @Query("test") test: Boolean
    ): Single<String>

和 LiveData:

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 调用时,仅服务器响应的一部分。

是否有可能在下载后从这个字符串表示生成一个“真实”的 APK 文件,所以之后我可能能够将它安装在设备上?我知道这很奇怪,但客户希望我为此目的重复使用相同的 Web 服务。

我发现了一个类似的问题here。在 Kotlin 中如何做到这一点?提前致谢。

【问题讨论】:

    标签: android web-services kotlin apk


    【解决方案1】:

    是的,您需要将base64 解码为ByteArray,然后将字节写入后缀为.apk 的位置。你所拥有的是一个String,其中bytesencoded,使用base64 编码方案。

    由于您使用kotlin,您可能会在这里查看从String 获取ByteArray![1]。然后确保您编写的文件具有.apk 扩展名。

    [1]https://developer.android.com/reference/kotlin/java/util/Base64.Decoder#decode(kotlin.String)

    【讨论】:

    • 非常感谢您的帮助。我正在实施这个问题的解决方案,我会尽快在这里发布。
    【解决方案2】:

    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()
       }
    

    【讨论】:

      猜你喜欢
      • 2020-02-17
      • 1970-01-01
      • 2017-12-30
      • 1970-01-01
      • 1970-01-01
      • 2014-04-25
      • 2022-07-18
      • 1970-01-01
      • 2019-07-19
      相关资源
      最近更新 更多