Sie erhalten Informationen darüber, wie Ihre Anwendung und ihre Abhängigkeiten auf private Daten zugreifen
durch eine Audit-Funktion für den Datenzugriff. Dieses Verfahren ist auf Geräten mit Android 11 (API-Level 30) oder höher verfügbar. So können Sie potenziell unerwartete Datenzugriffe besser erkennen. Ihre App kann eine Instanz von AppOpsManager.OnOpNotedCallback
registrieren, die Aktionen ausführen kann, wenn eines der folgenden Ereignisse eintritt:
- Der Code Ihrer App greift auf private Daten zu. Wenn Sie herausfinden möchten, welcher logische Teil Ihrer App das Ereignis ausgelöst hat, können Sie den Datenzugriff nach Attributions-Tag prüfen.
- Code in einer abhängigen Bibliothek oder einem SDK greift auf private Daten zu.
Die Prüfung des Datenzugriffs wird in dem Thread aufgerufen, in dem die Datenanfrage erfolgt. Wenn also ein SDK oder eine Bibliothek eines Drittanbieters in Ihrer App eine API aufruft, die auf personenbezogene Daten zugreift, können Sie mithilfe der Datenzugriffsüberprüfung Informationen zum Aufruf prüfen. Normalerweise kann dieses Callback-Objekt anhand des aktuellen Status der App, z. B. des Stack-Traces des aktuellen Threads, erkennen, ob der Aufruf von Ihrer App oder dem SDK stammt.
Zugriff auf Daten protokollieren
Um Datenzugriff mit einer Instanz von
AppOpsManager.OnOpNotedCallback
, implementiere die Callback-Logik in der Komponente
in denen Sie den Datenzugriff prüfen möchten, z. B. in der
onCreate()
oder der Methode
onCreate()
-Methode.
Das folgende Code-Snippet definiert ein AppOpsManager.OnOpNotedCallback
für
Prüfung des Datenzugriffs innerhalb einer einzigen Aktivität:
override fun onCreate(savedInstanceState: Bundle?) { val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() { private fun logPrivateDataAccess(opCode: String, trace: String) { Log.i(MY_APP_TAG , "Private data accessed. " + "Operation: $opCode\nStack Trace:\n$trace") } override fun onNoted(syncNotedAppOp: SyncNotedAppOp) { logPrivateDataAccess( syncNotedAppOp.op, Throwable().stackTrace.toString()) } override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) { logPrivateDataAccess( syncNotedAppOp.op, Throwable().stackTrace.toString()) } override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) { logPrivateDataAccess(asyncNotedAppOp.op, asyncNotedAppOp.message) } } val appOpsManager = getSystemService(AppOpsManager::class.java) as AppOpsManager appOpsManager.setOnOpNotedCallback(mainExecutor, appOpsCallback) }
@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_TAG , "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); } }
Die Methoden onAsyncNoted()
und onSelfNoted()
werden in bestimmten Situationen aufgerufen:
onAsyncNoted()
wird aufgerufen, wenn der Datenzugriff nicht während des API-Aufrufs Ihrer App erfolgt. Das häufigste Beispiel ist, wenn Ihre App einen Listener registriert und der Datenzugriff jedes Mal erfolgt, wenn der Callback des Listeners aufgerufen wird.Das Argument
AsyncNotedOp
, das anonAsyncNoted()
übergeben wird, enthält einen mit dem NamengetMessage()
. Diese Methode liefert mehr Informationen über den Datenzugriff. Bei Standort-Callbacks enthält die Nachricht Den Systemidentitäts-Hash des ListenersonSelfNoted()
wird in sehr seltenen Fällen aufgerufen, wenn eine App ihre eigene UID annoteOp()
weitergibt.
Datenzugriff nach Attributions-Tag prüfen
Ihre App kann mehrere primäre Anwendungsfälle haben, z. B. ermöglicht es Nutzern,
und diese Fotos mit ihren Kontakten teilen. Wenn Sie eine
Mehrzweck-App verwenden, können Sie auf jeden Teil der App ein Attributions-Tag anwenden.
wenn Sie den Datenzugriff prüfen. Der Kontext attributionTag
wird zurückgegeben.
in den Objekten, die an die Aufrufe von onNoted()
übergeben werden.
So können Sie den Datenzugriff leichter auf logische Teile Ihres Codes zurückführen.
So definieren Sie Attributions-Tags in Ihrer App: .
Attributions-Tags im Manifest deklarieren
Wenn Ihre App auf Android 12 (API-Level 31) oder höher ausgerichtet ist, müssen Sie Attributions-Tags in der Manifestdatei Ihrer App im Format des folgenden Code-Snippets deklarieren. Wenn Sie versuchen, ein Attributions-Tag zu verwenden, das nicht in der Manifestdatei Ihrer App deklariert ist, erstellt das System ein null
-Tag für Sie und protokolliert eine Nachricht in Logcat.
<manifest ...> <!-- The value of "android:tag" must be a literal string, and the value of "android:label" must be a resource. The value of "android:label" is user-readable. --> <attribution android:tag="sharePhotos" android:label="@string/share_photos_attribution_label" /> ... </manifest>
Attributions-Tags erstellen
Rufen Sie in der Methode onCreate()
der Aktivität, bei der Sie auf Daten zugreifen, z. B. bei der Aktivität, bei der Sie den Standort anfordern oder auf die Kontaktliste des Nutzers zugreifen, createAttributionContext()
auf und geben Sie das Attribution-Tag ein, das Sie einem Teil Ihrer App zuordnen möchten.
Das folgende Code-Snippet zeigt, wie ein Attributions-Tag für einen Teil einer App erstellt wird, in dem Fotos mit Standortfreigabe geteilt werden:
class SharePhotoLocationActivity : AppCompatActivity() { lateinit var attributionContext: Context override fun onCreate(savedInstanceState: Bundle?) { attributionContext = createAttributionContext("sharePhotos") } fun getLocation() { val locationManager = attributionContext.getSystemService( LocationManager::class.java) as LocationManager // Use "locationManager" to access device location information. } }
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. } } }
Attributions-Tags in Zugriffslogs einschließen
Aktualisiere deinen AppOpsManager.OnOpNotedCallback
-Callback, damit die Logs deiner App gespeichert werden
die Namen der von Ihnen definierten Attributions-Tags enthalten.
Das folgende Code-Snippet enthält eine aktualisierte Logik, die Attributions-Tags protokolliert:
val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() { private fun logPrivateDataAccess( opCode: String, attributionTag: String, trace: String) { Log.i(MY_APP_TAG, "Private data accessed. " + "Operation: $opCode\n " + "Attribution Tag:$attributionTag\nStack Trace:\n$trace") } override fun onNoted(syncNotedAppOp: SyncNotedAppOp) { logPrivateDataAccess(syncNotedAppOp.op, syncNotedAppOp.attributionTag, Throwable().stackTrace.toString()) } override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) { logPrivateDataAccess(syncNotedAppOp.op, syncNotedAppOp.attributionTag, Throwable().stackTrace.toString()) } override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) { logPrivateDataAccess(asyncNotedAppOp.op, asyncNotedAppOp.attributionTag, asyncNotedAppOp.message) } }
@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); } }