From f01b31663c5bb9a9d900968ca44e08dd2267307d Mon Sep 17 00:00:00 2001 From: pkumar Date: Thu, 30 Jul 2015 14:54:06 -0700 Subject: [PATCH] First modified version --- .gitignore | 3 + package.json | 33 +++--- src/android/AdvertisingIdClient.java | 154 +++++++++++++++++++++++++++ src/android/AndroidIDFA.java | 145 +++++++++++++++++++++++++ src/android/CoreException.java | 9 ++ www/androidIDFA.js | 25 +++++ 6 files changed, 356 insertions(+), 13 deletions(-) create mode 100644 src/android/AdvertisingIdClient.java create mode 100644 src/android/AndroidIDFA.java create mode 100644 src/android/CoreException.java create mode 100644 www/androidIDFA.js diff --git a/.gitignore b/.gitignore index 32858aa..9c027bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.idea/ +.DS_Store + *.class # Mobile Tools for Java (J2ME) diff --git a/package.json b/package.json index a88a60e..cb72da8 100644 --- a/package.json +++ b/package.json @@ -11,16 +11,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/praves77/cordova-plugin-android-idfa.git" - }, - "bugs": { - "url": "https://github.com/praves77/cordova-plugin-android-idfa/issues" - }, - "engines": { - "cordova": ">= 3.0.0" - }, - "scripts": { - "test": "grunt test" + "url": "git+https://github.com/praves77/cordova-plugin-android-idfa.git" }, "dependencies": { "com.google.play.services": "*" @@ -28,6 +19,9 @@ "keywords": [ "cordova", "idfa", + "google", + "google play", + "advertising id", "idfa for android", "cordova plugin", "advertiserId", @@ -35,11 +29,20 @@ "advertising id for android", "advertising id for android using google play", "advertising id for android using google play services", + "android", + "download", + "install", "ecosystem:cordova", "cordova-android" ], - "author": { - "name" : "praves", + "engines": [ + { + "name": "cordova", + "version": ">=3.0.0" + } + ], + "author": { + "name" : "praves", "email": "praves.dev@outlook.com" }, "licenses": [ @@ -47,5 +50,9 @@ "type": "MIT", "url": "https://github.com/praves77/cordova-plugin-android-idfa/LICENSE.md" } - ] + ], + "bugs": { + "url": "https://github.com/praves77/cordova-plugin-android-idfa/issues" + }, + "homepage": "https://github.com/praves77/cordova-plugin-android-idfa#readme" } diff --git a/src/android/AdvertisingIdClient.java b/src/android/AdvertisingIdClient.java new file mode 100644 index 0000000..d404d4f --- /dev/null +++ b/src/android/AdvertisingIdClient.java @@ -0,0 +1,154 @@ +package com.praves.cordova.android.idfa; + +/** + * Created by pkumar on 7/28/15. + */ + +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"); +// } + + 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"); + } + + private static final class AdvertisingConnection implements ServiceConnection { + boolean retrieved = false; + private final LinkedBlockingQueue queue = new LinkedBlockingQueue(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; + } + } +} + diff --git a/src/android/AndroidIDFA.java b/src/android/AndroidIDFA.java new file mode 100644 index 0000000..ef7c813 --- /dev/null +++ b/src/android/AndroidIDFA.java @@ -0,0 +1,145 @@ +package com.praves.cordova.android.idfa; + +//Cordova imports +import org.apache.cordova.CordovaInterface; +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CordovaWebView; + +//Android imports +import android.content.Context; +import android.app.Application; +import android.app.Activity; +//import android.telephony.TelephonyManager; +import android.util.Log; + +//JSON Imports +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONException; + +//Java Imports +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Iterator; + +////PG Class Imports +//import com.personagraph.api.PGAgent; +//import com.personagraph.api.PGSensorState; +//import com.personagraph.api.PGSettings; +//import com.personagraph.api.PGUserProfileCallback; +//import com.personagraph.api.PGSourceType; + +//pgcore import +import com.praves.cordova.android.idfa.CoreException; + +public class AndroidIDFA extends CordovaPlugin { + + Context context; + Application app; + boolean enableLog; + Activity activity; + public static final String TAG = "AndroidIDFA"; + + //Constructor function. + public void initialize(CordovaInterface cordova, CordovaWebView webView) { + super.initialize(cordova, webView); + context = this.cordova.getActivity().getApplicationContext(); + app = this.cordova.getActivity().getApplication(); + activity = this.cordova.getActivity(); + enableLog = false; + } + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + try { + if ("getAdInfo".equals(action)) { + getAdInfo(callbackContext); + } else if ("getAdId".equals(action)) { + getAdId(callbackContext); + } else if ("getLimitAd".equals(action)) { + getLimitAd(callbackContext); + } + + return true; + }catch (Exception e){ + if(enableLog){ + e.printStackTrace(); + System.err.println("AndroidIDFA execute Exception: " + e.getMessage()); + } + callbackContext.error(e.getMessage()); + return false; + } + } + + @Override + public void onPause(boolean multitasking) { + + if(enableLog) + Log.d(TAG, "Activity on pause is called"); + + super.onPause(multitasking); + } + + @Override + public void onResume(boolean multitasking) { + + if(enableLog) + Log.d(TAG, "Activity on resume is called"); + + super.onResume(multitasking); + } + + private void _getAdInfo(final CallbackContext callbackContext, final int flag) { + new Thread(new Runnable() { + public void run() { + try { + AdvertisingIdClient.AdInfo adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context); + String advertisingId = adInfo.getId(); + boolean optOutEnabled = adInfo.isLimitAdTrackingEnabled(); + + JSONObject result = new JSONObject(); + + switch(flag) { + + case 1: + result.put("adId", advertisingId); + break; + case 2: + + result.put("limitAd", optOutEnabled); + break; + + case 0: + default: + + result.put("adId", advertisingId); + result.put("limitAd", optOutEnabled); + break; + } + callbackContext.success(result); + } catch (Exception e) { + callbackContext.error(e.getMessage()); + e.printStackTrace(); + } + } + }).start(); + } + + public void getAdInfo(final CallbackContext callbackContext) { + final int flag = 0; + _getAdInfo(callbackContext, flag); + } + + public void getAdId(final CallbackContext callbackContext) { + final int flag = 1; + _getAdInfo(callbackContext, flag); + } + + public void getLimitAd(final CallbackContext callbackContext) { + final int flag = 2; + _getAdInfo(callbackContext, flag); + } + +} \ No newline at end of file diff --git a/src/android/CoreException.java b/src/android/CoreException.java new file mode 100644 index 0000000..635aeab --- /dev/null +++ b/src/android/CoreException.java @@ -0,0 +1,9 @@ +package com.praves.cordova.android.idfa; + +class CoreException extends Exception { + + public CoreException(String message){ + super(message); + } + +} \ No newline at end of file diff --git a/www/androidIDFA.js b/www/androidIDFA.js new file mode 100644 index 0000000..6af09e0 --- /dev/null +++ b/www/androidIDFA.js @@ -0,0 +1,25 @@ + var cordova = require('cordova'); + var androidIDFA = { + + pluginVersion : "1.0.1", //TODO Need to read from plugin.xml file. this value should be in sync plugin.xml value + + getPluginVersion : function(successCallback, errorCallback){ + successCallback(this.pluginVersion); + }, + + getAdInfo : function(successCallback, errorCallback){ + cordova.exec(successCallback, errorCallback, 'AndroidIDFA', 'getAdInfo', []); + }, + + getAdId : function(successCallback, errorCallback){ + cordova.exec(successCallback, errorCallback, 'AndroidIDFA', 'getAdId', []); + }, + + getLimitAd : function(successCallback, errorCallback){ + cordova.exec(successCallback, errorCallback, 'AndroidIDFA', 'getLimitAd', []); + } + + }; + + module.exports = androidIDFA; +