From 818981190d1709ab7a4aa1d493ff53b5dca41940 Mon Sep 17 00:00:00 2001 From: Jannik Date: Sun, 11 Oct 2020 10:02:00 +0200 Subject: [PATCH] add media fragment, add stream parsing --- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 3 +- .../java/org/mosad/teapod/MainActivity.kt | 83 +++++++++++++++---- .../java/org/mosad/teapod/parser/AoDParser.kt | 65 ++++++++------- .../java/org/mosad/teapod/ui/MediaFragment.kt | 42 ++++++++++ .../org/mosad/teapod/ui/home/HomeFragment.kt | 2 +- .../teapod/ui/library/LibraryFragment.kt | 35 +++++++- app/src/main/res/layout/fragment_account.xml | 37 +++++---- app/src/main/res/layout/fragment_home.xml | 1 + app/src/main/res/layout/fragment_library.xml | 1 + app/src/main/res/layout/fragment_media.xml | 61 ++++++++++++++ app/src/main/res/layout/fragment_search.xml | 1 + 12 files changed, 265 insertions(+), 70 deletions(-) create mode 100644 app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt create mode 100644 app/src/main/res/layout/fragment_media.xml diff --git a/app/build.gradle b/app/build.gradle index 0da0ce1..91a85df 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,7 +38,8 @@ dependencies { implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'com.google.android.material:material:1.2.1' - implementation 'androidx.constraintlayout:constraintlayout:2.0.1' + implementation 'com.google.code.gson:gson:2.8.6' + implementation 'androidx.constraintlayout:constraintlayout:2.0.2' implementation 'androidx.navigation:navigation-fragment:2.3.0' implementation 'androidx.navigation:navigation-ui:2.3.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' @@ -49,6 +50,7 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.11.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.2' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 55889fa..3a11a13 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,8 @@ - + + 0) { + supportFragmentManager.popBackStack() + } else { + if (activeFragment !is HomeFragment) { + nav_view.selectedItemId = R.id.navigation_home + } else { + super.onBackPressed() + } + } + } + + override fun onNavigationItemSelected(item: MenuItem): Boolean { + val ret = when (item.itemId) { + R.id.navigation_home -> { + activeFragment = HomeFragment() + true + } + R.id.navigation_library -> { + activeFragment = LibraryFragment() + true + } + R.id.navigation_search -> { + activeFragment = SearchFragment() + true + } + R.id.navigation_account -> { + activeFragment = AccountFragment() + true + } + else -> false + } + + supportFragmentManager.commit { + replace(R.id.nav_host_fragment, activeFragment) + } + + return ret + } + private fun load() { // TODO } + + fun showDetailFragment(media: GUIMedia) { + val streams = AoDParser().loadStreams(media.link) // load the streams for the selected media + + val mediaFragment = MediaFragment(media, streams) + supportFragmentManager.commit { + add(R.id.nav_host_fragment, mediaFragment, "MediaFragment") + addToBackStack(null) + show(mediaFragment) + } + + println("visible !!!: " + mediaFragment.isVisible) + println(supportFragmentManager.backStackEntryCount) + } } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt index 4ddc2cf..680751b 100644 --- a/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt +++ b/app/src/main/java/org/mosad/teapod/parser/AoDParser.kt @@ -1,7 +1,7 @@ package org.mosad.teapod.parser +import com.google.gson.JsonParser import kotlinx.coroutines.* -import org.json.JSONObject import org.jsoup.Connection import org.jsoup.Jsoup import org.mosad.teapod.util.GUIMedia @@ -15,8 +15,12 @@ class AoDParser { private val login = "" private val pwd = "" - private var sessionCookies = mutableMapOf() - private var loginSuccess = false + companion object { + private var sessionCookies = mutableMapOf() + private var loginSuccess = false + + val mediaList = arrayListOf() + } private fun login() = runBlocking { @@ -63,14 +67,14 @@ class AoDParser { if (sessionCookies.isEmpty()) login() withContext(Dispatchers.Default) { - val res = Jsoup.connect("$baseURL/animes") + val resAnimes = Jsoup.connect("$baseURL/animes") .cookies(sessionCookies) .get() - //println(res) + //println(resAnimes) - val animes = arrayListOf() - res.select("div.animebox").forEach { + mediaList.clear() + resAnimes.select("div.animebox").forEach { val media = GUIMedia( it.select("h3.animebox-title").text(), it.select("p.animebox-image").select("img").attr("src"), @@ -78,25 +82,27 @@ class AoDParser { it.select("p.animebox-link").select("a").attr("href") ) - animes.add(media) + mediaList.add(media) } - println("got ${animes.size} anime") + println("got ${mediaList.size} anime") - return@withContext animes + return@withContext mediaList } } - fun loadDetails(mediaPath: String) = runBlocking { + /** + * load streams for the media path + */ + fun loadStreams(mediaPath: String): List = runBlocking { if (sessionCookies.isEmpty()) login() if (!loginSuccess) { - println("please log in") - return@runBlocking + println("please log in") // TODO + return@runBlocking listOf() } withContext(Dispatchers.Default) { - println(baseURL + mediaPath) val res = Jsoup.connect(baseURL + mediaPath) .cookies(sessionCookies) @@ -105,19 +111,20 @@ class AoDParser { //println(res) val playlists = res.select("input.streamstarter_html5").eachAttr("data-playlist") - println(playlists.first()) - val csrfToken = res.select("meta[name=csrf-token]").attr("content") - println("csrf token is: $csrfToken") - loadStreamInfo(playlists.first(), csrfToken) + //println("first entry: ${playlists.first()}") + //println("csrf token is: $csrfToken") + + return@withContext loadStreamInfo(playlists.first(), csrfToken) } } - private fun loadStreamInfo(playlistPath: String, csrfToken: String) = runBlocking { + /** + * load the playlist path and parse it, read the stream info from json + */ + private fun loadStreamInfo(playlistPath: String, csrfToken: String): List = runBlocking { withContext(Dispatchers.Default) { - println(baseURL + playlistPath) - val headers = mutableMapOf( Pair("Accept", "application/json, text/javascript, */*; q=0.01"), Pair("Accept-Language", "de,en-US;q=0.7,en;q=0.3"), @@ -126,7 +133,6 @@ class AoDParser { Pair("X-Requested-With", "XMLHttpRequest"), ) - val res = Jsoup.connect(baseURL + playlistPath) .ignoreContentType(true) .cookies(sessionCookies) @@ -135,16 +141,15 @@ class AoDParser { //println(res.body()) - // TODO replace with gson - val jsonObject = JSONObject(res.body()) - val sourcesObject = jsonObject.getJSONArray("playlist").get(0).toString() + // TODO if it's a series there sources for each episode + val sources = JsonParser.parseString(res.body()).asJsonObject + .get("playlist").asJsonArray.first().asJsonObject + .get("sources").asJsonArray - val sourcesArray = JSONObject(sourcesObject).getJSONArray("sources") - - for (i in 0 until sourcesArray.length()) { - println(sourcesArray[i].toString()) + return@withContext sources.toList().map { + it.asJsonObject.get("file").toString() } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt b/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt new file mode 100644 index 0000000..8f7bdbc --- /dev/null +++ b/app/src/main/java/org/mosad/teapod/ui/MediaFragment.kt @@ -0,0 +1,42 @@ +package org.mosad.teapod.ui + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.bumptech.glide.Glide +import kotlinx.android.synthetic.main.fragment_media.* +import org.mosad.teapod.R +import org.mosad.teapod.util.GUIMedia + +class MediaFragment(val media: GUIMedia, val streams: List) : Fragment() { + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.fragment_media, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + // load poster + Glide.with(requireContext()).load(media.posterLink).into(image_poster) + text_title.text = media.title + text_desc.text = media.shortDesc + + println("media streams: $streams") + + initActions() + } + + private fun initActions() { + button_play.setOnClickListener { onClickButtonPlay() } + } + + private fun onClickButtonPlay() { + println("play ${streams.first()}") + + + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/ui/home/HomeFragment.kt b/app/src/main/java/org/mosad/teapod/ui/home/HomeFragment.kt index fc95faa..aba569c 100644 --- a/app/src/main/java/org/mosad/teapod/ui/home/HomeFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/home/HomeFragment.kt @@ -27,6 +27,6 @@ class HomeFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - println("created!!!!") + println("HomeFragment created") } } \ No newline at end of file diff --git a/app/src/main/java/org/mosad/teapod/ui/library/LibraryFragment.kt b/app/src/main/java/org/mosad/teapod/ui/library/LibraryFragment.kt index 2e75e3d..cc2a253 100644 --- a/app/src/main/java/org/mosad/teapod/ui/library/LibraryFragment.kt +++ b/app/src/main/java/org/mosad/teapod/ui/library/LibraryFragment.kt @@ -5,10 +5,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.fragment.app.commit import kotlinx.android.synthetic.main.fragment_library.* import kotlinx.coroutines.* +import org.mosad.teapod.MainActivity import org.mosad.teapod.R import org.mosad.teapod.parser.AoDParser +import org.mosad.teapod.ui.MediaFragment import org.mosad.teapod.util.CustomAdapter import org.mosad.teapod.util.GUIMedia @@ -19,6 +22,7 @@ class LibraryFragment : Fragment() { private var mediaList = arrayListOf() private lateinit var adapter : CustomAdapter + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_library, container, false) } @@ -27,7 +31,11 @@ class LibraryFragment : Fragment() { super.onViewCreated(view, savedInstanceState) GlobalScope.launch { - mediaList = parser.listAnimes() + if (AoDParser.mediaList.isEmpty()) { + AoDParser().listAnimes() + } + + mediaList = AoDParser.mediaList // create and set the adapter, needs context withContext(Dispatchers.Main) { @@ -43,14 +51,33 @@ class LibraryFragment : Fragment() { private fun initActions() { list_library.setOnItemClickListener { parent, view, position, id -> println("selected item is: ${mediaList[position]}") - showDetailFragment(mediaList[position]) + //showDetailFragment(mediaList[position]) + + val mainActivity = activity as MainActivity + mainActivity.showDetailFragment(mediaList[position]) } } private fun showDetailFragment(media: GUIMedia) { - parser.loadDetails(media.link) + val streams = parser.loadStreams(media.link) // load the streams for the selected media + println("done: $streams") - println("done") + // TODO create detail fragment + val mediaFragment = MediaFragment(media, streams) + + activity?.supportFragmentManager?.commit { + add(mediaFragment, "MediaFragment") + addToBackStack(null) + } + +// activity?.supportFragmentManager?.beginTransaction()?.let { +// it.replace(mContainer.id, mediaFragment, "MediaFragment") +// it.addToBackStack("MediaFragment") +// it.commit() +// } + + + println("done!!!") } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_account.xml b/app/src/main/res/layout/fragment_account.xml index 4a44756..bf02d59 100644 --- a/app/src/main/res/layout/fragment_account.xml +++ b/app/src/main/res/layout/fragment_account.xml @@ -1,22 +1,23 @@ - - + android:layout_height="match_parent" + android:background="#fafafa" + tools:context=".ui.account.AccountFragment"> + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index f3d9b08..8c2300d 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="#fafafa" tools:context=".ui.home.HomeFragment"> + + + + + + +