1.通訊錄短信通話記錄等權(quán)限優(yōu)先級(jí)
google現(xiàn)在的政策是禁止拿用戶的通話記錄和短信的,不要觸碰,通訊錄在你有正當(dāng)使用的場(chǎng)景的時(shí)候是可以拿到的但是必須做到一下四點(diǎn)
1.通訊錄的應(yīng)用場(chǎng)景必須合適,使用時(shí)彈窗提示用戶我們拿通訊錄的用途
2.上傳之前必須能夠提示用戶要上傳通訊錄了,讓用戶能夠做出選擇
3.上傳不能太頻繁
4.隱私政策聲明
還有一個(gè)問(wèn)題就是在10.0之后是沒(méi)法拿到用戶的獲取通話次數(shù),通話時(shí)間了。
2.最新的位置權(quán)限要求(goolge于2020 年 4 月 16 日更新)
- 如果應(yīng)用不再需要利用受位置權(quán)限(例如 ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION、ACCESS_BACKGROUND_LOCATION)保護(hù)的數(shù)據(jù)來(lái)提供應(yīng)用內(nèi)的現(xiàn)有功能或服務(wù),就不得再使用這些數(shù)據(jù)。
- 您不得純粹出于廣告投放或數(shù)據(jù)分析的目的而請(qǐng)求用戶授予位置權(quán)限。如果應(yīng)用在此類數(shù)據(jù)的許可用途基礎(chǔ)上額外將其用于廣告投放的目的,則必須遵守我們的廣告政策。
- 即使是出于提供現(xiàn)有功能或服務(wù)的目的而需要使用位置信息,應(yīng)用也應(yīng)請(qǐng)求最小范圍的必要權(quán)限(即應(yīng)請(qǐng)求粗略權(quán)限、前臺(tái)權(quán)限,而非精細(xì)權(quán)限、后臺(tái)權(quán)限),并且為相應(yīng)功能或服務(wù)所請(qǐng)求的位置權(quán)限級(jí)別應(yīng)在用戶的合理預(yù)期范圍內(nèi)。例如,如果應(yīng)用請(qǐng)求或訪問(wèn)后臺(tái)位置信息,但理由缺乏說(shuō)服力,我們可能會(huì)拒絕該應(yīng)用。
- 后臺(tái)位置信息僅可用于提供對(duì)用戶有益及與應(yīng)用核心功能相關(guān)的功能。
在滿足以下條件的情況下,應(yīng)用可以使用前臺(tái)服務(wù)(當(dāng)應(yīng)用僅有前臺(tái)訪問(wèn)權(quán)限時(shí),例如“使用時(shí)”)權(quán)限訪問(wèn)位置信息:
- 使用此權(quán)限使是為了完成用戶在應(yīng)用內(nèi)發(fā)起的操作的后續(xù)操作;并且
- 在應(yīng)用按用戶發(fā)起操作的意圖完成相關(guān)用例后立即終止使用該權(quán)限。
這次更新對(duì)位置的權(quán)限使用更嚴(yán)格了,有相關(guān)下架風(fēng)險(xiǎn)的要及時(shí)修改
3.應(yīng)用更新的問(wèn)題
上次有個(gè)問(wèn)題就是我們應(yīng)用自帶更新功能導(dǎo)致從google play下架
根據(jù)google郵件提示就是我們自己的APP可能會(huì)從我們自己的服務(wù)器上下載APK包,把我們自己的內(nèi)部更新去掉統(tǒng)一走google商店更新就好了。
4.獲取用戶的wifi_ssid和具體gps定位的問(wèn)題。
先把我自己獲取wifi_ssid的代碼貼上來(lái)
public static String getWIFISSID() {
String ssid = "";
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O) {
WifiManager mWifiManager = (WifiManager) BaseApplication.getContext().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
assert mWifiManager != null;
WifiInfo info = mWifiManager.getConnectionInfo();
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
return info.getSSID().replace("\"", "");
} else {
return info.getSSID();
}
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) {
ConnectivityManager connManager = (ConnectivityManager) BaseApplication.getContext().getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
assert connManager != null;
NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
if (networkInfo == null) {
return ssid;
} else if (networkInfo.isConnected()&&networkInfo.getExtraInfo() != nul) {
return networkInfo.getExtraInfo().replace("\"", "");
}
} else {
WifiManager wifiManager = (WifiManager) BaseApplication.getContext().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
assert wifiManager != null;
WifiInfo info = wifiManager.getConnectionInfo();
int networkId = info.getNetworkId();
List<WifiConfiguration> configurations = wifiManager.getConfiguredNetworks();
for (WifiConfiguration c : configurations) {
if (c.networkId == networkId) {
return c.SSID.replace("\"", "");
}
}
}
return ssid;
}
直接說(shuō)答案了...如果你的手機(jī)版本是9及以上在你獲取用戶的wifi_ssid和具體gps定位的時(shí)候必須要得到ACCESS_FINE_LOCATION這個(gè)權(quán)限,另外還需要開(kāi)啟手機(jī)的gps開(kāi)關(guān)。9以下就沒(méi)這些問(wèn)題了。
5.facebook的延遲深度鏈接問(wèn)題
需求場(chǎng)景:我們目前的項(xiàng)目都是主要在facebook上投放廣告導(dǎo)流,雖然說(shuō)是facebook后臺(tái)也提供了一些統(tǒng)計(jì)的工具,但是我們自己的廣告后臺(tái)也需要看一些廣告的數(shù)據(jù),比如區(qū)分一些廣告流量和自然流量等等。還有為什么我這里只說(shuō)facebook的延遲深度鏈接,facebook的常規(guī)深度鏈接在他們的開(kāi)發(fā)者文檔和一些博客介紹的很詳細(xì)了,我貼一個(gè)鏈接有需要的可以看這里的Android Deeplink,F(xiàn)acebook 廣告deeplink配置與測(cè)試
其實(shí)延遲深度鏈接的配置和一般的深度鏈接都是一樣的可以參考上面的那篇文章,另外測(cè)試也是那個(gè)網(wǎng)址,不過(guò)你需要勾選上延遲選項(xiàng)。測(cè)試時(shí)有一點(diǎn)需要說(shuō)明是你的廣告后臺(tái)的測(cè)試賬號(hào)需要和你手機(jī)登錄facebook的app賬號(hào)相同。
其實(shí)延遲深度鏈接就是在你的application中增加這一行
AppLinkData.fetchDeferredAppLinkData(this,
new AppLinkData.CompletionHandler() {
@Override
public void onDeferredAppLinkDataFetched(AppLinkData appLinkData) {
if (appLinkData!=null&&appLinkData.getTargetUri()!=null){
//你的 //你的上報(bào)處理appLinkData.getTargetUri().toString()
處理appLinkData.getTargetUri().toString()
}
}
}
);
但是我發(fā)現(xiàn)facebook的延遲深度鏈接TargetUri并不需要嚴(yán)格按照你的配置文件進(jìn)行推送,因?yàn)椴还芪彝频牡氖裁磚ri過(guò)來(lái)只要觸發(fā)了這個(gè)回調(diào)并且appLinkData不為null,我們就可以拿到他的TargetUri。在看完facebook sdk相關(guān)源碼后覺(jué)得一切順理成章,在AppLinkData這個(gè)類中會(huì)異步調(diào)用fetchDeferredAppLinkFromServer這個(gè)方法,顧名思義就是這個(gè)applink這個(gè)值是存在facebook后臺(tái)的。打開(kāi)APP就會(huì)去facebook后臺(tái)進(jìn)行查詢
public static void fetchDeferredAppLinkData(
Context context,
String applicationId,
final CompletionHandler completionHandler) {
Validate.notNull(context, "context");
Validate.notNull(completionHandler, "completionHandler");
if (applicationId == null) {
applicationId = Utility.getMetadataApplicationId(context);
}
Validate.notNull(applicationId, "applicationId");
final Context applicationContext = context.getApplicationContext();
final String applicationIdCopy = applicationId;
FacebookSdk.getExecutor().execute(new Runnable() {
@Override
public void run() {
fetchDeferredAppLinkFromServer(
applicationContext, applicationIdCopy, completionHandler);
}
});
}
private static void fetchDeferredAppLinkFromServer(
Context context,
String applicationId,
final CompletionHandler completionHandler) {
JSONObject deferredApplinkParams = new JSONObject();
try {
deferredApplinkParams.put("event", DEFERRED_APP_LINK_EVENT);
Utility.setAppEventAttributionParameters(deferredApplinkParams,
AttributionIdentifiers.getAttributionIdentifiers(context),
AppEventsLogger.getAnonymousAppDeviceGUID(context),
FacebookSdk.getLimitEventAndDataUsage(context));
Utility.setAppEventExtendedDeviceInfoParameters(
deferredApplinkParams,
FacebookSdk.getApplicationContext());
deferredApplinkParams.put("application_package_name", context.getPackageName());
} catch (JSONException e) {
throw new FacebookException("An error occurred while preparing deferred app link", e);
}
String deferredApplinkUrlPath = String.format(DEFERRED_APP_LINK_PATH, applicationId);
AppLinkData appLinkData = null;
try {
GraphRequest deferredApplinkRequest = GraphRequest.newPostRequest(
null, deferredApplinkUrlPath, deferredApplinkParams, null);
GraphResponse deferredApplinkResponse = deferredApplinkRequest.executeAndWait();
JSONObject jsonResponse = deferredApplinkResponse.getJSONObject();
if (jsonResponse != null) {
final String appLinkArgsJsonString =
jsonResponse.optString(DEFERRED_APP_LINK_ARGS_FIELD);
final long tapTimeUtc =
jsonResponse.optLong(DEFERRED_APP_LINK_CLICK_TIME_FIELD, -1);
final String appLinkClassName =
jsonResponse.optString(DEFERRED_APP_LINK_CLASS_FIELD);
final String appLinkUrl = jsonResponse.optString(DEFERRED_APP_LINK_URL_FIELD);
if (!TextUtils.isEmpty(appLinkArgsJsonString)) {
appLinkData = createFromJson(appLinkArgsJsonString);
if (tapTimeUtc != -1) {
try {
if (appLinkData.arguments != null) {
appLinkData.arguments.put(ARGUMENTS_TAPTIME_KEY, tapTimeUtc);
}
if (appLinkData.argumentBundle != null) {
appLinkData.argumentBundle.putString(
ARGUMENTS_TAPTIME_KEY, Long.toString(tapTimeUtc));
}
} catch (JSONException e) {
Utility.logd(TAG, "Unable to put tap time in AppLinkData.arguments");
}
}
if (appLinkClassName != null) {
try {
if (appLinkData.arguments != null) {
appLinkData.arguments.put(
ARGUMENTS_NATIVE_CLASS_KEY, appLinkClassName);
}
if (appLinkData.argumentBundle != null) {
appLinkData.argumentBundle.putString(
ARGUMENTS_NATIVE_CLASS_KEY, appLinkClassName);
}
} catch (JSONException e) {
Utility.logd(TAG, "Unable to put tap time in AppLinkData.arguments");
}
}
if (appLinkUrl != null) {
try {
if (appLinkData.arguments != null) {
appLinkData.arguments.put(ARGUMENTS_NATIVE_URL, appLinkUrl);
}
if (appLinkData.argumentBundle != null) {
appLinkData.argumentBundle.putString(
ARGUMENTS_NATIVE_URL, appLinkUrl);
}
} catch (JSONException e) {
Utility.logd(TAG, "Unable to put tap time in AppLinkData.arguments");
}
}
}
}
} catch (Exception e) {
Utility.logd(TAG, "Unable to fetch deferred applink from server");
}
completionHandler.onDeferredAppLinkDataFetched(appLinkData);
}
總結(jié)了以下Facebook的延遲深度鏈接大概原理就是,如果用戶尚未安裝這個(gè)廣告的APP點(diǎn)擊進(jìn)入googleplay就會(huì)把這個(gè)設(shè)備的一些信息和TargetUri進(jìn)行上傳,當(dāng)有用戶下載了打開(kāi)了這個(gè)APP就去facebook后臺(tái)查詢獲取這個(gè)用戶特定的TargetUri,由于從facebook跳轉(zhuǎn)到google商店之后的操作facebook是無(wú)法控制的所以只能采取這種方法了