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