是否可以从 base64String API 响应调用生成 APK 文件?

Posted

技术标签:

【中文标题】是否可以从 base64String API 响应调用生成 APK 文件?【英文标题】:Is it possible to generate an APK file from a base64String API response call? 【发布时间】: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 中如何做到这一点?提前致谢。

【问题讨论】:

【参考方案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()
   

【讨论】:

以上是关于是否可以从 base64String API 响应调用生成 APK 文件?的主要内容,如果未能解决你的问题,请参考以下文章