Android広告SDKはAndroidの新しい広告主IDを使用することは非常に理にかなっています。
http://developer.Android.com/google/play-services/id.html のように、GoogleサービスSDKを使用しないとIDを取得できないようです。
Google play services sdkを使用するには、google-play-services_libプロジェクトを参照する必要があるため、いくつかの問題が発生します。
リソースを使用せずに広告主IDのみを取得する方法はありますか?
同じ問題が発生しましたが、advertiserIdだけが必要な場合は、インテントを使用して直接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();
エイドリアンの解決策は優れており、私はそれを自分で使用しています。
しかし、今日、Google Play開発者サービスがデバイスにインストールされていないときにバグがあることを発見しました。アクティビティ/サービスが停止すると、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
がfalse
を返しても、Context.bindService
が呼び出されます。
注:プロジェクトに含めるGooglePlayServicesライブラリの部分を選択できるようになったため、私の答えはGradleでは古くなっています
最近、私が取り組んでいるプロジェクトが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内にテキスト(引用符なし)を貼り付けます。
「com.google.Android.gms.ads.identifier.AdvertisingIdClientを保持」
保持したい他のクラスが必要な場合は、ここに追加できます。
コマンドプロンプトファイルを開き、作業フォルダーへのパスを変更します。 Windowsでは、[cd]コマンドを使用します。
次のコマンドを記述します。
Java -jar [jarjarアーカイブ]プロセス[rulesFile] [inJar] [outJar]
JarJarリンクコマンドとルールの詳細については、こちらをご覧ください。 https://code.google.com/p/jarjar/wiki/CommandLineDocs
例を挙げれば、私が書かなければならないコマンドは次のようになりました(ファイル名に応じてコマンドを変更してください)。
Java -jar jarjar-1.4.jarプロセス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を必ず保持してください。
グーグルプレイサービスのためのマニフェストメタデータを追加することを忘れないでください。
これにより、プロジェクトのサイズを2.5 MBを超えて縮小し、Googleの広告主IDにアクセスしながら、65kのdexクラスとメソッドの制限を守ることができました。
それもあなたを助けることを願っています。
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
お役に立てれば。