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>
<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

View file

@ -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 {

View file

@ -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()

View file

@ -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)
}
}
}

View file

@ -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()
}

View file

@ -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,

View file

@ -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
}

View file

@ -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()

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_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>