Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to main #40

Merged
merged 7 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@
</intent-filter>
</activity>

<activity
android:name=".ExtensionOpenerActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:mimeType="application/octet-stream" />
</intent-filter>
</activity>

<service
android:name=".PlayerService"
android:exported="true"
Expand Down Expand Up @@ -99,6 +111,17 @@
<activity
android:name=".ExceptionActivity"
android:exported="true" />

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:enabled="true"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>

</manifest>
2 changes: 2 additions & 0 deletions app/src/main/java/dev/brahmkshatriya/echo/EchoApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.google.android.material.color.DynamicColors
import com.google.android.material.color.DynamicColorsOptions
import com.google.android.material.color.ThemeUtils
import dagger.hilt.android.HiltAndroidApp
import dev.brahmkshatriya.echo.ExtensionOpenerActivity.Companion.cleanupTempApks
import dev.brahmkshatriya.echo.ui.exception.ExceptionFragment.Companion.getDetails
import dev.brahmkshatriya.echo.ui.exception.ExceptionFragment.Companion.getTitle
import dev.brahmkshatriya.echo.ui.settings.LookFragment.Companion.AMOLED_KEY
Expand Down Expand Up @@ -39,6 +40,7 @@ class EchoApplication : Application() {
//UI
applyLocale(settings)
applyUiChanges(this, settings)
cleanupTempApks()

//Crash Handling
Thread.setDefaultUncaughtExceptionHandler { _, exception ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package dev.brahmkshatriya.echo

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import androidx.activity.viewModels
import androidx.core.net.toFile
import androidx.core.net.toUri
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import dev.brahmkshatriya.echo.ui.extension.ExtensionInstallerBottomSheet
import dev.brahmkshatriya.echo.viewmodels.ExtensionViewModel
import kotlinx.coroutines.launch
import java.io.File

class ExtensionOpenerActivity : Activity() {
override fun onStart() {
super.onStart()
val uri = intent.data

val file = when (uri?.scheme) {
"content" -> getTempFile(uri)
else -> null
}

if (file == null) Toast.makeText(
this, getString(R.string.could_not_find_the_file), Toast.LENGTH_SHORT
).show()

finish()
val startIntent = Intent(this, MainActivity::class.java)
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startIntent.data = file?.let { Uri.fromFile(it) }
startActivity(startIntent)
}

private fun getTempFile(uri: Uri): File? {
val stream = contentResolver.openInputStream(uri) ?: return null
val bytes = stream.readBytes()
val tempFile = File.createTempFile("temp", ".apk", getTempApkDir())
tempFile.writeBytes(bytes)
return tempFile
}

companion object {
const val EXTENSION_INSTALLER = "extensionInstaller"

fun Context.getTempApkDir() = File(cacheDir, "apks").apply { mkdirs() }

fun Context.cleanupTempApks() {
getTempApkDir().deleteRecursively()
}

fun FragmentActivity.openExtensionInstaller(uri: Uri) {

ExtensionInstallerBottomSheet.newInstance(uri.toString())
.show(supportFragmentManager, null)

supportFragmentManager.setFragmentResultListener(EXTENSION_INSTALLER, this) { _, b ->
val file = b.getString("file")?.toUri()?.toFile()
val install = b.getBoolean("install")
val installAsApk = b.getBoolean("installAsApk")
val context = this
if (install && file != null) {
val extensionViewModel by viewModels<ExtensionViewModel>()
lifecycleScope.launch {
extensionViewModel.install(context, file, installAsApk)
}
}
}
}
}
}
61 changes: 8 additions & 53 deletions app/src/main/java/dev/brahmkshatriya/echo/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,9 @@ import com.google.android.material.navigation.NavigationBarView
import com.google.android.material.navigationrail.NavigationRailView
import com.google.common.util.concurrent.ListenableFuture
import dagger.hilt.android.AndroidEntryPoint
import dev.brahmkshatriya.echo.common.models.Album
import dev.brahmkshatriya.echo.common.models.Artist
import dev.brahmkshatriya.echo.common.models.EchoMediaItem
import dev.brahmkshatriya.echo.common.models.EchoMediaItem.Companion.toMediaItem
import dev.brahmkshatriya.echo.common.models.Playlist
import dev.brahmkshatriya.echo.common.models.Track
import dev.brahmkshatriya.echo.common.models.User
import dev.brahmkshatriya.echo.ExtensionOpenerActivity.Companion.openExtensionInstaller
import dev.brahmkshatriya.echo.databinding.ActivityMainBinding
import dev.brahmkshatriya.echo.ui.common.openFragment
import dev.brahmkshatriya.echo.ui.item.ItemFragment
import dev.brahmkshatriya.echo.ui.common.openItemFragmentFromUri
import dev.brahmkshatriya.echo.ui.settings.LookFragment.Companion.NAVBAR_GRADIENT
import dev.brahmkshatriya.echo.utils.animateTranslation
import dev.brahmkshatriya.echo.utils.checkAudioPermissions
Expand All @@ -38,7 +31,6 @@ import dev.brahmkshatriya.echo.utils.listenFuture
import dev.brahmkshatriya.echo.utils.observe
import dev.brahmkshatriya.echo.viewmodels.PlayerViewModel
import dev.brahmkshatriya.echo.viewmodels.PlayerViewModel.Companion.connectPlayerToUI
import dev.brahmkshatriya.echo.viewmodels.SnackBar
import dev.brahmkshatriya.echo.viewmodels.SnackBar.Companion.configureSnackBar
import dev.brahmkshatriya.echo.viewmodels.UiViewModel
import dev.brahmkshatriya.echo.viewmodels.UiViewModel.Companion.isNightMode
Expand Down Expand Up @@ -83,9 +75,9 @@ class MainActivity : AppCompatActivity() {

ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, insets ->
uiViewModel.setSystemInsets(this, insets)
val navBarSize = uiViewModel.systemInsets.value.bottom
val navBarSize = uiViewModel.systemInsets.value.bottom
val full = playerViewModel.settings.getBoolean(NAVBAR_GRADIENT, true)
navView.createNavDrawable(isRail,navBarSize, !full)
navView.createNavDrawable(isRail, navBarSize, !full)
insets
}

Expand Down Expand Up @@ -152,47 +144,10 @@ class MainActivity : AppCompatActivity() {
return
}
val uri = data
if (uri != null) {
fun createSnack(id: Int) {
val snackbar by viewModels<SnackBar>()
val message = getString(id)
snackbar.create(SnackBar.Message(message))
}

val extensionType = uri.host
when (extensionType) {
"music" -> {
val extensionId = uri.pathSegments.firstOrNull()
if (extensionId == null) {
createSnack(R.string.error_no_client)
return
}
val type = uri.pathSegments.getOrNull(1)
val id = uri.pathSegments.getOrNull(2)
if (id == null) {
createSnack(R.string.error_no_id)
return
}
val name = uri.getQueryParameter("name").orEmpty()
val item: EchoMediaItem? = when (type) {
"user" -> User(id, name).toMediaItem()
"artist" -> Artist(id, name).toMediaItem()
"track" -> Track(id, name).toMediaItem()
"album" -> Album(id, name).toMediaItem()
"playlist" -> Playlist(id, name, false).toMediaItem()
else -> null
}
if (item == null) {
createSnack(R.string.error_invalid_type)
return
}
openFragment(ItemFragment.newInstance(extensionId, item))
}

else -> {
createSnack(R.string.invalid_extension_host)
}
}
println("URI: $uri")
when (uri?.scheme) {
"echo" -> openItemFragmentFromUri(uri)
"file" -> openExtensionInstaller(uri)
}
}

Expand Down
4 changes: 1 addition & 3 deletions app/src/main/java/dev/brahmkshatriya/echo/PlayerService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,6 @@ class PlayerService : MediaLibraryService() {
}
}

//TODO: Radio Item
//TODO: Open .eapk files
//TODO: extension updater
//TODO: Spotify
//TODO: EQ, Pitch, Tempo, Reverb & Sleep Timer(5m, 10m, 15m, 30m, 45m, 1hr, End of track)
Expand All @@ -158,7 +156,7 @@ class PlayerService : MediaLibraryService() {
}

override fun onTaskRemoved(rootIntent: Intent?) {
val stopPlayer = settings.getBoolean(CLOSE_PLAYER, false)
val stopPlayer = settings.getBoolean(CLOSE_PLAYER, true)
val player = mediaSession?.player ?: return stopSelf()
if (stopPlayer || !player.isPlaying) stopSelf()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package dev.brahmkshatriya.echo.di

import android.app.Application
import android.content.SharedPreferences
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
import androidx.media3.datasource.cache.SimpleCache
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -21,9 +24,11 @@ import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
class ExtensionModule {

@OptIn(UnstableApi::class)
@Provides
@Singleton
fun provideOfflineExtension(context: Application) = OfflineExtension(context)
fun provideOfflineExtension(context: Application, cache: SimpleCache) =
OfflineExtension(context, cache)

@Provides
@Singleton
Expand Down
Loading