डेटा ऐक्सेस ऑडिटिंग की मदद से, यह जानकारी हासिल की जा सकती है कि आपका ऐप्लिकेशन और उस पर निर्भर सेवाएं, उपयोगकर्ताओं के निजी डेटा को कैसे ऐक्सेस करती हैं. यह प्रोसेस, Android 11 (एपीआई लेवल 30) और इसके बाद के वर्शन वाले डिवाइसों पर उपलब्ध है. इससे आपको डेटा के संभावित अनचाहे ऐक्सेस की बेहतर पहचान करने में मदद मिलती है. आपका ऐप्लिकेशन, AppOpsManager.OnOpNotedCallback का एक इंस्टेंस रजिस्टर कर सकता है. यह इंस्टेंस, इनमें से कोई भी इवेंट होने पर कार्रवाइयां कर सकता है:
- आपके ऐप्लिकेशन का कोड, निजी डेटा को ऐक्सेस करता है. आपके ऐप्लिकेशन के किस लॉजिकल पार्ट ने इवेंट को ट्रिगर किया, यह तय करने में आपकी मदद करने के लिए, एट्रिब्यूशन टैग की मदद से डेटा ऐक्सेस का ऑडिट किया जा सकता है.
- डिपेंडेंट लाइब्रेरी या SDK टूल में मौजूद कोड, निजी डेटा को ऐक्सेस करता है.
डेटा ऐक्सेस ऑडिटिंग को उस थ्रेड पर शुरू किया जाता है जहां डेटा का अनुरोध किया जाता है. इसका मतलब है कि अगर आपके ऐप्लिकेशन में मौजूद तीसरे पक्ष का कोई SDK टूल या लाइब्रेरी, निजी डेटा को ऐक्सेस करने वाले किसी एपीआई को कॉल करती है, तो डेटा ऐक्सेस ऑडिटिंग की सुविधा आपके OnOpNotedCallback को कॉल की जानकारी की जांच करने की अनुमति देती है. आम तौर पर, यह कॉलबैक ऑब्जेक्ट, ऐप्लिकेशन की मौजूदा स्थिति को देखकर बता सकता है कि कॉल आपके ऐप्लिकेशन से आया है या एसडीके से. जैसे, मौजूदा थ्रेड का स्टैक ट्रेस.
डेटा के ऐक्सेस को लॉग करना
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()में पास करता है.
एट्रिब्यूशन टैग के हिसाब से डेटा ऐक्सेस का ऑडिट करना
आपके ऐप्लिकेशन के कई मुख्य इस्तेमाल हो सकते हैं. जैसे, उपयोगकर्ताओं को फ़ोटो खींचने और उन्हें अपने संपर्कों के साथ शेयर करने की सुविधा देना. अगर आपने कई कामों के लिए इस्तेमाल किया जाने वाला ऐप्लिकेशन बनाया है, तो डेटा ऐक्सेस का ऑडिट करते समय, ऐप्लिकेशन के हर हिस्से पर एट्रिब्यूशन टैग लागू किया जा सकता है. attributionTag कॉन्टेक्स्ट, onNoted() को किए गए कॉल में पास किए गए ऑब्जेक्ट में वापस भेजा जाता है.
इससे आपको डेटा ऐक्सेस को अपने कोड के लॉजिकल हिस्सों तक आसानी से ट्रेस करने में मदद मिलती है.
अपने ऐप्लिकेशन में एट्रिब्यूशन टैग तय करने के लिए, यहां दिए गए सेक्शन में बताया गया तरीका अपनाएं.
मेनिफ़ेस्ट में एट्रिब्यूशन टैग तय करना
अगर आपका ऐप्लिकेशन 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.setOnOpNotedCallback(getMainExecutor(), appOpsCallback); } }