Files
Radio/app/src/main/java/com/michatec/radio/search/RadioBrowserSearch.kt
2025-04-27 15:07:05 +02:00

144 lines
4.5 KiB
Kotlin

/*
* RadioBrowserSearch.kt
* Implements the RadioBrowserSearch class
* A RadioBrowserSearch performs searches on the radio-browser.info database
*
* This file is part of
* TRANSISTOR - Radio App for Android
*
* Copyright (c) 2015-22 - Y20K.org
* Licensed under the MIT-License
* http://opensource.org/licenses/MIT
*/
package com.michatec.radio.search
import android.content.Context
import android.util.Log
import com.android.volley.*
import com.android.volley.toolbox.JsonArrayRequest
import com.android.volley.toolbox.Volley
import com.google.gson.GsonBuilder
import org.json.JSONArray
import com.michatec.radio.BuildConfig
import com.michatec.radio.Keys
import com.michatec.radio.helpers.NetworkHelper
import com.michatec.radio.helpers.PreferencesHelper
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
/*
* RadioBrowserSearch class
*/
class RadioBrowserSearch(private var radioBrowserSearchListener: RadioBrowserSearchListener) {
/* Define log tag */
private val TAG: String = RadioBrowserSearch::class.java.simpleName
/* Interface used to send back search results */
interface RadioBrowserSearchListener {
fun onRadioBrowserSearchResults(results: Array<RadioBrowserResult>) {
}
}
/* Main class variables */
private var radioBrowserApi: String
private lateinit var requestQueue: RequestQueue
/* Init constructor */
init {
// get address of radio-browser.info api and update it in background
radioBrowserApi = PreferencesHelper.loadRadioBrowserApiAddress()
updateRadioBrowserApi()
}
/* Searches station(s) on radio-browser.info */
fun searchStation(context: Context, query: String, searchType: Int) {
Log.v(TAG, "Search - Querying $radioBrowserApi for: $query")
// create queue and request
requestQueue = Volley.newRequestQueue(context)
val requestUrl: String = when (searchType) {
// CASE: single station search - by radio browser UUID
Keys.SEARCH_TYPE_BY_UUID -> "https://${radioBrowserApi}/json/stations/byuuid/${query}"
// CASE: multiple results search by search term
else -> "https://${radioBrowserApi}/json/stations/search?name=${query.replace(" ", "+")}"
}
// request data from request URL
val stringRequest = object: JsonArrayRequest(Method.GET, requestUrl, null, responseListener, errorListener) {
@Throws(AuthFailureError::class)
override fun getHeaders(): Map<String, String> {
val params = HashMap<String, String>()
params["User-Agent"] = "$Keys.APPLICATION_NAME ${BuildConfig.VERSION_NAME}"
return params
}
}
// override retry policy
stringRequest.retryPolicy = object : RetryPolicy {
override fun getCurrentTimeout(): Int {
return 30000
}
override fun getCurrentRetryCount(): Int {
return 30000
}
@Throws(VolleyError::class)
override fun retry(error: VolleyError) {
Log.w(TAG, "Error: $error")
}
}
// add to RequestQueue.
requestQueue.add(stringRequest)
}
fun stopSearchRequest() {
if (this::requestQueue.isInitialized) {
requestQueue.stop()
}
}
/* Converts search result JSON string */
private fun createRadioBrowserResult(result: String): Array<RadioBrowserResult> {
val gsonBuilder = GsonBuilder()
gsonBuilder.setDateFormat("M/d/yy hh:mm a")
val gson = gsonBuilder.create()
return gson.fromJson(result, Array<RadioBrowserResult>::class.java)
}
/* Updates the address of the radio-browser.info api */
private fun updateRadioBrowserApi() {
CoroutineScope(IO).launch {
val deferred: Deferred<String> = async { NetworkHelper.getRadioBrowserServerSuspended() }
radioBrowserApi = deferred.await()
}
}
/* Listens for (positive) server responses to search requests */
private val responseListener: Response.Listener<JSONArray> = Response.Listener<JSONArray> { response ->
if (response != null) {
radioBrowserSearchListener.onRadioBrowserSearchResults(createRadioBrowserResult(response.toString()))
}
}
/* Listens for error response from server */
private val errorListener: Response.ErrorListener = Response.ErrorListener { error ->
Log.w(TAG, "Error: $error")
}
}