calling kotlin module inside react native app

63 views Asked by At

im a newbie in RN and i have no idea about kotlin, i have this kotlin module in RN app,

is working fine sending the location data to the backend, instead of sending to the backend from the kotlin module i want to send from the rn app so i want to receive the data in the rn app from the kotlin module

class ForegroundService(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

    companion object {
        private const val CHANNEL_ID = "ForegroundServiceChannel"
        private const val NOTIFICATION_ID = 1
    }

    override fun getName() = "ForegroundService"

    @ReactMethod
    fun startForegroundService() {
        Log.d("ForegroundService", "ForegroundService started QQQQQQQQQQQQQQQQQQQQQQQ")

        val serviceIntent = Intent(reactApplicationContext, LocationService::class.java)
        ContextCompat.startForegroundService(reactApplicationContext, serviceIntent)

    }



    private fun createNotificationChannel(context: Context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                CHANNEL_ID,
                "Foreground Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            val notificationManager =
                ContextCompat.getSystemService(context, NotificationManager::class.java)
            notificationManager?.createNotificationChannel(channel)
        }
    }

    private fun buildNotification(context: Context): Notification {
        val intent = Intent(context, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            context,
            0,
            intent,
            PendingIntent.FLAG_IMMUTABLE
        )

        return NotificationCompat.Builder(context, CHANNEL_ID)
            .setContentTitle("Foreground Service")
            .setContentText("Running...")
            .setSmallIcon(R.mipmap.ic_launcher)
            .setContentIntent(pendingIntent)
            .build()
    }

    private fun startForegroundService(context: Context, notification: Notification) {
        val serviceIntent = Intent(context, ForegroundService::class.java)
        ContextCompat.startForegroundService(context, serviceIntent)
        val notificationManager = NotificationManagerCompat.from(context)
        notificationManager.notify(NOTIFICATION_ID, notification)
    }
}
LocationService.kt
package locationService

import android.Manifest
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Location
import android.os.Build
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.foregroundserviceapplication.MainActivity
import com.foregroundserviceapplication.R
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import locationService.api.ApiService
import locationService.api.LocationData
import locationService.api.RetrofitClient
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response


class LocationService : Service() {

    companion object {
        private const val CHANNEL_ID = "LocationServiceChannel"
        private const val NOTIFICATION_ID = 1
    }

    private lateinit var notificationManager: NotificationManagerCompat
    private lateinit var fusedLocationClient: FusedLocationProviderClient
    private lateinit var locationCallback: LocationCallback
    private var locationUpdateInterval: Long = 10 * 1 * 1000 // 30 seconds
    private val locationHandler = Handler()
    private var isLocationTracking = false
    private var elapsedTime = 0L

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        super.onCreate()

        notificationManager = NotificationManagerCompat.from(this)

        createNotificationChannel()

        val notification = buildNotification("Fetching location...")

        startForeground(NOTIFICATION_ID, notification)



        fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        startLocationUpdates()

        // Schedule a task to stop the service after 30 minutes
        locationHandler.postDelayed({
            stopLocationUpdates()
            stopForeground(true)
            stopSelf()
        }, 30 * 60 * 1000) // 30 minutes

        return START_STICKY
    }

    private fun createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                CHANNEL_ID,
                "Location Service Channel",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }
    }

    private fun buildNotification(contentText: String): Notification {
        val intent = Intent(this, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            this,
            0,
            intent,
            PendingIntent.FLAG_IMMUTABLE
        )

        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Location Service")
            .setContentText(contentText)
            .setSmallIcon(R.drawable.baseline_my_location_24)
            .setContentIntent(pendingIntent)
            .setOngoing(true)
            .build()
    }

    private fun startLocationUpdates() {
        if (!isLocationTracking) {
            isLocationTracking = true
            if (ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.ACCESS_FINE_LOCATION
                ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.ACCESS_COARSE_LOCATION
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                // TODO: Consider calling
                //    ActivityCompat#requestPermissions
                // here to request the missing permissions, and then overriding
                //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
                //                                          int[] grantResults)
                // to handle the case where the user grants the permission. See the documentation
                // for ActivityCompat#requestPermissions for more details.
                return
            }
            fusedLocationClient.requestLocationUpdates(
                getLocationRequest(),
                getLocationCallback(),
                Looper.getMainLooper()
            )
            sendLocationUpdates()
        }
    }

    private fun stopLocationUpdates() {
        if (isLocationTracking) {
            isLocationTracking = false
            fusedLocationClient.removeLocationUpdates(locationCallback)
            locationHandler.removeCallbacksAndMessages(null)
        }
    }

    private fun getLocationRequest(): LocationRequest {
        return LocationRequest.create().apply {
            interval = locationUpdateInterval
            fastestInterval = locationUpdateInterval
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
    }

    private fun getLocationCallback(): LocationCallback {
        locationCallback = object : LocationCallback() {

            override fun onLocationResult(p0: LocationResult) {
                p0.lastLocation?.let { location ->
                   sendLocationToBackend(location)
                               }

            }

        }
        return locationCallback
    }

    private fun sendLocationToBackend(location: Location) {
        //val timestamp = System.currentTimeMillis()
        Log.e("LocationService",  location.longitude.toString()+ location.latitude.toString() + location.speed.toString())
        val locationData = LocationData(location.longitude,location.latitude,location.speed)
        val apiService = RetrofitClient.retrofit.create(ApiService::class.java)
        val call = apiService.sendLocation(locationData)
        call.enqueue(object : Callback<Void> {
            override fun onResponse(call: Call<Void>, response: Response<Void>) {
                if (response.isSuccessful) {
                    Log.e("LocationService", "Location sent successfully")
                } else {
                    Log.e("LocationService", "Failed to send location. Response code: ${response.code()}")
                }
            }
            override fun onFailure(call: Call<Void>, t: Throwable) {
                Log.e("LocationService", "Failed to send location: ${t.message}")
            }
        }) 
    }
 

    private fun sendLocationUpdates() {
        locationHandler.postDelayed({
            elapsedTime += locationUpdateInterval
            sendLocationUpdates()
        }, locationUpdateInterval)
    }

    override fun onDestroy() {
        super.onDestroy()
        stopLocationUpdates()
    }
}
App.js
  const handleStartForegroundService = async () => {
    try {
      return await ForegroundService.startForegroundService();}
catch (error) {
      console.error(error);
    }
}
0

There are 0 answers