update
This commit is contained in:
parent
70e1ef66c8
commit
44e13d2903
@ -64,7 +64,6 @@ class App : Application() {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
importList = databaseManager.getAllAudioFiles()
|
||||
withContext(Dispatchers.Main) {
|
||||
Log.d("ocean", "initImportAudio importList->${importList.size}")
|
||||
callback(importList)
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,6 @@ class MainActivity : BaseActivity() {
|
||||
binding.playingStatusLayout.visibility = View.VISIBLE
|
||||
val currentAudio = App.currentPlayingAudio
|
||||
|
||||
Log.d("ocean","main currentAudio->$currentAudio")
|
||||
val maxProgress = try {
|
||||
getAudioDurationFromAssets(this, currentAudio?.file!!)
|
||||
} catch (e: Exception) {
|
||||
@ -127,7 +126,6 @@ class MainActivity : BaseActivity() {
|
||||
binding.playBlackBtn.setOnClickListener {
|
||||
val currentPlayer = MediaControllerManager.getController()
|
||||
if (currentPlayer != null) {
|
||||
Log.d("ocean", "currentPlayer.playbackState->${currentPlayer.playbackState}")
|
||||
if (currentPlayer.playbackState == Player.STATE_READY) {
|
||||
if (currentPlayer.isPlaying) {
|
||||
currentPlayer.pause()
|
||||
@ -144,19 +142,16 @@ class MainActivity : BaseActivity() {
|
||||
playWhenReady: Boolean,
|
||||
reason: Int
|
||||
) {
|
||||
Log.d("ocean", "main2 onPlayWhenReadyChanged")
|
||||
updatePlayState(playWhenReady)
|
||||
updateProgressState()
|
||||
}
|
||||
|
||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||
Log.d("ocean", "main2 onPlaybackStateChanged")
|
||||
updateProgressState()
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
Log.d("ocean", "main currentPlayer == null")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,7 +52,6 @@ class PlayDetailsActivity : BaseActivity() {
|
||||
onBackPressed()
|
||||
Toast.makeText(this, getString(R.string.data_error), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
Log.d("ocean", "PlayDetailsActivity audio->$audio")
|
||||
initView()
|
||||
|
||||
}
|
||||
@ -104,13 +103,11 @@ class PlayDetailsActivity : BaseActivity() {
|
||||
playWhenReady: Boolean,
|
||||
reason: Int
|
||||
) {
|
||||
Log.d("ocean", "details onPlayWhenReadyChanged")
|
||||
updatePlayState(playWhenReady, "playWhenReady")
|
||||
updateProgressState()
|
||||
}
|
||||
|
||||
override fun onPlaybackStateChanged(playbackState: Int) {
|
||||
Log.d("ocean", "details onPlaybackStateChanged")
|
||||
updateProgressState()
|
||||
}
|
||||
})
|
||||
|
||||
@ -200,13 +200,6 @@ class ImportFragment : Fragment() {
|
||||
musicFiles.add(contentUri.toString())
|
||||
// 如果你想要获取文件的具体路径,可以使用 data 变量
|
||||
// musicFiles.add(data)
|
||||
Log.d(
|
||||
"ocean",
|
||||
"name->${name} " +
|
||||
"uri.toString()->${contentUri.toString()} " +
|
||||
"duration2->$duration2 "
|
||||
+ "data->$data"
|
||||
)
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
if (audio.duration > 0) {
|
||||
|
||||
@ -8,10 +8,14 @@ import com.player.musicoo.databinding.FragmentMoHomeBinding
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
import com.player.musicoo.innertube.models.MusicCarouselShelfRenderer
|
||||
import com.player.musicoo.innertube.requests.homePage
|
||||
import com.player.musicoo.innertube.requests.homePageMore
|
||||
import com.player.musicoo.view.MusicResponsiveListView
|
||||
import com.player.musicoo.view.MusicTowRowListView
|
||||
|
||||
class MoHomeFragment : MoBaseFragment<FragmentMoHomeBinding>() {
|
||||
|
||||
// private var baseHomePage: Innertube.BaseHomePage? = null
|
||||
|
||||
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentMoHomeBinding
|
||||
get() = FragmentMoHomeBinding::inflate
|
||||
|
||||
@ -27,11 +31,37 @@ class MoHomeFragment : MoBaseFragment<FragmentMoHomeBinding>() {
|
||||
}
|
||||
|
||||
private suspend fun initView() {
|
||||
Innertube.homePage()?.onFailure {
|
||||
Log.d("ocean", "onFailure->$it")
|
||||
}
|
||||
?.onSuccess {
|
||||
for (home: Innertube.HomePage in it) {
|
||||
Innertube.homePage()?.onSuccess {
|
||||
for (home: Innertube.HomePage in it.homePage) {
|
||||
for (content: MusicCarouselShelfRenderer.Content in home.contents) {
|
||||
if (content.musicResponsiveListItemRenderer != null) {
|
||||
binding.contentLayout.addView(
|
||||
MusicResponsiveListView(
|
||||
requireActivity(),
|
||||
home
|
||||
)
|
||||
)
|
||||
break
|
||||
}
|
||||
if (content.musicTwoRowItemRenderer != null) {
|
||||
binding.contentLayout.addView(
|
||||
MusicTowRowListView(
|
||||
requireActivity(),
|
||||
home
|
||||
)
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
initHomeDataMore(it)
|
||||
}?.onFailure { Log.d(TAG, "homePage onFailure->${it}") }
|
||||
}
|
||||
|
||||
private suspend fun initHomeDataMore(baseHomePage: Innertube.BaseHomePage) {
|
||||
if (baseHomePage.cToken?.isNotEmpty() == true) {
|
||||
Innertube.homePageMore(baseHomePage)?.onSuccess {
|
||||
for (home: Innertube.HomePage in it.homePage) {
|
||||
for (content: MusicCarouselShelfRenderer.Content in home.contents) {
|
||||
if (content.musicResponsiveListItemRenderer != null) {
|
||||
binding.contentLayout.addView(
|
||||
@ -53,9 +83,11 @@ class MoHomeFragment : MoBaseFragment<FragmentMoHomeBinding>() {
|
||||
}
|
||||
}
|
||||
}
|
||||
initHomeDataMore(it)
|
||||
}?.onFailure {
|
||||
Log.d(TAG, "initHomeDataMore onFailure ->${it}")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
||||
@ -16,10 +16,12 @@ import com.player.musicoo.innertube.models.NavigationEndpoint
|
||||
import com.player.musicoo.innertube.models.Runs
|
||||
import com.player.musicoo.innertube.models.Thumbnail
|
||||
import com.player.musicoo.innertube.utils.brotli
|
||||
import com.player.musicoo.util.LogTag
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
object Innertube {
|
||||
val TAG = LogTag.VO_API_LOG
|
||||
val client = HttpClient(OkHttp) {
|
||||
BrowserUserAgent()
|
||||
|
||||
@ -39,7 +41,7 @@ object Innertube {
|
||||
}
|
||||
|
||||
defaultRequest {
|
||||
url(scheme = "https", host ="music.youtube.com") {
|
||||
url(scheme = "https", host = "music.youtube.com") {
|
||||
headers.append(HttpHeaders.ContentType, ContentType.Application.Json.toString())
|
||||
headers.append("X-Goog-Api-Key", "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8")
|
||||
parameters.append("prettyPrint", "false")
|
||||
@ -54,9 +56,12 @@ object Innertube {
|
||||
internal const val search = "/youtubei/v1/search"
|
||||
internal const val searchSuggestions = "/youtubei/v1/music/get_search_suggestions"
|
||||
|
||||
internal const val musicResponsiveListItemRendererMask = "musicResponsiveListItemRenderer(flexColumns,fixedColumns,thumbnail,navigationEndpoint)"
|
||||
internal const val musicTwoRowItemRendererMask = "musicTwoRowItemRenderer(thumbnailRenderer,title,subtitle,navigationEndpoint)"
|
||||
const val playlistPanelVideoRendererMask = "playlistPanelVideoRenderer(title,navigationEndpoint,longBylineText,shortBylineText,thumbnail,lengthText)"
|
||||
internal const val musicResponsiveListItemRendererMask =
|
||||
"musicResponsiveListItemRenderer(flexColumns,fixedColumns,thumbnail,navigationEndpoint)"
|
||||
internal const val musicTwoRowItemRendererMask =
|
||||
"musicTwoRowItemRenderer(thumbnailRenderer,title,subtitle,navigationEndpoint)"
|
||||
const val playlistPanelVideoRendererMask =
|
||||
"playlistPanelVideoRenderer(title,navigationEndpoint,longBylineText,shortBylineText,thumbnail,lengthText)"
|
||||
|
||||
internal fun HttpRequestBuilder.mask(value: String = "*") =
|
||||
header("X-Goog-FieldMask", value)
|
||||
@ -159,6 +164,14 @@ object Innertube {
|
||||
companion object
|
||||
}
|
||||
|
||||
data class BaseHomePage(
|
||||
val visitorData: String?,
|
||||
val cToken: String?,
|
||||
val continuation: String,
|
||||
val itct: String,
|
||||
val homePage: List<HomePage>
|
||||
)
|
||||
|
||||
data class HomePage(
|
||||
val title: String?,
|
||||
val contents: List<MusicCarouselShelfRenderer.Content>
|
||||
|
||||
@ -6,16 +6,29 @@ import kotlinx.serialization.json.JsonNames
|
||||
|
||||
@Serializable
|
||||
data class BrowseResponse(
|
||||
val responseContext: ResponseContext?,
|
||||
val contents: Contents?,
|
||||
val header: Header?,
|
||||
val microformat: Microformat?
|
||||
val microformat: Microformat?,
|
||||
val continuationContents: ContinuationContents?
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class ResponseContext(
|
||||
val visitorData: String?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Contents(
|
||||
val singleColumnBrowseResultsRenderer: Tabs?,
|
||||
val sectionListRenderer: SectionListRenderer?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ContinuationContents(
|
||||
val sectionListContinuation : SectionListContinuation?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Header @OptIn(ExperimentalSerializationApi::class) constructor(
|
||||
@JsonNames("musicVisualHeaderRenderer")
|
||||
@ -60,4 +73,5 @@ data class BrowseResponse(
|
||||
val urlCanonical: String?
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ data class Context(
|
||||
val clientVersion: String,
|
||||
val platform: String,
|
||||
val hl: String = "zh",
|
||||
// val visitorData: String = "CgtEUlRINDFjdm1YayjX1pSaBg%3D%3D",
|
||||
val visitorData: String? = null,
|
||||
val androidSdkVersion: Int? = null,
|
||||
val userAgent: String? = null
|
||||
)
|
||||
|
||||
@ -12,6 +12,7 @@ data class Continuation(
|
||||
) {
|
||||
@Serializable
|
||||
data class Data(
|
||||
val continuation: String?
|
||||
val continuation: String?,
|
||||
val clickTrackingParams: String
|
||||
)
|
||||
}
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package com.player.musicoo.innertube.models
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonNames
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Serializable
|
||||
data class SectionListContinuation(
|
||||
val contents: List<Content>?,
|
||||
val continuations: List<Continuation>?
|
||||
) {
|
||||
@Serializable
|
||||
data class Content(
|
||||
@JsonNames("musicImmersiveCarouselShelfRenderer")
|
||||
val musicCarouselShelfRenderer: MusicCarouselShelfRenderer?,
|
||||
@JsonNames("musicPlaylistShelfRenderer")
|
||||
val musicShelfRenderer: MusicShelfRenderer?,
|
||||
val gridRenderer: GridRenderer?,
|
||||
val musicDescriptionShelfRenderer: MusicDescriptionShelfRenderer?,
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class MusicDescriptionShelfRenderer(
|
||||
val description: Runs?,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.player.musicoo.innertube.models.bodies
|
||||
|
||||
import com.player.musicoo.innertube.models.Context
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BrowseMoreBody(
|
||||
val context: Context = Context.DefaultWeb,
|
||||
)
|
||||
@ -12,7 +12,7 @@ import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
|
||||
//
|
||||
suspend fun Innertube.homePage(): Result<List<Innertube.HomePage>>? =
|
||||
suspend fun Innertube.homePage(): Result<Innertube.BaseHomePage>? =
|
||||
runCatchingNonCancellable {
|
||||
|
||||
val response = client.post(browse) {
|
||||
@ -29,7 +29,17 @@ suspend fun Innertube.homePage(): Result<List<Innertube.HomePage>>? =
|
||||
?.sectionListRenderer
|
||||
|
||||
val contents = sectionListRenderer?.contents
|
||||
Log.d("ocean","contents->$contents")
|
||||
|
||||
val visitorData = response.responseContext?.visitorData
|
||||
|
||||
val continuations = sectionListRenderer?.continuations
|
||||
val nextContinuationData = continuations
|
||||
?.firstOrNull()
|
||||
?.nextContinuationData
|
||||
|
||||
val cToken = nextContinuationData?.continuation
|
||||
val itct = nextContinuationData?.clickTrackingParams
|
||||
|
||||
|
||||
val searchList: MutableList<Innertube.HomePage> = mutableListOf()
|
||||
|
||||
@ -45,7 +55,8 @@ suspend fun Innertube.homePage(): Result<List<Innertube.HomePage>>? =
|
||||
|
||||
val homePage =
|
||||
content.musicCarouselShelfRenderer?.contents?.let {
|
||||
Innertube.HomePage(text,
|
||||
Innertube.HomePage(
|
||||
text,
|
||||
it
|
||||
)
|
||||
}
|
||||
@ -54,5 +65,14 @@ suspend fun Innertube.homePage(): Result<List<Innertube.HomePage>>? =
|
||||
}
|
||||
}
|
||||
}
|
||||
searchList
|
||||
val baseHomePage =
|
||||
Innertube.BaseHomePage(
|
||||
visitorData,
|
||||
cToken,
|
||||
cToken.toString(),
|
||||
itct.toString(),
|
||||
searchList
|
||||
)
|
||||
|
||||
baseHomePage
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package com.player.musicoo.innertube.requests
|
||||
|
||||
import com.player.musicoo.innertube.Innertube
|
||||
import com.player.musicoo.innertube.models.BrowseResponse
|
||||
import com.player.musicoo.innertube.models.Context
|
||||
import com.player.musicoo.innertube.models.SectionListContinuation
|
||||
import com.player.musicoo.innertube.models.bodies.BrowseMoreBody
|
||||
import com.player.musicoo.innertube.utils.runCatchingNonCancellable
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
|
||||
suspend fun Innertube.homePageMore(
|
||||
baseHomePage: Innertube.BaseHomePage
|
||||
): Result<Innertube.BaseHomePage>? =
|
||||
runCatchingNonCancellable {
|
||||
|
||||
val defaultWeb = Context(
|
||||
client = Context.Client(
|
||||
clientName = "WEB_REMIX",
|
||||
clientVersion = "1.20220918",
|
||||
platform = "DESKTOP",
|
||||
visitorData = baseHomePage.visitorData
|
||||
)
|
||||
)
|
||||
|
||||
val url =
|
||||
browse + "?ctoken=${baseHomePage.cToken}&continuation=${baseHomePage.continuation}&type=next&itct=${baseHomePage.itct}&prettyPrint=false"
|
||||
|
||||
val response = client.post(url) {
|
||||
setBody(BrowseMoreBody(defaultWeb))
|
||||
}.body<BrowseResponse>()
|
||||
|
||||
val sectionListContinuation = response
|
||||
.continuationContents
|
||||
?.sectionListContinuation
|
||||
|
||||
val contents = sectionListContinuation?.contents
|
||||
|
||||
val visitorData = baseHomePage.visitorData//保存上次的data
|
||||
|
||||
val continuations = sectionListContinuation?.continuations
|
||||
val nextContinuationData = continuations
|
||||
?.firstOrNull()
|
||||
?.nextContinuationData
|
||||
|
||||
val cToken = nextContinuationData?.continuation
|
||||
val itct = nextContinuationData?.clickTrackingParams
|
||||
|
||||
val searchList: MutableList<Innertube.HomePage> = mutableListOf()
|
||||
|
||||
if (contents != null) {
|
||||
for (content: SectionListContinuation.Content in contents) {
|
||||
val text = content.musicCarouselShelfRenderer
|
||||
?.header
|
||||
?.musicCarouselShelfBasicHeaderRenderer
|
||||
?.title
|
||||
?.runs
|
||||
?.firstOrNull()
|
||||
?.text
|
||||
|
||||
val homePage =
|
||||
content.musicCarouselShelfRenderer?.contents?.let {
|
||||
Innertube.HomePage(
|
||||
text,
|
||||
it
|
||||
)
|
||||
}
|
||||
if (homePage != null) {
|
||||
searchList.add(homePage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Innertube.BaseHomePage(
|
||||
visitorData,
|
||||
cToken,
|
||||
cToken.toString(),
|
||||
itct.toString(),
|
||||
searchList
|
||||
)
|
||||
}
|
||||
@ -33,9 +33,6 @@ object MediaControllerManager {
|
||||
controllerFuture = MediaController.Builder(context, sessionToken).buildAsync()
|
||||
controllerFuture?.addListener({
|
||||
mediaController = controllerFuture?.get()
|
||||
Log.d("ocean", "MediaControllerManager init")
|
||||
|
||||
Log.d("ocean", "MediaController connected: ${mediaController?.isConnected}")
|
||||
}, MoreExecutors.directExecutor())
|
||||
}
|
||||
|
||||
@ -57,7 +54,6 @@ object MediaControllerManager {
|
||||
Uri.parse("file:///android_asset/$currentAudioFile")
|
||||
}
|
||||
|
||||
Log.d("ocean","uri->$uri")
|
||||
|
||||
val resourceId = R.mipmap.musicoo_logo_img
|
||||
val imgUri: Uri? = if (audio.image.isNotEmpty()) {
|
||||
@ -114,7 +110,6 @@ object MediaControllerManager {
|
||||
Uri.parse("file:///android_asset/$currentAudioFile")
|
||||
}
|
||||
|
||||
Log.d("ocean","uri->$uri")
|
||||
|
||||
val resourceId = R.mipmap.musicoo_logo_img
|
||||
val imgUri: Uri? = if (audio.image.isNotEmpty()) {
|
||||
|
||||
@ -2,5 +2,6 @@ package com.player.musicoo.util
|
||||
|
||||
object LogTag {
|
||||
const val VO_ACT_LOG = "vo-act—log"
|
||||
const val VO_FRAGMENT_LOG = "vo_fragment_log"
|
||||
const val VO_FRAGMENT_LOG = "vo-fragment-log"
|
||||
const val VO_API_LOG = "vo-api—log"
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user