diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 44a9db690..e0ebe4a6b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -277,8 +277,12 @@
+ android:exported="false" />
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/github/libretube/Globals.kt b/app/src/main/java/com/github/libretube/Globals.kt
index 6c8e4b871..3dac425a9 100644
--- a/app/src/main/java/com/github/libretube/Globals.kt
+++ b/app/src/main/java/com/github/libretube/Globals.kt
@@ -5,9 +5,12 @@ package com.github.libretube
*/
object Globals {
// for the player fragment
- var isFullScreen = false
- var isMiniPlayerVisible = false
+ var IS_FULL_SCREEN = false
+ var MINI_PLAYER_VISIBLE = false
// for the data saver mode
- var dataSaverModeEnabled = false
+ var DATA_SAVER_MODE_ENABLED = false
+
+ // for downloads
+ var IS_DOWNLOAD_RUNNING = false
}
diff --git a/app/src/main/java/com/github/libretube/MyApp.kt b/app/src/main/java/com/github/libretube/MyApp.kt
index c2bcc9c57..1baa1f2dc 100644
--- a/app/src/main/java/com/github/libretube/MyApp.kt
+++ b/app/src/main/java/com/github/libretube/MyApp.kt
@@ -4,6 +4,8 @@ import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.os.Build
+import android.os.StrictMode
+import android.os.StrictMode.VmPolicy
import com.github.libretube.preferences.PreferenceHelper
class MyApp : Application() {
@@ -19,6 +21,12 @@ class MyApp : Application() {
* set the applicationContext as context for the [PreferenceHelper]
*/
PreferenceHelper.setContext(applicationContext)
+
+ /**
+ * bypassing fileUriExposedException, see https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed
+ */
+ val builder = VmPolicy.Builder()
+ StrictMode.setVmPolicy(builder.build())
}
/**
diff --git a/app/src/main/java/com/github/libretube/activities/MainActivity.kt b/app/src/main/java/com/github/libretube/activities/MainActivity.kt
index 37a642a51..fb989dd3a 100644
--- a/app/src/main/java/com/github/libretube/activities/MainActivity.kt
+++ b/app/src/main/java/com/github/libretube/activities/MainActivity.kt
@@ -76,7 +76,7 @@ class MainActivity : AppCompatActivity() {
}
// save whether the data saver mode is enabled
- Globals.dataSaverModeEnabled = PreferenceHelper.getBoolean(
+ Globals.DATA_SAVER_MODE_ENABLED = PreferenceHelper.getBoolean(
PreferenceKeys.DATA_SAVER_MODE,
false
)
@@ -320,7 +320,7 @@ class MainActivity : AppCompatActivity() {
enableTransition(R.id.yt_transition, true)
}
findViewById(R.id.linLayout).visibility = View.VISIBLE
- Globals.isFullScreen = false
+ Globals.IS_FULL_SCREEN = false
}
override fun onConfigurationChanged(newConfig: Configuration) {
diff --git a/app/src/main/java/com/github/libretube/dialogs/DownloadDialog.kt b/app/src/main/java/com/github/libretube/dialogs/DownloadDialog.kt
index 771bd2c8e..60afa6c48 100644
--- a/app/src/main/java/com/github/libretube/dialogs/DownloadDialog.kt
+++ b/app/src/main/java/com/github/libretube/dialogs/DownloadDialog.kt
@@ -1,24 +1,20 @@
package com.github.libretube.dialogs
-import android.Manifest
import android.app.Dialog
import android.content.Intent
-import android.content.pm.PackageManager
-import android.os.Build
import android.os.Bundle
-import android.os.Environment
import android.util.Log
import android.widget.ArrayAdapter
import android.widget.Toast
-import androidx.core.app.ActivityCompat
+import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.size
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import com.github.libretube.R
-import com.github.libretube.activities.MainActivity
import com.github.libretube.databinding.DialogDownloadBinding
import com.github.libretube.obj.Streams
import com.github.libretube.services.DownloadService
+import com.github.libretube.util.PermissionHelper
import com.github.libretube.util.RetrofitInstance
import com.github.libretube.util.ThemeHelper
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@@ -36,45 +32,12 @@ class DownloadDialog : DialogFragment() {
return activity?.let {
videoId = arguments?.getString("video_id")!!
- val mainActivity = activity as MainActivity
val builder = MaterialAlertDialogBuilder(it)
binding = DialogDownloadBinding.inflate(layoutInflater)
fetchAvailableSources()
- // request storage permissions if not granted yet
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- Log.d("myz", "" + Build.VERSION.SDK_INT)
- if (!Environment.isExternalStorageManager()) {
- ActivityCompat.requestPermissions(
- mainActivity,
- arrayOf(
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.MANAGE_EXTERNAL_STORAGE
- ),
- 1
- ) // permission request code is just an int
- }
- } else {
- if (ActivityCompat.checkSelfPermission(
- requireContext(),
- Manifest.permission.READ_EXTERNAL_STORAGE
- ) != PackageManager.PERMISSION_GRANTED ||
- ActivityCompat.checkSelfPermission(
- requireContext(),
- Manifest.permission.WRITE_EXTERNAL_STORAGE
- ) != PackageManager.PERMISSION_GRANTED
- ) {
- ActivityCompat.requestPermissions(
- mainActivity,
- arrayOf(
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.WRITE_EXTERNAL_STORAGE
- ),
- 1
- )
- }
- }
+ PermissionHelper.requestReadWrite(activity as AppCompatActivity)
binding.title.text = ThemeHelper.getStyledAppName(requireContext())
diff --git a/app/src/main/java/com/github/libretube/dialogs/UpdateDialog.kt b/app/src/main/java/com/github/libretube/dialogs/UpdateDialog.kt
index 7b35766c3..48f102639 100644
--- a/app/src/main/java/com/github/libretube/dialogs/UpdateDialog.kt
+++ b/app/src/main/java/com/github/libretube/dialogs/UpdateDialog.kt
@@ -3,43 +3,51 @@ package com.github.libretube.dialogs
import android.app.Dialog
import android.content.Intent
import android.net.Uri
+import android.os.Build
import android.os.Bundle
+import android.util.Log
import androidx.fragment.app.DialogFragment
import com.github.libretube.R
+import com.github.libretube.services.UpdateService
+import com.github.libretube.update.UpdateInfo
import com.google.android.material.dialog.MaterialAlertDialogBuilder
-class UpdateAvailableDialog(
- private val versionTag: String,
- private val updateLink: String
+class UpdateDialog(
+ private val updateInfo: UpdateInfo
) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
MaterialAlertDialogBuilder(requireContext())
- .setTitle(context?.getString(R.string.update_available, versionTag))
- .setMessage(context?.getString(R.string.update_available_text))
+ .setTitle(context?.getString(R.string.update_available, updateInfo.name))
+ .setMessage(context?.getString(R.string.update_now))
.setNegativeButton(context?.getString(R.string.cancel)) { _, _ ->
dismiss()
}
.setPositiveButton(context?.getString(R.string.okay)) { _, _ ->
- val uri = Uri.parse(updateLink)
- val intent = Intent(Intent.ACTION_VIEW).setData(uri)
- startActivity(intent)
+ val downloadUrl = getDownloadUrl(updateInfo)
+ Log.i("downloadUrl", downloadUrl.toString())
+ if (downloadUrl != null) {
+ val intent = Intent(context, UpdateService::class.java)
+ intent.putExtra("downloadUrl", downloadUrl)
+ context?.startService(intent)
+ } else {
+ val uri = Uri.parse(updateInfo.html_url)
+ val intent = Intent(Intent.ACTION_VIEW).setData(uri)
+ startActivity(intent)
+ }
}
.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
-}
-class NoUpdateAvailableDialog : DialogFragment() {
-
- override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- return activity?.let {
- MaterialAlertDialogBuilder(requireContext())
- .setTitle(context?.getString(R.string.app_uptodate))
- .setMessage(context?.getString(R.string.no_update_available))
- .setPositiveButton(context?.getString(R.string.okay)) { _, _ -> }
- .create()
- } ?: throw IllegalStateException("Activity cannot be null")
+ private fun getDownloadUrl(updateInfo: UpdateInfo): String? {
+ val supportedArchitectures = Build.SUPPORTED_ABIS
+ supportedArchitectures.forEach { arch ->
+ updateInfo.assets.forEach {
+ if (it.browser_download_url.contains(arch)) return it.browser_download_url
+ }
+ }
+ return null
}
}
diff --git a/app/src/main/java/com/github/libretube/fragments/LibraryFragment.kt b/app/src/main/java/com/github/libretube/fragments/LibraryFragment.kt
index 296922a52..67b348a2a 100644
--- a/app/src/main/java/com/github/libretube/fragments/LibraryFragment.kt
+++ b/app/src/main/java/com/github/libretube/fragments/LibraryFragment.kt
@@ -79,7 +79,7 @@ class LibraryFragment : Fragment() {
override fun onResume() {
// optimize CreatePlaylistFab bottom margin if miniPlayer active
val layoutParams = binding.createPlaylist.layoutParams as ViewGroup.MarginLayoutParams
- layoutParams.bottomMargin = if (Globals.isMiniPlayerVisible) 180 else 64
+ layoutParams.bottomMargin = if (Globals.MINI_PLAYER_VISIBLE) 180 else 64
binding.createPlaylist.layoutParams = layoutParams
super.onResume()
}
diff --git a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt
index 376cf6393..8736460df 100644
--- a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt
+++ b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt
@@ -358,11 +358,11 @@ class PlayerFragment : Fragment() {
val mainMotionLayout =
mainActivity.binding.mainMotionLayout
if (currentId == eId) {
- Globals.isMiniPlayerVisible = true
+ Globals.MINI_PLAYER_VISIBLE = true
exoPlayerView.useController = false
mainMotionLayout.progress = 1F
} else if (currentId == sId) {
- Globals.isMiniPlayerVisible = false
+ Globals.MINI_PLAYER_VISIBLE = false
exoPlayerView.useController = true
mainMotionLayout.progress = 0F
}
@@ -384,7 +384,7 @@ class PlayerFragment : Fragment() {
// actions that don't depend on video information
private fun initializeOnClickActions() {
binding.closeImageView.setOnClickListener {
- Globals.isMiniPlayerVisible = false
+ Globals.MINI_PLAYER_VISIBLE = false
binding.playerMotionLayout.transitionToEnd()
val mainActivity = activity as MainActivity
mainActivity.supportFragmentManager.beginTransaction()
@@ -392,7 +392,7 @@ class PlayerFragment : Fragment() {
.commit()
}
playerBinding.closeImageButton.setOnClickListener {
- Globals.isMiniPlayerVisible = false
+ Globals.MINI_PLAYER_VISIBLE = false
binding.playerMotionLayout.transitionToEnd()
val mainActivity = activity as MainActivity
mainActivity.supportFragmentManager.beginTransaction()
@@ -436,7 +436,7 @@ class PlayerFragment : Fragment() {
playerBinding.fullscreen.setOnClickListener {
// hide player controller
exoPlayerView.hideController()
- if (!Globals.isFullScreen) {
+ if (!Globals.IS_FULL_SCREEN) {
// go to fullscreen mode
setFullscreen()
} else {
@@ -578,7 +578,7 @@ class PlayerFragment : Fragment() {
mainActivity.requestedOrientation = orientation
}
- Globals.isFullScreen = true
+ Globals.IS_FULL_SCREEN = true
}
private fun unsetFullscreen() {
@@ -602,7 +602,7 @@ class PlayerFragment : Fragment() {
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
}
- Globals.isFullScreen = false
+ Globals.IS_FULL_SCREEN = false
}
private fun scaleControls(scaleFactor: Float) {
@@ -983,7 +983,7 @@ class PlayerFragment : Fragment() {
if (response.duration!! > 0) {
// download clicked
binding.relPlayerDownload.setOnClickListener {
- if (!IS_DOWNLOAD_RUNNING) {
+ if (!Globals.IS_DOWNLOAD_RUNNING) {
val newFragment = DownloadDialog()
val bundle = Bundle()
bundle.putString("video_id", videoId)
@@ -1214,7 +1214,7 @@ class PlayerFragment : Fragment() {
}
playerBinding.chapterLL.visibility = View.VISIBLE
playerBinding.chapterLL.setOnClickListener {
- if (Globals.isFullScreen) {
+ if (Globals.IS_FULL_SCREEN) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.chapters)
.setItems(titles.toTypedArray()) { _, index ->
@@ -1505,13 +1505,13 @@ class PlayerFragment : Fragment() {
playerBinding.closeImageButton.visibility = visibility
playerBinding.exoTitle.visibility =
if (isLocked &&
- Globals.isFullScreen
+ Globals.IS_FULL_SCREEN
) View.VISIBLE else View.INVISIBLE
// hide the close image button
playerBinding.closeImageButton.visibility =
if (isLocked &&
- !(Globals.isFullScreen && !autoRotationEnabled)
+ !(Globals.IS_FULL_SCREEN && !autoRotationEnabled)
) View.VISIBLE else View.GONE
// disable double tap to seek when the player is locked
@@ -1674,7 +1674,7 @@ class PlayerFragment : Fragment() {
}
binding.linLayout.visibility = View.GONE
- Globals.isFullScreen = false
+ Globals.IS_FULL_SCREEN = false
} else {
// enable exoPlayer controls again
exoPlayerView.useController = true
@@ -1692,7 +1692,7 @@ class PlayerFragment : Fragment() {
binding.playerScrollView.getHitRect(bounds)
if (SDK_INT >= Build.VERSION_CODES.O &&
- (binding.playerScrollView.getLocalVisibleRect(bounds) || Globals.isFullScreen)
+ (binding.playerScrollView.getLocalVisibleRect(bounds) || Globals.IS_FULL_SCREEN)
) {
activity?.enterPictureInPictureMode(updatePipParams())
}
diff --git a/app/src/main/java/com/github/libretube/obj/VersionInfo.kt b/app/src/main/java/com/github/libretube/obj/VersionInfo.kt
deleted file mode 100644
index e52d7ef79..000000000
--- a/app/src/main/java/com/github/libretube/obj/VersionInfo.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.github.libretube.obj
-
-// data class for the update info, required to return the data
-data class VersionInfo(
- val updateUrl: String,
- val tagName: String
-)
diff --git a/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt b/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt
index 968442743..0b7799539 100644
--- a/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt
+++ b/app/src/main/java/com/github/libretube/preferences/InstanceSettings.kt
@@ -1,18 +1,14 @@
package com.github.libretube.preferences
-import android.Manifest
import android.content.ContentResolver
import android.content.Intent
-import android.content.pm.PackageManager
import android.net.Uri
-import android.os.Build
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
-import androidx.core.app.ActivityCompat
-import androidx.core.content.ContextCompat
+import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.preference.ListPreference
@@ -26,6 +22,7 @@ import com.github.libretube.dialogs.DeleteAccountDialog
import com.github.libretube.dialogs.LoginDialog
import com.github.libretube.dialogs.LogoutDialog
import com.github.libretube.dialogs.RequireRestartDialog
+import com.github.libretube.util.PermissionHelper
import com.github.libretube.util.RetrofitInstance
import org.json.JSONObject
import org.json.JSONTokener
@@ -288,51 +285,7 @@ class InstanceSettings : PreferenceFragmentCompat() {
private fun importSubscriptions() {
val token = PreferenceHelper.getToken()
// check StorageAccess
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- Log.d("myz", "" + Build.VERSION.SDK_INT)
- if (ContextCompat.checkSelfPermission(
- this.requireContext(),
- Manifest.permission.READ_EXTERNAL_STORAGE
- )
- != PackageManager.PERMISSION_GRANTED
- ) {
- ActivityCompat.requestPermissions(
- this.requireActivity(),
- arrayOf(
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.MANAGE_EXTERNAL_STORAGE
- ),
- 1
- ) // permission request code is just an int
- } else if (token != "") {
- MainSettings.getContent.launch("*/*")
- } else {
- Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
- }
- } else {
- if (ActivityCompat.checkSelfPermission(
- requireContext(),
- Manifest.permission.READ_EXTERNAL_STORAGE
- ) != PackageManager.PERMISSION_GRANTED ||
- ActivityCompat.checkSelfPermission(
- requireContext(),
- Manifest.permission.WRITE_EXTERNAL_STORAGE
- ) != PackageManager.PERMISSION_GRANTED
- ) {
- ActivityCompat.requestPermissions(
- this.requireActivity(),
- arrayOf(
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.WRITE_EXTERNAL_STORAGE
- ),
- 1
- )
- } else if (token != "") {
- MainSettings.getContent.launch("*/*")
- } else {
- Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
- }
- }
+ PermissionHelper.requestReadWrite(activity as AppCompatActivity)
}
private fun subscribe(channels: List) {
diff --git a/app/src/main/java/com/github/libretube/preferences/MainSettings.kt b/app/src/main/java/com/github/libretube/preferences/MainSettings.kt
index 2006db60d..00c565816 100644
--- a/app/src/main/java/com/github/libretube/preferences/MainSettings.kt
+++ b/app/src/main/java/com/github/libretube/preferences/MainSettings.kt
@@ -10,9 +10,9 @@ import com.github.libretube.BuildConfig
import com.github.libretube.R
import com.github.libretube.activities.SettingsActivity
import com.github.libretube.dialogs.RequireRestartDialog
-import com.github.libretube.dialogs.UpdateAvailableDialog
+import com.github.libretube.dialogs.UpdateDialog
+import com.github.libretube.update.UpdateChecker
import com.github.libretube.util.ThemeHelper
-import com.github.libretube.util.checkUpdate
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -93,13 +93,10 @@ class MainSettings : PreferenceFragmentCompat() {
update?.setOnPreferenceClickListener {
CoroutineScope(Dispatchers.IO).launch {
// check for update
- val versionInfo = checkUpdate()
- if (versionInfo?.tagName != "" && BuildConfig.VERSION_NAME != versionInfo?.tagName) {
+ val updateInfo = UpdateChecker.checkUpdate()
+ if (updateInfo?.name != "" && BuildConfig.VERSION_NAME != updateInfo?.name) {
// show the UpdateAvailableDialog if there's an update available
- val updateAvailableDialog = UpdateAvailableDialog(
- versionInfo!!.tagName,
- versionInfo.updateUrl
- )
+ val updateAvailableDialog = UpdateDialog(updateInfo!!)
updateAvailableDialog.show(childFragmentManager, "UpdateAvailableDialog")
} else {
// otherwise show the no update available snackBar
diff --git a/app/src/main/java/com/github/libretube/services/DownloadService.kt b/app/src/main/java/com/github/libretube/services/DownloadService.kt
index f01a9a903..a34955453 100644
--- a/app/src/main/java/com/github/libretube/services/DownloadService.kt
+++ b/app/src/main/java/com/github/libretube/services/DownloadService.kt
@@ -18,14 +18,13 @@ import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.arthenica.ffmpegkit.FFmpegKit
+import com.github.libretube.Globals
import com.github.libretube.R
import com.github.libretube.obj.DownloadType
import com.github.libretube.preferences.PreferenceHelper
import com.github.libretube.preferences.PreferenceKeys
import java.io.File
-var IS_DOWNLOAD_RUNNING = false
-
class DownloadService : Service() {
val TAG = "DownloadService"
@@ -45,7 +44,7 @@ class DownloadService : Service() {
private lateinit var tempDir: File
override fun onCreate() {
super.onCreate()
- IS_DOWNLOAD_RUNNING = true
+ Globals.IS_DOWNLOAD_RUNNING = true
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
@@ -164,7 +163,10 @@ class DownloadService : Service() {
onDestroy()
}
} else {
- muxDownloadedMedia()
+ try {
+ muxDownloadedMedia()
+ } catch (e: Exception) {
+ }
}
}
}
@@ -280,7 +282,7 @@ class DownloadService : Service() {
} catch (e: Exception) {
}
- IS_DOWNLOAD_RUNNING = false
+ Globals.IS_DOWNLOAD_RUNNING = false
Log.d(TAG, "dl finished!")
stopForeground(true)
stopService(Intent(this@DownloadService, DownloadService::class.java))
diff --git a/app/src/main/java/com/github/libretube/services/UpdateService.kt b/app/src/main/java/com/github/libretube/services/UpdateService.kt
new file mode 100644
index 000000000..3e161074e
--- /dev/null
+++ b/app/src/main/java/com/github/libretube/services/UpdateService.kt
@@ -0,0 +1,79 @@
+package com.github.libretube.services
+
+import android.app.DownloadManager
+import android.app.Service
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.net.Uri
+import android.os.Environment
+import android.os.IBinder
+import java.io.File
+
+class UpdateService : Service() {
+ private val TAG = "UpdateService"
+ private lateinit var downloadUrl: String
+ private var downloadId: Long = -1
+ private lateinit var file: File
+ private lateinit var downloadManager: DownloadManager
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ downloadUrl = intent?.getStringExtra("downloadUrl")!!
+
+ downloadApk(downloadUrl)
+
+ return super.onStartCommand(intent, flags, startId)
+ }
+
+ private fun downloadApk(downloadUrl: String) {
+ val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
+ // val dir = applicationContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
+ file = File(dir, "release.apk")
+
+ val request: DownloadManager.Request =
+ DownloadManager.Request(Uri.parse(downloadUrl))
+ .setTitle("Downloading APK ...")
+ .setDescription("")
+ .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
+ .setDestinationUri(Uri.fromFile(file))
+ .setAllowedOverMetered(true)
+ .setAllowedOverRoaming(true)
+
+ downloadManager =
+ applicationContext.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
+
+ downloadId = downloadManager.enqueue(request)
+
+ // listener for the download to end
+ registerReceiver(
+ onDownloadComplete,
+ IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
+ )
+ }
+
+ private val onDownloadComplete: BroadcastReceiver = object : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
+ if (downloadId == id) {
+ // install the apk after download finished
+ val installIntent = Intent(Intent.ACTION_VIEW)
+ installIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ installIntent.setDataAndType(
+ Uri.fromFile(file),
+ downloadManager.getMimeTypeForDownloadedFile(downloadId)
+ )
+ startActivity(installIntent)
+ }
+ }
+ }
+
+ override fun onDestroy() {
+ unregisterReceiver(onDownloadComplete)
+ super.onDestroy()
+ }
+
+ override fun onBind(p0: Intent?): IBinder? {
+ TODO("Not yet implemented")
+ }
+}
diff --git a/app/src/main/java/com/github/libretube/update/UpdateChecker.kt b/app/src/main/java/com/github/libretube/update/UpdateChecker.kt
new file mode 100644
index 000000000..5a2b8d86b
--- /dev/null
+++ b/app/src/main/java/com/github/libretube/update/UpdateChecker.kt
@@ -0,0 +1,44 @@
+package com.github.libretube.update
+
+import com.github.libretube.GITHUB_API_URL
+import com.google.gson.Gson
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.net.URL
+import javax.net.ssl.HttpsURLConnection
+
+object UpdateChecker {
+ fun checkUpdate(): UpdateInfo? {
+ var versionInfo: UpdateInfo? = null
+ // run http request as thread to make it async
+ val thread = Thread {
+ // otherwise crashes without internet
+ try {
+ versionInfo = getUpdateInfo()
+ } catch (e: Exception) {
+ }
+ }
+ thread.start()
+ // wait for the thread to finish
+ thread.join()
+
+ // return the information about the latest version
+ return versionInfo
+ }
+
+ fun getUpdateInfo(): UpdateInfo? {
+ val latest = URL(GITHUB_API_URL)
+ val json = StringBuilder()
+ val urlConnection: HttpsURLConnection?
+ urlConnection = latest.openConnection() as HttpsURLConnection
+
+ // read json
+ val br = BufferedReader(InputStreamReader(urlConnection.inputStream))
+ var line: String?
+ while (br.readLine().also { line = it } != null) json.append(line)
+
+ // Parse and return the json data
+ val gson = Gson()
+ return gson.fromJson(json.toString(), UpdateInfo::class.java)
+ }
+}
diff --git a/app/src/main/java/com/github/libretube/util/ConnectionHelper.kt b/app/src/main/java/com/github/libretube/util/ConnectionHelper.kt
index e248e3d92..a1056f9d5 100644
--- a/app/src/main/java/com/github/libretube/util/ConnectionHelper.kt
+++ b/app/src/main/java/com/github/libretube/util/ConnectionHelper.kt
@@ -40,7 +40,7 @@ object ConnectionHelper {
// load an image from a url into an imageView
fun loadImage(url: String?, target: ImageView) {
// only load the image if the data saver mode is disabled
- if (!Globals.dataSaverModeEnabled) {
+ if (!Globals.DATA_SAVER_MODE_ENABLED) {
Picasso.get().load(url).fit().centerCrop().into(target)
}
}
diff --git a/app/src/main/java/com/github/libretube/util/PermissionHelper.kt b/app/src/main/java/com/github/libretube/util/PermissionHelper.kt
new file mode 100644
index 000000000..6e68f270e
--- /dev/null
+++ b/app/src/main/java/com/github/libretube/util/PermissionHelper.kt
@@ -0,0 +1,47 @@
+package com.github.libretube.util
+
+import android.Manifest
+import android.content.pm.PackageManager
+import android.os.Build
+import android.os.Environment
+import android.util.Log
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
+
+object PermissionHelper {
+ fun requestReadWrite(activity: AppCompatActivity) {
+ // request storage permissions if not granted yet
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ Log.d("myz", "" + Build.VERSION.SDK_INT)
+ if (!Environment.isExternalStorageManager()) {
+ ActivityCompat.requestPermissions(
+ activity,
+ arrayOf(
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission.MANAGE_EXTERNAL_STORAGE
+ ),
+ 1
+ ) // permission request code is just an int
+ }
+ } else {
+ if (ActivityCompat.checkSelfPermission(
+ activity,
+ Manifest.permission.READ_EXTERNAL_STORAGE
+ ) != PackageManager.PERMISSION_GRANTED ||
+ ActivityCompat.checkSelfPermission(
+ activity,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ ActivityCompat.requestPermissions(
+ activity,
+ arrayOf(
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
+ ),
+ 1
+ )
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/github/libretube/util/UpdateChecker.kt b/app/src/main/java/com/github/libretube/util/UpdateChecker.kt
deleted file mode 100644
index 1620f0a6b..000000000
--- a/app/src/main/java/com/github/libretube/util/UpdateChecker.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.github.libretube.util
-
-import com.github.libretube.GITHUB_API_URL
-import com.github.libretube.obj.VersionInfo
-import com.github.libretube.update.UpdateInfo
-import com.google.gson.Gson
-import java.io.BufferedReader
-import java.io.InputStreamReader
-import java.net.URL
-import javax.net.ssl.HttpsURLConnection
-
-fun checkUpdate(): VersionInfo? {
- var versionInfo: VersionInfo? = null
- // run http request as thread to make it async
- val thread = Thread {
- // otherwise crashes without internet
- try {
- versionInfo = getUpdateInfo()
- } catch (e: Exception) {
- }
- }
- thread.start()
- // wait for the thread to finish
- thread.join()
-
- // return the information about the latest version
- return versionInfo
-}
-
-fun getUpdateInfo(): VersionInfo? {
- val latest = URL(GITHUB_API_URL)
- val json = StringBuilder()
- val urlConnection: HttpsURLConnection?
- urlConnection = latest.openConnection() as HttpsURLConnection
- val br = BufferedReader(InputStreamReader(urlConnection.inputStream))
-
- var line: String?
- while (br.readLine().also { line = it } != null) json.append(line)
-
- // Parse and return the json data
- val gson = Gson()
- val updateInfo = gson.fromJson(json.toString(), UpdateInfo::class.java)
-
- return VersionInfo(
- updateInfo.html_url,
- updateInfo.name
- )
-}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 39684473a..2e780a185 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -252,4 +252,5 @@
System caption style
Captions
None
+ Do you want to update the app now?
\ No newline at end of file