Używanie nowego identyfikatora reklamodawcy Androida w SDK

To ma sens, że Android ad SDK będzie używać Android ' s nowy identyfikator reklamodawcy.

Wydaje się, że można uzyskać identyfikator tylko za pomocą zestawu SDK usług google, jak wspomniano tutaj: http://developer.android.com/google/play-services/id.html .

Korzystanie z zestawu SDK usług google play wymaga odwołania się do projektu google-play-services_lib, co powoduje kilka problemów:

  1. wiele SDK to słoiki, co oznacza, że nie mogą używać google-play-services_lib tak jak jest (ponieważ nie mogą zawierać zasobów).
  2. Jeśli chcę tylko identyfikator reklamodawcy, muszę dodać google-play-services_lib do mojego projektu, który waży prawie 1 MB.

Czy istnieje sposób na uzyskanie tylko identyfikatora reklamodawcy, bez korzystania z zasobów?

Author: dors, 2013-11-20

5 answers

Natknąłem się na ten sam problem, jeśli potrzebujesz advertiserId, możesz wejść w interakcję z usługą Google Play bezpośrednio za pomocą intencji. Przykład klasy niestandardowej:

import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
import android.os.Parcel;
import android.os.RemoteException;

public final class AdvertisingIdClient {

public static final class AdInfo {
    private final String advertisingId;
    private final boolean limitAdTrackingEnabled;

    AdInfo(String advertisingId, boolean limitAdTrackingEnabled) {
        this.advertisingId = advertisingId;
        this.limitAdTrackingEnabled = limitAdTrackingEnabled;
    }

    public String getId() {
        return this.advertisingId;
    }

    public boolean isLimitAdTrackingEnabled() {
        return this.limitAdTrackingEnabled;
    }
}

public static AdInfo getAdvertisingIdInfo(Context context) throws Exception {
    if(Looper.myLooper() == Looper.getMainLooper()) throw new IllegalStateException("Cannot be called from the main thread");

    try { PackageManager pm = context.getPackageManager(); pm.getPackageInfo("com.android.vending", 0); }  
    catch (Exception e) { throw e; }

    AdvertisingConnection connection = new AdvertisingConnection();
    Intent intent = new Intent("com.google.android.gms.ads.identifier.service.START");
    intent.setPackage("com.google.android.gms");
    if(context.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
        try {
            AdvertisingInterface adInterface = new AdvertisingInterface(connection.getBinder());
            AdInfo adInfo = new AdInfo(adInterface.getId(), adInterface.isLimitAdTrackingEnabled(true));
            return adInfo;
        } catch (Exception exception) {
            throw exception;
        } finally {
            context.unbindService(connection);
        }
    }       
    throw new IOException("Google Play connection failed");     
}

private static final class AdvertisingConnection implements ServiceConnection {
    boolean retrieved = false;
    private final LinkedBlockingQueue<IBinder> queue = new LinkedBlockingQueue<IBinder>(1);

    public void onServiceConnected(ComponentName name, IBinder service) {
        try { this.queue.put(service); }
        catch (InterruptedException localInterruptedException){}
    }

    public void onServiceDisconnected(ComponentName name){}

    public IBinder getBinder() throws InterruptedException {
        if (this.retrieved) throw new IllegalStateException();
        this.retrieved = true;
        return (IBinder)this.queue.take();
    }
}

private static final class AdvertisingInterface implements IInterface {
    private IBinder binder;

    public AdvertisingInterface(IBinder pBinder) {
        binder = pBinder;
    }

    public IBinder asBinder() {
        return binder;
    }

    public String getId() throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        String id;
        try {
            data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService");
            binder.transact(1, data, reply, 0);
            reply.readException();
            id = reply.readString();
        } finally {
            reply.recycle();
            data.recycle();
        }
        return id;
    }

    public boolean isLimitAdTrackingEnabled(boolean paramBoolean) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        boolean limitAdTracking;
        try {
            data.writeInterfaceToken("com.google.android.gms.ads.identifier.internal.IAdvertisingIdService");
            data.writeInt(paramBoolean ? 1 : 0);
            binder.transact(2, data, reply, 0);
            reply.readException();
            limitAdTracking = 0 != reply.readInt();
        } finally {
            reply.recycle();
            data.recycle();
        }
        return limitAdTracking;
    }
}
}

Upewnij się, że nie wywołujesz tego z głównego wątku UI. Na przykład użyj czegoś w stylu:

new Thread(new Runnable() {        
    public void run() {
        try {
            AdInfo adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context);
            advertisingId = adInfo.getId();
            optOutEnabled = adInfo.isLimitAdTrackingEnabled();
        } catch (Exception e) {
            e.printStackTrace();                            
        }                       
    }
}).start();
 36
Author: Adrian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-05 03:35:20

Uwaga: moja odpowiedź jest nieaktualna dla Gradle, ponieważ teraz możesz wybrać, które części biblioteki GooglePlayServices chcesz włączyć do swojego projektu

Napotkałem ten sam problem ostatnio, gdy projekt, nad którym pracowałem osiągnął limit 65K dex.

Oto jak to rozwiązałem:

  • Przejdź do https://code.google.com/p/jarjar/downloads/list i pobierz najnowsze linki Jar jar w .format jar. Umieść plik w folderze roboczym. W tym przykładzie użyję pulpit.

  • Przejdź do [Android SDK Path] \ extras \ google \ google_play_services \ libproject\google-play-services_lib\libs i skopiuj google-play-services.jar do tego samego folderu roboczego.

  • W tym samym folderze Utwórz plik tekstowy o nazwie rules.txt (nazwa nie ma znaczenia).

  • Wewnątrz zasad.txt wklej tekst (bez cudzysłowów):

"keep com.google.android.gms.reklamy.identyfikator.AdvertisingIdClient "

  • Jeśli chcesz inne klasy, które chcesz zachować, możesz dodać je tutaj.

  • Otwórz plik wiersza polecenia i zmień ścieżkę do folderu roboczego. W systemie Windows użyj polecenia [cd].

  • Napisz następującą komendę:

Java-jar [archiwum jarjar] process [rulesFile] [inJar] [outJar]

Java-jar jarjar-1.4.zasady procesu jar.txt google-play-services.jar google-play-services-lite.jar

  • wykonaj polecenie.

CO ROBI:

  • polecenie wygeneruje nową Javę archiwum (*.jar) w folderze roboczym, który będzie zawierał tylko klasę potrzebną do uzyskania identyfikatora reklamodawcy i jego zależności. Więc, usługi google-play.jar spadnie z 2,2 Mb do ~50Kb

JAK GO UŻYWAĆ:

  • Zaimportuj usługi google play z zestawu sdk do swojego projektu jak zwykle, upewnij się, że skopiujesz je do obszaru roboczego. W folderze libs zastąp usługi google-play.słoik ze słoikiem, który wcześniej wygenerowałeś.

  • Jeśli tam jesteś, możesz Usuń też zasoby, aby uwolnić kolejne 0,5 mb. Pamiętaj, aby zachować wartości / common_strings.xml i wartości / wersja.xml.

  • Nie zapomnij dodać metadanych manifestu dla usług google play.

Pomogło mi to zmniejszyć rozmiar projektu o więcej niż 2,5 mb i utrzymać limit klas i metod 65K dex, jednocześnie uzyskując dostęp do Google advertiser id.

Mam nadzieję, że tobie też pomoże.

 6
Author: Andrei Lupsa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-13 12:53:09

Rozwiązanie Adriana jest doskonałe i sam z niego korzystam.

Jednak dzisiaj odkryłem, że ma błąd, gdy usługi Google Play nie są zainstalowane na urządzeniu. Gdy Twoja aktywność/usługa zostanie zatrzymana, otrzymasz wiadomość o wycieku ServiceConnection. W rzeczywistości jest to błąd w Context.bindService: gdy powiązanie z usługą nie powiedzie się (w tym przypadku, ponieważ usługi Google Play nie są zainstalowane), Context.bindService zwraca false, ale nie usuwa odniesienia do ServiceConnection i oczekuje, że wywołasz Context.unbindService nawet chociaż usługa nie istnieje!

Obejściem problemu jest zmiana kodu getAdvertisingIdInfo w następujący sposób:

public static AdInfo getAdvertisingIdInfo(Context context) throws Exception {
    if(Looper.myLooper() == Looper.getMainLooper())
        throw new IllegalStateException("Cannot be called from the main thread");

    try {
        PackageManager pm = context.getPackageManager();
        pm.getPackageInfo("com.android.vending", 0);
    } catch(Exception e) {
        throw e;
    }

    AdvertisingConnection connection = new AdvertisingConnection();
    Intent intent = new Intent("com.google.android.gms.ads.identifier.service.START");
    intent.setPackage("com.google.android.gms");
    try {
        if(context.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
            AdvertisingInterface adInterface = new AdvertisingInterface(connection.getBinder());
            AdInfo adInfo = new AdInfo(adInterface.getId(), adInterface.isLimitAdTrackingEnabled(true));
            return adInfo;
        }
    } catch(Exception exception) {
        throw exception;
    } finally {
        context.unbindService(connection);
    }
    throw new IOException("Google Play connection failed");
}

W ten sposób Context.unbindService zostanie wywołane, nawet jeśli Context.bindService zwróci false.

 4
Author: Avi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-27 14:17:43

MoPub i kilku innych dużych graczy nie włącza GPS do swoich SDK. Ze strony pomocy Mopuba:

MoPub SDK nie wymaga usług Google Play. Jeśli masz go zainstalowany, automatycznie użyjemy nowego identyfikatora reklam Google. Jeśli nie zainstalujesz usług Google Play, nadal będziemy przekazywać stary identyfikator Androida. Pamiętaj, że wszyscy wydawcy muszą używać GPS w swojej aplikacji do 1 sierpnia, aby zapobiec odrzuceniu ich aplikacji przez Google Play Store

Sprawdź ten link, aby uzyskać więcej szczegółów:

Http://help.mopub.com/customer/portal/articles/1523610-google-advertising-id-faqs

Mam nadzieję, że to pomoże.

 1
Author: ankit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-01 07:00:58

Jedyną obsługiwaną metodą dostępu do identyfikatora reklamowego jest bezpośrednie połączenie z zestawem SDK usług Play i dostęp do identyfikatora reklamowego za pośrednictwem tych interfejsów API. Google nie zaleca ani nie wspiera żadnego obejścia problemu, który pozwala uniknąć bezpośredniego dostępu do interfejsów API usług Play, ponieważ narusza funkcjonalność użytkownika (np. obsługę błędów w przypadku, gdy aplikacja usług Play na urządzeniu jest przestarzała), a jej zachowanie będzie nieprzewidywalne w przyszłych wydaniach usług Play.

Google Play Zasady programu dla programistów wymagają dostępu do interfejsów API Google Play tylko w autoryzowany sposób.

 -1
Author: Eric Leichtenschlag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-02 21:18:02