Android广告SDK将使用Android的新广告客户ID非常有意义。
您似乎只能通过使用google服务sdk来获取ID,如下所述: http://developer.android.com/google/play-services/id.html
使用google play services sdk,需要引用google-play-services_lib项目,这会导致一些问题:
有没有办法只使用广告客户ID而不使用资源?
答案 0 :(得分:38)
我遇到了同样的问题,如果您只是需要广告客户,您可以直接使用Intent与Google Play服务进行互动。自定义类的示例:
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;
}
}
}
确保您没有从主UI线程中调用它。 例如,使用类似:
的内容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();
答案 1 :(得分:6)
注意:我的答案已过时Gradle,因为现在您可以选择要在项目中包含的GooglePlayServices库的哪些部分
当我正在进行的项目达到65k dex限制时,我最近遇到了同样的问题。
以下是我如何解决它:
转到https://code.google.com/p/jarjar/downloads/list并以.jar格式下载最新的Jar jar链接。将文件放在工作文件夹中。对于此示例,我将使用桌面。
转到[Android SDK路径] \ extras \ google \ google_play_services \ libproject \ google-play-services_lib \ libs并将google-play-services.jar复制到同一个工作文件夹。
在同一个文件夹中创建一个名为rules.txt的文本文件(名称并不重要)。
在rules.txt内部粘贴文本(不带引号):
&#34;保留com.google.android.gms.ads.identifier.AdvertisingIdClient&#34;
如果您想要保留其他课程,可以在此处添加。
打开命令提示符文件并更改工作文件夹的路径。在Windows上使用[cd]命令。
编写以下命令:
java -jar [jarjar archive] process [rulesFile] [inJar] [outJar]
您可以在此处找到有关JarJar链接命令和规则的更多详细信息: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
它做了什么:
如何使用它:
像往常一样将sdk中的google play服务导入您的项目,请务必将其复制到您的工作区。在libs文件夹中,将google-play-services.jar替换为您之前生成的jar。
如果您在那里,您也可以删除资源以释放另外0.5 MB。确保保留values / common_strings.xml和values / version.xml。
不要忘记为Google Play服务添加清单元数据。
这有助于我减少超过2.5百万的项目规模,并且能够访问Google广告客户ID,并保持在65k dex类和方法限制之下。
希望它也会帮助你。
答案 2 :(得分:6)
Adrian的解决方案很棒,我自己也使用它。
但是,今天我发现当设备上没有安装Google Play服务时,它有一个错误。当您的活动/服务停止时,您将收到有关泄露ServiceConnection
的消息。这实际上是Context.bindService
中的一个错误:当绑定到服务失败时(在这种情况下,因为未安装Google Play服务),Context.bindService
返回false,但它不会清除对{的引用{1}},即使该服务不存在,也希望您拨打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
。
答案 3 :(得分:1)
MoPub和其他一些大型玩家未将GPS纳入他们的SDK。从MoPub的帮助页面:
MoPub SDK不需要Google Play服务。如果您已安装,我们将自动使用新的Google广告ID。如果您不安装Google Play服务,我们会继续传递旧的Android ID。请注意,所有发布商都需要在8月1日之前在其应用中使用GPS,以防止他们的应用被Google Play商店拒绝
查看此链接以获取更多详细信息:
http://help.mopub.com/customer/portal/articles/1523610-google-advertising-id-faqs
希望这有帮助。
答案 4 :(得分:-1)
唯一受支持的访问广告ID的方法是直接链接到Play服务SDK并通过这些API访问广告ID。 Google不建议或支持任何避免直接访问Play服务API的解决方法,因为它会破坏面向用户的功能(例如,如果设备上的Play服务应用已过时,则会出现错误处理),并且其行为将无法预测服务发布。
Google Play Developer Program Policies要求您仅以授权方式访问Google Play API。