Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get a geographic location use Intent Service #53

Open
thanhnguyenduc157 opened this issue Jun 21, 2019 · 1 comment
Open

Get a geographic location use Intent Service #53

thanhnguyenduc157 opened this issue Jun 21, 2019 · 1 comment
Labels

Comments

@thanhnguyenduc157
Copy link

The getFromLocation() method provided by the Geocoder class accepts a latitude and longitude and returns a list of addresses. The method is synchronous and may take a long time to do its work, so you should not call it from the main, user interface (UI) thread of your app.

The IntentService class provides a structure for running a task on a background thread. Using this class, you can handle a long-running operation without affecting your UI's responsiveness.

Define a FetchAddressIntentService class that extends IntentService. This class is your address lookup service. The intent service handles an intent asynchronously on a worker thread and stops itself when it runs out of work. The intent extras provide the data needed by the service, including a Location object for conversion to an address and a ResultReceiver object to handle the results of the address lookup. The service uses a Geocoder to fetch the address for the location and sends the results to the ResultReceiver.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.google.android.gms.location.sample.locationaddress" >
    <application
        ...
        <service
            android:name=".FetchAddressIntentService"
            android:exported="false"/>
    </application>
    ...
</manifest>

protected fun onHandleIntent(intent: Intent?) {intent ?: return

    var errorMessage = ""

    // Get the location passed to this service through an extra.
    val location = intent.getParcelableExtra(
            Constants.LOCATION_DATA_EXTRA)

    // ...

    var addresses: List<Address> = emptyList()

    try {
        addresses = geocoder.getFromLocation(
                location.latitude,
                location.longitude,
                // In this sample, we get just a single address.
                1)
    } catch (ioException: IOException) {
        // Catch network or other I/O problems.
        errorMessage = getString(R.string.service_not_available)
        Log.e(TAG, errorMessage, ioException)
    } catch (illegalArgumentException: IllegalArgumentException) {
        // Catch invalid latitude or longitude values.
        errorMessage = getString(R.string.invalid_lat_long_used)
        Log.e(TAG, "$errorMessage. Latitude = $location.latitude , " +
                "Longitude =  $location.longitude", illegalArgumentException)
    }

    // Handle case where no address was found.
    if (addresses.isEmpty()) {
        if (errorMessage.isEmpty()) {
            errorMessage = getString(R.string.no_address_found)
            Log.e(TAG, errorMessage)
        }
        deliverResultToReceiver(Constants.FAILURE_RESULT, errorMessage)
    } else {
        val address = addresses[0]
        // Fetch the address lines using getAddressLine,
        // join them, and send them to the thread.
        val addressFragments = with(address) {
            (0..maxAddressLineIndex).map { getAddressLine(it) }
        }
        Log.i(TAG, getString(R.string.address_found))
        deliverResultToReceiver(Constants.SUCCESS_RESULT,
                addressFragments.joinToString(separator = "\n"))
    }
}
class FetchAddressIntentService : IntentService() {
    private var receiver: ResultReceiver? = null

    // ...

    private fun deliverResultToReceiver(resultCode: Int, message: String) {
        val bundle = Bundle().apply { putString(Constants.RESULT_DATA_KEY, message) }
        receiver?.send(resultCode, bundle)
    }

}

We can see all here : https://developer.android.com/training/location/display-address

and code here https://github.com/jimmy-jose/CurrentLocation

@MoustafaElsaghier
Copy link

thank you for giving me the idea for making it in background service but please note that IntentService is now deprecated and documentation advice using WorkManger you can learn it and perform same task from here
here's the full code

class AddressDetailsWorker(var context: Context, workerParams: WorkerParameters) :
    Worker(context, workerParams) {
    override fun doWork(): Result {
        val lang = inputData.getString("lang")
        val geoCoder = lang?.let {
            Geocoder(applicationContext, Locale(it))
        }
        val address = geoCoder?.getFromLocation(inputData.getDouble("latitude", 0.0),
            inputData.getDouble("longitude", 0.0), 1)
        try {
            address?.let {
                if (address.isNotEmpty()) {

                    //  WorkManger can take only specific parameters 
                    //  and not POJO or array list so make sure you send data as a primitive data type
                    //   if you tried to pass something else it'd throw an exception illegalargumentexception

                    val data = Data.Builder()
                        .putDataType("key_name", "value")
                        .build()
                    return Result.success(data)
                }
            }
        } catch (e: Throwable) {
            Timber.e(e)
        }
        return Result.failure()
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants