this's first app for me , i tried to use api from my website into my app , when i open the app it say field to connect and it's dont show any data from website
note that : i use kotlin + android studio last version
i have checked my website and api via Postman and it's work perfect , so i think the problem in my app
here's my full code
AdMobHelper.kt
package com.khm.jobstest
import android.app.Activity
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.MobileAds
object AdMobHelper {
fun initializeAdMob(activity: Activity) {
MobileAds.initialize(activity) {}
}
fun loadBannerAd(adView: AdView) {
val adRequest = AdRequest.Builder().build()
adView.loadAd(adRequest)
}
}
ApiService.kt
package com.khm.jobstest
import retrofit2.Call
import retrofit2.http.GET
interface ApiService {
@GET("jobs/") // Use the correct endpoint
fun getJobs(): Call<List<JobModel>>
}
JobAdapter.kt
package com.khm.jobstest
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
class JobAdapter(private val jobs: List<JobModel>) :
RecyclerView.Adapter<JobAdapter.JobViewHolder>() {
class JobViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val jobImage: ImageView = view.findViewById(R.id.jobImage)
val jobName: TextView = view.findViewById(R.id.jobName)
val jobDetails: TextView = view.findViewById(R.id.jobDetails)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JobViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_job, parent, false)
return JobViewHolder(view)
}
override fun onBindViewHolder(holder: JobViewHolder, position: Int) {
val job = jobs[position]
holder.jobName.text = job.name
holder.jobDetails.text = job.app_contect
Glide.with(holder.itemView.context).load(job.app_image).into(holder.jobImage)
}
override fun getItemCount(): Int = jobs.size
}
JobModel.kt
package com.khm.jobstest
data class JobModel(
val name: String,
val app_contect: String,
val app_image: String
)
MainActivity.kt
package com.khm.jobstest
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.MobileAds
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var adView: AdView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initialize RecyclerView
recyclerView = findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(this)
// Initialize AdMob
MobileAds.initialize(this) {}
adView = findViewById(R.id.adView)
adView.loadAd(AdRequest.Builder().build())
// Check internet connection
if (!NetworkUtils.isOnline(this)) {
Toast.makeText(this, "يجب أن تستخدم الإنترنت للتصفح، حاول لاحقًا.", Toast.LENGTH_LONG).show()
return
}
// Fetch data from API
val retrofit = Retrofit.Builder()
.baseUrl("https://trainermods.net/api/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val apiService = retrofit.create(ApiService::class.java)
apiService.getJobs().enqueue(object : Callback<List<JobModel>> {
override fun onResponse(call: Call<List<JobModel>>, response: Response<List<JobModel>>) {
if (response.isSuccessful && response.body() != null) {
recyclerView.adapter = JobAdapter(response.body()!!)
} else {
Toast.makeText(this@MainActivity, "البيانات غير صالحة", Toast.LENGTH_SHORT).show()
}
}
override fun onFailure(call: Call<List<JobModel>>, t: Throwable) {
Toast.makeText(this@MainActivity, "فشل تحميل البيانات: ${t.message}", Toast.LENGTH_SHORT).show()
}
})
}
}
NetworkUtils.kt
package com.khm.jobstest
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
object NetworkUtils {
fun isOnline(context: Context): Boolean {
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
}
}
RetrofitInstance.kt
package com.khm.jobstest
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitInstance {
private const val BASE_URL = "https://trainermods.net/api/"
val retrofit: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
fun getRetrofitInstance(): Retrofit {
return retrofit
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- إذن الوصول إلى الإنترنت -->
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.JobTest"
tools:targetApi="31">
<!-- إضافة App ID لإعلانات AdMob -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
<!-- تعريف MainActivity مع تحديد android:exported -->
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.gms.ads.AdView
android:id="@+id/adView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
ads:adSize="BANNER"
ads:adUnitId="ca-app-pub-3940256099942544/6300978111" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
item_job.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<ImageView
android:id="@+id/jobImage"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/jobName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="اسم الوظيفة"
android:textSize="18sp"
android:textStyle="bold"
android:paddingTop="8dp" />
<TextView
android:id="@+id/jobDetails"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="وصف الوظيفة"
android:textSize="14sp"
android:paddingTop="4dp" />
</LinearLayout>
so please any idea, i need help
I think the problem is not in your Kotlin code, but in your API itself
As I can see your api is not returning pure JSON code. It's returning some html code and below it the Json string. This will make Kotlin code unable to parse the data properly.