Подтвердить что ты не робот

Использование нового идентификатора рекламодателя Android внутри SDK

Очень важно, что Android-объявления SDK будут использовать Android для нового идентификатора рекламодателя.

Кажется, что вы можете получить идентификатор только с помощью служб google services sdk, как указано здесь: http://developer.android.com/google/play-services/id.html.

Используя службы sgk для игры google, требуется ссылка на проект google-play-services_lib, что вызывает ряд проблем:

  • Многие SDK - это банки, то есть они не могут использовать google-play-services_lib как есть (потому что они не могут включать ресурсы).
  • Если мне нужен только идентификатор рекламодателя, мне нужно добавить google-play-services_lib в мой проект, который весит почти 1 МБ.

Есть ли способ получить идентификатор рекламодателя без использования ресурсов?

4b9b3361

Ответ 1

Я столкнулся с той же проблемой, если вам просто нужен рекламодатель, если бы вы могли напрямую взаимодействовать с Google Play Service, используя намерение. Пример пользовательского класса:

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;
    }
}
}

Убедитесь, что вы не вызываете это из основного потока пользовательского интерфейса. Например, используйте что-то вроде:

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();

Ответ 2

ПРИМЕЧАНИЕ. Мой ответ устарел для Gradle, так как теперь вы можете выбрать, какие части библиотеки GooglePlayServices вы хотите включить в свой проект.

Я столкнулся с той же проблемой в последнее время, когда проект, над которым я работал, достиг предела 65 тыс. дек.

Вот как я решил это:

  • Перейдите в https://code.google.com/p/jarjar/downloads/list и загрузите последние ссылки Jar jar в формате .jar. Поместите файл в рабочую папку. В этом примере я буду использовать рабочий стол.

  • Перейдите на страницу [Android SDK Path]\extras\google\google_play_services\libproject\google-play-services_lib\libs и скопируйте google-play-services.jar в ту же рабочую папку.

  • В той же папке создайте текстовый файл с именем rules.txt(имя на самом деле не имеет значения).

  • Внутри файла rules.txt вставьте текст (без кавычек):

"сохранить com.google.android.gms.ads.identifier.AdvertisingIdClient"

  • Если вам нужны другие классы, которые вы хотите сохранить, вы можете добавить их здесь.

  • Откройте файл командной строки и измените путь к вашей рабочей папке. В Windows используйте команду [cd].

  • Напишите следующую команду:

java -jar [jarjar archive] process [rulesFile] [inJar] [outJar]

  • Более подробную информацию о командах и правилах JarJar Links можно найти здесь: https://code.google.com/p/jarjar/wiki/CommandLineDocs

  • Чтобы привести пример, команда, которую я должен был написать, выглядела так: измените их в соответствии с вашими именами файлов:

java -jar jarjar-1.4.jar process rules.txt google-play-services.jar google-play-services-lite.jar

  • Выполните команду.

ЧТО ЭТО:

  • Команда создаст новый java-архив (*.jar) в рабочей папке, который будет содержать только класс, необходимый для получения вашего идентификатора рекламодателя и его зависимостей. Таким образом, google-play-services.jar будет снижаться с 2,2 МБ до ~ 50 кбайт

КАК ИСПОЛЬЗОВАТЬ ЭТО:

  • Импортируйте сервисы google play из sdk в свой проект, как обычно, не забудьте скопировать его в рабочее пространство. В папке libs замените google-play-services.jar банком, который вы создали ранее.

  • Если вы там, вы можете удалить ресурсы, чтобы освободить еще 0,5 мб. Обязательно сохраняйте значения /common _strings.xml и values ​​/version.xml.

  • Не забудьте добавить метаданные манифеста для сервисов Google Play.

Это помогло мне уменьшить размер проекта с более чем 2,5 мб и остаться под 65k dex классами и методами, ограничивая доступ к идентификатору рекламодателя Google.

Надеюсь, что это тоже поможет.

Ответ 3

Решение Adrian превосходно, и я использую его сам.

Однако сегодня я обнаружил, что у него есть ошибка, когда Google Play Services не установлен на устройстве. Вы получите сообщение об утечке ServiceConnection, когда ваша активность/служба остановлена. На самом деле это ошибка в Context.bindService: при сбое привязки к службе (в этом случае, поскольку службы Google Play не установлены), Context.bindService возвращает false, но не очищает ссылку на ServiceConnection и ожидает, что вы вызовете Context.unbindService, хотя сервис не существует!

Обходной путь заключается в изменении кода getAdvertisingIdInfo следующим образом:

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");
}

Таким образом, Context.unbindService будет вызываться, даже если Context.bindService возвращает false.

Ответ 4

MoPub и несколько других крупных игроков не включают GPS в свои SDK. На странице справки MoPub:

SDK MoPub не требует услуг Google Play. Если вы его установили, мы автоматически будем использовать новый идентификатор рекламы Google. Если вы НЕ устанавливаете сервисы Google Play, мы продолжим передавать старый идентификатор Android. Обратите внимание, что все издатели должны использовать GPS в своем приложении к 1 августа, чтобы запретить их приложения отклоняться в Google Play Store.

Посмотрите эту ссылку для получения более подробной информации:

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

Надеюсь, что это поможет.

Ответ 5

Единственный поддерживаемый способ доступа к рекламному идентификатору - это прямая ссылка на SDK Play Services и доступ к рекламному идентификатору через эти API. Google не рекомендует или не поддерживает какое-либо обходное решение, которое позволяет избежать прямого доступа к API-интерфейсам Play Services, поскольку он нарушает функциональность, обращенную к пользователю (например, обработка ошибок в случаях, когда приложение Службы Службы устарело), ​​и его поведение будет непредсказуемым с будущей игрой Выпуски служб.

Политики программы разработчика Google Play требуют, чтобы вы обращались к API Google Play только авторизованным образом.