From d9bd716a59ca564caca5e59115aafd446ea1541d Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Wed, 5 Mar 2025 14:50:30 +0700 Subject: [PATCH 1/2] Convert AudiosFragment file extension from .java to .kt --- .../ui/audio/{AudiosFragment.java => AudiosFragment.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/main/java/ai/elimu/content_provider/ui/audio/{AudiosFragment.java => AudiosFragment.kt} (100%) diff --git a/app/src/main/java/ai/elimu/content_provider/ui/audio/AudiosFragment.java b/app/src/main/java/ai/elimu/content_provider/ui/audio/AudiosFragment.kt similarity index 100% rename from app/src/main/java/ai/elimu/content_provider/ui/audio/AudiosFragment.java rename to app/src/main/java/ai/elimu/content_provider/ui/audio/AudiosFragment.kt From 30574dd3e03c72da8981df05f0487e518436e834 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Wed, 5 Mar 2025 14:53:54 +0700 Subject: [PATCH 2/2] Convert AudiosFragment from Java to Kotlin --- .../ui/audio/AudiosFragment.kt | 263 +++++++++--------- 1 file changed, 126 insertions(+), 137 deletions(-) diff --git a/app/src/main/java/ai/elimu/content_provider/ui/audio/AudiosFragment.kt b/app/src/main/java/ai/elimu/content_provider/ui/audio/AudiosFragment.kt index 2b3fc29e..c9cad71c 100644 --- a/app/src/main/java/ai/elimu/content_provider/ui/audio/AudiosFragment.kt +++ b/app/src/main/java/ai/elimu/content_provider/ui/audio/AudiosFragment.kt @@ -1,177 +1,166 @@ -package ai.elimu.content_provider.ui.audio; - -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProvider; - -import com.google.android.material.snackbar.Snackbar; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import ai.elimu.content_provider.BaseApplication; -import ai.elimu.content_provider.R; -import ai.elimu.content_provider.rest.AudiosService; -import ai.elimu.content_provider.room.GsonToRoomConverter; -import ai.elimu.content_provider.room.dao.AudioDao; -import ai.elimu.content_provider.room.db.RoomDb; -import ai.elimu.content_provider.room.entity.Audio; -import ai.elimu.content_provider.util.FileHelper; -import ai.elimu.content_provider.util.MultimediaDownloader; -import ai.elimu.model.v2.gson.content.AudioGson; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; -import retrofit2.Retrofit; - -public class AudiosFragment extends Fragment { - - private AudiosViewModel audiosViewModel; - - private ProgressBar progressBar; - - private TextView textView; - - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - Log.i(getClass().getName(), "onCreateView"); - - audiosViewModel = new ViewModelProvider(this).get(AudiosViewModel.class); - View root = inflater.inflate(R.layout.fragment_audios, container, false); - progressBar = root.findViewById(R.id.progress_bar_audios); - textView = root.findViewById(R.id.text_audios); - audiosViewModel.getText().observe(getViewLifecycleOwner(), new Observer() { - @Override - public void onChanged(@Nullable String s) { - Log.i(getClass().getName(), "onChanged"); - textView.setText(s); +package ai.elimu.content_provider.ui.audio + +import ai.elimu.content_provider.BaseApplication +import ai.elimu.content_provider.R +import ai.elimu.content_provider.rest.AudiosService +import ai.elimu.content_provider.room.GsonToRoomConverter +import ai.elimu.content_provider.room.db.RoomDb +import ai.elimu.content_provider.util.FileHelper +import ai.elimu.content_provider.util.MultimediaDownloader +import ai.elimu.model.v2.gson.content.AudioGson +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ProgressBar +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import com.google.android.material.snackbar.Snackbar +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import java.io.FileNotFoundException +import java.io.FileOutputStream +import java.io.IOException +import java.util.concurrent.Executors + +class AudiosFragment : Fragment() { + private var audiosViewModel: AudiosViewModel? = null + + private var progressBar: ProgressBar? = null + + private var textView: TextView? = null + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + Log.i(javaClass.name, "onCreateView") + + audiosViewModel = ViewModelProvider(this).get(AudiosViewModel::class.java) + val root = inflater.inflate(R.layout.fragment_audios, container, false) + progressBar = root.findViewById(R.id.progress_bar_audios) + textView = root.findViewById(R.id.text_audios) as? TextView + audiosViewModel!!.text.observe(viewLifecycleOwner, object : Observer { + override fun onChanged(s: String?) { + Log.i(javaClass.name, "onChanged") + textView?.text = s } - }); - return root; + }) + return root } - @Override - public void onStart() { - Log.i(getClass().getName(), "onStart"); - super.onStart(); + override fun onStart() { + Log.i(javaClass.name, "onStart") + super.onStart() // Download Audios from REST API, and store them in the database - BaseApplication baseApplication = (BaseApplication) getActivity().getApplication(); - Retrofit retrofit = baseApplication.getRetrofit(); - AudiosService audiosService = retrofit.create(AudiosService.class); - Call> audioGsonsCall = audiosService.listAudios(); - Log.i(getClass().getName(), "audioGsonsCall.request(): " + audioGsonsCall.request()); - audioGsonsCall.enqueue(new Callback>() { - - @Override - public void onResponse(Call> call, Response> response) { - Log.i(getClass().getName(), "onResponse"); - - Log.i(getClass().getName(), "response: " + response); - if (response.isSuccessful()) { - List audioGsons = response.body(); - Log.i(getClass().getName(), "audioGsons.size(): " + audioGsons.size()); - - if (audioGsons.size() > 0) { - processResponseBody(audioGsons); + val baseApplication = activity!!.application as BaseApplication + val retrofit = baseApplication.retrofit + val audiosService = retrofit.create(AudiosService::class.java) + val audioGsonsCall = audiosService.listAudios() + Log.i(javaClass.name, "audioGsonsCall.request(): " + audioGsonsCall.request()) + audioGsonsCall.enqueue(object : Callback> { + override fun onResponse( + call: Call>, + response: Response> + ) { + Log.i(javaClass.name, "onResponse") + + Log.i(javaClass.name, "response: $response") + if (response.isSuccessful) { + val audioGsons = response.body()!! + Log.i(javaClass.name, "audioGsons.size(): " + audioGsons.size) + + if (audioGsons.size > 0) { + processResponseBody(audioGsons) } } else { // Handle error - Snackbar.make(textView, response.toString(), Snackbar.LENGTH_LONG) - .setBackgroundTint(getResources().getColor(R.color.deep_orange_darken_4)) - .show(); - progressBar.setVisibility(View.GONE); + Snackbar.make(textView!!, response.toString(), Snackbar.LENGTH_LONG) + .setBackgroundTint(resources.getColor(R.color.deep_orange_darken_4)) + .show() + progressBar!!.visibility = View.GONE } } - @Override - public void onFailure(Call> call, Throwable t) { - Log.e(getClass().getName(), "onFailure", t); + override fun onFailure(call: Call>, t: Throwable) { + Log.e(javaClass.name, "onFailure", t) - Log.e(getClass().getName(), "t.getCause():", t.getCause()); + Log.e(javaClass.name, "t.getCause():", t.cause) // Handle error - Snackbar.make(textView, t.getCause().toString(), Snackbar.LENGTH_LONG) - .setBackgroundTint(getResources().getColor(R.color.deep_orange_darken_4)) - .show(); - progressBar.setVisibility(View.GONE); + Snackbar.make(textView!!, t.cause.toString(), Snackbar.LENGTH_LONG) + .setBackgroundTint(resources.getColor(R.color.deep_orange_darken_4)) + .show() + progressBar!!.visibility = View.GONE } - }); + }) } - private void processResponseBody(List audioGsons) { - Log.i(getClass().getName(), "processResponseBody"); + private fun processResponseBody(audioGsons: List) { + Log.i(javaClass.name, "processResponseBody") - ExecutorService executorService = Executors.newSingleThreadExecutor(); - executorService.execute(new Runnable() { - @Override - public void run() { - Log.i(getClass().getName(), "run"); + val executorService = Executors.newSingleThreadExecutor() + executorService.execute(object : Runnable { + override fun run() { + Log.i(javaClass.name, "run") - RoomDb roomDb = RoomDb.getDatabase(getContext()); - AudioDao audioDao = roomDb.audioDao(); + val roomDb = RoomDb.getDatabase(context) + val audioDao = roomDb.audioDao() // Empty the database table before downloading up-to-date content - audioDao.deleteAll(); - // TODO: also delete corresponding audio files (only those that are no longer used) + audioDao.deleteAll() - for (AudioGson audioGson : audioGsons) { - Log.i(getClass().getName(), "audioGson.getId(): " + audioGson.getId()); + // TODO: also delete corresponding audio files (only those that are no longer used) + for (audioGson in audioGsons) { + Log.i(javaClass.name, "audioGson.getId(): " + audioGson.id) - Audio audio = GsonToRoomConverter.getAudio(audioGson); + val audio = GsonToRoomConverter.getAudio(audioGson) // Check if the corresponding audio file has already been downloaded - File audioFile = FileHelper.getAudioFile(audioGson, getContext()); - Log.i(getClass().getName(), "audioFile: " + audioFile); - Log.i(getClass().getName(), "audioFile.exists(): " + audioFile.exists()); + val audioFile = FileHelper.getAudioFile(audioGson, context) + Log.i(javaClass.name, "audioFile: $audioFile") + Log.i(javaClass.name, "audioFile.exists(): " + audioFile.exists()) if (!audioFile.exists()) { // Download file bytes - BaseApplication baseApplication = (BaseApplication) getActivity().getApplication(); - String downloadUrl = baseApplication.getBaseUrl() + audioGson.getBytesUrl(); - Log.i(getClass().getName(), "downloadUrl: " + downloadUrl); - byte[] bytes = MultimediaDownloader.downloadFileBytes(downloadUrl); - Log.i(getClass().getName(), "bytes.length: " + bytes.length); + val baseApplication = activity!!.application as BaseApplication + val downloadUrl = baseApplication.baseUrl + audioGson.bytesUrl + Log.i(javaClass.name, "downloadUrl: $downloadUrl") + val bytes = MultimediaDownloader.downloadFileBytes(downloadUrl) + Log.i(javaClass.name, "bytes.length: " + bytes.size) // Store the downloaded file in the external storage directory try { - FileOutputStream fileOutputStream = new FileOutputStream(audioFile); - fileOutputStream.write(bytes); - } catch (FileNotFoundException e) { - Log.e(getClass().getName(), null, e); - } catch (IOException e) { - Log.e(getClass().getName(), null, e); + val fileOutputStream = FileOutputStream(audioFile) + fileOutputStream.write(bytes) + } catch (e: FileNotFoundException) { + Log.e(javaClass.name, null, e) + } catch (e: IOException) { + Log.e(javaClass.name, null, e) } - Log.i(getClass().getName(), "audioFile.exists(): " + audioFile.exists()); + Log.i(javaClass.name, "audioFile.exists(): " + audioFile.exists()) } // Store the Audio in the database - audioDao.insert(audio); - Log.i(getClass().getName(), "Stored Audio in database with ID " + audio.getId()); + audioDao.insert(audio) + Log.i(javaClass.name, "Stored Audio in database with ID " + audio.id) } // Update the UI - List