@ -0,0 +1,55 @@
|
|||||||
|
package fr.iut.cinecool
|
||||||
|
|
||||||
|
class ApiClient {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
/*private const val BASE_URL = "https://api.themoviedb.org/3/"
|
||||||
|
|
||||||
|
fun create(): ApiService {
|
||||||
|
|
||||||
|
val gson = GsonBuilder()
|
||||||
|
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||||
|
.create()
|
||||||
|
|
||||||
|
val logger = HttpLoggingInterceptor()
|
||||||
|
logger.level = HttpLoggingInterceptor.Level.BASIC
|
||||||
|
|
||||||
|
val client = OkHttpClient.Builder()
|
||||||
|
.addInterceptor(logger)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create(gson))
|
||||||
|
.client(client)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return retrofit.create(ApiService::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
val retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl("https://api.themoviedb.org/3/")
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val movieApiService = retrofit.create(ApiService::class.java)
|
||||||
|
|
||||||
|
val apiKey = "a97243d7813d31446f6c43284e6854d5"
|
||||||
|
val call = movieApiService.getPopularMovies(apiKey)
|
||||||
|
|
||||||
|
|
||||||
|
call.enqueue(object : Callback<MovieResponse> {
|
||||||
|
override fun onResponse(call: Call<MovieResponse>, response: Response<MovieResponse>) {
|
||||||
|
// Code à exécuter lorsque la réponse est reçue
|
||||||
|
val movies = response.body()?.results
|
||||||
|
// Traitez les films renvoyés ici
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: Call<MovieResponse>, t: Throwable) {
|
||||||
|
// Code à exécuter en cas d'échec de la requête
|
||||||
|
}
|
||||||
|
})
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package fr.iut.cinecool
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.ImageButton
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import fr.iut.cinecool.interfaces.ITheMovieDbApiCallback
|
||||||
|
import fr.iut.cinecool.model.Movie
|
||||||
|
import fr.iut.cinecool.model.MovieAPI
|
||||||
|
import fr.iut.cinecool.services.TheMovieDbApiClient
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Response
|
||||||
|
import javax.security.auth.callback.Callback
|
||||||
|
|
||||||
|
class DetailActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.vu_detail)
|
||||||
|
|
||||||
|
// Récupérer l'identifiant du film depuis les extras de l'intent
|
||||||
|
val movieId = intent.getIntExtra("movieId", -1)
|
||||||
|
|
||||||
|
// Appeler la méthode pour charger les détails du film
|
||||||
|
// loadMovieDetails(movieId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*private fun loadMovieDetails(movieId: Int) {
|
||||||
|
val apiClient = TheMovieDbApiClient(getString(R.string.tmdb_api_key))
|
||||||
|
apiClient.getMovieDetails(movieId, object : ITheMovieDbApiCallback<MovieAPI> {
|
||||||
|
override fun onSuccess(result: MovieAPI) {
|
||||||
|
// Afficher les détails du film dans la vue
|
||||||
|
titreFilm.text = result.title
|
||||||
|
description.text = result.overview
|
||||||
|
Picasso.get().load("https://image.tmdb.org/t/p/w500/${result.posterPath}").into(afficheFilm)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(error: Throwable) {
|
||||||
|
// Gérer l'erreur de récupération des détails du film
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package fr.iut.cinecool
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class MovieDetailFragment : Fragment() {
|
||||||
|
/*
|
||||||
|
private lateinit var binding: FragmentMovieDetailBinding
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?, savedInstanceState: Bundle?): View
|
||||||
|
{
|
||||||
|
binding = FragmentMovieDetailBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
|
||||||
|
{
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
val movieId = arguments?.getInt(ARG_MOVIE_ID)
|
||||||
|
|
||||||
|
// Appel de l'API pour récupérer les détails du film
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
val response = movieId?.let { MovieApiService().getMovieDetails(it) }
|
||||||
|
withContext(Dispatchers.Main)
|
||||||
|
{
|
||||||
|
if (response != null) {
|
||||||
|
if (response.isSuccessful)
|
||||||
|
{
|
||||||
|
val movie = response.body()
|
||||||
|
if (movie != null)
|
||||||
|
{
|
||||||
|
// Affichage des détails du film dans l'interface utilisateur
|
||||||
|
binding.titreFilm.text = movie.title
|
||||||
|
binding.description.text = movie.overview
|
||||||
|
binding.afficheFilm.load("https://image.tmdb.org/t/p/w500${movie.posterPath}") // Utilisation de la librairie Coil pour charger l'image
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Toast.makeText(
|
||||||
|
requireContext(),
|
||||||
|
getString(R.string.error_loading_movie),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Ajout d'un écouteur de clic pour le bouton de retour
|
||||||
|
binding.backButton.setOnClickListener {
|
||||||
|
requireActivity().onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ARG_MOVIE_ID = "movie_id"
|
||||||
|
|
||||||
|
fun newInstance(movieId: Int): MovieDetailFragment {
|
||||||
|
val args = Bundle().apply {
|
||||||
|
putInt(ARG_MOVIE_ID, movieId)
|
||||||
|
}
|
||||||
|
return MovieDetailFragment().apply {
|
||||||
|
arguments = args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package fr.iut.cinecool
|
||||||
|
|
||||||
|
import fr.iut.cinecool.services.TheMovieDbApiClient
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
object RetrofitClient {
|
||||||
|
private const val BASE_URL = "https://api.themoviedb.org/3/"
|
||||||
|
|
||||||
|
private val okHttpClient = OkHttpClient.Builder()
|
||||||
|
.connectTimeout(60, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(60, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(60, TimeUnit.SECONDS)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
private val retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL)
|
||||||
|
.client(okHttpClient)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val api: TheMovieDbApiClient = retrofit.create(TheMovieDbApiClient::class.java)
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package fr.iut.cinecool.interfaces
|
||||||
|
|
||||||
|
interface ITheMovieDbApiCallback<T> {
|
||||||
|
fun onSuccess(result: T)
|
||||||
|
fun onError(error: Throwable)
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package fr.iut.cinecool.interfaces
|
||||||
|
|
||||||
|
import fr.iut.cinecool.model.Movie
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Path
|
||||||
|
import retrofit2.http.Query
|
||||||
|
|
||||||
|
interface ITheMovieDbService {
|
||||||
|
@GET("movie/{movieId}")
|
||||||
|
fun getMovieDetails(@Path("movieId") movieId: Int, @Query("api_key") apiKey: String): Call<Movie>
|
||||||
|
}
|
@ -1,5 +1,14 @@
|
|||||||
package fr.iut.cinecool.model
|
package fr.iut.cinecool.model
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
data class Movie(val id:Int, val name:String, var mark:Int, val realisator:String, var duration: Double, val icon:Int)
|
||||||
|
|
||||||
data class Movie(val id:Int, val name:String, var mark:Int, val realisator:String, var duration: Double, val icon:Int)
|
// D'après l'API (TheMovieDB)
|
||||||
|
data class MovieAPI(
|
||||||
|
@SerializedName("id") val id: Int,
|
||||||
|
@SerializedName("title") val title: String,
|
||||||
|
@SerializedName("overview") val overview: String,
|
||||||
|
@SerializedName("poster_path") val posterPath: String?,
|
||||||
|
@SerializedName("vote_average") val voteAverage: Float
|
||||||
|
)
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
package fr.iut.cinecool.services
|
||||||
|
|
||||||
|
import fr.iut.cinecool.interfaces.ITheMovieDbApiCallback
|
||||||
|
import fr.iut.cinecool.interfaces.ITheMovieDbService
|
||||||
|
import fr.iut.cinecool.model.MovieAPI
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class TheMovieDbApiClient(apiKey: String) {
|
||||||
|
private val service: ITheMovieDbService = Retrofit.Builder()
|
||||||
|
.baseUrl("https://api.themoviedb.org/3/")
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
.create(ITheMovieDbService::class.java)
|
||||||
|
|
||||||
|
private val apiKeyInterceptor = Interceptor { chain ->
|
||||||
|
val url = chain.request().url.newBuilder()
|
||||||
|
.addQueryParameter("tmdb_api_key", apiKey)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = chain.request().newBuilder()
|
||||||
|
.url(url)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
chain.proceed(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val client: OkHttpClient = OkHttpClient.Builder()
|
||||||
|
.addInterceptor(apiKeyInterceptor)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
/*fun getMovieDetails(movieId: Int, callback: ITheMovieDbApiCallback<MovieAPI>) {
|
||||||
|
service.getMovieDetails(movieId).enqueue(object : Callback<MovieAPI> {
|
||||||
|
override fun onResponse(call: Call<MovieAPI>, response: Response<MovieAPI>) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
val result = response.body()
|
||||||
|
if (result != null) {
|
||||||
|
callback.onSuccess(result)
|
||||||
|
} else {
|
||||||
|
callback.onError(Throwable("Empty response body"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback.onError(Throwable("Error ${response.code()}: ${response.message()}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: Call<MovieAPI>, t: Throwable) {
|
||||||
|
callback.onError(t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}*/
|
||||||
|
}
|
After Width: | Height: | Size: 5.5 KiB |
After Width: | Height: | Size: 6.1 KiB |
@ -0,0 +1,60 @@
|
|||||||
|
<?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:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/backButton"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="55dp"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/back_arrow" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/titreFilm"
|
||||||
|
android:layout_width="220dp"
|
||||||
|
android:layout_height="25dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginTop="80dp"
|
||||||
|
android:text="TextView"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/logo"
|
||||||
|
android:layout_width="65dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/cinema"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/afficheFilm"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="400dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/titreFilm"
|
||||||
|
app:srcCompat="@drawable/imitation_game" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/description"
|
||||||
|
android:layout_width="380dp"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_marginTop="25dp"
|
||||||
|
android:text="TextView"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/afficheFilm" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,50 @@
|
|||||||
|
<?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:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/imageView"
|
||||||
|
android:layout_width="66dp"
|
||||||
|
android:layout_height="54dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/cinema" />
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="211dp"
|
||||||
|
android:layout_height="27dp"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/imageButton5"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||||
|
tools:layout_editor_absoluteY="29dp">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.SearchView
|
||||||
|
android:id="@+id/search_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:iconifiedByDefault="false"
|
||||||
|
app:queryHint="Rechercher" />
|
||||||
|
|
||||||
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/imageButton5"
|
||||||
|
android:layout_width="56dp"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:srcCompat="@drawable/filtrage"
|
||||||
|
tools:layout_editor_absoluteY="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in new issue