是否可以从 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 文件?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在填充猫鼬中将缓冲区转换为 base64string?

使用 GitHub API 下载文件时解码 base64

来自 Google Vision API OCR 的响应 400,带有指定图像的 base64 字符串

使用base64将视频从服务器流式传输到移动设备

将图像(base64 字符串)作为文件流上传到 Web API

我的响应不是 url,如何使用 base64 显示不是 url 且响应不包含 bodyBytes 的图像?