Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AdvertisingIdClient getAdvertisingIdInfo blocked by main thread

I'm trying to wait the response of AdvertisingIdClient.getAdvertisingIdInfo(activity) without success. This method never response until the main thread has finished.

import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import com.google.android.gms.ads.identifier.AdvertisingIdClient;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesUtil;
import java.io.IOException;


public class MyActivity extends Activity {

    private Activity m_activity = null;
    private AdvertisingIdClient.Info m_info = null;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // start the thread with the getAdvertisingIdInfo()
        startGoogleAdvertisingIdRequest(this);

        // simulate a waiting loop, others app init, ...
        for (int i=0; i<20; i++) {
            SystemClock.sleep(100);
        }

        // get the uuid
        String uuid = getGoogleAdvertisingId();

        // call a method who need the uuid
        Log.i("UUID", "receive uuid: " + uuid);
    }


    public String getGoogleAdvertisingId() {
        String uuid = null;
        if (m_info != null) {
            if (!m_info.isLimitAdTrackingEnabled()) {
                uuid = m_info.getId();
            } else {
                uuid = "another uuid";
            }
        } else {
            uuid = "another uuid";
        }

        return uuid;
    }

    public void startGoogleAdvertisingIdRequest(final Activity activity) {
        m_activity = activity;
        if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity) == ConnectionResult.SUCCESS) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    AdvertisingIdClient.Info adInfo = null;
                    try {
                        Log.i("UUID", "before google request");
                        adInfo = AdvertisingIdClient.getAdvertisingIdInfo(activity);
                        Log.i("UUID", "after google request");
                    } catch (IOException e) {
                        Log.w("UUID", "getAdvertisingIdInfo IOException: " + e.getMessage());
                    } catch (GooglePlayServicesNotAvailableException e) {
                        Log.w("UUID", "GooglePlayServicesNotAvailableException: " + e.getMessage());
                    } catch (Exception e) {
                        Log.w("UUID", "GooglePlayServicesException: " + e.getMessage());
                    } finally {
                        finished(adInfo);
                    }
                }
            }).start();
        }
    }

    private void finished(final AdvertisingIdClient.Info adInfo){
        if(adInfo != null){
            m_activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    m_info = adInfo;
                    Log.i("UUID", "runOnUiThread id: " + adInfo.getId());
                }
            });
        }
    }
}

Logcat of this code

11:29:52.103  30810-30828/com.example.testuuid I/UUID﹕ before google request
11:29:54.107  30810-30810/com.example.testuuid I/UUID﹕ receive uuid: another uuid
11:29:54.127  30810-30828/com.example.testuuid I/UUID﹕ after google request
11:29:54.151  30810-30810/com.example.testuuid I/UUID﹕ runOnUiThread id: d5dc3bfb-4756-490c-8f8e-2bedfb5e827a

Same logcat with more waiting time (5s)

11:36:14.215  31413-31436/com.example.testuuid I/UUID﹕ before google request
11:36:19.225  31413-31413/com.example.testuuid I/UUID﹕ receive uuid: another uuid
11:36:19.293  31413-31436/com.example.testuuid I/UUID﹕ after google request
11:36:19.315  31413-31413/com.example.testuuid I/UUID﹕ runOnUiThread id: d5dc3bfb-4756-490c-8f8e-2bedfb5e827a

Each time the getAdvertisingIdInfo(), who is in another thread, is blocked by the main thread.

What is the reason ? and how to do this ?

like image 228
Mapond Avatar asked Jan 15 '15 10:01

Mapond


2 Answers

To get the google ad ID you need not to run the method getAdvertisingIdInfo on the main thread. I use Async Task to manage the extraction of the google ad ID.

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.google.android.gms.ads.identifier.AdvertisingIdClient;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
String GAID; // this is the String of the Google Ad ID that you'll receive upon onPostExecute

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    new GetGAIDTask().execute();
}

private class GetGAIDTask extends AsyncTask<String, Integer, String> {

    @Override
    protected String doInBackground(String... strings) {
        AdvertisingIdClient.Info adInfo;
        adInfo = null;
            try {
                adInfo = AdvertisingIdClient.getAdvertisingIdInfo(MainActivity.this.getApplicationContext());
                if (adInfo.isLimitAdTrackingEnabled()) // check if user has opted out of tracking
                    return "did not found GAID... sorry";
            } catch (IOException e) {
                e.printStackTrace();
            } catch (GooglePlayServicesNotAvailableException e) {
                e.printStackTrace();
            } catch (GooglePlayServicesRepairableException e) {
                e.printStackTrace();
            }
        return adInfo.getId();
    }

    @Override
    protected void onPostExecute(String s) {
        GAID = s;
    }
}

You also need to add to the app build.gradle on the dependencies the line

compile 'com.google.android.gms:play-services-ads:7.8.0'

And be sure you have on the Android SDK manager the "EXTRAS Google Repository" updated

like image 128
WhiteRabbit Avatar answered Oct 07 '22 01:10

WhiteRabbit


The issue you are seeing, where no amount of time seems long enough for the getAdvertisingIdInfo call to complete, is caused by how you are waiting and how runOnUiThread works. The key is that runOnUiThread will queue the code to be run after what is currently running on the ui thread, in this case the onCreate. The sleep calls used to "simulate waiting" will let your background thread run and do its work, but the final operation to set m_info will always be queued and executed after onCreate completes.

One solution would be to ensure that m_info is safe to access from multiple threads and simply assign it on the background thread. There would be no need for runOnUiThread. This would remove queuing, and allow your code to work with minimal changes.

A better solution would be to keep the use of runOnUiThread and remove the sleep used to wait. You would need to keep in mind that m_info will always be null in onCreate, but other events can check if the value is non null and use it as needed.

https://developer.android.com/reference/android/app/Activity#runOnUiThread(java.lang.Runnable)

Runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread.

like image 37
Simon G Avatar answered Oct 07 '22 00:10

Simon G