審核對(duì)數(shù)據(jù)的訪問(wèn)
您可以通過(guò)執(zhí)行數(shù)據(jù)訪問(wèn)審核來(lái)了解您的應(yīng)用及其依賴(lài)項(xiàng)如何訪問(wèn)用戶(hù)的私密數(shù)據(jù)。此流程在搭載 Android 11(API 級(jí)別 30)及更高版本的設(shè)備上可用,可讓您更好地識(shí)別可能出現(xiàn)的意外數(shù)據(jù)訪問(wèn)攀甚。您的應(yīng)用可以注冊(cè) AppOpsManager.OnOpNotedCallback
實(shí)例,該實(shí)例可在每次發(fā)生以下任一事件時(shí)執(zhí)行相應(yīng)操作:
- 應(yīng)用的代碼訪問(wèn)私密數(shù)據(jù)旦签。為了幫助您確定應(yīng)用的哪個(gè)邏輯部分調(diào)用了事件拾稳,您可以按歸因標(biāo)記審核數(shù)據(jù)訪問(wèn)。
- 依賴(lài)庫(kù)或 SDK 中的代碼訪問(wèn)私密數(shù)據(jù)参淹。
數(shù)據(jù)訪問(wèn)審核是在發(fā)生數(shù)據(jù)請(qǐng)求的線程上調(diào)用的醉锄。這意味著,如果應(yīng)用中的第三方 SDK 或庫(kù)調(diào)用訪問(wèn)私密數(shù)據(jù)的 API浙值,您的 OnOpNotedCallback
可以調(diào)用數(shù)據(jù)訪問(wèn)審核檢查有關(guān)該調(diào)用的信息榆鼠。通常,此回調(diào)對(duì)象可以通過(guò)查看應(yīng)用的當(dāng)前狀態(tài)(例如當(dāng)前線程的堆棧軌跡)以判斷調(diào)用是來(lái)自您的應(yīng)用還是來(lái)自 SDK亥鸠。
記錄數(shù)據(jù)訪問(wèn)
如需使用 AppOpsManager.OnOpNotedCallback
實(shí)例執(zhí)行數(shù)據(jù)訪問(wèn)審核妆够,請(qǐng)?jiān)谀蛩銓徍藬?shù)據(jù)訪問(wèn)的組件中實(shí)現(xiàn)回調(diào)邏輯,例如在某個(gè) Activity 的 onCreate()
方法中负蚊。
注意:如果您的應(yīng)用在多個(gè)組件(例如在前臺(tái)服務(wù)和后臺(tái)任務(wù))中訪問(wèn)數(shù)據(jù)神妹,請(qǐng)創(chuàng)建自定義子類(lèi) Application
,并在子類(lèi)的 onCreate()
方法中定義 AppOpsManager.OnOpNotedCallback
家妆。
以下代碼段定義了在單個(gè) Activity 中用于審核數(shù)據(jù)訪問(wèn)的 AppOpsManager.OnOpNotedCallback:
@Override
public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
AppOpsManager.OnOpNotedCallback appOpsCallback =
new AppOpsManager.OnOpNotedCallback() {
private void logPrivateDataAccess(String opCode, String trace) {
Log.i(MY_APP_TAG1
, "Private data accessed. " +
"Operation: $opCode\nStack Trace:\n$trace");
}
@Override
public void onNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
logPrivateDataAccess(syncNotedAppOp.getOp(),
Arrays.toString(new Throwable().getStackTrace()));
}
@Override
public void onSelfNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
logPrivateDataAccess(syncNotedAppOp.getOp(),
Arrays.toString(new Throwable().getStackTrace()));
}
@Override
public void onAsyncNoted(@NonNull AsyncNotedAppOp asyncNotedAppOp) {
logPrivateDataAccess(asyncNotedAppOp.getOp(),
asyncNotedAppOp.getMessage());
}
};
AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
if (appOpsManager != null) {
appOpsManager.setOnOpNotedCallback(getMainExecutor(), appOpsCallback);
}
}
在特定情況下鸵荠,需要調(diào)用 onAsyncNoted()
和 onSelfNoted()
方法:
-
如果數(shù)據(jù)訪問(wèn)并非發(fā)生在應(yīng)用調(diào)用 API 期間,需要調(diào)用
onAsyncNoted()
伤极。最常見(jiàn)的一個(gè)例子就是蛹找,在您的應(yīng)用注冊(cè)了監(jiān)聽(tīng)器后姨伤,每次調(diào)用該監(jiān)聽(tīng)器的回調(diào)時(shí)都會(huì)發(fā)生數(shù)據(jù)訪問(wèn)。傳遞到
onAsyncNoted()
中的AsyncNotedOp
參數(shù)包含名為getMessage()
的方法庸疾。此方法提供了有關(guān)數(shù)據(jù)訪問(wèn)的詳細(xì)信息乍楚。如果是位置信息回調(diào),該消息將包含監(jiān)聽(tīng)器的系統(tǒng)身份哈希值届慈。 在極少數(shù)情況下徒溪,如果應(yīng)用將自身的 UID 傳遞到
noteOp()
,需要調(diào)用onSelfNoted()
金顿。
按歸因標(biāo)記審核數(shù)據(jù)訪問(wèn)
您的應(yīng)用可能有幾種主要用例臊泌,例如允許用戶(hù)拍照并與聯(lián)系人分享這些照片。如果您開(kāi)發(fā)的是一款多用途應(yīng)用揍拆,可以在審核應(yīng)用的數(shù)據(jù)訪問(wèn)時(shí)對(duì)應(yīng)用的各部分使用歸因標(biāo)記渠概。在傳遞到 onNoted()
調(diào)用的對(duì)象中會(huì)返回 attributionTag
上下文。這可以幫助您更輕松地將數(shù)據(jù)訪問(wèn)回溯至代碼的邏輯部分嫂拴。
如需在應(yīng)用中定義歸因標(biāo)記播揪,請(qǐng)完成以下部分中的步驟。
創(chuàng)建歸因標(biāo)記
如果您在某個(gè) Activity 中訪問(wèn)數(shù)據(jù)(例如請(qǐng)求位置信息或訪問(wèn)用戶(hù)的聯(lián)系人列表)顷牌,請(qǐng)?jiān)谠?Activity 的 onCreate()
方法中調(diào)用 createAttributionContext()
剪芍,并傳入您希望與應(yīng)用的一部分相關(guān)聯(lián)的歸因標(biāo)記。
以下代碼段展示了如何為應(yīng)用的“照片位置信息分享”部分創(chuàng)建歸因標(biāo)記:
public class SharePhotoLocationActivity extends AppCompatActivity {
private Context attributionContext;
@Override
public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
attributionContext = createAttributionContext("sharePhotos");
}
public void getLocation() {
LocationManager locationManager =
attributionContext.getSystemService(LocationManager.class);
if (locationManager != null) {
// Use "locationManager" to access device location information.
}
}
}
在訪問(wèn)日志中包含歸因標(biāo)記
更新您的 AppOpsManager.OnOpNotedCallback
回調(diào)窟蓝,以將您定義的歸因標(biāo)記的名稱(chēng)包含于應(yīng)用的日志中罪裹。
注意:如果歸因標(biāo)記的返回值為 null
,意味著當(dāng)前的 Context
對(duì)象與您應(yīng)用的主要部分相關(guān)聯(lián)运挫。
以下代碼段展示了記錄歸因代碼的更新邏輯:
@Override
public void onCreate(@Nullable Bundle savedInstanceState,
@Nullable PersistableBundle persistentState) {
AppOpsManager.OnOpNotedCallback appOpsCallback =
new AppOpsManager.OnOpNotedCallback() {
private void logPrivateDataAccess(String opCode,
String attributionTag, String trace) {
Log.i("MY_APP_TAG", "Private data accessed. " +
"Operation: $opCode\n " +
"Attribution Tag:$attributionTag\nStack Trace:\n$trace");
}
@Override
public void onNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
logPrivateDataAccess(syncNotedAppOp.getOp(),
syncNotedAppOp.getAttributionTag(),
Arrays.toString(new Throwable().getStackTrace()));
}
@Override
public void onSelfNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
logPrivateDataAccess(syncNotedAppOp.getOp(),
syncNotedAppOp.getAttributionTag(),
Arrays.toString(new Throwable().getStackTrace()));
}
@Override
public void onAsyncNoted(@NonNull AsyncNotedAppOp asyncNotedAppOp) {
logPrivateDataAccess(asyncNotedAppOp.getOp(),
asyncNotedAppOp.getAttributionTag(),
asyncNotedAppOp.getMessage());
}
};
AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
if (appOpsManager != null) {
appOpsManager.setNotedAppOpsCollector(appOpsCollector);
}
}
資料來(lái)源:https://developer.android.google.cn/guide/topics/data/audit-access#java