Skip to content

Commit

Permalink
[CHORE]: Updated dependencies to latest versions.
Browse files Browse the repository at this point in the history
[FIX]: Fixed minor issues in `Promotions.kt`.
[FEAT]: Added necessary extension methods for querying `MediaStore`: `ContentResolver.getVideos`.
[FEAT]: Added required permission for videos.
[FEAT]: Removed the drawer display; now the app will show the NavRail regardless of the device type.
[FEAT]: Added Videos Destination - Now, instead of opening the Android system video file selector, users can utilize the built-in one.
[FEAT]: Implemented corresponding methods in `ContentResolver.kt` and `Repository.kt` for fetching video content from the device.
[FEAT]: Permission Update - To fetch videos, users must provide an additional permission called `READ_VIDEOS`.
[FEAT]: Added dependency on Coil for fetching video thumbnails.
  • Loading branch information
iZakirSheikh committed Jun 4, 2024
1 parent 8f1a1bc commit 3410edb
Show file tree
Hide file tree
Showing 16 changed files with 752 additions and 54 deletions.
8 changes: 8 additions & 0 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ android {
applicationId = "com.prime.player"
minSdk = 21
targetSdk = 34
versionCode = 87
versionName = "2.10.1"
versionCode = 88
versionName = "2.11.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables { useSupportLibrary = true }
//Load secrets into BuildConfig
Expand Down Expand Up @@ -118,6 +118,7 @@ dependencies {
implementation(libs.media3.ui)
implementation(libs.mp3agic)
implementation(libs.play.feature.delivery)
implementation(libs.coil.video)
//TODO - Updating dependencies caused the app not to compile becasue of some issue with
// internal below dependency and hence this. Remove this in next update.
implementation("com.google.j2objc:j2objc-annotations:3.0.0")
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
Expand Down
13 changes: 5 additions & 8 deletions app/src/main/java/com/prime/media/Audiofy.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.os.Build
import android.provider.MediaStore
import coil.ImageLoader
import coil.ImageLoaderFactory
import coil.decode.VideoFrameDecoder
import coil.disk.DiskCache
import coil.fetch.Fetcher
import coil.fetch.Fetcher.Factory
Expand Down Expand Up @@ -50,12 +51,6 @@ class Audiofy : Application(), ImageLoaderFactory {
* https://developers.google.com/android/reference/com/google/android/gms/common/GooglePlayServicesUtil.html#GOOGLE_PLAY_STORE_PACKAGE
*/
const val PKG_GOOGLE_PLAY_STORE = "com.android.vending"

val STORAGE_PERMISSION =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
android.Manifest.permission.READ_MEDIA_AUDIO
else
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
}

/**
Expand Down Expand Up @@ -96,11 +91,13 @@ class Audiofy : Application(), ImageLoaderFactory {
}
}


override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(this)
// Add the MediaMetaDataArtFactory
.components { add(MediaMetaDataArtFactory()) }
.components {
add(MediaMetaDataArtFactory())
add(VideoFrameDecoder.Factory())
}
.memoryCache {
MemoryCache.Builder(this)
.strongReferencesEnabled(true)
Expand Down
81 changes: 50 additions & 31 deletions app/src/main/java/com/prime/media/Home.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ package com.prime.media
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.tween
Expand Down Expand Up @@ -85,7 +84,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.dialog
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberPermissionState
import com.google.accompanist.permissions.rememberMultiplePermissionsState
import com.google.firebase.Firebase
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.analytics
Expand Down Expand Up @@ -130,8 +129,10 @@ import com.prime.media.impl.ConsoleViewModel
import com.prime.media.impl.LibraryViewModel
import com.prime.media.impl.SettingsViewModel
import com.prime.media.impl.TagEditorViewModel
import com.prime.media.impl.VideosViewModel
import com.prime.media.library.Library
import com.prime.media.settings.Settings
import com.prime.media.videos.Videos
import com.primex.core.Amber
import com.primex.core.BlueLilac
import com.primex.core.DahliaYellow
Expand Down Expand Up @@ -280,6 +281,15 @@ private val ExitTransition = fadeOut(tween(700))
*/
private const val PERMISSION_ROUTE = "_route_storage_permission"

private val STORAGE_PERMISSIONS =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
listOf(
android.Manifest.permission.READ_MEDIA_AUDIO,
android.Manifest.permission.READ_MEDIA_VIDEO
)
else
listOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)

/**
* The permission screen.
*/
Expand All @@ -290,8 +300,8 @@ private fun Permission() {
// Compose the permission state.
// Once granted set different route like folders as start.
// Navigate from here to there.
val permission = rememberPermissionState(permission = Audiofy.STORAGE_PERMISSION) {
if (!it) return@rememberPermissionState
val permission = rememberMultiplePermissionsState(permissions = STORAGE_PERMISSIONS) {
if (!it.all { it.value }) return@rememberMultiplePermissionsState
controller.graph.setStartDestination(Library.route)
controller.navigate(Library.route) { popUpTo(PERMISSION_ROUTE) { inclusive = true } }
}
Expand All @@ -302,7 +312,7 @@ private fun Permission() {
vertical = LocalWindowSize.current.widthRange == Range.Compact
) {
OutlinedButton(
onClick = { permission.launchPermissionRequest() },
onClick = { permission.launchMultiplePermissionRequest() },
modifier = Modifier.size(width = 200.dp, height = 46.dp),
elevation = null,
label = stringResource(R.string.allow),
Expand Down Expand Up @@ -408,8 +418,10 @@ private fun NavGraph(
val context = LocalContext.current
// Load start destination based on if storage permission is set or not.
val startDestination =
when (ContextCompat.checkSelfPermission(context, Audiofy.STORAGE_PERMISSION)) {
PackageManager.PERMISSION_GRANTED -> Library.route
when (STORAGE_PERMISSIONS.all {
ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED
}) {
true -> Library.route
else -> PERMISSION_ROUTE
}
// In order to navigate and remove the need to pass controller below UI components.
Expand Down Expand Up @@ -482,6 +494,11 @@ private fun NavGraph(
val viewModel = hiltViewModel<ConsoleViewModel>()
Console(state = viewModel)
}

composable(Videos.route) {
val viewModel = hiltViewModel<VideosViewModel>()
Videos(state = viewModel)
}
},
)
}
Expand Down Expand Up @@ -521,10 +538,10 @@ private fun NavController.toRoute(route: String) {

private const val MIME_TYPE_VIDEO = "video/*"

// The different NavTypes shown in differnrt screen sizes.
private val TYPE_RAIL_NAV = 0
private val TYPE_DRAWER_NAV = 1
private val TYPE_BOTTOM_NAV = 2
// The different NavTypes shown in different screen sizes.
private const val TYPE_RAIL_NAV = 0
private const val TYPE_DRAWER_NAV = 1
private const val TYPE_BOTTOM_NAV = 2

/**
* return the navigation type based on the window size.
Expand All @@ -533,7 +550,8 @@ private inline val WindowSize.navType
get() = when {
widthRange < Range.Medium -> TYPE_BOTTOM_NAV
widthRange < Range.xLarge -> TYPE_RAIL_NAV
else -> TYPE_DRAWER_NAV
// FixME - For now return only rail as drawer looks pretty bad.
else -> TYPE_RAIL_NAV //TYPE_DRAWER_NAV
}

private val NAV_RAIL_WIDTH = 96.dp
Expand Down Expand Up @@ -660,21 +678,22 @@ private fun NavBar(
)

// Videos
val context = LocalContext.current as MainActivity
val launcher =
rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
if (it == null) return@rememberLauncherForActivityResult
val intnet = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(it, MIME_TYPE_VIDEO)
this.`package` = context.packageName
}
context.startActivity(intnet)
}
// val context = LocalContext.current as MainActivity
// val launcher =
// rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) {
// if (it == null) return@rememberLauncherForActivityResult
// val intnet = Intent(Intent.ACTION_VIEW).apply {
// setDataAndType(it, MIME_TYPE_VIDEO)
// this.`package` = context.packageName
// }
// context.startActivity(intnet)
// }
// launcher.launch(arrayOf(MIME_TYPE_VIDEO))
NavigationItem(
label = textResource(id = R.string.videos),
icon = Icons.Outlined.VideoLibrary,
checked = false,
onClick = { launcher.launch(arrayOf(MIME_TYPE_VIDEO)) },
checked = current?.destination?.route == Videos.route,
onClick = { navController.navigate(Videos.direction()) },
type = type,
colors = colors
)
Expand Down Expand Up @@ -834,13 +853,13 @@ fun Home(channel: Channel) {
val navDestChangeListener =
{ _: NavController, destination: NavDestination, _: Bundle? ->
// create params for the event.
val params = Bundle().apply {
putString(FirebaseAnalytics.Param.SCREEN_NAME, destination.route as String?)
//putString(FirebaseAnalytics.Param.SCREEN_CLASS, destination.label as String?)
val params = Bundle().apply {
putString(FirebaseAnalytics.Param.SCREEN_NAME, destination.route as String?)
//putString(FirebaseAnalytics.Param.SCREEN_CLASS, destination.label as String?)
}
// Log the event.
firebase.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, params)
}
// Log the event.
firebase.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, params)
}
// Register the intent listener with the activity.
activity.addOnNewIntentListener(listener)
navController.addOnDestinationChangedListener(navDestChangeListener)
Expand Down
Loading

0 comments on commit 3410edb

Please sign in to comment.