Fix: Fixed the update manager to work when reloading app.
Signed-off-by: HeCodes2Much <wayne6324@gmail.com>
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
package com.github.droidworksstudio.launcher.helper
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.content.*
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.github.droidworksstudio.common.showLongToast
|
||||
import com.github.droidworksstudio.launcher.BuildConfig
|
||||
import com.github.droidworksstudio.launcher.utils.Constants
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import okhttp3.*
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
class UpdateManagerHelper(private val fragment: Fragment) {
|
||||
private val sharedPreferences by lazy {
|
||||
fragment.requireContext().getSharedPreferences("update_prefs", Context.MODE_PRIVATE)
|
||||
}
|
||||
|
||||
private val context = fragment.requireContext()
|
||||
private val activity = fragment.requireActivity()
|
||||
|
||||
fun checkForUpdates() {
|
||||
val currentVersion = BuildConfig.VERSION_NAME
|
||||
val url = "https://api.github.com/repos/DroidWorksStudio/EasyLauncher/releases/latest"
|
||||
|
||||
val request = Request.Builder().url(url).build()
|
||||
OkHttpClient().newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
// Handle the error
|
||||
Log.e("UpdateManager", "Failed to check for updates", e)
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
if (response.isSuccessful) {
|
||||
val json = response.body()?.string()
|
||||
val jsonObject = JSONObject(json.toString())
|
||||
val tagName = jsonObject.getString("tag_name")
|
||||
val latestVersion = tagName.replace("v", "")
|
||||
val assets = jsonObject.getJSONArray("assets")
|
||||
val apkUrl = (assets.get(1) as JSONObject).getString("browser_download_url")
|
||||
|
||||
Log.d("UpdateManager", "Latest version: $latestVersion | Current version: $currentVersion")
|
||||
|
||||
if (latestVersion > currentVersion) {
|
||||
val declinedVersion = sharedPreferences.getString("declined_version", "")
|
||||
|
||||
Log.d("UpdateManager", "Declined version: $declinedVersion")
|
||||
|
||||
if (latestVersion != declinedVersion) {
|
||||
// Ask the user if they want to update
|
||||
activity.runOnUiThread {
|
||||
showUpdateDialog(latestVersion, apkUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
private fun showUpdateDialog(latestVersion: String, apkUrl: String) {
|
||||
MaterialAlertDialogBuilder(context).apply {
|
||||
setTitle("Update Available")
|
||||
setMessage("A new version of the app is available. Do you want to update?")
|
||||
setPositiveButton("Update") { _, _ ->
|
||||
downloadApk(apkUrl)
|
||||
}
|
||||
setNegativeButton("Later") { _, _ ->
|
||||
// Save the declined version
|
||||
with(sharedPreferences.edit()) {
|
||||
putString("declined_version", latestVersion)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
setCancelable(false)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
private fun downloadApk(apkUrl: String) {
|
||||
val request = DownloadManager.Request(Uri.parse(apkUrl)).apply {
|
||||
setTitle("Downloading update")
|
||||
setDescription("Your app is downloading the latest update")
|
||||
setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "${Constants.PACKAGE_NAME}.apk")
|
||||
}
|
||||
|
||||
val manager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
val downloadId = manager.enqueue(request)
|
||||
|
||||
// Register a BroadcastReceiver to listen for completion of the download
|
||||
val onComplete = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val action = intent.action
|
||||
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) {
|
||||
val query = DownloadManager.Query().setFilterById(downloadId)
|
||||
val cursor = manager.query(query)
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
val statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
|
||||
if (statusIndex != -1) {
|
||||
val status = cursor.getInt(statusIndex)
|
||||
if (status == DownloadManager.STATUS_SUCCESSFUL) {
|
||||
// Download completed successfully, now call installApk()
|
||||
requestInstallPermission()
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor?.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context.registerReceiver(onComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), Context.RECEIVER_NOT_EXPORTED)
|
||||
}
|
||||
|
||||
private fun requestInstallPermission() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!context.packageManager.canRequestPackageInstalls()) {
|
||||
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
|
||||
data = Uri.parse("package:${context.packageName}")
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
fragment.startActivityForResult(intent, Constants.REQUEST_INSTALL_PERMISSION)
|
||||
} else {
|
||||
// Permission already granted, proceed with installation
|
||||
installApk()
|
||||
}
|
||||
} else {
|
||||
// For devices below Android Oreo, installation permission is granted by default
|
||||
installApk()
|
||||
}
|
||||
}
|
||||
|
||||
private fun installApk() {
|
||||
val apkFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "${Constants.PACKAGE_NAME}.apk")
|
||||
val apkUri = FileProvider.getUriForFile(context.applicationContext, "${context.packageName}.provider", apkFile)
|
||||
|
||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
||||
setDataAndType(apkUri, "application/vnd.android.package-archive")
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == Constants.REQUEST_INSTALL_PERMISSION) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val canInstallPackages = context.packageManager.canRequestPackageInstalls()
|
||||
if (canInstallPackages) {
|
||||
// Permission granted, proceed with installation
|
||||
installApk()
|
||||
} else {
|
||||
// Permission still not granted, handle accordingly
|
||||
context.applicationContext.showLongToast("Please allow install permission to install.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,24 +2,17 @@ package com.github.droidworksstudio.launcher.ui.activities
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.DownloadManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.location.Location
|
||||
import android.location.LocationListener
|
||||
import android.location.LocationManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Settings
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||
@@ -29,7 +22,6 @@ import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.findNavController
|
||||
@@ -38,8 +30,6 @@ import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import com.github.droidworksstudio.common.hasInternetPermission
|
||||
import com.github.droidworksstudio.common.isTablet
|
||||
import com.github.droidworksstudio.common.showLongToast
|
||||
import com.github.droidworksstudio.launcher.BuildConfig
|
||||
import com.github.droidworksstudio.launcher.R
|
||||
import com.github.droidworksstudio.launcher.databinding.ActivityMainBinding
|
||||
import com.github.droidworksstudio.launcher.helper.AppHelper
|
||||
@@ -47,17 +37,8 @@ import com.github.droidworksstudio.launcher.helper.PreferenceHelper
|
||||
import com.github.droidworksstudio.launcher.utils.Constants
|
||||
import com.github.droidworksstudio.launcher.viewmodel.AppViewModel
|
||||
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.Call
|
||||
import okhttp3.Callback
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.json.JSONObject
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
@@ -130,7 +111,6 @@ class MainActivity : AppCompatActivity(), LocationListener {
|
||||
}
|
||||
handler.removeCallbacks(saveLocationRunnable)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@@ -282,7 +262,6 @@ class MainActivity : AppCompatActivity(), LocationListener {
|
||||
backToHomeScreen()
|
||||
if (applicationContext.hasInternetPermission()) {
|
||||
checkLocationPermission()
|
||||
checkForUpdates()
|
||||
}
|
||||
setupDataBase()
|
||||
observeUI()
|
||||
@@ -311,147 +290,4 @@ class MainActivity : AppCompatActivity(), LocationListener {
|
||||
if (navController.currentDestination?.id != R.id.HomeFragment)
|
||||
navController.navigate(R.id.HomeFragment)
|
||||
}
|
||||
|
||||
private fun checkForUpdates() {
|
||||
val currentVersion = BuildConfig.VERSION_NAME
|
||||
val url = "https://api.github.com/repos/DroidWorksStudio/EasyLauncher/releases/latest"
|
||||
|
||||
val request = Request.Builder().url(url).build()
|
||||
OkHttpClient().newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
// Handle the error
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
if (response.isSuccessful) {
|
||||
val json = response.body()?.string()
|
||||
val jsonObject = JSONObject(json.toString())
|
||||
val tagName = jsonObject.getString("tag_name")
|
||||
val latestVersion = tagName.replace("v", "")
|
||||
val assets = jsonObject.getJSONArray("assets")
|
||||
val apkUrl = (assets.get(1) as JSONObject).getString("browser_download_url")
|
||||
|
||||
if (latestVersion > currentVersion) {
|
||||
val sharedPreferences = getSharedPreferences("update_prefs", Context.MODE_PRIVATE)
|
||||
val declinedVersion = sharedPreferences.getString("declined_version", "")
|
||||
|
||||
if (latestVersion != declinedVersion) {
|
||||
// Ask the user if they want to update
|
||||
runOnUiThread {
|
||||
showUpdateDialog(latestVersion, apkUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
fun showUpdateDialog(latestVersion: String, apkUrl: String) {
|
||||
MaterialAlertDialogBuilder(this).apply {
|
||||
setTitle("Update Available")
|
||||
setMessage("A new version of the app is available. Do you want to update?")
|
||||
setPositiveButton("Update") { _, _ ->
|
||||
downloadApk(apkUrl)
|
||||
}
|
||||
setNegativeButton("Later") { _, _ ->
|
||||
// Save the declined version
|
||||
val sharedPreferences = getSharedPreferences("update_prefs", Context.MODE_PRIVATE)
|
||||
with(sharedPreferences.edit()) {
|
||||
putString("declined_version", latestVersion)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
setCancelable(false)
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private fun downloadApk(apkUrl: String) {
|
||||
val request = DownloadManager.Request(Uri.parse(apkUrl)).apply {
|
||||
setTitle("Downloading update")
|
||||
setDescription("Your app is downloading the latest update")
|
||||
setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "${Constants.PACKAGE_NAME}.apk")
|
||||
}
|
||||
|
||||
val manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
val downloadId = manager.enqueue(request)
|
||||
|
||||
// Register a BroadcastReceiver to listen for completion of the download
|
||||
val onComplete = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val action = intent.action
|
||||
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE == action) {
|
||||
val query = DownloadManager.Query().setFilterById(downloadId)
|
||||
val cursor = manager.query(query)
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
val statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
|
||||
if (statusIndex != -1) {
|
||||
val status = cursor.getInt(statusIndex)
|
||||
if (status == DownloadManager.STATUS_SUCCESSFUL) {
|
||||
// Download completed successfully, now call installApk()
|
||||
requestInstallPermission()
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor?.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerReceiver(onComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), RECEIVER_EXPORTED)
|
||||
}
|
||||
|
||||
private fun requestInstallPermission() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (!packageManager.canRequestPackageInstalls()) {
|
||||
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
|
||||
data = Uri.parse("package:$packageName")
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
startActivityForResult(intent, Constants.REQUEST_INSTALL_PERMISSION)
|
||||
return
|
||||
} else {
|
||||
// Permission already granted, proceed with installation
|
||||
installApk()
|
||||
}
|
||||
} else {
|
||||
// For devices below Android Oreo, installation permission is granted by default
|
||||
installApk()
|
||||
}
|
||||
}
|
||||
|
||||
private fun installApk() {
|
||||
val apkFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "${Constants.PACKAGE_NAME}.apk")
|
||||
val apkUri = FileProvider.getUriForFile(applicationContext, "$packageName.provider", apkFile)
|
||||
|
||||
val intent = Intent(Intent.ACTION_VIEW).apply {
|
||||
setDataAndType(apkUri, "application/vnd.android.package-archive")
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == Constants.REQUEST_INSTALL_PERMISSION) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val canInstallPackages = packageManager.canRequestPackageInstalls()
|
||||
if (canInstallPackages) {
|
||||
// Permission granted, proceed with installation
|
||||
installApk()
|
||||
} else {
|
||||
// Permission still not granted, handle accordingly
|
||||
applicationContext.showLongToast("Please allow install permission to install.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import com.github.droidworksstudio.launcher.databinding.FragmentHomeBinding
|
||||
import com.github.droidworksstudio.launcher.helper.AppHelper
|
||||
import com.github.droidworksstudio.launcher.helper.FingerprintHelper
|
||||
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
|
||||
import com.github.droidworksstudio.launcher.helper.UpdateManagerHelper
|
||||
import com.github.droidworksstudio.launcher.listener.OnItemClickedListener
|
||||
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
|
||||
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
|
||||
@@ -73,6 +74,7 @@ class HomeFragment : Fragment(),
|
||||
@Inject
|
||||
lateinit var appHelper: AppHelper
|
||||
|
||||
|
||||
@Inject
|
||||
lateinit var fingerHelper: FingerprintHelper
|
||||
|
||||
@@ -83,6 +85,7 @@ class HomeFragment : Fragment(),
|
||||
|
||||
private lateinit var batteryReceiver: BroadcastReceiver
|
||||
private lateinit var biometricPrompt: BiometricPrompt
|
||||
private lateinit var updateManager: UpdateManagerHelper
|
||||
|
||||
private lateinit var context: Context
|
||||
|
||||
@@ -106,6 +109,9 @@ class HomeFragment : Fragment(),
|
||||
setupRecyclerView()
|
||||
observeSwipeTouchListener()
|
||||
observeUserInterfaceSettings()
|
||||
|
||||
updateManager = UpdateManagerHelper(this)
|
||||
updateManager.checkForUpdates()
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@@ -479,6 +485,8 @@ class HomeFragment : Fragment(),
|
||||
binding.nestScrollView.hideKeyboard()
|
||||
observeUserInterfaceSettings()
|
||||
observeFavoriteAppList()
|
||||
|
||||
updateManager.checkForUpdates()
|
||||
}
|
||||
|
||||
override fun onAppClicked(appInfo: AppInfo) {
|
||||
|
||||
Reference in New Issue
Block a user