ডেটাতে অডিট অ্যাক্সেস

ডেটা অ্যাক্সেস অডিট করার মাধ্যমে আপনি কীভাবে আপনার অ্যাপ এবং এর নির্ভরতা ব্যবহারকারীদের কাছ থেকে ব্যক্তিগত ডেটা অ্যাক্সেস করে সে সম্পর্কে অন্তর্দৃষ্টি পেতে পারেন। অ্যান্ড্রয়েড 11 (API লেভেল 30) এবং উচ্চতর চালিত ডিভাইসগুলিতে উপলব্ধ এই প্রক্রিয়াটি আপনাকে সম্ভাব্য অপ্রত্যাশিত ডেটা অ্যাক্সেস আরও ভালভাবে সনাক্ত করতে দেয়। আপনার অ্যাপ AppOpsManager.OnOpNotedCallback এর একটি উদাহরণ নিবন্ধন করতে পারে, যেটি প্রতিবার নিম্নলিখিত ইভেন্টগুলির মধ্যে একটি ঘটলেই ক্রিয়া সম্পাদন করতে পারে:

  • আপনার অ্যাপের কোড ব্যক্তিগত ডেটা অ্যাক্সেস করে। আপনার অ্যাপের কোন যৌক্তিক অংশটি ইভেন্টটি শুরু করেছে তা নির্ধারণ করতে সাহায্য করার জন্য, আপনি অ্যাট্রিবিউশন ট্যাগ দ্বারা ডেটা অ্যাক্সেস অডিট করতে পারেন৷
  • একটি নির্ভরশীল লাইব্রেরিতে কোড বা SDK ব্যক্তিগত ডেটা অ্যাক্সেস করে।

ডেটা অ্যাক্সেস অডিটিং থ্রেডে আহ্বান করা হয় যেখানে ডেটা অনুরোধ করা হয়। এর মানে হল যে যদি আপনার অ্যাপে একটি তৃতীয় পক্ষের SDK বা লাইব্রেরি এমন একটি API কল করে যা ব্যক্তিগত ডেটা অ্যাক্সেস করে, ডেটা অ্যাক্সেস অডিটিং আপনার OnOpNotedCallback কল সম্পর্কে তথ্য পরীক্ষা করতে দেয়। সাধারণত, এই কলব্যাক অবজেক্টটি অ্যাপের বর্তমান স্থিতি, যেমন বর্তমান থ্রেডের স্ট্যাক ট্রেস দেখে কলটি আপনার অ্যাপ বা SDK থেকে এসেছে কিনা তা বলতে পারে।

তথ্য লগ অ্যাক্সেস

AppOpsManager.OnOpNotedCallback এর একটি উদাহরণ ব্যবহার করে ডেটা অ্যাক্সেস অডিটিং সঞ্চালন করতে, যে উপাদানটিতে আপনি ডেটা অ্যাক্সেস অডিট করতে চান সেখানে কলব্যাক যুক্তি প্রয়োগ করুন, যেমন একটি কার্যকলাপের onCreate() পদ্ধতি বা একটি অ্যাপ্লিকেশনের onCreate() পদ্ধতির মধ্যে৷

নিম্নলিখিত কোড স্নিপেট একটি AppOpsManager.OnOpNotedCallback সংজ্ঞায়িত করে একটি একক কার্যকলাপের মধ্যে ডেটা অ্যাক্সেস অডিট করার জন্য:

কোটলিন

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);
    }
}

onAsyncNoted() এবং onSelfNoted() পদ্ধতিগুলিকে নির্দিষ্ট পরিস্থিতিতে বলা হয়:

  • onAsyncNoted() কল করা হয় যদি আপনার অ্যাপের API কল চলাকালীন ডেটা অ্যাক্সেস না হয়। সবচেয়ে সাধারণ উদাহরণ হল যখন আপনার অ্যাপ একজন শ্রোতাকে নিবন্ধন করে এবং প্রতিবার শ্রোতার কলব্যাক ডাকার সময় ডেটা অ্যাক্সেস ঘটে।

    AsyncNotedOp আর্গুমেন্ট যা onAsyncNoted() এ পাস করা হয়েছে তাতে getMessage() নামে একটি পদ্ধতি রয়েছে। এই পদ্ধতি ডেটা অ্যাক্সেস সম্পর্কে আরও তথ্য প্রদান করে। অবস্থান কলব্যাকের ক্ষেত্রে, বার্তাটিতে শ্রোতার সিস্টেম-পরিচয়-হ্যাশ থাকে।

  • onSelfNoted() খুব বিরল ক্ষেত্রে বলা হয় যখন একটি অ্যাপ তার নিজস্ব UID noteOp() এ পাস করে।

অ্যাট্রিবিউশন ট্যাগ দ্বারা অডিট ডেটা অ্যাক্সেস

আপনার অ্যাপের অনেকগুলি প্রাথমিক ব্যবহারের ক্ষেত্রে থাকতে পারে, যেমন ব্যবহারকারীদের ফটো ক্যাপচার করতে দেওয়া এবং তাদের পরিচিতির সাথে এই ফটোগুলি শেয়ার করা। আপনি যদি একটি বহু-উদ্দেশ্য অ্যাপ্লিকেশন বিকাশ করেন, আপনি যখন এটির ডেটা অ্যাক্সেস অডিট করেন তখন আপনি আপনার অ্যাপের প্রতিটি অংশে একটি অ্যাট্রিবিউশন ট্যাগ প্রয়োগ করতে পারেন৷ attributionTag প্রসঙ্গটি onNoted() এ কলে পাস করা বস্তুগুলিতে ফেরত দেওয়া হয়। এটি আপনাকে আরও সহজে আপনার কোডের যৌক্তিক অংশগুলিতে ডেটা অ্যাক্সেস ট্রেস করতে সহায়তা করে৷

আপনার অ্যাপে অ্যাট্রিবিউশন ট্যাগগুলি সংজ্ঞায়িত করতে, নিম্নলিখিত বিভাগগুলির ধাপগুলি সম্পূর্ণ করুন৷

ম্যানিফেস্টে অ্যাট্রিবিউশন ট্যাগ ঘোষণা করুন

যদি আপনার অ্যাপটি Android 12 (API লেভেল 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() কল করুন , অ্যাট্রিবিউশন ট্যাগটি পাস করে যা আপনি আপনার একটি অংশের সাথে যুক্ত করতে চান অ্যাপ

নিম্নলিখিত কোড স্নিপেট প্রদর্শন করে কিভাবে একটি অ্যাপের ফটো-অবস্থান-শেয়ারিং অংশের জন্য একটি অ্যাট্রিবিউশন ট্যাগ তৈরি করতে হয়:

কোটলিন

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.
        }
    }
}

অ্যাক্সেস লগগুলিতে অ্যাট্রিবিউশন ট্যাগগুলি অন্তর্ভুক্ত করুন

আপনার AppOpsManager.OnOpNotedCallback কলব্যাক আপডেট করুন যাতে আপনার অ্যাপের লগগুলিতে আপনার সংজ্ঞায়িত অ্যাট্রিবিউশন ট্যাগের নাম অন্তর্ভুক্ত থাকে।

নিম্নলিখিত কোড স্নিপেট আপডেট করা যুক্তি দেখায় যা অ্যাট্রিবিউশন ট্যাগ লগ করে:

কোটলিন

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);
    }
}
,

ডেটা অ্যাক্সেস অডিট করার মাধ্যমে আপনি কীভাবে আপনার অ্যাপ এবং এর নির্ভরতা ব্যবহারকারীদের কাছ থেকে ব্যক্তিগত ডেটা অ্যাক্সেস করে সে সম্পর্কে অন্তর্দৃষ্টি পেতে পারেন। অ্যান্ড্রয়েড 11 (API লেভেল 30) এবং উচ্চতর চালিত ডিভাইসগুলিতে উপলব্ধ এই প্রক্রিয়াটি আপনাকে সম্ভাব্য অপ্রত্যাশিত ডেটা অ্যাক্সেস আরও ভালভাবে সনাক্ত করতে দেয়। আপনার অ্যাপ AppOpsManager.OnOpNotedCallback এর একটি উদাহরণ নিবন্ধন করতে পারে, যেটি প্রতিবার নিম্নলিখিত ইভেন্টগুলির মধ্যে একটি ঘটলেই ক্রিয়া সম্পাদন করতে পারে:

  • আপনার অ্যাপের কোড ব্যক্তিগত ডেটা অ্যাক্সেস করে। আপনার অ্যাপের কোন যৌক্তিক অংশটি ইভেন্টটি শুরু করেছে তা নির্ধারণ করতে সাহায্য করার জন্য, আপনি অ্যাট্রিবিউশন ট্যাগ দ্বারা ডেটা অ্যাক্সেস অডিট করতে পারেন৷
  • একটি নির্ভরশীল লাইব্রেরিতে কোড বা SDK ব্যক্তিগত ডেটা অ্যাক্সেস করে।

ডেটা অ্যাক্সেস অডিটিং থ্রেডে আহ্বান করা হয় যেখানে ডেটা অনুরোধ করা হয়। এর মানে হল যে যদি আপনার অ্যাপে একটি তৃতীয় পক্ষের SDK বা লাইব্রেরি এমন একটি API কল করে যা ব্যক্তিগত ডেটা অ্যাক্সেস করে, ডেটা অ্যাক্সেস অডিটিং আপনার OnOpNotedCallback কল সম্পর্কে তথ্য পরীক্ষা করতে দেয়। সাধারণত, এই কলব্যাক অবজেক্টটি অ্যাপের বর্তমান স্থিতি, যেমন বর্তমান থ্রেডের স্ট্যাক ট্রেস দেখে কলটি আপনার অ্যাপ বা SDK থেকে এসেছে কিনা তা বলতে পারে।

তথ্য লগ অ্যাক্সেস

AppOpsManager.OnOpNotedCallback এর একটি উদাহরণ ব্যবহার করে ডেটা অ্যাক্সেস অডিটিং সঞ্চালন করতে, যে উপাদানটিতে আপনি ডেটা অ্যাক্সেস অডিট করতে চান সেখানে কলব্যাক যুক্তি প্রয়োগ করুন, যেমন একটি কার্যকলাপের onCreate() পদ্ধতি বা একটি অ্যাপ্লিকেশনের onCreate() পদ্ধতির মধ্যে৷

নিম্নলিখিত কোড স্নিপেট একটি AppOpsManager.OnOpNotedCallback সংজ্ঞায়িত করে একটি একক কার্যকলাপের মধ্যে ডেটা অ্যাক্সেস অডিট করার জন্য:

কোটলিন

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);
    }
}

onAsyncNoted() এবং onSelfNoted() পদ্ধতিগুলিকে নির্দিষ্ট পরিস্থিতিতে বলা হয়:

  • onAsyncNoted() কল করা হয় যদি আপনার অ্যাপের API কল চলাকালীন ডেটা অ্যাক্সেস না হয়। সবচেয়ে সাধারণ উদাহরণ হল যখন আপনার অ্যাপ একজন শ্রোতাকে নিবন্ধন করে এবং প্রতিবার শ্রোতার কলব্যাক ডাকার সময় ডেটা অ্যাক্সেস ঘটে।

    AsyncNotedOp আর্গুমেন্ট যা onAsyncNoted() এ পাস করা হয়েছে তাতে getMessage() নামে একটি পদ্ধতি রয়েছে। এই পদ্ধতি ডেটা অ্যাক্সেস সম্পর্কে আরও তথ্য প্রদান করে। অবস্থান কলব্যাকের ক্ষেত্রে, বার্তাটিতে শ্রোতার সিস্টেম-পরিচয়-হ্যাশ থাকে।

  • onSelfNoted() খুব বিরল ক্ষেত্রে বলা হয় যখন একটি অ্যাপ তার নিজস্ব UID noteOp() এ পাস করে।

অ্যাট্রিবিউশন ট্যাগ দ্বারা অডিট ডেটা অ্যাক্সেস

আপনার অ্যাপের অনেকগুলি প্রাথমিক ব্যবহারের ক্ষেত্রে থাকতে পারে, যেমন ব্যবহারকারীদের ফটো ক্যাপচার করতে দেওয়া এবং তাদের পরিচিতির সাথে এই ফটোগুলি শেয়ার করা। আপনি যদি একটি বহু-উদ্দেশ্য অ্যাপ্লিকেশন বিকাশ করেন, আপনি যখন এটির ডেটা অ্যাক্সেস অডিট করেন তখন আপনি আপনার অ্যাপের প্রতিটি অংশে একটি অ্যাট্রিবিউশন ট্যাগ প্রয়োগ করতে পারেন৷ attributionTag প্রসঙ্গটি onNoted() এ কলে পাস করা বস্তুগুলিতে ফেরত দেওয়া হয়। এটি আপনাকে আরও সহজে আপনার কোডের যৌক্তিক অংশগুলিতে ডেটা অ্যাক্সেস ট্রেস করতে সহায়তা করে৷

আপনার অ্যাপে অ্যাট্রিবিউশন ট্যাগগুলি সংজ্ঞায়িত করতে, নিম্নলিখিত বিভাগগুলির ধাপগুলি সম্পূর্ণ করুন৷

ম্যানিফেস্টে অ্যাট্রিবিউশন ট্যাগ ঘোষণা করুন

যদি আপনার অ্যাপটি Android 12 (API লেভেল 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() কল করুন , অ্যাট্রিবিউশন ট্যাগটি পাস করে যা আপনি আপনার একটি অংশের সাথে যুক্ত করতে চান অ্যাপ

নিম্নলিখিত কোড স্নিপেট প্রদর্শন করে কিভাবে একটি অ্যাপের ফটো-অবস্থান-শেয়ারিং অংশের জন্য একটি অ্যাট্রিবিউশন ট্যাগ তৈরি করতে হয়:

কোটলিন

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.
        }
    }
}

অ্যাক্সেস লগগুলিতে অ্যাট্রিবিউশন ট্যাগগুলি অন্তর্ভুক্ত করুন

আপনার AppOpsManager.OnOpNotedCallback কলব্যাক আপডেট করুন যাতে আপনার অ্যাপের লগগুলিতে আপনার সংজ্ঞায়িত অ্যাট্রিবিউশন ট্যাগের নাম অন্তর্ভুক্ত থাকে।

নিম্নলিখিত কোড স্নিপেট আপডেট করা যুক্তি দেখায় যা অ্যাট্রিবিউশন ট্যাগ লগ করে:

কোটলিন

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);
    }
}
,

ডেটা অ্যাক্সেস অডিট করার মাধ্যমে আপনি কীভাবে আপনার অ্যাপ এবং এর নির্ভরতা ব্যবহারকারীদের কাছ থেকে ব্যক্তিগত ডেটা অ্যাক্সেস করে সে সম্পর্কে অন্তর্দৃষ্টি পেতে পারেন। অ্যান্ড্রয়েড 11 (API লেভেল 30) এবং উচ্চতর চালিত ডিভাইসগুলিতে উপলব্ধ এই প্রক্রিয়াটি আপনাকে সম্ভাব্য অপ্রত্যাশিত ডেটা অ্যাক্সেস আরও ভালভাবে সনাক্ত করতে দেয়। আপনার অ্যাপ AppOpsManager.OnOpNotedCallback এর একটি উদাহরণ নিবন্ধন করতে পারে, যেটি প্রতিবার নিম্নলিখিত ইভেন্টগুলির মধ্যে একটি ঘটলেই ক্রিয়া সম্পাদন করতে পারে:

  • আপনার অ্যাপের কোড ব্যক্তিগত ডেটা অ্যাক্সেস করে। আপনার অ্যাপের কোন যৌক্তিক অংশটি ইভেন্টটি শুরু করেছে তা নির্ধারণ করতে সাহায্য করার জন্য, আপনি অ্যাট্রিবিউশন ট্যাগ দ্বারা ডেটা অ্যাক্সেস অডিট করতে পারেন৷
  • একটি নির্ভরশীল লাইব্রেরিতে কোড বা SDK ব্যক্তিগত ডেটা অ্যাক্সেস করে।

ডেটা অ্যাক্সেস অডিটিং থ্রেডে আহ্বান করা হয় যেখানে ডেটা অনুরোধ করা হয়। এর মানে হল যে যদি আপনার অ্যাপে একটি তৃতীয় পক্ষের SDK বা লাইব্রেরি এমন একটি API কল করে যা ব্যক্তিগত ডেটা অ্যাক্সেস করে, ডেটা অ্যাক্সেস অডিটিং আপনার OnOpNotedCallback কল সম্পর্কে তথ্য পরীক্ষা করতে দেয়। সাধারণত, এই কলব্যাক অবজেক্টটি অ্যাপের বর্তমান স্থিতি, যেমন বর্তমান থ্রেডের স্ট্যাক ট্রেস দেখে কলটি আপনার অ্যাপ বা SDK থেকে এসেছে কিনা তা বলতে পারে।

তথ্য লগ অ্যাক্সেস

AppOpsManager.OnOpNotedCallback এর একটি উদাহরণ ব্যবহার করে ডেটা অ্যাক্সেস অডিটিং সঞ্চালন করতে, যে উপাদানটিতে আপনি ডেটা অ্যাক্সেস অডিট করতে চান সেখানে কলব্যাক যুক্তি প্রয়োগ করুন, যেমন একটি কার্যকলাপের onCreate() পদ্ধতি বা একটি অ্যাপ্লিকেশনের onCreate() পদ্ধতির মধ্যে৷

নিম্নলিখিত কোড স্নিপেট একটি AppOpsManager.OnOpNotedCallback সংজ্ঞায়িত করে একটি একক কার্যকলাপের মধ্যে ডেটা অ্যাক্সেস অডিট করার জন্য:

কোটলিন

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);
    }
}

onAsyncNoted() এবং onSelfNoted() পদ্ধতিগুলিকে নির্দিষ্ট পরিস্থিতিতে বলা হয়:

  • onAsyncNoted() কল করা হয় যদি আপনার অ্যাপের API কল চলাকালীন ডেটা অ্যাক্সেস না হয়। সবচেয়ে সাধারণ উদাহরণ হল যখন আপনার অ্যাপ একজন শ্রোতাকে নিবন্ধন করে এবং প্রতিবার শ্রোতার কলব্যাক ডাকার সময় ডেটা অ্যাক্সেস ঘটে।

    AsyncNotedOp আর্গুমেন্ট যা onAsyncNoted() এ পাস করা হয়েছে তাতে getMessage() নামে একটি পদ্ধতি রয়েছে। এই পদ্ধতি ডেটা অ্যাক্সেস সম্পর্কে আরও তথ্য প্রদান করে। অবস্থান কলব্যাকের ক্ষেত্রে, বার্তাটিতে শ্রোতার সিস্টেম-পরিচয়-হ্যাশ থাকে।

  • onSelfNoted() খুব বিরল ক্ষেত্রে বলা হয় যখন একটি অ্যাপ তার নিজস্ব UID noteOp() এ পাস করে।

অ্যাট্রিবিউশন ট্যাগ দ্বারা অডিট ডেটা অ্যাক্সেস

আপনার অ্যাপের অনেকগুলি প্রাথমিক ব্যবহারের ক্ষেত্রে থাকতে পারে, যেমন ব্যবহারকারীদের ফটো ক্যাপচার করতে দেওয়া এবং তাদের পরিচিতির সাথে এই ফটোগুলি শেয়ার করা। আপনি যদি একটি বহু-উদ্দেশ্য অ্যাপ্লিকেশন বিকাশ করেন, আপনি যখন এটির ডেটা অ্যাক্সেস অডিট করেন তখন আপনি আপনার অ্যাপের প্রতিটি অংশে একটি অ্যাট্রিবিউশন ট্যাগ প্রয়োগ করতে পারেন৷ attributionTag প্রসঙ্গটি onNoted() এ কলে পাস করা বস্তুগুলিতে ফেরত দেওয়া হয়। এটি আপনাকে আরও সহজে আপনার কোডের যৌক্তিক অংশগুলিতে ডেটা অ্যাক্সেস ট্রেস করতে সহায়তা করে৷

আপনার অ্যাপে অ্যাট্রিবিউশন ট্যাগগুলি সংজ্ঞায়িত করতে, নিম্নলিখিত বিভাগগুলির ধাপগুলি সম্পূর্ণ করুন৷

ম্যানিফেস্টে অ্যাট্রিবিউশন ট্যাগ ঘোষণা করুন

যদি আপনার অ্যাপটি Android 12 (API লেভেল 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() কল করুন , অ্যাট্রিবিউশন ট্যাগটি পাস করে যা আপনি আপনার একটি অংশের সাথে যুক্ত করতে চান অ্যাপ

নিম্নলিখিত কোড স্নিপেট প্রদর্শন করে কিভাবে একটি অ্যাপের ফটো-অবস্থান-শেয়ারিং অংশের জন্য একটি অ্যাট্রিবিউশন ট্যাগ তৈরি করতে হয়:

কোটলিন

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.
        }
    }
}

অ্যাক্সেস লগগুলিতে অ্যাট্রিবিউশন ট্যাগগুলি অন্তর্ভুক্ত করুন

আপনার AppOpsManager.OnOpNotedCallback কলব্যাক আপডেট করুন যাতে আপনার অ্যাপের লগগুলিতে আপনার সংজ্ঞায়িত অ্যাট্রিবিউশন ট্যাগের নাম অন্তর্ভুক্ত থাকে।

নিম্নলিখিত কোড স্নিপেট আপডেট করা যুক্তি দেখায় যা অ্যাট্রিবিউশন ট্যাগ লগ করে:

কোটলিন

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);
    }
}