2014-04-30 51 views
9

Próbuję uzyskać identyfikator reklamy z interfejsu API usług Google Play. Oto przykładowy kod:AdvertisingIdClient getAdvertisingIdInfo zawiesza się na zawsze

... 
import com.google.android.gms.ads.identifier.AdvertisingIdClient; 
import com.google.android.gms.common.GooglePlayServicesNotAvailableException; 
import com.google.android.gms.common.GooglePlayServicesRepairableException; 
... 

public class MyActivity extends Activity { 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     Thread thr = new Thread(new Runnable() { 
      @Override 
      public void run() { 
      try { 
       Context ctx = MyActivity.this.getApplicationContext(); 
       AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(ctx); 
      } catch (IllegalStateException e) { 
       e.printStackTrace(); 
      } catch (GooglePlayServicesRepairableException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } catch (GooglePlayServicesNotAvailableException e) { 
       e.printStackTrace(); 
      } 
     }); 

     thr.start(); 
     synchronized (thr) { 
      try { 
       thr.join(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

Kiedy dzwonię metodę getAdvertisingIdInfo, aplikacja zawiesza się zawsze (bez względu na to z debuggera, czy nie).

Używam Windows ADT 22,3, Android SDK API 19, SDK Google Play rev. 16, Android 4.4.2 urządzenia Nexus. Integruję interfejs API w sposób opisany tutaj: https://developer.android.com/google/play-services/id.html

Co może być powodem?

Odpowiedz

10

Znalazłem przyczynę. Nie powinien on blokować programu obsługi onStart(), ponieważ zablokowany kontekst blokuje API Play w uzyskiwaniu ustawień identyfikatora. Naprawiony kod wygląda następująco:

@Override 
protected void onStart() { 
    super.onStart(); 
    Thread thr = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       Context ctx = MyActivity.this.getApplicationContext(); 
       AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(ctx); 
       finished(adInfo); 
      } catch (...) { 
       // All exceptions blocks 
      } 

      finished(null); 
     } 
    }); 

    thr.start(); 
} 

private void finished(final AdvertisingIdClient.Info adInfo){ 
    if(adInfo!=null){ 
     // In case you need to use adInfo in UI thread 
     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       // Do some stuff with adInfo 
      } 
     }); 
    } 
} 

Byłoby pomocne, gdyby oficjalne instrukcje zawierały takie uwagi.

+2

Zgadzam się, przykładowy kod Google na ten temat jest zły! –

+0

i kiedy postępuję zgodnie z ich dokumentem, otrzymuję miły błąd fint lint "Nieosiągalny catch catch dla GooglePlayServicesAvailabilityException. Ten wyjątek nigdy nie jest wyrzucany z ciała instrukcji try ". Przez całe moje życie z systemem Windows Microsoft przynajmniej dokumentował swoje rzeczy poprawnie - i pozwalał na opinie na temat dokumentów! FFS –

+0

Lub lepiej, użyj AsyncTask. – RominaV

1

Niestety wywołanie getAdvertisingIdInfo musi zostać wykonane z wątku tła, nie powinieneś blokować głównego wątku podczas jego wywoływania. Wygląda na to, że nie ma opcji, aby uzyskać AdId synchronicznie.

---- EDIT ----

mogę to osiągnąć poprzez uruchomienie na nowym wątku. Oto, co wreszcie działa dla mnie. Nie jest już zawieszany (może nie być idealny)

getGAIDSync(){ 
final CountDownLatch latch = new CountDownLatch(1); 
new Thread(new Runnable() { 
      @Override 
      public void run() {    
       getGoogleAdsIDAsyncTask.execute().get(5000, TimeUnit.MilliSecond); 
       latch.countDown();     
    }}).start(); 
    try { 
     latch.await(5000,TimeUnit.MILLISECONDS); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

}