دسترسی حسابرسی به داده ها

می‌توانید با انجام ممیزی دسترسی به داده، اطلاعاتی درباره نحوه دسترسی برنامه و وابستگی‌های آن به داده‌های خصوصی کاربران به دست آورید. این فرآیند، در دستگاه‌هایی که Android 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() در شرایط خاص فراخوانی می شوند:

  • در صورتی که دسترسی به داده در طول تماس API برنامه شما انجام نشود، onAsyncNoted() فراخوانی می شود. رایج ترین مثال زمانی است که برنامه شما یک شنونده را ثبت می کند و دسترسی به داده ها هر بار که تماس پاسخ شنونده فراخوانی می شود اتفاق می افتد.

    آرگومان 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() را فراخوانی کنید، تگ attribution را که می‌خواهید با بخشی از خود مرتبط کنید، ارسال کنید. برنامه

قطعه کد زیر نحوه ایجاد یک تگ انتساب برای قسمت اشتراک‌گذاری مکان عکس از یک برنامه را نشان می‌دهد:

کاتلین

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