Add file intent

Add the ability to view a music file in auxio when selecting the file from another app. The ability to play it will be added later.
This commit is contained in:
OxygenCobalt 2021-02-19 14:22:58 -07:00
parent e631ddd730
commit 2dfd916736
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
9 changed files with 73 additions and 5 deletions

View file

@ -26,7 +26,19 @@
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.APP_MUSIC" />
<action android:name="android.intent.action.MUSIC_PLAYER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
<data android:mimeType="audio/*" />
</intent-filter> </intent-filter>
</activity> </activity>
<service <service

View file

@ -18,7 +18,6 @@ import org.oxycblt.auxio.ui.isEdgeOn
* The single [AppCompatActivity] for Auxio. * The single [AppCompatActivity] for Auxio.
*/ */
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -47,6 +46,15 @@ class MainActivity : AppCompatActivity() {
startService(Intent(this, PlaybackService::class.java)) startService(Intent(this, PlaybackService::class.java))
} }
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// Since the activity is set to singleTask [Given that theres only MainActivity]
// We have to manually push the intent whenever we get one so that MainFragment
// can catch any file intents
setIntent(intent)
}
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private fun doEdgeToEdgeSetup(binding: ActivityMainBinding) { private fun doEdgeToEdgeSetup(binding: ActivityMainBinding) {
window?.apply { window?.apply {

View file

@ -1,5 +1,6 @@
package org.oxycblt.auxio package org.oxycblt.auxio
import android.content.Intent
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -117,6 +118,17 @@ class MainFragment : Fragment() {
return binding.root return binding.root
} }
override fun onResume() {
super.onResume()
val intent = requireActivity().intent
if (intent != null && intent.action == Intent.ACTION_VIEW) {
logD("Attempting to navigate from file intent")
detailModel.navigateWithIntent(intent, requireActivity().application)
}
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()

View file

@ -1,12 +1,17 @@
package org.oxycblt.auxio.detail package org.oxycblt.auxio.detail
import android.app.Application
import android.content.Intent
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.BaseModel
import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.MusicStore
import org.oxycblt.auxio.recycler.SortMode import org.oxycblt.auxio.recycler.SortMode
/** /**
@ -40,6 +45,8 @@ class DetailViewModel : ViewModel() {
private val mNavToItem = MutableLiveData<BaseModel?>() private val mNavToItem = MutableLiveData<BaseModel?>()
val navToItem: LiveData<BaseModel?> get() = mNavToItem val navToItem: LiveData<BaseModel?> get() = mNavToItem
private val musicStore = MusicStore.getInstance()
/** /**
* Update the current navigation status * Update the current navigation status
* @param value Whether the current [DetailFragment] is navigating or not. * @param value Whether the current [DetailFragment] is navigating or not.
@ -107,4 +114,13 @@ class DetailViewModel : ViewModel() {
fun doneWithNavToItem() { fun doneWithNavToItem() {
mNavToItem.value = null mNavToItem.value = null
} }
/** Navigate to an item using a file [Intent] */
fun navigateWithIntent(intent: Intent, app: Application) {
val uri = intent.data ?: return
viewModelScope.launch {
mNavToItem.value = musicStore.getSongForUri(uri, app.contentResolver)
}
}
} }

View file

@ -62,7 +62,7 @@ class LoadingFragment : Fragment() {
if (noPermissions()) { if (noPermissions()) {
// MusicStore.Response.NO_PERMS isnt actually returned by MusicStore, its just // MusicStore.Response.NO_PERMS isnt actually returned by MusicStore, its just
// a way to keep the current permission state on_hand // a way to keep the current permission state across device changes
loadingModel.notifyNoPermissions() loadingModel.notifyNoPermissions()
} }

View file

@ -23,6 +23,7 @@ sealed class Parent : BaseModel()
/** /**
* The data object for a song. Inherits [BaseModel]. * The data object for a song. Inherits [BaseModel].
* @property fileName The raw filename for this track
* @property albumId The Song's Album ID. Never use this outside of when attaching a song to its album. * @property albumId The Song's Album ID. Never use this outside of when attaching a song to its album.
* @property track The Song's Track number * @property track The Song's Track number
* @property duration The duration of the song, in millis. * @property duration The duration of the song, in millis.
@ -35,6 +36,7 @@ sealed class Parent : BaseModel()
data class Song( data class Song(
override val id: Long = -1, override val id: Long = -1,
override val name: String, override val name: String,
val fileName: String,
val albumId: Long = -1, val albumId: Long = -1,
val track: Int = -1, val track: Int = -1,
val duration: Long = 0, val duration: Long = 0,

View file

@ -1,6 +1,9 @@
package org.oxycblt.auxio.music package org.oxycblt.auxio.music
import android.app.Application import android.app.Application
import android.content.ContentResolver
import android.net.Uri
import android.provider.OpenableColumns
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.oxycblt.auxio.logD import org.oxycblt.auxio.logD
@ -72,6 +75,20 @@ class MusicStore private constructor() {
} }
} }
/**
* Get the song for a specific URI.
*/
suspend fun getSongForUri(uri: Uri, resolver: ContentResolver): Song? {
return withContext(Dispatchers.IO) {
resolver.query(uri, null, null, null, null)?.use { cursor ->
cursor.moveToFirst()
val fileName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
return@withContext songs.find { it.fileName == fileName }
}
}
}
enum class Response { enum class Response {
NO_MUSIC, NO_PERMS, FAILED, SUCCESS NO_MUSIC, NO_PERMS, FAILED, SUCCESS
} }

View file

@ -158,12 +158,13 @@ class MusicLoader(private val app: Application) {
while (cursor.moveToNext()) { while (cursor.moveToNext()) {
val id = cursor.getLong(idIndex) val id = cursor.getLong(idIndex)
val title = cursor.getString(titleIndex) ?: cursor.getString(fileIndex) val title = cursor.getString(titleIndex)
val fileName = cursor.getString(fileIndex)
val albumId = cursor.getLong(albumIndex) val albumId = cursor.getLong(albumIndex)
val track = cursor.getInt(trackIndex) val track = cursor.getInt(trackIndex)
val duration = cursor.getLong(durationIndex) val duration = cursor.getLong(durationIndex)
songs.add(Song(id, title, albumId, track, duration)) songs.add(Song(id, title ?: fileName, fileName, albumId, track, duration))
} }
cursor.close() cursor.close()

View file

@ -87,7 +87,7 @@
<string name="setting_behavior_rewind_prev">Zurückspulen, bevor zurück springen</string> <string name="setting_behavior_rewind_prev">Zurückspulen, bevor zurück springen</string>
<string name="setting_behavior_rewind_prev_desc">Zurückspulen, bevor zum vorheriger Lied springen</string> <string name="setting_behavior_rewind_prev_desc">Zurückspulen, bevor zum vorheriger Lied springen</string>
<string name="setting_behavior_save" >Wiedergabezustand abspeichern</string> <string name="setting_behavior_save" >Wiedergabezustand abspeichern</string>
<string name="setting_behavior_save_desc">der aktuell Wiedergabezustand jetzt abspeichern</string> <string name="setting_behavior_save_desc">Der aktuell Wiedergabezustand jetzt abspeichern</string>
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="error_no_music">Keine Musik gefunden</string> <string name="error_no_music">Keine Musik gefunden</string>