Android Studio/Kotlin. I'm assuimng the issue is coming from it not being able to convert the json to gson. But I'm not sure if that the case. But based on what I could uncover myself before giving up and asking for help is it might be a error from the rockService. Because I can connent to the network fine and it does retrive the data but still pulls the error message and says it failed. Any help would be appricated
RockService
import com.google.gson.Gson
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
class RockService {
private val gson by lazy{
Gson().newBuilder()
}
private val loggingInterceptor by lazy{
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
}
private val okHttpClient by lazy {
OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30,TimeUnit.SECONDS)
.readTimeout(30,TimeUnit.SECONDS)
.build()
}
val rockAPI: RockAPI by lazy{
Retrofit.Builder()
.baseUrl(RockAPI.BASR_URL)
.addConverterFactory(GsonConverterFactory.create(gson.create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build()
.create(RockAPI::class.java)
}
}
RockNetworkItem
import com.google.gson.annotations.SerializedName
data class RockNetworkItem (
@SerializedName("Id")
val artId : Int? = null,
@SerializedName("NameOfArt")
val nameOfArt : String? = null,
@SerializedName("NameOfCollection")
val nameOfCollection : String? = null,
@SerializedName("TrackPrice")
val trackPrice : Double? = null,
@SerializedName("artworkUrl")
val artworkUrl60: String ? = null,
)
RockAPI
import io.reactivex.Single
import retrofit2.http.GET
interface RockAPI {
@GET("search?term=rock&media=music&entity=song&limit=50")
fun getAllRocks() : Single<List<RockNetworkItem>>
companion object{
const val BASR_URL = "https://itunes.apple.com/"
}
}
RockDomain
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.gson.annotations.SerializedName
@Entity(tableName = "Rock_Table")
class RockDomain (
@PrimaryKey
@SerializedName("artistId")
val artistId: Int,
@SerializedName("artistName")
val artistName: String,
@SerializedName("collectionName")
val collectionName: String,
@SerializedName("trackPrice")
val trackPrice: Double,
@SerializedName("artworkUrl60")
val artworkUrl60: String,
)
fun List<RockNetworkItem>
.mapToDomainRockList(): List<RockDomain> =
this.map {
RockDomain(
artistName = it.nameOfArt ?: "",
collectionName = it.nameOfCollection ?: "",
trackPrice = (it.trackPrice ?: 999999) as Double,
artistId = it.artId ?: 999999,
artworkUrl60 = it.artworkUrl60?: "",
)
}
fun RockNetworkItem.mapToDomainRock(): RockDomain =
RockDomain(
artistName = this.nameOfArt ?: "",
collectionName = this.nameOfCollection?: "",
trackPrice = (this.trackPrice ?: 99999) as Double,
artistId = this.artId ?: 999999,
artworkUrl60 = this.artworkUrl60?: ""
)
RockModel
import androidx.room.PrimaryKey
import com.google.gson.annotations.SerializedName
data class RockModerl(
@PrimaryKey (autoGenerate = false)
@SerializedName("artistId")
val artistId: Int,
@SerializedName("artistName")
val artistName: String,
@SerializedName("artistViewUrl")
val artistViewUrl: String,
@SerializedName("artworkUrl100")
val artworkUrl100: String,
@SerializedName("artworkUrl30")
val artworkUrl30: String,
@SerializedName("artworkUrl60")
val artworkUrl60: String,
@SerializedName("collectionCensoredName")
val collectionCensoredName: String,
@SerializedName("collectionExplicitness")
val collectionExplicitness: String,
@SerializedName("collectionId")
val collectionId: Int,
@SerializedName("collectionName")
val collectionName: String,
@SerializedName("collectionPrice")
val collectionPrice: Double,
@SerializedName("collectionViewUrl")
val collectionViewUrl: String,
@SerializedName("contentAdvisoryRating")
val contentAdvisoryRating: String,
@SerializedName("country")
val country: String,
@SerializedName("currency")
val currency: String,
@SerializedName("discCount")
val discCount: Int,
@SerializedName("discNumber")
val discNumber: Int,
@SerializedName("isStreamable")
val isStreamable: Boolean,
@SerializedName("kind")
val kind: String,
@SerializedName("previewUrl")
val previewUrl: String,
@SerializedName("primaryGenreName")
val primaryGenreName: String,
@SerializedName("releaseDate")
val releaseDate: String,
@SerializedName("trackCensoredName")
val trackCensoredName: String,
@SerializedName("trackCount")
val trackCount: Int,
@SerializedName("trackExplicitness")
val trackExplicitness: String,
@SerializedName("trackId")
val trackId: Int,
@SerializedName("trackName")
val trackName: String,
@SerializedName("trackNumber")
val trackNumber: Int,
@SerializedName("trackPrice")
val trackPrice: Double,
@SerializedName("trackTimeMillis")
val trackTimeMillis: Int,
@SerializedName("trackViewUrl")
val trackViewUrl: String,
@SerializedName("wrapperType")
val wrapperType: String
)
Rockpresenter
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import com.example.homework3.rockdata.model.RockDomain
import io.reactivex.disposables.CompositeDisposable
import javax.inject.Inject
/**
* Rock presenter to for the rock fragment
*/
interface RockPresenter {
fun init(viewContract: ViewContractRock)
fun checkNetworkConnection(connectivityManager: ConnectivityManager)
fun getRock()
fun destroy()
}
interface ViewContractRock
{
fun loadingRock(isLoading : Boolean)
fun onSuccess(rock : List<RockDomain>)
fun onFailure(error: Throwable)
}
class AllRockPresenterImpl(
private val rockDAO: RockDAO,
private val repository : RockReposiory = RockRe(rockDAO),
private val disposable : CompositeDisposable = CompositeDisposable()
) : RockPresenter
{
private var contractRock : ViewContractRock? = null
override fun init(viewContract: ViewContractRock) {
contractRock = viewContract
}
override fun checkNetworkConnection(connectivityManager: ConnectivityManager) {
connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)?.let {
if (it.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
contractRock?.onFailure(Throwable("No"))
}
}
}
override fun getRock() {
contractRock?.loadingRock(true)
repository.getAllRock().subscribe(
{roccks -> contractRock?.onSuccess(roccks)},
{ error -> contractRock?.onFailure(error)} // This should load from the data base
) .also { disposable.add(it) }
}
override fun destroy() {
TODO("Not yet implemented")
}
}
RockFragment
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.room.Room
import com.example.homework3.databinding.FragmentRockBinding
import com.example.homework3.rockdata.*
import com.example.homework3.rockdata.model.RockDomain
import javax.inject.Inject
class RockFragment : Fragment(),ViewContractRock {
private val binding by lazy{
FragmentRockBinding.inflate(layoutInflater)
}
private val rockAdapter by lazy{
RockA()
}
//make an adapter and pass value here
private val rockDB by lazy{
RockDB.getRockDataBaseIn(requireContext())
}
private val presenter by lazy{
AllRockPresenterImpl(rockDB.Dao())
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
presenter.init(this)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding.RockRE.apply {
layoutManager = LinearLayoutManager(requireContext(),LinearLayoutManager.VERTICAL,false)
adapter = RockA()
}
presenter.getRock()
return binding.root
}
override fun loadingRock(isLoading: Boolean) {
Toast.makeText(requireContext(), "Loading", Toast.LENGTH_LONG).show()
Log.d("Network", "Loading Data")
}
override fun onSuccess(rock: List<RockDomain>) {
//rockAdapter.
//Use adapater to change view to add the data
rockAdapter.updateRock(rock)
Toast.makeText(requireContext(), "Success", Toast.LENGTH_LONG).show()
Log.d("Network", "Data has loaded")
}
override fun onFailure(error: Throwable) {
Log.e("Network", "onFailure: ${error.localizedMessage}", error)
Toast.makeText(requireContext(), "Failed", Toast.LENGTH_LONG).show()
}
}