Как я могу программно обновлять приложения на Android с помощью S3? - PullRequest
0 голосов
/ 17 июня 2020

Это код, который я использую для обновления моего приложения с настроенным CDN (я думаю, он также называется настроенным приложением, которое используется в частном порядке).

    private fun downloadApk(url: String) {
        forceUpdateDialog?.dismiss()

        // instantiate it within the onCreate method
        mProgressDialog = ProgressDialog(this)
        mProgressDialog!!.setMessage("Downloading new version...")
        mProgressDialog!!.isIndeterminate = true
        mProgressDialog!!.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
        mProgressDialog!!.setCancelable(false)
        mProgressDialog!!.window!!.requestFeature(Window.FEATURE_NO_TITLE)
//        mProgressDialog!!.window!!.setBackgroundDrawableResource(android.R.color.transparent)
        mProgressDialog!!.setCanceledOnTouchOutside(false)
        mProgressDialog!!.setOnCancelListener {
            // TODO: nothing
        }

        // execute this when the downloader must be fired
        val downloadTask = DownloadTask(this) // DownloadTask
        downloadTask.execute(url)

        mProgressDialog!!.setOnCancelListener {
            downloadTask.cancel(true) //cancel the task
        }
    }
    private class DownloadTask(context: Context) : AsyncTask<String, Int, String?>() {
        var context: Context? = context
        var mWakeLock: PowerManager.WakeLock? = null

        //set destination
        val fileName = NetworkConstants.APK_NAME
        var destination = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            "${context.getExternalFilesDir(null)}/$fileName"
        } else {
            "${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/$fileName"
        }

        override fun doInBackground(vararg params: String?): String? {
            var input: InputStream? = null
            var output: OutputStream? = null
            var connection: HttpURLConnection? = null

            try {
                val url = URL(params[0])
                connection = url.openConnection() as HttpURLConnection
                connection.connect()

                // expect HTTP 200 OK, so we don't mistakenly save error report
                // instead of the file
                if (connection.responseCode != HttpURLConnection.HTTP_OK) {
                    return "Server returned HTTP ${connection.responseCode}\n${connection.responseMessage}"
                }

                // this will be useful to display download percentage
                // might be -1: server did not report the length
                val fileLength = connection.contentLength

                // download the file
                input = connection.inputStream
                output = FileOutputStream(destination)

                val data = ByteArray(4096)

                var total = 0
                var count = 0

                while ({ count = input.read(data); count }() != -1) {
                    // allow canceling with back button
                    if (isCancelled) {
                        input.close()
                        return null
                    }
                    total += count

                    // publishing the progress....
                    if (fileLength > 0) // only if total length is known
                        publishProgress((total * 100 / fileLength))
                    output.write(data, 0, count)
                }
            } catch (e: Exception) {
                return e.toString()
            } finally {
                try {
                    output?.close()
                    input?.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                }
                connection?.disconnect()
            }
            return null
        }

        override fun onProgressUpdate(vararg values: Int?) {
            super.onProgressUpdate(*values)
            // if we get here, length is known, now set indeterminate to false
            mProgressDialog!!.isIndeterminate = false
            mProgressDialog!!.max = 100
            mProgressDialog!!.progress = values[0] as Int
        }

        override fun onPreExecute() {
            super.onPreExecute()
            // take CPU lock to prevent CPU from going off if the user
            // presses the power button during download
            val pm = context!!.getSystemService(Context.POWER_SERVICE) as PowerManager
            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, javaClass.name)
            mWakeLock!!.acquire() // no need to set time
            mProgressDialog!!.show()

            deleteApk()
        }

        override fun onPostExecute(result: String?) {
            mWakeLock?.release()
            mProgressDialog?.dismiss()

            if (result != null) {
                Toast.makeText(context, "Update Failed: $result", Toast.LENGTH_LONG).show()
                (context as LoginActivity).finish()
            } else {
                Toast.makeText(context, "Updating...", Toast.LENGTH_SHORT).show()

                val file = File(destination)
                installApk(file)
            }
        }

        fun installApk(file: File) {
            val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                Log.d("test", BuildConfig.APPLICATION_ID)
                FileProvider.getUriForFile(
                    context!!,
                    "${BuildConfig.APPLICATION_ID}.fileprovider",
                    file
                )
            } else {
                Uri.fromFile(file)
            }

            val intent = Intent(Intent.ACTION_VIEW).apply {
                setDataAndType(uri, "application/vnd.android.package-archive")
                addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            }
            context!!.startActivity(intent)
            (context as LoginActivity).overridePendingTransition(
                R.anim.abc_fade_in,
                R.anim.abc_fade_out
            )
            (context as LoginActivity).finish()
        }

        /**
         * Delete my apk for
         */
        private fun deleteApk() {
            val fileName = NetworkConstants.APK_NAME
            val destination = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                "${context!!.getExternalFilesDir(null)}/$fileName"
            } else {
                "${Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)}/$fileName"
            }
            val file = File(destination)
            if (file.exists()) {
                file.delete()
            }
        }
    }

APP_NAME - это например my_app.apk.

В первый раз обновляется хорошо. Однако, начиная со второго обновления, он повторяет то же действие (появляется диалоговое окно принудительного выполнения> загрузка> успешное обновление> та же версия> принудительное обновление> ... X 00)

Итак, я подумал, что это потому, что apk дублируется. Итак, я попытался удалить apk всякий раз, когда приложение открывает что-то вроде этого.

override onCreate(){
    super.onCreate()
    deleteApk()
}

Однако это то же самое. Итак, я думаю, это из-за S3? как проблема с кешем? Или я могу управлять этим из Манифеста? Я вижу атрибут allowBackup. И я изменил его на false. Похоже, это не работает. Что я могу сделать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...