diff --git a/CineCool/.idea/gradle.xml b/CineCool/.idea/gradle.xml index a2d7c21..a0de2a1 100644 --- a/CineCool/.idea/gradle.xml +++ b/CineCool/.idea/gradle.xml @@ -7,6 +7,7 @@ + diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/ApiClient.kt b/CineCool/app/src/main/java/fr/iut/cinecool/ApiClient.kt new file mode 100644 index 0000000..ff126be --- /dev/null +++ b/CineCool/app/src/main/java/fr/iut/cinecool/ApiClient.kt @@ -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 { + override fun onResponse(call: Call, response: Response) { + // 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, t: Throwable) { + // Code à exécuter en cas d'échec de la requête + } + }) + */ + } +} diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/DetailActivity.kt b/CineCool/app/src/main/java/fr/iut/cinecool/DetailActivity.kt new file mode 100644 index 0000000..2ecf9c7 --- /dev/null +++ b/CineCool/app/src/main/java/fr/iut/cinecool/DetailActivity.kt @@ -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 { + 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 + } + }) + }*/ + +} \ No newline at end of file diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/MainActivity.kt b/CineCool/app/src/main/java/fr/iut/cinecool/MainActivity.kt index eb774ec..df7894a 100644 --- a/CineCool/app/src/main/java/fr/iut/cinecool/MainActivity.kt +++ b/CineCool/app/src/main/java/fr/iut/cinecool/MainActivity.kt @@ -1,18 +1,10 @@ package fr.iut.cinecool -import android.Manifest import android.content.Intent import android.os.Bundle import android.widget.EditText import android.widget.ImageView -import com.google.android.material.snackbar.Snackbar import androidx.appcompat.app.AppCompatActivity -import androidx.core.app.ActivityCompat -import androidx.navigation.findNavController -import androidx.navigation.ui.AppBarConfiguration -import androidx.navigation.ui.navigateUp -import androidx.navigation.ui.setupActionBarWithNavController -import fr.iut.cinecool.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -36,4 +28,5 @@ class MainActivity : AppCompatActivity() { System.out.println(name) } } -} \ No newline at end of file +} + diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/MovieDetailFragment.kt b/CineCool/app/src/main/java/fr/iut/cinecool/MovieDetailFragment.kt new file mode 100644 index 0000000..98df4ed --- /dev/null +++ b/CineCool/app/src/main/java/fr/iut/cinecool/MovieDetailFragment.kt @@ -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 + } + } + }*/ +} \ No newline at end of file diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/RetrofitClient.kt b/CineCool/app/src/main/java/fr/iut/cinecool/RetrofitClient.kt new file mode 100644 index 0000000..66d1a23 --- /dev/null +++ b/CineCool/app/src/main/java/fr/iut/cinecool/RetrofitClient.kt @@ -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) +} diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/interfaces/ITheMovieDbApiCallback.kt b/CineCool/app/src/main/java/fr/iut/cinecool/interfaces/ITheMovieDbApiCallback.kt new file mode 100644 index 0000000..4184600 --- /dev/null +++ b/CineCool/app/src/main/java/fr/iut/cinecool/interfaces/ITheMovieDbApiCallback.kt @@ -0,0 +1,6 @@ +package fr.iut.cinecool.interfaces + +interface ITheMovieDbApiCallback { + fun onSuccess(result: T) + fun onError(error: Throwable) +} diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/interfaces/ITheMovieDbService.kt b/CineCool/app/src/main/java/fr/iut/cinecool/interfaces/ITheMovieDbService.kt new file mode 100644 index 0000000..5ab8bbd --- /dev/null +++ b/CineCool/app/src/main/java/fr/iut/cinecool/interfaces/ITheMovieDbService.kt @@ -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 +} diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/model/Movie.kt b/CineCool/app/src/main/java/fr/iut/cinecool/model/Movie.kt index c250227..1a00ecf 100644 --- a/CineCool/app/src/main/java/fr/iut/cinecool/model/Movie.kt +++ b/CineCool/app/src/main/java/fr/iut/cinecool/model/Movie.kt @@ -1,5 +1,14 @@ package fr.iut.cinecool.model 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) \ No newline at end of file +// 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 +) diff --git a/CineCool/app/src/main/java/fr/iut/cinecool/services/TheMovieDbApiClient.kt b/CineCool/app/src/main/java/fr/iut/cinecool/services/TheMovieDbApiClient.kt new file mode 100644 index 0000000..a6a474d --- /dev/null +++ b/CineCool/app/src/main/java/fr/iut/cinecool/services/TheMovieDbApiClient.kt @@ -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) { + service.getMovieDetails(movieId).enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + 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, t: Throwable) { + callback.onError(t) + } + }) + }*/ +} diff --git a/CineCool/app/src/main/res/drawable/back_arrow.png b/CineCool/app/src/main/res/drawable/back_arrow.png new file mode 100644 index 0000000..759b0b6 Binary files /dev/null and b/CineCool/app/src/main/res/drawable/back_arrow.png differ diff --git a/CineCool/app/src/main/res/drawable/filtrage.png b/CineCool/app/src/main/res/drawable/filtrage.png new file mode 100644 index 0000000..6447ce8 Binary files /dev/null and b/CineCool/app/src/main/res/drawable/filtrage.png differ diff --git a/CineCool/app/src/main/res/layout/vu_detail.xml b/CineCool/app/src/main/res/layout/vu_detail.xml new file mode 100644 index 0000000..e913444 --- /dev/null +++ b/CineCool/app/src/main/res/layout/vu_detail.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/CineCool/app/src/main/res/layout/vu_master_temp.xml b/CineCool/app/src/main/res/layout/vu_master_temp.xml new file mode 100644 index 0000000..c8efc90 --- /dev/null +++ b/CineCool/app/src/main/res/layout/vu_master_temp.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CineCool/app/src/main/res/values/strings.xml b/CineCool/app/src/main/res/values/strings.xml index 4a365df..1811ba6 100644 --- a/CineCool/app/src/main/res/values/strings.xml +++ b/CineCool/app/src/main/res/values/strings.xml @@ -9,6 +9,6 @@ Hello first fragment Hello second fragment. Arg: %1$s - - Hello blank fragment + erreur de chargement des films + a97243d7813d31446f6c43284e6854d5 \ No newline at end of file diff --git a/CineCool/build.gradle b/CineCool/build.gradle index ab2b874..3e76939 100644 --- a/CineCool/build.gradle +++ b/CineCool/build.gradle @@ -2,5 +2,5 @@ plugins { id 'com.android.application' version '7.4.2' apply false id 'com.android.library' version '7.4.2' apply false - id 'org.jetbrains.kotlin.android' version '1.8.0' apply false + id 'org.jetbrains.kotlin.android' version '1.8.20-RC2' apply false } \ No newline at end of file