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:
parent
e631ddd730
commit
2dfd916736
9 changed files with 73 additions and 5 deletions
|
@ -26,7 +26,19 @@
|
|||
|
||||
<intent-filter>
|
||||
<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.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>
|
||||
</activity>
|
||||
<service
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.oxycblt.auxio.ui.isEdgeOn
|
|||
* The single [AppCompatActivity] for Auxio.
|
||||
*/
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
|
@ -47,6 +46,15 @@ class MainActivity : AppCompatActivity() {
|
|||
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")
|
||||
private fun doEdgeToEdgeSetup(binding: ActivityMainBinding) {
|
||||
window?.apply {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.oxycblt.auxio
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.res.ColorStateList
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
|
@ -117,6 +118,17 @@ class MainFragment : Fragment() {
|
|||
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() {
|
||||
super.onDestroyView()
|
||||
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package org.oxycblt.auxio.detail
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.oxycblt.auxio.music.Album
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.music.BaseModel
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.music.MusicStore
|
||||
import org.oxycblt.auxio.recycler.SortMode
|
||||
|
||||
/**
|
||||
|
@ -40,6 +45,8 @@ class DetailViewModel : ViewModel() {
|
|||
private val mNavToItem = MutableLiveData<BaseModel?>()
|
||||
val navToItem: LiveData<BaseModel?> get() = mNavToItem
|
||||
|
||||
private val musicStore = MusicStore.getInstance()
|
||||
|
||||
/**
|
||||
* Update the current navigation status
|
||||
* @param value Whether the current [DetailFragment] is navigating or not.
|
||||
|
@ -107,4 +114,13 @@ class DetailViewModel : ViewModel() {
|
|||
fun doneWithNavToItem() {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class LoadingFragment : Fragment() {
|
|||
|
||||
if (noPermissions()) {
|
||||
// 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()
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ sealed class Parent : 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 track The Song's Track number
|
||||
* @property duration The duration of the song, in millis.
|
||||
|
@ -35,6 +36,7 @@ sealed class Parent : BaseModel()
|
|||
data class Song(
|
||||
override val id: Long = -1,
|
||||
override val name: String,
|
||||
val fileName: String,
|
||||
val albumId: Long = -1,
|
||||
val track: Int = -1,
|
||||
val duration: Long = 0,
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package org.oxycblt.auxio.music
|
||||
|
||||
import android.app.Application
|
||||
import android.content.ContentResolver
|
||||
import android.net.Uri
|
||||
import android.provider.OpenableColumns
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
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 {
|
||||
NO_MUSIC, NO_PERMS, FAILED, SUCCESS
|
||||
}
|
||||
|
|
|
@ -158,12 +158,13 @@ class MusicLoader(private val app: Application) {
|
|||
|
||||
while (cursor.moveToNext()) {
|
||||
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 track = cursor.getInt(trackIndex)
|
||||
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()
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
<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_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 -->
|
||||
<string name="error_no_music">Keine Musik gefunden</string>
|
||||
|
|
Loading…
Reference in a new issue