add the API logic

master
Julien THEME 2 years ago
parent 7b8d1cdb9d
commit e6571ba2bf

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/pixel_5_-_api_33.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-01-28T19:11:20.665081Z" />
</component>
</project>

@ -45,7 +45,8 @@ android {
dependencies {
implementation 'com.android.volley:volley:1.2.1'
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:converter-moshi:2.9.0"
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
@ -59,7 +60,6 @@ dependencies {
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
implementation 'androidx.navigation:navigation-compose:2.4.0-alpha10'
implementation 'androidx.compose.ui:ui:1.1.1'
implementation 'androidx.compose.material:material-icons-core:1.1.1'
implementation 'androidx.compose.material:material-icons-extended:1.1.1'
@ -69,4 +69,8 @@ dependencies {
implementation "androidx.compose.material:material:1.1.1"
implementation "androidx.compose.material:material-ripple:1.1.1"
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
}

@ -4,9 +4,9 @@ import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.example.cinapp.databinding.ActivityMainBinding
import com.example.cinapp.navigation.MovieFragment
import com.example.cinapp.navigation.SearchFragment
import com.example.cinapp.navigation.SerieFragment
import com.example.cinapp.model.navigation.MovieFragment
import com.example.cinapp.model.navigation.SearchFragment
import com.example.cinapp.model.navigation.SerieFragment
class MainActivity : AppCompatActivity() {

@ -0,0 +1,13 @@
package com.example.cinapp.Request
import com.example.cinapp.model.Movie
class Demmy (
var page: Int,
var results: List<MediaResponse>,
var total_pages: Int,
var total_results: Int
){
}

@ -0,0 +1,88 @@
package com.example.cinapp.Request
import android.util.Log
import com.example.cinapp.model.Media
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
class MediaApi {
private val retrofit = Retrofit.Builder()
.baseUrl("https://api.themoviedb.org/3/")
.addConverterFactory(MoshiConverterFactory.create())
.build()
private val service = retrofit.create(MediaService::class.java)
val mediaMapper = MediaMapper()
fun search(apiKey: String, language: String, query: String, page: Int, includeAdult: Boolean, callback: (List<Media>) -> Unit) {
val response: Call<Demmy> = service.searchMedia(apiKey, language, query, page, includeAdult)
val listMedia: MutableList<Media> = mutableListOf()
Log.d("TAG", "search: " + response.request().url())
response.enqueue(object : Callback<Demmy> {
override fun onResponse(call: Call<Demmy>, response: Response<Demmy>) {
Log.d("Liste1", response.body().toString())
val allMedia = response.body()
val listMediaResponse = allMedia?.results
listMediaResponse?.forEach { mediaResponse ->
val media = mediaMapper.searchMapToMedia(mediaResponse)
Log.d("Media", media.toString())
listMedia.add(media)
}
callback(listMedia)
}
override fun onFailure(call: Call<Demmy>, t: Throwable) {
Log.d("ErrorRetrofit", t.message.toString())
}
})
Log.d("Liste2", listMedia.size.toString())
}
fun getPopularMovies(apiKey: String): List<Media> {
val response: Call<Demmy> = service.getPopularMovies(apiKey)
val listMedia: MutableList<Media> = mutableListOf()
response.enqueue(object : Callback<Demmy> {
override fun onResponse(call: Call<Demmy>, response: Response<Demmy>) {
Log.d("Liste1", response.body().toString())
val allMedia = response.body()!!
val listMediaResponse = allMedia.results
listMediaResponse.forEach { mediaResponse ->
listMedia.add(mediaMapper.searchMapToMedia(mediaResponse))
}
}
override fun onFailure(call: Call<Demmy>, t: Throwable) {
Log.d("ErrorRetrofit", t.message.toString())
}
})
return listMedia
}
fun getForrestGump(): List<Media> {
val response: Call<Demmy> = service.getForrestGump()
val listMedia: MutableList<Media> = mutableListOf()
response.enqueue(object : Callback<Demmy> {
override fun onResponse(call: Call<Demmy>, response: Response<Demmy>) {
Log.d("Liste1", response.body().toString())
val allMedia = response.body()!!
val listMediaResponse = allMedia.results
listMediaResponse.forEach { mediaResponse ->
listMedia.add(mediaMapper.searchMapToMedia(mediaResponse))
}
}
override fun onFailure(call: Call<Demmy>, t: Throwable) {
Log.d("ErrorRetrofit", t.message.toString())
}
})
return listMedia
}
}

@ -0,0 +1,56 @@
package com.example.cinapp.Request
import com.example.cinapp.model.Media
import com.example.cinapp.model.Movie
import com.example.cinapp.model.Serie
class MediaMapper {
fun searchMapToMedia(mediaResponse: MediaResponse): Media {
return when (mediaResponse.media_type) {
"movie" -> searchMapToMovie(mediaResponse)
"tv" -> searchMapToSerie(mediaResponse)
else -> throw IllegalArgumentException("Invalid media type")
}
}
private fun searchMapToMovie(mediaResponse: MediaResponse): Movie {
return Movie(
id = mediaResponse.id,
title = mediaResponse.title,
overview = mediaResponse.overview,
posterPath = mediaResponse.poster_path,
releaseDate = mediaResponse.release_date,
genreIds = mediaResponse.genre_ids,
popularity = mediaResponse.popularity,
voteAverage = mediaResponse.vote_average,
voteCount = mediaResponse.vote_count,
adult = mediaResponse.adult,
backdropPath = mediaResponse.backdrop_path,
originalLanguage = mediaResponse.original_language,
originalName = mediaResponse.original_title,
originCountry = mediaResponse.origin_country
)
}
private fun searchMapToSerie(mediaResponse: MediaResponse): Serie {
return Serie(
id = mediaResponse.id,
title = mediaResponse.name,
overview = mediaResponse.overview,
posterPath = mediaResponse.poster_path,
releaseDate = mediaResponse.first_air_date,
genreIds = mediaResponse.genre_ids,
popularity = mediaResponse.popularity,
voteAverage = mediaResponse.vote_average,
voteCount = mediaResponse.vote_count,
adult = mediaResponse.adult,
backdropPath = mediaResponse.backdrop_path,
originalLanguage = mediaResponse.original_language,
originalName = mediaResponse.original_name,
originCountry = mediaResponse.origin_country
//seasons = mediaResponse.seasons,
//numberOfSeasons = mediaResponse.numberOfSeasons,
//numberOfEpisodes = mediaResponse.numberOfEpisodes
)
}
}

@ -0,0 +1,30 @@
package com.example.cinapp.Request
import com.example.cinapp.model.Season
class MediaResponse(
val adult: Boolean,
val id: Int,
val name: String,
val media_type: String,
val backdrop_path: String,
val first_air_date: String,
val origin_country: List<String>,
val original_language: String,
val original_name: String,
val overview : String,
val popularity: Double,
val poster_path: String,
val vote_average: Double,
val vote_count: Int,
val genre_ids: List<Int>,
val original_title: String,
val title: String,
val video: Boolean,
val release_date: String,
var seasons: List<Season>? = null,
var numberOfSeasons: Int? = null,
var numberOfEpisodes: Int? = null
) {
}

@ -0,0 +1,22 @@
package com.example.cinapp.Request
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
interface MediaService {
@GET("search/movie?api_key=e53e59cf1e29b9afff93d9ca1208f0cf&query=Forrest%20Gump&language=fr")
fun getForrestGump(): Call<Demmy>
@GET("search/multi")
fun searchMedia(
@Query("api_key") apiKey: String,
@Query("language") language: String,
@Query("query") query: String,
@Query("page") page: Int,
@Query("include_adult") includeAdult: Boolean
): Call<Demmy>
@GET("movie/popular")
fun getPopularMovies(@Query("api_key") apiKey: String): Call<Demmy>
}

@ -0,0 +1,32 @@
package com.example.cinapp.Request
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.cinapp.R
import com.example.cinapp.model.Movie
class MoviesAdapter(private val movies: List<Movie>) : RecyclerView.Adapter<MoviesAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_movie, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val movie = movies[position]
//holder.name.text = movie.name
Glide.with(holder.itemView.context).load(movie.posterPath).into(holder.image)
}
override fun getItemCount() = movies.size
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
//val name: TextView = itemView.findViewById(R.id.text_view_movie_name)
val image: ImageView = itemView.findViewById(R.id.image_view_movie)
}
}

@ -1,17 +1,19 @@
package com.example.cinapp.model
abstract class Media {
abstract val id: Int
abstract val name: String
abstract val backdropPath: String
abstract val releaseDate: String
abstract val originCountry: List<String>
abstract val originalLanguage: String
abstract val originalName: String
abstract val overview : String
abstract val popularity: Double
abstract val posterPath: String
abstract val voteAverage: Double
abstract val voteCount: Int
abstract val genreIds: List<Int>
open class Media (
val adult: Boolean? = null,
val id: Int,
val title: String? = null,
val backdropPath: String? = null,
val releaseDate: String? = null,
val originCountry: List<String>? = null,
val originalLanguage: String? = null,
val originalName: String? = null,
val overview : String? = null,
val popularity: Double? = null,
val posterPath: String? = null,
val voteAverage: Double? = null,
val voteCount: Int? = null,
val genreIds: List<Int>? = null
){
}

@ -1,44 +1,6 @@
package com.example.cinapp.model
class MediasLibrary(
var id : Int,
var mediasLibrary: List<Media>
){
override fun toString(): String {
return "MediasLibrary(id=$id, mediasLibrary=$mediasLibrary)"
}
//add a media to the library
fun addMedia(media: Media){
mediasLibrary += media
}
//remove a media from the library
fun removeMedia(media: Media){
mediasLibrary -= media
}
//get a media from the library
fun getMedia(media: Media): Media?{
return mediasLibrary.find { it.id == media.id }
}
//get all medias from the library
fun getAllMedias(): List<Media>{
return mediasLibrary
}
//get all medias from the library
fun getAllMediasByType(type: String): List<Media>{
var medias = mutableListOf<Media>()
for (media in mediasLibrary){
if (media is Movie && type == "movie"){
medias.add(media)
}
if (media is Serie && type == "serie"){
medias.add(media)
}
}
return medias
}
}

@ -1,19 +1,34 @@
package com.example.cinapp.model
class Movie(
override val id: Int,
override val name: String,
override val backdropPath: String,
override val releaseDate: String,
override val originCountry: List<String>,
override val originalLanguage: String,
override val originalName: String,
override val overview: String,
override val popularity: Double,
override val posterPath: String,
override val voteAverage: Double,
override val voteCount: Int,
override val genreIds: List<Int>
) : Media() {
adult: Boolean? = null,
id: Int,
title: String? = null,
backdropPath: String? = null,
releaseDate: String? = null,
originCountry: List<String>? = null,
originalLanguage: String? = null,
originalName: String? = null,
overview : String? = null,
popularity: Double? = null,
posterPath: String? = null,
voteAverage: Double? = null,
voteCount: Int? = null,
genreIds: List<Int>? = null
): Media(
adult,
id,
title,
backdropPath,
releaseDate,
originCountry,
originalLanguage,
originalName,
overview,
popularity,
posterPath,
voteAverage,
voteCount,
genreIds
) {
}

@ -1,21 +1,37 @@
package com.example.cinapp.model
class Serie(
override val id: Int,
override val name: String,
override val backdropPath: String,
override val releaseDate: String,
override val originCountry: List<String>,
override val originalLanguage: String,
override val originalName: String,
override val overview: String,
override val popularity: Double,
override val posterPath: String,
override val voteAverage: Double,
override val voteCount: Int,
override val genreIds: List<Int>,
var seasons: List<Season>,
var numberOfSeasons: Int,
var numberOfEpisodes: Int
) : Media() {
adult: Boolean? = null,
id: Int,
title: String? = null,
backdropPath: String? = null,
releaseDate: String? = null,
originCountry: List<String>? = null,
originalLanguage: String? = null,
originalName: String? = null,
overview : String? = null,
popularity: Double? = null,
posterPath: String? = null,
voteAverage: Double? = null,
voteCount: Int? = null,
genreIds: List<Int>? = null,
var seasons: List<Season>? = null,
var numberOfSeasons: Int? = null,
var numberOfEpisodes: Int? = null
) : Media(
adult,
id,
title,
backdropPath,
releaseDate,
originCountry,
originalLanguage,
originalName,
overview,
popularity,
posterPath,
voteAverage,
voteCount,
genreIds
) {
}

@ -1,11 +1,26 @@
package com.example.cinapp.navigation
package com.example.cinapp.model.navigation
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.cinapp.R
import com.example.cinapp.Request.Demmy
import com.example.cinapp.Request.MediaApi
import com.example.cinapp.Request.MediaService
import com.example.cinapp.Request.MoviesAdapter
import com.example.cinapp.model.Media
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
@ -28,14 +43,37 @@ class MovieFragment : Fragment() {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_movie, container, false)
// Récupération de la vue racine
val rootView = inflater.inflate(R.layout.fragment_movie, container, false)
// Récupération de la vue souhaitée
val myView = rootView.findViewById<TextView>(R.id.name)
//var listMedias : Unit = MediaApi().search("e53e59cf1e29b9afff93d9ca1208f0cf", "en-US", "One Piece", 1, false) { listMedia -> listMedia }
//var listMedia : List<Media> = MediaApi().getPopularMovies("e53e59cf1e29b9afff93d9ca1208f0cf")
//var listMedia : List<Media> = MediaApi().getForrestGump()
val apiKey = "e53e59cf1e29b9afff93d9ca1208f0cf"
val language = "en-US"
val query = "One Piece"
val page = 1
val includeAdult = false
MediaApi().search(apiKey, language, query, page, includeAdult) { listMedia ->
//Do something with listMedia
Log.d("TAG", "onCreateView: " + listMedia)
Log.d("Image", "onCreateView: " + listMedia[0].posterPath.toString())
myView.text = listMedia[0].title.toString() + " " + listMedia[0].id.toString() + " " + listMedia[0].posterPath.toString()
}
return rootView
}
companion object {

@ -1,4 +1,4 @@
package com.example.cinapp.navigation
package com.example.cinapp.model.navigation
import android.os.Bundle
import androidx.fragment.app.Fragment

@ -1,4 +1,4 @@
package com.example.cinapp.navigation
package com.example.cinapp.model.navigation
import android.os.Bundle
import androidx.fragment.app.Fragment

@ -1,4 +1,4 @@
package com.example.cinapp.navigation
package com.example.cinapp.model.navigation
import android.os.Bundle
import androidx.fragment.app.Fragment

@ -1,4 +1,4 @@
package com.example.cinapp.navigation
package com.example.cinapp.model.navigation
import android.os.Bundle
import androidx.fragment.app.Fragment

@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/material_dynamic_secondary30"
tools:context=".navigation.MovieFragment">
tools:context=".model.navigation.MovieFragment">
<com.google.android.material.tabs.TabLayout
@ -27,14 +27,24 @@
</com.google.android.material.tabs.TabLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/movie_layout"
android:layout_width="0dp"
android:layout_height="0dp"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view_movies"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/purple_200"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tabLayout" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".navigation.Movies2SeeFragment">
tools:context=".model.navigation.Movies2SeeFragment">
<!-- TODO: Update blank fragment layout -->
<TextView

@ -1,24 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/searchcl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/purple_700"
tools:context=".navigation.SearchFragment">
tools:context=".model.navigation.SearchFragment">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Search"
android:textSize="26dp"
android:layout_gravity="center"/>
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="MissingConstraints">
<SearchView
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Seen movies" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Movies to see" />
</com.google.android.material.tabs.TabLayout>
<androidx.appcompat.widget.SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:layout_constraintTop_toTopOf="parent" />
android:background="@color/black"
android:queryHint="Search"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:iconifiedByDefault="false"
app:layout_constraintTop_toBottomOf="@+id/tabLayout" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".navigation.SeenMoviesFragment">
tools:context=".model.navigation.SeenMoviesFragment">
<!-- TODO: Update blank fragment layout -->
<TextView

@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/purple_200"
tools:context=".navigation.SerieFragment">
tools:context=".model.navigation.SerieFragment">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/material_dynamic_secondary30"
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="vertical">
<ImageView
android:id="@+id/image_view_movie"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="MissingConstraints"/>
<TextView
android:id="@+id/text_view_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Title"/>
<!--<TextView
android:id="@+id/text_view_movie_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="16dp" />-->
</androidx.constraintlayout.widget.ConstraintLayout>
Loading…
Cancel
Save