player stuff

This commit is contained in:
LagradOst 2021-06-11 01:00:22 +02:00
parent 47e3876e4a
commit a102d5f66d
15 changed files with 338 additions and 38 deletions

View file

@ -1,26 +1,29 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lagradost.cloudstream3"> xmlns:tools="http://schemas.android.com/tools" package="com.lagradost.cloudstream3">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<application <application
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:usesCleartextTraffic="true"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme" android:fullBackupContent="@xml/backup_descriptor">
<meta-data <meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME" android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.lagradost.cloudstream3.utils.CastOptionsProvider"/> android:value="com.lagradost.cloudstream3.utils.CastOptionsProvider"/>
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden|navigation"
android:label="@string/app_name"> android:label="@string/app_name"
android:resizeableActivity="true"
android:supportsPictureInPicture="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
@ -41,5 +44,4 @@
android:resource="@xml/provider_paths"/> android:resource="@xml/provider_paths"/>
</provider> </provider>
</application> </application>
</manifest> </manifest>

View file

@ -1,17 +1,24 @@
package com.lagradost.cloudstream3 package com.lagradost.cloudstream3
import android.app.PictureInPictureParams
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.lifecycle.ViewModelStore import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner import androidx.lifecycle.ViewModelStoreOwner
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.lagradost.cloudstream3.UIHelper.checkWrite import com.lagradost.cloudstream3.UIHelper.checkWrite
import com.lagradost.cloudstream3.UIHelper.hasPIPPermission
import com.lagradost.cloudstream3.UIHelper.requestRW import com.lagradost.cloudstream3.UIHelper.requestRW
import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode
class MainActivity : AppCompatActivity() {/*, ViewModelStoreOwner { class MainActivity : AppCompatActivity() {
/*, ViewModelStoreOwner {
private val appViewModelStore: ViewModelStore by lazy { private val appViewModelStore: ViewModelStore by lazy {
ViewModelStore() ViewModelStore()
} }
@ -19,6 +26,33 @@ class MainActivity : AppCompatActivity() {/*, ViewModelStoreOwner {
override fun getViewModelStore(): ViewModelStore { override fun getViewModelStore(): ViewModelStore {
return appViewModelStore return appViewModelStore
}*/ }*/
companion object {
var isInPlayer: Boolean = false
var canShowPipMode: Boolean = false
var isInPIPMode: Boolean = false
}
private fun enterPIPMode() {
if (!shouldShowPIPMode(isInPlayer) || !canShowPipMode) return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
enterPictureInPictureMode(PictureInPictureParams.Builder().build())
} catch (e: Exception) {
enterPictureInPictureMode()
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
enterPictureInPictureMode()
}
}
}
override fun onUserLeaveHint() {
super.onUserLeaveHint()
if (isInPlayer && canShowPipMode) {
enterPIPMode()
}
}
private fun AppCompatActivity.backPressed(): Boolean { private fun AppCompatActivity.backPressed(): Boolean {
val currentFragment = supportFragmentManager.fragments.last { val currentFragment = supportFragmentManager.fragments.last {
@ -46,6 +80,13 @@ class MainActivity : AppCompatActivity() {/*, ViewModelStoreOwner {
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view) val navView: BottomNavigationView = findViewById(R.id.nav_view)
//https://stackoverflow.com/questions/52594181/how-to-know-if-user-has-disabled-picture-in-picture-feature-permission
//https://developer.android.com/guide/topics/ui/picture-in-picture
canShowPipMode =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && // OS SUPPORT
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) && // HAS FEATURE, MIGHT BE BLOCKED DUE TO POWER DRAIN
hasPIPPermission() // CHECK IF FEATURE IS ENABLED IN SETTINGS
val navController = findNavController(R.id.nav_host_fragment) val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each // Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations. // menu should be considered as top level destinations.

View file

@ -2,6 +2,7 @@ package com.lagradost.cloudstream3
import android.Manifest import android.Manifest
import android.app.Activity import android.app.Activity
import android.app.AppOpsManager
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Resources import android.content.res.Resources
@ -11,6 +12,7 @@ import android.media.AudioManager
import android.os.Build import android.os.Build
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -19,6 +21,7 @@ import androidx.preference.PreferenceManager
import com.google.android.gms.cast.framework.CastContext import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.common.ConnectionResult import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability import com.google.android.gms.common.GoogleApiAvailability
import com.lagradost.cloudstream3.UIHelper.getGridFormat
import com.lagradost.cloudstream3.ui.result.ResultFragment import com.lagradost.cloudstream3.ui.result.ResultFragment
import com.lagradost.cloudstream3.utils.Event import com.lagradost.cloudstream3.utils.Event
@ -261,4 +264,24 @@ object UIHelper {
) // or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION ) // or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
// window.clearFlags(View.KEEP_SCREEN_ON) // window.clearFlags(View.KEEP_SCREEN_ON)
} }
fun Context.shouldShowPIPMode(isInPlayer: Boolean): Boolean {
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
return settingsManager?.getBoolean("pip_enabled", true) ?: true && isInPlayer
}
fun Context.hasPIPPermission(): Boolean {
val appOps =
getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
return appOps.checkOpNoThrow(
AppOpsManager.OPSTR_PICTURE_IN_PICTURE,
android.os.Process.myUid(),
packageName
) == AppOpsManager.MODE_ALLOWED
}
fun Context.hideKeyboard(view: View) {
val inputMethodManager = getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
}
} }

View file

@ -3,22 +3,28 @@ package com.lagradost.cloudstream3.ui.player
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.app.PendingIntent
import android.app.PictureInPictureParams
import android.app.RemoteAction
import android.content.*
import android.content.Context.AUDIO_SERVICE import android.content.Context.AUDIO_SERVICE
import android.content.SharedPreferences
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.res.Resources import android.content.res.Resources
import android.database.ContentObserver import android.database.ContentObserver
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.Icon
import android.media.AudioManager import android.media.AudioManager
import android.net.Uri import android.net.Uri
import android.os.* import android.os.*
import android.util.DisplayMetrics
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.View.* import android.view.View.*
import android.view.ViewGroup import android.view.ViewGroup
import android.view.animation.* import android.view.animation.AccelerateInterpolator
import android.view.animation.AlphaAnimation
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_SHORT import android.widget.Toast.LENGTH_SHORT
@ -26,7 +32,6 @@ import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.mediarouter.app.MediaRouteButton
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.transition.Fade import androidx.transition.Fade
import androidx.transition.Transition import androidx.transition.Transition
@ -44,6 +49,7 @@ import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory
import com.google.android.exoplayer2.util.MimeTypes import com.google.android.exoplayer2.util.MimeTypes
import com.google.android.exoplayer2.util.Util
import com.google.android.gms.cast.MediaInfo import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaMetadata import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.cast.MediaQueueItem import com.google.android.gms.cast.MediaQueueItem
@ -53,10 +59,13 @@ import com.google.android.gms.cast.framework.CastContext
import com.google.android.gms.cast.framework.CastState import com.google.android.gms.cast.framework.CastState
import com.google.android.gms.common.images.WebImage import com.google.android.gms.common.images.WebImage
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.MainActivity.Companion.isInPIPMode
import com.lagradost.cloudstream3.MainActivity.Companion.isInPlayer
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.UIHelper.getFocusRequest import com.lagradost.cloudstream3.UIHelper.getFocusRequest
import com.lagradost.cloudstream3.UIHelper.getNavigationBarHeight import com.lagradost.cloudstream3.UIHelper.getNavigationBarHeight
import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight
import com.lagradost.cloudstream3.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.UIHelper.hideSystemUI import com.lagradost.cloudstream3.UIHelper.hideSystemUI
import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable
import com.lagradost.cloudstream3.UIHelper.popCurrentPage import com.lagradost.cloudstream3.UIHelper.popCurrentPage
@ -72,12 +81,10 @@ import com.lagradost.cloudstream3.utils.DataStore.setKey
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.getId import com.lagradost.cloudstream3.utils.getId
import kotlinx.android.synthetic.main.fragment_player.* import kotlinx.android.synthetic.main.fragment_player.*
import kotlinx.android.synthetic.main.fragment_result.*
import kotlinx.android.synthetic.main.player_custom_layout.* import kotlinx.android.synthetic.main.player_custom_layout.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.json.JSONObject import org.json.JSONObject
import java.io.File import java.io.File
import java.util.*
import javax.net.ssl.HttpsURLConnection import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSession import javax.net.ssl.SSLSession
@ -129,12 +136,12 @@ data class PlayerData(
) )
class PlayerFragment : Fragment() { class PlayerFragment : Fragment() {
private var isCurrentlyPlaying: Boolean = false
private val mapper = JsonMapper.builder().addModule(KotlinModule()) private val mapper = JsonMapper.builder().addModule(KotlinModule())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()
private var isFullscreen = false private var isFullscreen = false
private var isPlayerPlaying = true private var isPlayerPlaying = true
private var doubleTapEnabled = false
private lateinit var viewModel: ResultViewModel private lateinit var viewModel: ResultViewModel
private lateinit var playerData: PlayerData private lateinit var playerData: PlayerData
private var isLoading = true private var isLoading = true
@ -281,20 +288,21 @@ class PlayerFragment : Fragment() {
) )
} }
fun skipOP() { private fun skipOP() {
seekTime(85000L) seekTime(85000L)
} }
private var swipeEnabled = true //<settingsManager!!.getBoolean("swipe_enabled", true)
private var swipeVerticalEnabled = true//settingsManager.getBoolean("swipe_vertical_enabled", true)
private var playBackSpeedEnabled = true//settingsManager!!.getBoolean("playback_speed_enabled", false)
private var playerResizeEnabled = true//settingsManager!!.getBoolean("player_resize_enabled", false)
private var doubleTapEnabled = false
private var skipTime = 0L private var skipTime = 0L
private var prevDiffX = 0.0 private var prevDiffX = 0.0
private var preventHorizontalSwipe = false private var preventHorizontalSwipe = false
private var hasPassedVerticalSwipeThreshold = false private var hasPassedVerticalSwipeThreshold = false
private var hasPassedSkipLimit = false private var hasPassedSkipLimit = false
private val swipeEnabled = true //<settingsManager!!.getBoolean("swipe_enabled", true)
private val swipeVerticalEnabled = true//settingsManager.getBoolean("swipe_vertical_enabled", true)
private val playBackSpeedEnabled = true//settingsManager!!.getBoolean("playback_speed_enabled", false)
private val playerResizeEnabled = true//settingsManager!!.getBoolean("player_resize_enabled", false)
private val swipeEdgeSize = 10.toPx
private var isMovingStartTime = 0L private var isMovingStartTime = 0L
private var currentX = 0F private var currentX = 0F
@ -499,6 +507,7 @@ class PlayerFragment : Fragment() {
private var hasUsedFirstRender = false private var hasUsedFirstRender = false
private fun releasePlayer() { private fun releasePlayer() {
isCurrentlyPlaying = false
val alphaAnimation = AlphaAnimation(0f, 1f) val alphaAnimation = AlphaAnimation(0f, 1f)
alphaAnimation.duration = 100 alphaAnimation.duration = 100
alphaAnimation.fillAfter = true alphaAnimation.fillAfter = true
@ -563,7 +572,7 @@ class PlayerFragment : Fragment() {
video_locked_img.setColorFilter(color) video_locked_img.setColorFilter(color)
val isClick = !isLocked val isClick = !isLocked
println("UPDATED LOCK $isClick")
exo_play.isClickable = isClick exo_play.isClickable = isClick
exo_pause.isClickable = isClick exo_pause.isClickable = isClick
exo_ffwd.isClickable = isClick exo_ffwd.isClickable = isClick
@ -597,10 +606,109 @@ class PlayerFragment : Fragment() {
private var episodes: ArrayList<ResultEpisode> = ArrayList() private var episodes: ArrayList<ResultEpisode> = ArrayList()
var currentPoster: String? = null var currentPoster: String? = null
//region PIP MODE
private fun getPen(code: PlayerEventType): PendingIntent {
return getPen(code.value)
}
private fun getPen(code: Int): PendingIntent {
return PendingIntent.getBroadcast(
activity,
code,
Intent("media_control").putExtra("control_type", code),
0
)
}
@SuppressLint("NewApi")
private fun getRemoteAction(id: Int, title: String, event: PlayerEventType): RemoteAction {
return RemoteAction(
Icon.createWithResource(activity, id),
title,
title,
getPen(event)
)
}
@SuppressLint("NewApi")
private fun updatePIPModeActions() {
if (!isInPIPMode || !this::exoPlayer.isInitialized) return
val actions: ArrayList<RemoteAction> = ArrayList()
actions.add(getRemoteAction(R.drawable.go_back_30, "Go Back", PlayerEventType.SeekBack))
if (exoPlayer.isPlaying) {
actions.add(getRemoteAction(R.drawable.netflix_pause, "Pause", PlayerEventType.Pause))
} else {
actions.add(getRemoteAction(R.drawable.ic_baseline_play_arrow_24, "Play", PlayerEventType.Play))
}
actions.add(getRemoteAction(R.drawable.go_forward_30, "Go Forward", PlayerEventType.SeekForward))
activity?.setPictureInPictureParams(PictureInPictureParams.Builder().setActions(actions).build())
}
private var receiver: BroadcastReceiver? = null
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
isInPIPMode = isInPictureInPictureMode
if (isInPictureInPictureMode) {
// Hide the full-screen UI (controls, etc.) while in picture-in-picture mode.
player_holder.alpha = 0f
receiver = object : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent,
) {
if (ACTION_MEDIA_CONTROL != intent.action) {
return
}
handlePlayerEvent(intent.getIntExtra(EXTRA_CONTROL_TYPE, 0))
}
}
val filter = IntentFilter()
filter.addAction(
ACTION_MEDIA_CONTROL
)
activity?.registerReceiver(receiver, filter)
updatePIPModeActions()
} else {
// Restore the full-screen UI.
player_holder.alpha = 1f
receiver?.let {
activity?.unregisterReceiver(it)
}
activity?.hideSystemUI()
this.view?.let { activity?.hideKeyboard(it) }
}
}
private fun handlePlayerEvent(event: PlayerEventType) {
handlePlayerEvent(event.value)
}
private fun handlePlayerEvent(event: Int) {
when (event) {
PlayerEventType.Play.value -> exoPlayer.play()
PlayerEventType.Pause.value -> exoPlayer.pause()
PlayerEventType.SeekBack.value -> seekTime(-30000L)
PlayerEventType.SeekForward.value -> seekTime(30000L)
}
}
//endregion
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
settingsManager = PreferenceManager.getDefaultSharedPreferences(activity)
swipeEnabled = settingsManager.getBoolean("swipe_enabled", true)
swipeVerticalEnabled = settingsManager.getBoolean("swipe_vertical_enabled", true)
playBackSpeedEnabled = settingsManager.getBoolean("playback_speed_enabled", false)
playerResizeEnabled = settingsManager.getBoolean("player_resize_enabled", true)
doubleTapEnabled = settingsManager.getBoolean("double_tap_enabled", false)
isInPlayer = true // NEED REFERENCE TO MAIN ACTIVITY FOR PIP
navigationBarHeight = requireContext().getNavigationBarHeight() navigationBarHeight = requireContext().getNavigationBarHeight()
statusBarHeight = requireContext().getStatusBarHeight() statusBarHeight = requireContext().getStatusBarHeight()
@ -723,9 +831,6 @@ class PlayerFragment : Fragment() {
} }
} }
println(episodes)
settingsManager = PreferenceManager.getDefaultSharedPreferences(activity)
val fastForwardTime = settingsManager.getInt("fast_forward_button_time", 10) val fastForwardTime = settingsManager.getInt("fast_forward_button_time", 10)
exo_rew_text.text = fastForwardTime.toString() exo_rew_text.text = fastForwardTime.toString()
exo_ffwd_text.text = fastForwardTime.toString() exo_ffwd_text.text = fastForwardTime.toString()
@ -928,6 +1033,8 @@ class PlayerFragment : Fragment() {
} }
changeSkip() changeSkip()
initPlayer()
} }
private fun getCurrentUrl(): ExtractorLink? { private fun getCurrentUrl(): ExtractorLink? {
@ -1003,24 +1110,28 @@ class PlayerFragment : Fragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
thread { if (!isCurrentlyPlaying) {
// initPlayer() initPlayer()
if (player_view != null) player_view.onResume()
} }
if (player_view != null) player_view.onResume()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
activity?.hideSystemUI() activity?.hideSystemUI()
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
thread { if (Util.SDK_INT <= 23) {
if (!isCurrentlyPlaying) {
initPlayer() initPlayer()
}
if (player_view != null) player_view.onResume() if (player_view != null) player_view.onResume()
} }
} }
//TODO FIX NON PIP MODE BUG
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
isInPlayer = false
// releasePlayer() // releasePlayer()
activity?.showSystemUI() activity?.showSystemUI()
@ -1029,15 +1140,19 @@ class PlayerFragment : Fragment() {
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
if (Util.SDK_INT <= 23) {
if (player_view != null) player_view.onPause() if (player_view != null) player_view.onPause()
releasePlayer() releasePlayer()
} }
}
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
if (Util.SDK_INT > 23) {
if (player_view != null) player_view.onPause() if (player_view != null) player_view.onPause()
releasePlayer() releasePlayer()
} }
}
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
if (this::exoPlayer.isInitialized) { if (this::exoPlayer.isInitialized) {
@ -1229,7 +1344,7 @@ class PlayerFragment : Fragment() {
} }
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) { override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
// updatePIPModeActions() updatePIPModeActions()
if (activity == null) return if (activity == null) return
if (playWhenReady) { if (playWhenReady) {
when (playbackState) { when (playbackState) {
@ -1296,6 +1411,7 @@ class PlayerFragment : Fragment() {
//http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4 //http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun initPlayer() { private fun initPlayer() {
isCurrentlyPlaying = true
println("INIT PLAYER") println("INIT PLAYER")
view?.setOnTouchListener { _, _ -> return@setOnTouchListener true } // VERY IMPORTANT https://stackoverflow.com/questions/28818926/prevent-clicking-on-a-button-in-an-activity-while-showing-a-fragment view?.setOnTouchListener { _, _ -> return@setOnTouchListener true } // VERY IMPORTANT https://stackoverflow.com/questions/28818926/prevent-clicking-on-a-button-in-an-activity-while-showing-a-fragment
val tempUrl = getCurrentUrl() val tempUrl = getCurrentUrl()

View file

@ -0,0 +1,11 @@
package com.lagradost.cloudstream3.ui.settings
import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
import com.lagradost.cloudstream3.R
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings, rootKey)
}
}

View file

@ -0,0 +1,6 @@
<vector android:height="27.5dp" android:tint="?attr/white"
android:viewportHeight="293" android:viewportWidth="256"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white"
android:pathData="M226.011429,0 L29.9885714,0 C13.4582857,0 0,13.4582857 0,30.1348571 L0,227.913143 C0,244.589714 13.4582857,258.048 29.9885714,258.048 L195.876571,258.048 L188.123429,230.985143 L206.848,248.393143 L224.548571,264.777143 L256,292.571429 L256,30.1348571 C256,13.4582857 242.541714,0 226.011429,0 Z M169.545143,191.049143 C169.545143,191.049143 164.278857,184.758857 159.890286,179.2 C179.053714,173.787429 186.368,161.792 186.368,161.792 C180.370286,165.741714 174.665143,168.521143 169.545143,170.422857 C162.230857,173.494857 155.209143,175.542857 148.333714,176.713143 C134.290286,179.346286 121.417143,178.614857 110.445714,176.566857 C102.107429,174.957714 94.9394286,172.617143 88.9417143,170.276571 C85.5771429,168.96 81.92,167.350857 78.2628571,165.302857 C77.824,165.010286 77.3851429,164.864 76.9462857,164.571429 C76.6537143,164.425143 76.5074286,164.278857 76.3611429,164.132571 C73.728,162.669714 72.2651429,161.645714 72.2651429,161.645714 C72.2651429,161.645714 79.2868571,173.348571 97.8651429,178.907429 C93.4765714,184.466286 88.064,191.049143 88.064,191.049143 C55.7348571,190.025143 43.4468571,168.813714 43.4468571,168.813714 C43.4468571,121.709714 64.512,83.5291429 64.512,83.5291429 C85.5771429,67.7302857 105.618286,68.1691429 105.618286,68.1691429 L107.081143,69.9245714 C80.7497143,77.5314286 68.608,89.088 68.608,89.088 C68.608,89.088 71.8262857,87.3325714 77.2388571,84.8457143 C92.8914286,77.9702857 105.325714,76.0685714 110.445714,75.6297143 C111.323429,75.4834286 112.054857,75.3371429 112.932571,75.3371429 C121.856,74.1668571 131.949714,73.8742857 142.482286,75.0445714 C156.379429,76.6537143 171.300571,80.7497143 186.514286,89.088 C186.514286,89.088 174.957714,78.1165714 150.089143,70.5097143 L152.137143,68.1691429 C152.137143,68.1691429 172.178286,67.7302857 193.243429,83.5291429 C193.243429,83.5291429 214.308571,121.709714 214.308571,168.813714 C214.308571,168.813714 201.874286,190.025143 169.545143,191.049143 Z M101.522286,122.733714 C93.184,122.733714 86.6011429,130.048 86.6011429,138.971429 C86.6011429,147.894857 93.3302857,155.209143 101.522286,155.209143 C109.860571,155.209143 116.443429,147.894857 116.443429,138.971429 C116.589714,130.048 109.860571,122.733714 101.522286,122.733714 M154.916571,122.733714 C146.578286,122.733714 139.995429,130.048 139.995429,138.971429 C139.995429,147.894857 146.724571,155.209143 154.916571,155.209143 C163.254857,155.209143 169.837714,147.894857 169.837714,138.971429 C169.837714,130.048 163.254857,122.733714 154.916571,122.733714"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M21,3L3,3c-1.11,0 -2,0.89 -2,2v12c0,1.1 0.89,2 2,2h5v2h8v-2h5c1.1,0 1.99,-0.9 1.99,-2L23,5c0,-1.11 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12zM16,11l-7,4L9,7z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19,11h-8v6h8v-6zM23,19L23,4.98C23,3.88 22.1,3 21,3L3,3c-1.1,0 -2,0.88 -2,1.98L1,19c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2zM21,19.02L3,19.02L3,4.97h18v14.05z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M9,11.24V7.5C9,6.12 10.12,5 11.5,5S14,6.12 14,7.5v3.74c1.21,-0.81 2,-2.18 2,-3.74C16,5.01 13.99,3 11.5,3S7,5.01 7,7.5C7,9.06 7.79,10.43 9,11.24zM18.84,15.87l-4.54,-2.26c-0.17,-0.07 -0.35,-0.11 -0.54,-0.11H13v-6C13,6.67 12.33,6 11.5,6S10,6.67 10,7.5v10.74c-3.6,-0.76 -3.54,-0.75 -3.67,-0.75c-0.31,0 -0.59,0.13 -0.79,0.33l-0.79,0.8l4.94,4.94C9.96,23.83 10.34,24 10.75,24h6.79c0.75,0 1.33,-0.55 1.44,-1.28l0.75,-5.27c0.01,-0.07 0.02,-0.14 0.02,-0.2C19.75,16.63 19.37,16.09 18.84,15.87z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:tint="?attr/white" xmlns:tools="http://schemas.android.com/tools" android:height="24dp" android:viewportHeight="1000"
android:viewportWidth="1000" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/white" android:pathData="M455.34,24.62c-61.96,5.16 -121.85,22.37 -176.93,49.91c-80.55,40.62 -140.44,94.66 -190.36,170.73c-35.8,54.39 -60.24,116 -72.29,182.78C7.85,471.07 8.2,555.75 16.11,597.4c33.05,172.45 148.36,312.21 307.73,372.1c26.16,9.98 36.49,10.33 45.44,1.38c6.2,-6.2 6.88,-11.36 6.88,-52.67l0,-45.44l-43.72,-0c-37.86,-0 -46.47,-1.03 -60.24,-7.57c-27.19,-12.39 -45.44,-32.35 -62.65,-68.16c-15.15,-31.67 -34.42,-55.42 -58.17,-72.29c-23.75,-16.87 -5.16,-29.95 28.57,-20.31c14.8,4.48 23.06,9.64 37.86,25.13c10.33,10.67 24.44,26.85 30.98,36.14c7.57,10.67 18.93,20.65 30.98,27.54c16.52,9.29 22.03,10.67 44.75,10.33c14.11,-0.35 31.67,-2.76 38.9,-5.16c12.05,-4.48 13.77,-7.23 20.65,-27.54c4.13,-12.05 11.02,-26.85 15.49,-32.36l7.92,-9.98l-35.46,-7.57c-63.68,-13.43 -99.82,-32.01 -132.52,-68.16c-33.73,-36.83 -52.67,-94.31 -52.67,-160.4c0,-51.63 9.98,-84.68 36.83,-121.17l11.7,-16.18l-4.13,-21c-7.23,-37.52 2.75,-103.96 16.52,-109.12c14.46,-5.51 72.97,15.83 112.21,40.96l16.18,10.33l32.01,-6.2c44.06,-8.95 139.41,-9.29 183.47,-0.34l31.33,6.54l30.29,-17.56c33.73,-19.28 64.71,-30.64 87.43,-32.01l15.49,-1.03l6.54,17.21c8.61,22.03 11.71,70.91 5.85,93.97l-4.13,17.56l15.49,23.41c27.54,41.99 31.67,57.14 31.67,116.35c-0.34,43.37 -1.38,56.11 -7.92,79.17c-19.28,67.12 -60.24,110.84 -125.3,134.59c-8.26,3.1 -30.64,8.95 -50.25,13.08l-35.46,7.57l7.57,9.29c4.13,5.51 10.67,17.9 14.46,27.54c6.88,16.18 7.57,26.16 8.61,107.4c0.69,59.9 2.41,90.88 5.16,93.97c11.71,14.46 27.88,11.71 83.65,-14.8c67.12,-31.32 136.31,-88.12 182.09,-149.39c42.68,-56.45 77.11,-136.31 89.84,-206.88c7.92,-43.72 7.92,-121.51 0,-165.23c-19.96,-110.5 -81.58,-218.24 -165.57,-288.8C716.26,54.91 586.14,12.92 455.34,24.62z"
tools:ignore="VectorPath"/>
</vector>

View file

@ -15,5 +15,9 @@
android:id="@+id/navigation_notifications" android:id="@+id/navigation_notifications"
android:icon="@drawable/netflix_download" android:icon="@drawable/netflix_download"
android:title="@string/title_downloads"/> android:title="@string/title_downloads"/>
<item
android:id="@+id/navigation_settings"
android:icon="@drawable/netflix_download"
android:title="@string/title_settings"/>
</menu> </menu>

View file

@ -22,4 +22,10 @@
android:name="com.lagradost.cloudstream3.ui.notifications.NotificationsFragment" android:name="com.lagradost.cloudstream3.ui.notifications.NotificationsFragment"
android:label="@string/title_downloads" android:label="@string/title_downloads"
tools:layout="@layout/fragment_notifications"/> tools:layout="@layout/fragment_notifications"/>
<fragment
android:id="@+id/navigation_settings"
android:layout_height="match_parent"
android:name="com.lagradost.cloudstream3.ui.settings.SettingsFragment"
android:label="@string/title_settings"
/>
</navigation> </navigation>

View file

@ -3,6 +3,7 @@
<string name="title_home">Home</string> <string name="title_home">Home</string>
<string name="title_search">Search</string> <string name="title_search">Search</string>
<string name="title_downloads">Downloads</string> <string name="title_downloads">Downloads</string>
<string name="title_settings">Settings</string>
<string name="search_hint">Search...</string> <string name="search_hint">Search...</string>
<string name="change_providers_descript">Change Providers</string> <string name="change_providers_descript">Change Providers</string>
<string name="search_providers_list_key">search_providers_list</string> <string name="search_providers_list_key">search_providers_list</string>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
</full-backup-content>

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory/>
<PreferenceCategory
android:key="video"
android:title="Player"
app:isPreferenceVisible="true"
>
<SwitchPreference
android:icon="@drawable/ic_baseline_picture_in_picture_alt_24"
app:key="pip_enabled"
android:title="Picture-in-picture"
android:summary="Continues playback in a miniature player on top of other apps"
app:defaultValue="true"
/>
<SwitchPreference
android:icon="@drawable/ic_baseline_aspect_ratio_24"
app:key="player_resize_enabled"
android:title="Player resize button"
android:summary="Remove the black borders"
app:defaultValue="true"
/>
<SwitchPreference
android:icon="@drawable/ic_baseline_speed_24"
app:key="playback_speed_enabled"
android:title="Eigengrau Mode"
android:summary="Adds the speed option in the player"
app:defaultValue="true"
/>
<SwitchPreference
android:icon="@drawable/ic_baseline_ondemand_video_24"
app:key="swipe_enabled"
android:title="Swipe to seek"
android:summary="Swipe left or right to control time in the videoplayer"
app:defaultValue="true"
/>
<SwitchPreference
android:icon="@drawable/ic_baseline_ondemand_video_24"
app:key="swipe_vertical_enabled"
android:title="Swipe to change settings"
android:summary="Swipe on the left or right side to change brightness or volume"
app:defaultValue="true"
/>
<SwitchPreference
android:icon="@drawable/ic_baseline_touch_app_24"
app:key="double_tap_enabled"
android:title="Double tap to seek"
android:summary="Tap twice on the right or left side to seek forwards or backwards"
app:defaultValue="false"
/>
<Preference
android:title="Github"
android:icon="@drawable/ic_github_logo"
app:summary="https://github.com/LagradOst/CloudStream-3">
<intent android:action="android.intent.action.VIEW"
android:data="https://github.com/LagradOst/CloudStream-3"/>
</Preference>
<Preference
android:title="Join Discord"
android:icon="@drawable/ic_baseline_discord_24"
app:summary="https://discord.gg/5Hus6fM">
<intent android:action="android.intent.action.VIEW"
android:data="https://discord.gg/5Hus6fM"/>
</Preference>
</PreferenceCategory>
</PreferenceScreen>