I am a beginning computer science student. For school I have to make an app that can display data from an API. I use this API: http://openlibrary.org/search.json?q= The user of my app has to enter a booktitle or author, so they can find a book. I add the search value to the url. For example, if I want to search "The hobbit", the url would look like this: http://openlibrary.org/search.json?q=the%hobbit". However, the data does not get displayed. I don't have any errors either. Is there anyone that can help me? Thanks in advance!
My API service class
private const val BASE_URL = "http://openlibrary.org/"
private val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
private val retrofit = Retrofit.Builder()
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl(BASE_URL)
.build()
interface BoekenAPIService {
@GET("search.json")
suspend fun getBooksByTitle(@Query("q")search: String) : Base_BookTitle
}
object BookAPI {
val retrofitService : BoekenAPIService by lazy { retrofit.create(BoekenAPIService::class.java) }
}
My Base_BookTitle class
data class Base_BookTitle (
val numFound : Int,
val start : Int,
val numFoundExact : Boolean,
val docs : List<Q>,
val num_found : Int,
val book : String,
val offset : String
)
My Q class
@Parcelize
data class Q (
val key : String,
val type : String,
val seed : List<String>,
val title : String,
val title_suggest : String,
val has_fulltext : Boolean,
val edition_count : Int,
val edition_edition_key : List<String>,
val publish_date : List<String>,
val publish_year : List<Int>,
val first_publish_year : Int,
val number_of_pages_median : Int,
val lccn : List<Int>,
val publish_place : List<String>,
val oclc : List<Int>,
val contributor : List<String>,
val lcc : List<String>,
val ddc : List<Double>,
val isbn : List<Int>,
val last_modified_i : Int,
val ebook_count_i : Int,
val ia : List<String>,
val public_scan_b : Boolean,
val ia_collection_s : String,
val lending_edition_s : String,
val lending_identifier_s : String,
val printdisabled_s : String,
val cover_edition_cover_edition_key : String,
val cover_i : Int,
val publisher : List<String>,
val language : List<String>,
val author_author_key : List<String>,
val author_name : List<String>,
val author_alternative_name : List<String>,
val person : List<String>,
val place : List<String>,
val subject : List<String>,
val time : List<String>,
val id_alibris_id : List<Int>,
val id_amazon : List<String>,
val id_canadian_national_library_archive : List<Int>,
val id_depósito_legal : List<String>,
val id_goodreads : List<Int>,
val id_google : List<String>,
val id_librarything : List<Int>,
val id_overdrive : List<String>,
val id_paperback_swap : List<Int>,
val id_wikidata : List<String>,
val ia_loaded_id : List<String>,
val ia_box_id : List<String>,
val publisher_facet : List<String>,
val person_person_key : List<String>,
val place_place_key : List<String>,
val time_facet : List<String>,
val person_facet : List<String>,
val subject_facet : List<String>,
val _version_ : Int,
val place_facet : List<String>,
val lcc_sort : String,
val author_facet : List<String>,
val subject_subject_key : List<String>,
val ddc_sort : Double,
val time_time_key : List<String>
): Parcelable
I got the Base_Booktitle and Q class from a json to kotlin converter.
The ViewModel in which i call the method to display the data
class SearchViewModel(__user: User) : ViewModel() {
var _user = MutableLiveData<User>()
val user:LiveData<User>
get() {
return _user
}
var _baseBookTitle = MutableLiveData<Base_BookTitle?>()
val baseBooktitle : LiveData<Base_BookTitle?>
get() {
return _baseBookTitle
}
var search = MutableLiveData<String>()
var _error = MutableLiveData<String>()
val error : LiveData<String>
get() {
return _error
}
var _response = MutableLiveData<Q?>()
val response: LiveData<Q?>
get(){
return _response
}
init {
_user.value = __user
_error.value = null
}
fun searchBtnClicked(){
viewModelScope.launch {
try{
_baseBookTitle.value = BookAPI.retrofitService.getBooksByTitle(search.value!!)
}
catch (e: Exception){
_error.value = e.localizedMessage
}
}
}
fun onBookClicked(book: Q){
_response.value = book
}
fun navigateToBookFinished(){
_response.value = null
}
}
Thanks to a comment, I am now able to use a LoggingIntercepter
This is what I see in the logcat when I click the search button
2022-01-07 11:24:50.035 18171-18233/be.nienke.eindopdracht D/OkHttp: --> GET http://openlibrary.org/search.json?q=hobbit
2022-01-07 11:24:50.035 18171-18233/be.nienke.eindopdracht D/OkHttp: --> END GET
2022-01-07 11:24:50.055 18171-18215/be.nienke.eindopdracht I/OpenGLRenderer: Davey! duration=1591ms; Flags=0, IntendedVsync=183638171307131, Vsync=183639721307069, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=183639736870720, AnimationStart=183639736926020, PerformTraversalsStart=183639737189320, DrawStart=183639737431620, SyncQueued=183639738395720, SyncStart=183639738576620, IssueDrawCommandsStart=183639739072520, SwapBuffers=183639760591820, FrameCompleted=183639762891920, DequeueBufferDuration=250000, QueueBufferDuration=644000,
2022-01-07 11:24:50.237 18171-18233/be.nienke.eindopdracht D/OkHttp: <-- HTTP FAILED: java.net.UnknownServiceException: CLEARTEXT communication to openlibrary.org not permitted by network security policy
To solve the UnknownServiceException, I added this line to the AndroidManifest file:
android:usesCleartextTraffic="true"
Now the logcat shows the data from my API, but it doesn't display it on screen. Anyone that can help?