| 14792 |
manas |
1 |
/**
|
|
|
2 |
* Copyright 2010-present Facebook.
|
|
|
3 |
*
|
|
|
4 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
5 |
* you may not use this file except in compliance with the License.
|
|
|
6 |
* You may obtain a copy of the License at
|
|
|
7 |
*
|
|
|
8 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
9 |
*
|
|
|
10 |
* Unless required by applicable law or agreed to in writing, software
|
|
|
11 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
12 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
13 |
* See the License for the specific language governing permissions and
|
|
|
14 |
* limitations under the License.
|
|
|
15 |
*/
|
|
|
16 |
|
|
|
17 |
package com.facebook.internal;
|
|
|
18 |
|
|
|
19 |
import android.content.Context;
|
|
|
20 |
import android.database.Cursor;
|
|
|
21 |
import android.net.Uri;
|
|
|
22 |
import android.os.Looper;
|
|
|
23 |
import android.util.Log;
|
|
|
24 |
|
|
|
25 |
import com.facebook.FacebookException;
|
|
|
26 |
|
|
|
27 |
import java.lang.reflect.Method;
|
|
|
28 |
|
|
|
29 |
/**
|
|
|
30 |
* com.facebook.internal is solely for the use of other packages within the Facebook SDK for Android. Use of
|
|
|
31 |
* any of the classes in this package is unsupported, and they may be modified or removed without warning at
|
|
|
32 |
* any time.
|
|
|
33 |
*/
|
|
|
34 |
public class AttributionIdentifiers {
|
|
|
35 |
private static final String TAG = AttributionIdentifiers.class.getCanonicalName();
|
|
|
36 |
private static final Uri ATTRIBUTION_ID_CONTENT_URI =
|
|
|
37 |
Uri.parse("content://com.facebook.katana.provider.AttributionIdProvider");
|
|
|
38 |
private static final String ATTRIBUTION_ID_COLUMN_NAME = "aid";
|
|
|
39 |
private static final String ANDROID_ID_COLUMN_NAME = "androidid";
|
|
|
40 |
private static final String LIMIT_TRACKING_COLUMN_NAME = "limit_tracking";
|
|
|
41 |
|
|
|
42 |
// com.google.android.gms.common.ConnectionResult.SUCCESS
|
|
|
43 |
private static final int CONNECTION_RESULT_SUCCESS = 0;
|
|
|
44 |
|
|
|
45 |
private static final long IDENTIFIER_REFRESH_INTERVAL_MILLIS = 3600 * 1000;
|
|
|
46 |
|
|
|
47 |
private String attributionId;
|
|
|
48 |
private String androidAdvertiserId;
|
|
|
49 |
private boolean limitTracking;
|
|
|
50 |
private long fetchTime;
|
|
|
51 |
|
|
|
52 |
private static AttributionIdentifiers recentlyFetchedIdentifiers;
|
|
|
53 |
|
|
|
54 |
private static AttributionIdentifiers getAndroidId(Context context) {
|
|
|
55 |
AttributionIdentifiers identifiers = new AttributionIdentifiers();
|
|
|
56 |
try {
|
|
|
57 |
// We can't call getAdvertisingIdInfo on the main thread or the app will potentially
|
|
|
58 |
// freeze, if this is the case throw:
|
|
|
59 |
if (Looper.myLooper() == Looper.getMainLooper()) {
|
|
|
60 |
throw new FacebookException("getAndroidId cannot be called on the main thread.");
|
|
|
61 |
}
|
|
|
62 |
Method isGooglePlayServicesAvailable = Utility.getMethodQuietly(
|
|
|
63 |
"com.google.android.gms.common.GooglePlayServicesUtil",
|
|
|
64 |
"isGooglePlayServicesAvailable",
|
|
|
65 |
Context.class
|
|
|
66 |
);
|
|
|
67 |
|
|
|
68 |
if (isGooglePlayServicesAvailable == null) {
|
|
|
69 |
return identifiers;
|
|
|
70 |
}
|
|
|
71 |
|
|
|
72 |
Object connectionResult = Utility.invokeMethodQuietly(null, isGooglePlayServicesAvailable, context);
|
|
|
73 |
if (!(connectionResult instanceof Integer) || (Integer) connectionResult != CONNECTION_RESULT_SUCCESS) {
|
|
|
74 |
return identifiers;
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
Method getAdvertisingIdInfo = Utility.getMethodQuietly(
|
|
|
78 |
"com.google.android.gms.ads.identifier.AdvertisingIdClient",
|
|
|
79 |
"getAdvertisingIdInfo",
|
|
|
80 |
Context.class
|
|
|
81 |
);
|
|
|
82 |
if (getAdvertisingIdInfo == null) {
|
|
|
83 |
return identifiers;
|
|
|
84 |
}
|
|
|
85 |
Object advertisingInfo = Utility.invokeMethodQuietly(null, getAdvertisingIdInfo, context);
|
|
|
86 |
if (advertisingInfo == null) {
|
|
|
87 |
return identifiers;
|
|
|
88 |
}
|
|
|
89 |
|
|
|
90 |
Method getId = Utility.getMethodQuietly(advertisingInfo.getClass(), "getId");
|
|
|
91 |
Method isLimitAdTrackingEnabled = Utility.getMethodQuietly(advertisingInfo.getClass(), "isLimitAdTrackingEnabled");
|
|
|
92 |
if (getId == null || isLimitAdTrackingEnabled == null) {
|
|
|
93 |
return identifiers;
|
|
|
94 |
}
|
|
|
95 |
|
|
|
96 |
identifiers.androidAdvertiserId = (String) Utility.invokeMethodQuietly(advertisingInfo, getId);
|
|
|
97 |
identifiers.limitTracking = (Boolean) Utility.invokeMethodQuietly(advertisingInfo, isLimitAdTrackingEnabled);
|
|
|
98 |
} catch (Exception e) {
|
|
|
99 |
Utility.logd("android_id", e);
|
|
|
100 |
}
|
|
|
101 |
return identifiers;
|
|
|
102 |
}
|
|
|
103 |
|
|
|
104 |
public static AttributionIdentifiers getAttributionIdentifiers(Context context) {
|
|
|
105 |
if (recentlyFetchedIdentifiers != null &&
|
|
|
106 |
System.currentTimeMillis() - recentlyFetchedIdentifiers.fetchTime < IDENTIFIER_REFRESH_INTERVAL_MILLIS) {
|
|
|
107 |
return recentlyFetchedIdentifiers;
|
|
|
108 |
}
|
|
|
109 |
|
|
|
110 |
AttributionIdentifiers identifiers = getAndroidId(context);
|
|
|
111 |
Cursor c = null;
|
|
|
112 |
try {
|
|
|
113 |
String [] projection = {ATTRIBUTION_ID_COLUMN_NAME, ANDROID_ID_COLUMN_NAME, LIMIT_TRACKING_COLUMN_NAME};
|
|
|
114 |
c = context.getContentResolver().query(ATTRIBUTION_ID_CONTENT_URI, projection, null, null, null);
|
|
|
115 |
if (c == null || !c.moveToFirst()) {
|
|
|
116 |
return identifiers;
|
|
|
117 |
}
|
|
|
118 |
int attributionColumnIndex = c.getColumnIndex(ATTRIBUTION_ID_COLUMN_NAME);
|
|
|
119 |
int androidIdColumnIndex = c.getColumnIndex(ANDROID_ID_COLUMN_NAME);
|
|
|
120 |
int limitTrackingColumnIndex = c.getColumnIndex(LIMIT_TRACKING_COLUMN_NAME);
|
|
|
121 |
|
|
|
122 |
identifiers.attributionId = c.getString(attributionColumnIndex);
|
|
|
123 |
|
|
|
124 |
// if we failed to call Google's APIs directly (due to improper integration by the client), it may be
|
|
|
125 |
// possible for the local facebook application to relay it to us.
|
|
|
126 |
if (androidIdColumnIndex > 0 && limitTrackingColumnIndex > 0 && identifiers.getAndroidAdvertiserId() == null) {
|
|
|
127 |
identifiers.androidAdvertiserId = c.getString(androidIdColumnIndex);
|
|
|
128 |
identifiers.limitTracking = Boolean.parseBoolean(c.getString(limitTrackingColumnIndex));
|
|
|
129 |
}
|
|
|
130 |
} catch (Exception e) {
|
|
|
131 |
Log.d(TAG, "Caught unexpected exception in getAttributionId(): " + e.toString());
|
|
|
132 |
return null;
|
|
|
133 |
} finally {
|
|
|
134 |
if (c != null) {
|
|
|
135 |
c.close();
|
|
|
136 |
}
|
|
|
137 |
}
|
|
|
138 |
|
|
|
139 |
identifiers.fetchTime = System.currentTimeMillis();
|
|
|
140 |
recentlyFetchedIdentifiers = identifiers;
|
|
|
141 |
return identifiers;
|
|
|
142 |
}
|
|
|
143 |
|
|
|
144 |
public String getAttributionId() {
|
|
|
145 |
return attributionId;
|
|
|
146 |
}
|
|
|
147 |
|
|
|
148 |
public String getAndroidAdvertiserId() {
|
|
|
149 |
return androidAdvertiserId;
|
|
|
150 |
}
|
|
|
151 |
|
|
|
152 |
public boolean isTrackingLimited() {
|
|
|
153 |
return limitTracking;
|
|
|
154 |
}
|
|
|
155 |
}
|