डेटा ऐक्सेस ऑडिट करके, यह अहम जानकारी पाई जा सकती है कि आपका ऐप्लिकेशन और उसकी डिपेंडेंसी, उपयोगकर्ताओं के निजी डेटा को कैसे ऐक्सेस करती हैं. यह प्रोसेस, Android 11 (एपीआई लेवल 30) और इसके बाद के वर्शन वाले डिवाइसों पर उपलब्ध है. इससे, आपको डेटा को बिना आपकी अनुमति के ऐक्सेस करने की संभावित घटनाओं की बेहतर तरीके से पहचान करने में मदद मिलती है. आपका ऐप्लिकेशन, AppOpsManager.OnOpNotedCallback
का एक इंस्टेंस रजिस्टर कर सकता है. यह इंस्टेंस, यहां दिए गए हर इवेंट के होने पर कार्रवाई कर सकता है:
- आपके ऐप्लिकेशन का कोड, निजी डेटा को ऐक्सेस करता है. यह पता लगाने के लिए कि आपके ऐप्लिकेशन के किस लॉजिकल पार्ट ने इवेंट को शुरू किया है, एट्रिब्यूशन टैग के हिसाब से डेटा ऐक्सेस का ऑडिट करें.
- डिपेंडेंट लाइब्रेरी या SDK टूल में मौजूद कोड, निजी डेटा को ऐक्सेस करता है.
डेटा ऐक्सेस ऑडिटिंग को उस थ्रेड पर शुरू किया जाता है जहां डेटा का अनुरोध किया जाता है. इसका मतलब है कि अगर आपके ऐप्लिकेशन में मौजूद तीसरे पक्ष का कोई SDK टूल या लाइब्रेरी, निजी डेटा को ऐक्सेस करने वाले किसी एपीआई को कॉल करती है, तो डेटा ऐक्सेस ऑडिटिंग की सुविधा की मदद से, OnOpNotedCallback
कॉल के बारे में जानकारी देख सकते हैं. आम तौर पर, यह कॉलबैक ऑब्जेक्ट यह बता सकता है कि कॉल आपके ऐप्लिकेशन से आया है या SDK से. इसके लिए, वह ऐप्लिकेशन की मौजूदा स्थिति देखता है. जैसे, मौजूदा थ्रेड का स्टैक ट्रेस.
डेटा के ऐक्सेस को लॉग करना
AppOpsManager.OnOpNotedCallback
के किसी इंस्टेंस का इस्तेमाल करके, डेटा ऐक्सेस करने की ऑडिटिंग करने के लिए, उस कॉम्पोनेंट में कॉलबैक लॉजिक लागू करें जहां आपको डेटा ऐक्सेस करने की ऑडिटिंग करनी है. जैसे, किसी गतिविधि के onCreate()
तरीके या किसी ऐप्लिकेशन के onCreate()
तरीके में.
नीचे दिया गया कोड स्निपेट, एक ही गतिविधि में डेटा ऐक्सेस करने की ऑडिटिंग के लिए AppOpsManager.OnOpNotedCallback
को तय करता है:
Kotlin
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) }
Java
@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); } }
onAsyncNoted()
और onSelfNoted()
तरीकों को खास स्थितियों में कॉल किया जाता है:
onAsyncNoted()
को तब कॉल किया जाता है, जब आपके ऐप्लिकेशन के एपीआई कॉल के दौरान डेटा ऐक्सेस नहीं किया जाता है. इसका सबसे सामान्य उदाहरण तब होता है, जब आपका ऐप्लिकेशन किसी लिसनर को रजिस्टर करता है और लिसनर के कॉलबैक को हर बार शुरू किए जाने पर डेटा ऐक्सेस किया जाता है.onAsyncNoted()
में पास किए गएAsyncNotedOp
आर्ग्युमेंट मेंgetMessage()
नाम का एक तरीका शामिल है. इस तरीके से, डेटा ऐक्सेस करने के बारे में ज़्यादा जानकारी मिलती है. जगह की जानकारी देने वाले कॉलबैक के मामले में, मैसेज में लिसनर का सिस्टम-आइडेंटिटी-हैश होता है.onSelfNoted()
को बहुत कम मामलों में तब कॉल किया जाता है, जब कोई ऐप्लिकेशन अपना यूआईडीnoteOp()
में पास करता है.
एट्रिब्यूशन टैग के हिसाब से डेटा ऐक्सेस की ऑडिट करना
आपके ऐप्लिकेशन के कई मुख्य इस्तेमाल के उदाहरण हो सकते हैं. जैसे, उपयोगकर्ताओं को फ़ोटो कैप्चर करने और उन्हें अपने संपर्कों के साथ शेयर करने की सुविधा देना. अगर आपने एक से ज़्यादा कामों के लिए कोई ऐप्लिकेशन बनाया है, तो डेटा ऐक्सेस करने की ऑडिट करते समय, अपने ऐप्लिकेशन के हर हिस्से पर एट्रिब्यूशन टैग लागू किया जा सकता है. onNoted()
को किए गए कॉल में पास किए गए ऑब्जेक्ट में, attributionTag
कॉन्टेक्स्ट वापस कर दिया जाता है.
इससे आपको अपने कोड के लॉजिकल हिस्सों में डेटा ऐक्सेस को ज़्यादा आसानी से ट्रैक करने में मदद मिलती है.
अपने ऐप्लिकेशन में एट्रिब्यूशन टैग तय करने के लिए, यहां दिए गए सेक्शन में बताया गया तरीका अपनाएं.
मेनिफ़ेस्ट में एट्रिब्यूशन टैग की जानकारी देना
अगर आपका ऐप्लिकेशन, Android 12 (एपीआई लेवल 31) या उसके बाद के वर्शन को टारगेट करता है, तो आपको अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में एट्रिब्यूशन टैग के बारे में एलान करना होगा. इसके लिए, यहां दिए गए कोड स्निपेट में दिखाया गया फ़ॉर्मैट इस्तेमाल करें. अगर आपने किसी ऐसे एट्रिब्यूशन टैग का इस्तेमाल करने की कोशिश की है जिसे आपने अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में शामिल नहीं किया है, तो सिस्टम आपके लिए null
टैग बना देगा. साथ ही, 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>
एट्रिब्यूशन टैग बनाना
ऐसी गतिविधि में जहां डेटा ऐक्सेस किया जाता है, जैसे कि ऐसी गतिविधि जहां आपको लोकेशन का अनुरोध करना होता है या उपयोगकर्ता की संपर्क सूची को ऐक्सेस करना होता है, वहां onCreate()
तरीके का इस्तेमाल करें. इसके लिए, createAttributionContext()
को कॉल करें और एट्रिब्यूशन टैग पास करें. यह टैग, आपके ऐप्लिकेशन के किसी हिस्से से जुड़ा होना चाहिए.
यहां दिए गए कोड स्निपेट में, ऐप्लिकेशन के फ़ोटो और जगह की जानकारी शेयर करने वाले हिस्से के लिए एट्रिब्यूशन टैग बनाने का तरीका बताया गया है:
Kotlin
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. } }
Java
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. } } }
ऐक्सेस लॉग में एट्रिब्यूशन टैग शामिल करें
अपने AppOpsManager.OnOpNotedCallback
कॉलबैक को अपडेट करें, ताकि आपके ऐप्लिकेशन के लॉग में एट्रिब्यूशन टैग के वे नाम शामिल हों जिन्हें आपने तय किया है.
नीचे दिए गए कोड स्निपेट में, एट्रिब्यूशन टैग लॉग करने के लिए अपडेट किया गया लॉजिक दिखाया गया है:
Kotlin
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) } }
Java
@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); } }