improved tmdb data handling, added backdrop

This commit is contained in:
Jannik 2020-10-12 22:43:42 +02:00
parent ee063a5bbe
commit 00a6981ae5
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
5 changed files with 100 additions and 48 deletions

View File

@ -56,6 +56,7 @@ dependencies {
implementation 'org.jsoup:jsoup:1.13.1' implementation 'org.jsoup:jsoup:1.13.1'
implementation 'com.github.bumptech.glide:glide:4.11.0' implementation 'com.github.bumptech.glide:glide:4.11.0'
implementation 'jp.wasabeef:glide-transformations:4.3.0'
implementation 'com.afollestad.material-dialogs:core:3.3.0' implementation 'com.afollestad.material-dialogs:core:3.3.0'
implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0' implementation 'com.afollestad.material-dialogs:bottomsheets:3.3.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'

View File

@ -1,5 +1,8 @@
package org.mosad.teapod.ui package org.mosad.teapod.ui
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -9,6 +12,8 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import jp.wasabeef.glide.transformations.BlurTransformation
import kotlinx.android.synthetic.main.fragment_media.* import kotlinx.android.synthetic.main.fragment_media.*
import org.mosad.teapod.MainActivity import org.mosad.teapod.MainActivity
import org.mosad.teapod.R import org.mosad.teapod.R
@ -30,17 +35,38 @@ class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
initGUI()
initActions()
}
/**
* if tmdb data is present, use it, else use the aod data
*/
private fun initGUI() {
// generic gui // generic gui
text_title.text = media.title text_title.text = media.title
if (tmdb.posterUrl.isNotEmpty()) { if (tmdb.posterUrl.isNotEmpty()) {
Glide.with(requireContext()).load(tmdb.posterUrl).into(image_poster) Glide.with(requireContext()).load(tmdb.backdropUrl)
text_desc.text = tmdb.overview .apply(RequestOptions.placeholderOf(ColorDrawable(Color.DKGRAY)))
Log.d(javaClass.name, "TMDB data present") .apply(RequestOptions.bitmapTransform(BlurTransformation(25, 3)))
.into(image_backdrop)
} else { } else {
Glide.with(requireContext()).load(media.posterLink).into(image_poster) Glide.with(requireContext()).load(ColorDrawable(Color.DKGRAY)).into(image_poster)
text_desc.text = media.shortDesc }
Log.d(javaClass.name, "No TMDB data present, using Aod")
if (tmdb.posterUrl.isNotEmpty()) {
Glide.with(requireContext()).load(tmdb.posterUrl)
.into(image_poster)
} else {
Glide.with(requireContext()).load(media.posterLink)
.into(image_poster)
}
text_overview.text = if (tmdb.overview.isNotEmpty()) {
tmdb.overview
} else {
media.shortDesc
} }
// specific gui // specific gui
@ -55,11 +81,6 @@ class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) :
} else if (media.type == MediaType.MOVIE) { } else if (media.type == MediaType.MOVIE) {
recycler_episodes.visibility = View.GONE recycler_episodes.visibility = View.GONE
} }
println("media streams: ${media.episodes}")
initActions()
} }
private fun initActions() { private fun initActions() {
@ -67,7 +88,7 @@ class MediaFragment(private val media: Media, private val tmdb: TMDBResponse) :
when (media.type) { when (media.type) {
MediaType.MOVIE -> playStream(media.episodes.first().streamUrl) MediaType.MOVIE -> playStream(media.episodes.first().streamUrl)
MediaType.TVSHOW -> playStream(media.episodes.first().streamUrl) MediaType.TVSHOW -> playStream(media.episodes.first().streamUrl)
MediaType.OTHER -> Log.e(javaClass.name, "Wrong Type, please report this issue.") else -> Log.e(javaClass.name, "Wrong Type: $media.type")
} }
} }

View File

@ -1,6 +1,7 @@
package org.mosad.teapod.util package org.mosad.teapod.util
import android.util.Log import android.util.Log
import com.google.gson.JsonObject
import com.google.gson.JsonParser import com.google.gson.JsonParser
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async import kotlinx.coroutines.async
@ -16,24 +17,18 @@ class TMDBApiController {
private val searchTVUrl = "$apiUrl/search/tv" private val searchTVUrl = "$apiUrl/search/tv"
private val apiKey = "de959cf9c07a08b5ca7cb51cda9a40c2" private val apiKey = "de959cf9c07a08b5ca7cb51cda9a40c2"
private val language = "de" private val language = "de"
private val preparedParamters = "?api_key=$apiKey&language=$language" private val preparedParameters = "?api_key=$apiKey&language=$language"
private val imageUrl = "https://image.tmdb.org/t/p/w500" private val imageUrl = "https://image.tmdb.org/t/p/w500"
fun search(title: String, type: MediaType): TMDBResponse { fun search(title: String, type: MediaType): TMDBResponse {
val searchTerm = title.replace("(Sub)", "").trim()
return when (type) { return when (type) {
MediaType.MOVIE -> { MediaType.MOVIE -> searchMovie(searchTerm)
val test = searchMovie(title) MediaType.TVSHOW -> searchTVShow(searchTerm)
println("test: $test") else -> {
test Log.e(javaClass.name, "Wrong Type: $type")
}
MediaType.TVSHOW -> {
val test = searchTVShow(title)
println("test: $test")
test
}
MediaType.OTHER -> {
Log.e(javaClass.name, "Error")
TMDBResponse() TMDBResponse()
} }
} }
@ -41,17 +36,17 @@ class TMDBApiController {
} }
fun searchTVShow(title: String) = runBlocking { fun searchTVShow(title: String) = runBlocking {
val url = URL("$searchTVUrl$preparedParamters&query=${URLEncoder.encode(title, "UTF-8")}") val url = URL("$searchTVUrl$preparedParameters&query=${URLEncoder.encode(title, "UTF-8")}")
GlobalScope.async { GlobalScope.async {
val response = JsonParser.parseString(url.readText()).asJsonObject val response = JsonParser.parseString(url.readText()).asJsonObject
println(response) //println(response)
return@async if (response.get("total_results").asInt > 0) { return@async if (response.get("total_results").asInt > 0) {
response.get("results").asJsonArray.first().let { response.get("results").asJsonArray.first().asJsonObject.let {
val overview = it.asJsonObject.get("overview").asString val overview = getStringNotNull(it,"overview")
val posterPath = imageUrl + it.asJsonObject.get("poster_path").asString val posterPath = getStringNotNullPrefix(it, "poster_path", imageUrl)
val backdropPath = imageUrl + it.asJsonObject.get("backdrop_path").asString val backdropPath = getStringNotNullPrefix(it, "backdrop_path", imageUrl)
TMDBResponse("", overview, posterPath, backdropPath) TMDBResponse("", overview, posterPath, backdropPath)
} }
@ -63,17 +58,17 @@ class TMDBApiController {
} }
fun searchMovie(title: String) = runBlocking { fun searchMovie(title: String) = runBlocking {
val url = URL("$searchMovieUrl$preparedParamters&query=${URLEncoder.encode(title, "UTF-8")}") val url = URL("$searchMovieUrl$preparedParameters&query=${URLEncoder.encode(title, "UTF-8")}")
GlobalScope.async { GlobalScope.async {
val response = JsonParser.parseString(url.readText()).asJsonObject val response = JsonParser.parseString(url.readText()).asJsonObject
println(response) //println(response)
return@async if (response.get("total_results").asInt > 0) { return@async if (response.get("total_results").asInt > 0) {
response.get("results").asJsonArray.first().let { response.get("results").asJsonArray.first().asJsonObject.let {
val overview = it.asJsonObject.get("overview").asString val overview = getStringNotNull(it,"overview")
val posterPath = imageUrl + it.asJsonObject.get("poster_path").asString val posterPath = getStringNotNullPrefix(it, "poster_path", imageUrl)
val backdropPath = imageUrl + it.asJsonObject.get("backdrop_path").asString val backdropPath = getStringNotNullPrefix(it, "backdrop_path", imageUrl)
TMDBResponse("", overview, posterPath, backdropPath) TMDBResponse("", overview, posterPath, backdropPath)
} }
@ -85,4 +80,24 @@ class TMDBApiController {
}.await() }.await()
} }
/**
* return memberName as string if it's not JsonNull,
* else return an empty string
*/
private fun getStringNotNull(jsonObject: JsonObject, memberName: String): String {
return getStringNotNullPrefix(jsonObject, memberName, "")
}
/**
* return memberName as string with a prefix if it's not JsonNull,
* else return an empty string
*/
private fun getStringNotNullPrefix(jsonObject: JsonObject, memberName: String, prefix: String): String {
return if (!jsonObject.get(memberName).isJsonNull) {
prefix + jsonObject.get(memberName).asString
} else {
""
}
}
} }

View File

@ -17,14 +17,27 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" > android:orientation="vertical" >
<ImageView <FrameLayout
android:id="@+id/image_poster" android:layout_width="match_parent"
android:layout_width="wrap_content" android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_gravity="center" <ImageView
android:layout_marginTop="20dp" android:id="@+id/image_backdrop"
android:minHeight="200dp" android:layout_width="match_parent"
android:src="@drawable/ic_launcher_background" /> android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:maxHeight="231dp"
android:minHeight="220dp" />
<ImageView
android:id="@+id/image_poster"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:minHeight="200dp"
android:src="@drawable/ic_launcher_background" />
</FrameLayout>
<Button <Button
android:id="@+id/button_play" android:id="@+id/button_play"
@ -54,18 +67,18 @@
android:layout_marginStart="7dp" android:layout_marginStart="7dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:layout_marginEnd="7dp" android:layout_marginEnd="7dp"
android:text="TextView" android:text="@string/text_title_ex"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView <TextView
android:id="@+id/text_desc" android:id="@+id/text_overview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginStart="7dp" android:layout_marginStart="7dp"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:layout_marginEnd="7dp" android:layout_marginEnd="7dp"
android:text="TextView" /> android:text="@string/text_overview_ex" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_episodes" android:id="@+id/recycler_episodes"

View File

@ -10,6 +10,8 @@
<!-- media fragment --> <!-- media fragment -->
<string name="button_play">Play</string> <string name="button_play">Play</string>
<string name="text_title_ex">A Silent Voice</string>
<string name="text_overview_ex">Shouya Ishida ist ein sehr aktives Kind. Mit seinen Freunden …</string>
<!-- settings fragment --> <!-- settings fragment -->
<string name="account">Account</string> <string name="account">Account</string>