user1177054
user1177054

Reputation: 39

Getting Android Advertising ID via Kotlin Programmatically

I am rather new to android development and am trying to get the Advertising ID for a particular device. I've found some stack overflow suggestions on how to do so:

val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext())
val adId = adInfo?.id

in a worker thread). However this keeps on giving me the "Timed out waiting for the service connection" error.

Others seems to have suggest adding the following gradle dependencies help, but not for me:

implementation 'com.google.android.gms:play-services-ads-identifiers:17.0.0'
implementation 'com.google.android.gms:play-services-base:17.1.0'

as well as having

apply plugin: 'com.google.gms.google-services'

What am I missing to properly get the Advertising ID?

Upvotes: 2

Views: 6223

Answers (3)

Cuong Nguyen
Cuong Nguyen

Reputation: 1018

I use Rxjava to get aid, you can use Asyntask, coroutine...

  1. RxJava

    fun getAdId() {
        Observable.fromCallable { AdvertisingIdClient.getAdvertisingIdInfo(this).id }
            .subscribeOn(AppScheduler().backgroundThread())
            .observeOn(AppScheduler().mainThread())
            .subscribe(Consumer<String> {
                 val adId = it
             }, Consumer<Throwable> {
                 // nothing
             })
    }
    
  • Import Rxjava in app/build.gradle:

    implementation 'io.reactivex.rxjava2:rxjava:2.1.7'

    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

  1. With coroutine of Kotlin:

    GlobalScope.launch {
        val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(applicationContext)
        Log.d("text", adInfo.id ?: "unknown")
    }
    

Upvotes: 4

HBB20
HBB20

Reputation: 2958

If someone wonder (like me) why they get

 "Calling this from your main thread can lead to deadlock" 

when trying to read it from using viewModelScope and a suspend function. Here is what you need to do:

Since viewModelScope uses Dispatchers.Main by default you need it will throw this error.

Option 1:

Pass context when launched

viewModelScope.launch(Dispatchers.Default){
  // call your suspend function from here
}

but in this way you need to do some work when you want to do some work on main thread.


Option 2 (I prefer this):

use CoroutineContext in your suspend function

 suspend fun getAdId(): String? {
        return withContext(Dispatchers.Default) {
                try {
                    AdvertisingIdClient.getAdvertisingIdInfo(context).id
                } catch (exception: Exception) {
                    null // there still can be an exception for other reasons but not for thread issue
                }
            }
    }

Upvotes: 2

Gioan Le
Gioan Le

Reputation: 1168

Try to use this code:

fun getAdvertisingId(context: Context, callback: (advertisingId: String?) -> Unit) {
        Thread(Runnable {
            try {
                val info = AdvertisingIdClient.getAdvertisingIdInfo(context)
                val id = info.id
                callback(id)
            } catch (e: Exception) {
                callback(null)
            }
        }).start()
    }

Upvotes: 0

Related Questions