restablecer - package id android
Usar el nuevo ID de anunciante de Android dentro de un SDK (5)
El único método admitido para acceder a Advertising ID es mediante la vinculación directa con el SDK de Play Services y el acceso a Advertising ID a través de esas API. Google no recomienda ni admite ninguna solución que evite el acceso directo a las API de Play Services porque rompe la funcionalidad que enfrenta el usuario (como el manejo de errores en los casos en que la aplicación Play Services en el dispositivo está desactualizada) y su comportamiento será impredecible con la reproducción futura. Servicios de lanzamientos.
Las políticas del Programa para desarrolladores de Google Play requieren que acceda a las API de Google Play solo de manera autorizada.
Tiene mucho sentido que los SDK de anuncios de Android utilicen la nueva identificación de anunciante de Android.
Parece que solo puede obtener el ID utilizando el servicio de Google SDK, como se menciona aquí: http://developer.android.com/google/play-services/id.html
El uso del sdk de google play services, requiere hacer referencia al proyecto google-play-services_lib, lo que causa varios problemas:
- Muchos SDK son tarros, lo que significa que no pueden usar google-play-services_lib como es (porque no pueden incluir recursos).
- Si solo quiero la ID del anunciante, debo agregar google-play-services_lib a mi proyecto, que pesa casi 1 MB.
¿Hay una manera de obtener solo la identificación del anunciante, sin utilizar recursos?
La solución de Adrian es excelente, y la uso yo misma.
Sin embargo, hoy descubrí que tiene un error cuando Google Play Services no está instalado en el dispositivo. Recibirá un mensaje sobre la pérdida de una ServiceConnection
cuando su actividad / servicio se detenga. Esto es realmente un error en Context.bindService
: cuando falla la vinculación con el servicio (en este caso, porque Google Play Services no está instalado), Context.bindService
devuelve false, pero no borra la referencia a ServiceConnection
, y le espera para llamar a Context.unbindService
aunque el servicio no exista!
La solución es cambiar el código de getAdvertisingIdInfo
esta manera:
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");
}
De esa manera se llamará a Context.bindService
incluso si Context.bindService
devuelve false
.
Me encontré con el mismo problema, si solo necesitas el anunciante, puedes interactuar con el Servicio de Google Play directamente usando un Intent. Ejemplo de clase personalizada:
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;
}
}
}
Asegúrese de que no está llamando a esto desde el hilo principal de la interfaz de usuario. Por ejemplo, usa algo como:
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();
MoPub y algunos otros grandes jugadores no incluyen GPS en sus SDK. De la página de ayuda de MoPub:
El MoPub SDK no requiere los servicios de Google Play. Si lo tiene instalado, utilizaremos automáticamente la nueva ID de publicidad de Google. Si NO instala Google Play Services, continuaremos pasando la antigua ID de Android. Tenga en cuenta que todos los editores deben usar el GPS en su aplicación antes del 1 de agosto para evitar que Google Play Store rechace sus aplicaciones.
Compruebe este enlace para mucho más detalle:
http://help.mopub.com/customer/portal/articles/1523610-google-advertising-id-faqs
Espero que esto ayude.
NOTA: Mi respuesta está desactualizada para Gradle, ya que ahora puede elegir qué partes de la biblioteca GooglePlayServices desea incluir en su proyecto.
Me encontré con el mismo problema últimamente cuando el proyecto en el que estaba trabajando alcanzó el límite de 65k dex.
Así es como lo resolví:
Vaya a https://code.google.com/p/jarjar/downloads/list y descargue los últimos enlaces de Jar jar en formato .jar. Pon el archivo en una carpeta de trabajo. Para este ejemplo usaré el escritorio.
Vaya a [Ruta del SDK de Android] / extras / google / google_play_services / libproject / google-play-services_lib / libs y copie google-play-services.jar en la misma carpeta de trabajo.
En la misma carpeta, cree un archivo de texto llamado rules.txt (el nombre realmente no importa).
Dentro del rules.txt pegue el texto (sin las comillas):
"mantener com.google.android.gms.ads.identifier.AdvertisingIdClient"
Si quieres otras clases que quieres mantener, puedes agregarlas aquí.
Abra un archivo de símbolo del sistema y cambie la ruta a su carpeta de trabajo. En Windows usa el comando [cd].
Escribe el siguiente comando:
java -jar [archivo jarjar] proceso [rulesFile] [inJar] [outJar]
Puede encontrar más detalles sobre los comandos y reglas de JarJar Links aquí: https://code.google.com/p/jarjar/wiki/CommandLineDocs
Solo para dar un ejemplo, el comando que tuve que escribir se veía así (cambia el tuyo de acuerdo con los nombres de tus archivos):
java -jar jarjar-1.4.jar process rules.txt google-play-services.jar google-play-services-lite.jar
- Ejecuta el comando.
QUE HACE:
- El comando generará un nuevo archivo java (* .jar) en la carpeta de trabajo que contendrá solo la clase necesaria para obtener su ID de anunciante y sus dependencias. Por lo tanto, el google-play-services.jar bajará de 2.2 Mb a ~ 50kb
CÓMO USARLO:
Importe los servicios de Google Play desde el sdk a su proyecto como de costumbre, asegúrese de copiarlo en su área de trabajo. En la carpeta libs, reemplaza google-play-services.jar con el jar que generaste anteriormente.
Si estás allí, puedes eliminar los recursos también para liberar otros 0.5 mb. Asegúrese de mantener los valores / common_strings.xml y los valores / version.xml.
No olvide agregar metadatos de manifiesto para los servicios de Google Play.
Esto me ayudó a reducir el tamaño del proyecto con más de 2.5 mb y a mantenerme por debajo del límite de clases y métodos de 65k dex al mismo tiempo que puedo acceder al ID de anunciante de Google.
Espero que te ayude también.