forked from recloudstream/cloudstream
Added delayed updating on A13 to make it less jarring
This commit is contained in:
parent
0afb6b62aa
commit
657971d008
7 changed files with 78 additions and 37 deletions
|
@ -48,7 +48,7 @@ android {
|
|||
targetSdk = 33
|
||||
|
||||
versionCode = 55
|
||||
versionName = "3.3.0"
|
||||
versionName = "3.4.0"
|
||||
|
||||
resValue("string", "app_version", "${defaultConfig.versionName}${versionNameSuffix ?: ""}")
|
||||
|
||||
|
|
|
@ -4,25 +4,20 @@ import android.content.ComponentName
|
|||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.WindowManager
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.marginRight
|
||||
import androidx.core.view.setMargins
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentContainerView
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination
|
||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||
|
@ -77,6 +72,7 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.updateT
|
|||
import com.lagradost.cloudstream3.ui.settings.SettingsGeneral
|
||||
import com.lagradost.cloudstream3.ui.setup.HAS_DONE_SETUP_KEY
|
||||
import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
|
||||
|
@ -87,8 +83,6 @@ import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
|||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching
|
||||
import com.lagradost.cloudstream3.utils.Event
|
||||
import com.lagradost.cloudstream3.utils.IOnBackPressed
|
||||
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
|
||||
|
@ -97,9 +91,6 @@ import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor
|
|||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.navigate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||
import com.lagradost.cloudstream3.utils.USER_PROVIDER_API
|
||||
import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API
|
||||
import com.lagradost.nicehttp.Requests
|
||||
import com.lagradost.nicehttp.ResponseParser
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
|
@ -475,6 +466,11 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
|
||||
// Start any delayed updates
|
||||
if (ApkInstaller.delayedInstaller?.startInstallation() == true) {
|
||||
Toast.makeText(this, R.string.update_started, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
try {
|
||||
if (isCastApiAvailable()) {
|
||||
mSessionManager.removeSessionManagerListener(mSessionManagerListener)
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.webkit.CookieManager
|
|||
import androidx.annotation.AnyThread
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.mvvm.debugWarning
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.nicehttp.Requests.Companion.await
|
||||
import com.lagradost.nicehttp.cookies
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -26,7 +27,10 @@ class CloudflareKiller : Interceptor {
|
|||
|
||||
init {
|
||||
// Needs to clear cookies between sessions to generate new cookies.
|
||||
CookieManager.getInstance().removeAllCookies(null)
|
||||
normalSafeApiCall {
|
||||
// This can throw an exception on unsupported devices :(
|
||||
CookieManager.getInstance().removeAllCookies(null)
|
||||
}
|
||||
}
|
||||
|
||||
val savedCookies: MutableMap<String, Map<String, String>> = mutableMapOf()
|
||||
|
@ -35,7 +39,7 @@ class CloudflareKiller : Interceptor {
|
|||
* Gets the headers with cookies, webview user agent included!
|
||||
* */
|
||||
fun getCookieHeaders(url: String): Headers {
|
||||
val userAgentHeaders = WebViewResolver.webViewUserAgent?.let {
|
||||
val userAgentHeaders = WebViewResolver.webViewUserAgent?.let {
|
||||
mapOf("user-agent" to it)
|
||||
} ?: emptyMap()
|
||||
|
||||
|
|
|
@ -296,12 +296,21 @@ class InAppUpdater {
|
|||
val context = this
|
||||
builder.apply {
|
||||
setPositiveButton(R.string.update) { _, _ ->
|
||||
// Forcefully start any delayed installations
|
||||
if (ApkInstaller.delayedInstaller?.startInstallation() == true) return@setPositiveButton
|
||||
|
||||
showToast(context, R.string.download_started, Toast.LENGTH_LONG)
|
||||
|
||||
// Check if the setting hasn't been changed
|
||||
if (settingsManager.getInt(getString(R.string.apk_installer_key), -1) == -1) {
|
||||
if (settingsManager.getInt(
|
||||
getString(R.string.apk_installer_key),
|
||||
-1
|
||||
) == -1
|
||||
) {
|
||||
if (isMiUi()) // Set to legacy if using miui
|
||||
settingsManager.edit().putInt(getString(R.string.apk_installer_key), 1).apply()
|
||||
settingsManager.edit()
|
||||
.putInt(getString(R.string.apk_installer_key), 1)
|
||||
.apply()
|
||||
}
|
||||
|
||||
val currentInstaller =
|
||||
|
@ -358,30 +367,19 @@ class InAppUpdater {
|
|||
return false
|
||||
}
|
||||
|
||||
fun isMiUi(): Boolean {
|
||||
private fun isMiUi(): Boolean {
|
||||
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"))
|
||||
}
|
||||
|
||||
fun getSystemProperty(propName: String): String? {
|
||||
var line: String? = null
|
||||
var input: BufferedReader? = null
|
||||
try {
|
||||
private fun getSystemProperty(propName: String): String? {
|
||||
return try {
|
||||
val p = Runtime.getRuntime().exec("getprop $propName")
|
||||
input = BufferedReader(InputStreamReader(p.inputStream), 1024)
|
||||
line = input.readLine()
|
||||
input.close()
|
||||
} catch (ex: IOException) {
|
||||
return null
|
||||
} finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close()
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
BufferedReader(InputStreamReader(p.inputStream), 1024).use {
|
||||
it.readLine()
|
||||
}
|
||||
} catch (ex: IOException) {
|
||||
null
|
||||
}
|
||||
return line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,42 @@ import android.content.BroadcastReceiver
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.IntentSender
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import java.io.InputStream
|
||||
|
||||
const val INSTALL_ACTION = "ApkInstaller.INSTALL_ACTION"
|
||||
|
||||
|
||||
class ApkInstaller(private val service: PackageInstallerService) {
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Used for postponed installations
|
||||
**/
|
||||
var delayedInstaller: DelayedInstaller? = null
|
||||
}
|
||||
|
||||
inner class DelayedInstaller(
|
||||
private val session: PackageInstaller.Session,
|
||||
private val intent: IntentSender
|
||||
) {
|
||||
fun startInstallation(): Boolean {
|
||||
return try {
|
||||
session.commit(intent)
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}.also { delayedInstaller = null }
|
||||
}
|
||||
}
|
||||
|
||||
private val packageInstaller = service.packageManager.packageInstaller
|
||||
|
||||
enum class InstallProgressStatus {
|
||||
|
@ -76,7 +103,6 @@ class ApkInstaller(private val service: PackageInstallerService) {
|
|||
inputStream.close()
|
||||
}
|
||||
|
||||
installProgressStatus.invoke(InstallProgressStatus.Installing)
|
||||
|
||||
val intentSender = PendingIntent.getBroadcast(
|
||||
service,
|
||||
|
@ -85,7 +111,22 @@ class ApkInstaller(private val service: PackageInstallerService) {
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0,
|
||||
).intentSender
|
||||
|
||||
session.commit(intentSender)
|
||||
// Use delayed installations on android 13 and only if "allow from unknown sources" is enabled
|
||||
// if the app lacks installation permission it cannot ask for the permission when it's closed.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S &&
|
||||
context.packageManager.canRequestPackageInstalls()
|
||||
) {
|
||||
// Save for later installation since it's more jarring to have the app exit abruptly
|
||||
delayedInstaller = DelayedInstaller(session, intentSender)
|
||||
main {
|
||||
// Use real toast since it should show even if app is exited
|
||||
Toast.makeText(context, R.string.delayed_update_notice, Toast.LENGTH_LONG)
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
installProgressStatus.invoke(InstallProgressStatus.Installing)
|
||||
session.commit(intentSender)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ class PackageInstallerService : Service() {
|
|||
const val UPDATE_CHANNEL_ID = "cloudstream3.updates"
|
||||
const val UPDATE_CHANNEL_NAME = "App Updates"
|
||||
const val UPDATE_CHANNEL_DESCRIPTION = "App updates notification channel"
|
||||
const val UPDATE_NOTIFICATION_ID = -68454136
|
||||
const val UPDATE_NOTIFICATION_ID = -68454136 // Random unique
|
||||
|
||||
fun getIntent(
|
||||
context: Context,
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
<string name="download_canceled">Download Canceled</string>
|
||||
<string name="download_done">Download Done</string>
|
||||
<string name="download_format" translatable="false">%s - %s</string>
|
||||
<string name="update_started">Update Started</string>
|
||||
<string name="stream">Stream</string>
|
||||
<string name="error_loading_links_toast">Error Loading Links</string>
|
||||
<string name="download_storage_text">Internal Storage</string>
|
||||
|
@ -611,5 +612,6 @@
|
|||
|
||||
<string name="apk_installer_legacy">Legacy</string>
|
||||
<string name="apk_installer_package_installer">PackageInstaller</string>
|
||||
<string name="delayed_update_notice">App will be updated upon exit</string>
|
||||
|
||||
</resources>
|
Loading…
Reference in a new issue