Verilere erişimi denetleme

Veri erişimi denetimi yaparak uygulamanızın ve bağımlılıklarının kullanıcılardan gelen özel verilere nasıl eriştiği hakkında bilgi edinebilirsiniz. Android 11 (API düzeyi 30) ve sonraki sürümleri çalıştıran cihazlarda kullanılabilen bu işlem, beklenmedik veri erişimlerini daha iyi tanımlamanıza olanak tanır. Uygulamanız, aşağıdaki etkinliklerden biri her gerçekleştiğinde işlem yapabilen bir AppOpsManager.OnOpNotedCallback örneği kaydedebilir:

Veri erişimi denetimi, veri isteğinin gerçekleştiği ileti dizisinde çağrılır. Yani uygulamanızdaki bir üçüncü taraf SDK'sı veya kitaplığı, özel verilere erişen bir API'yi çağırırsa veri erişimi denetimi, OnOpNotedCallback uygulamanızın bu çağrıyla ilgili bilgileri incelemesine olanak tanır. Genellikle bu geri çağırma nesnesi, uygulamanın mevcut durumuna (ör. mevcut ileti dizisinin yığın izlemesi) bakarak çağrının uygulamanızdan mı yoksa SDK'dan mı geldiğini anlayabilir.

Verilere erişimi günlüğe kaydetme

AppOpsManager.OnOpNotedCallback örneğini kullanarak veri erişimi denetimi gerçekleştirmek için geri çağırma mantığını, veri erişimini denetlemek istediğiniz bileşende (ör. bir etkinliğin onCreate() yönteminde veya bir uygulamanın onCreate() yönteminde) uygulayın.

Aşağıdaki kod snippet'i, tek bir etkinlikte veri erişimini denetlemek için bir AppOpsManager.OnOpNotedCallback tanımlar:

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() ve onSelfNoted() yöntemleri belirli durumlarda çağrılır:

  • onAsyncNoted(), veri erişimi uygulamanızın API çağrısı sırasında gerçekleşmezse çağrılır. En yaygın örnek, uygulamanızın bir dinleyici kaydetmesi ve dinleyicinin geri çağırma işlevi her çağrıldığında veri erişiminin gerçekleşmesidir.

    onAsyncNoted() işlevine iletilen AsyncNotedOp bağımsız değişkeni, getMessage() adlı bir yöntem içerir. Bu yöntem, veri erişimi hakkında daha fazla bilgi sağlar. Konum geri çağırmaları söz konusu olduğunda mesaj, dinleyicinin system-identity-hash değerini içerir.

  • onSelfNoted(), bir uygulamanın kendi UID'sini noteOp() yöntemine ilettiği çok nadir durumlarda çağrılır.

İlişkilendirme etiketine göre veri erişimini denetleme

Uygulamanızın, kullanıcıların fotoğraf çekmesine ve bu fotoğrafları kişileriyle paylaşmasına olanak tanımak gibi birkaç temel kullanım alanı olabilir. Çok amaçlı bir uygulama geliştiriyorsanız veri erişimini denetlerken uygulamanızın her bölümüne bir ilişkilendirme etiketi uygulayabilirsiniz. attributionTag bağlamı, onNoted() çağrılarına iletilen nesnelerde döndürülür. Bu sayede, veri erişimini kodunuzun mantıksal bölümlerine daha kolay bir şekilde geri izleyebilirsiniz.

Uygulamanızda ilişkilendirme etiketleri tanımlamak için aşağıdaki bölümlerdeki adımları tamamlayın.

Manifest dosyasında ilişkilendirme etiketlerini bildirme

Uygulamanız Android 12 (API düzeyi 31) veya sonraki sürümleri hedefliyorsa aşağıdaki kod snippet'inde gösterilen biçimi kullanarak uygulamanızın manifest dosyasında ilişkilendirme etiketlerini beyan etmeniz gerekir. Uygulamanızın manifest dosyasında beyan etmediğiniz bir ilişkilendirme etiketi kullanmaya çalışırsanız sistem sizin için bir null etiketi oluşturur ve Logcat'e bir mesaj kaydeder.

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

İlişkilendirme etiketleri oluşturma

Konum istediğiniz veya kullanıcının kişi listesine eriştiğiniz etkinlik gibi verilere eriştiğiniz etkinliğin onCreate() yönteminde, uygulamanızın bir bölümüyle ilişkilendirmek istediğiniz ilişkilendirme etiketini ileterek createAttributionContext() yöntemini çağırın.

Aşağıdaki kod snippet'inde, bir uygulamanın fotoğraf konumu paylaşma bölümü için ilişkilendirme etiketinin nasıl oluşturulacağı gösterilmektedir:

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

Erişim günlüklerine ilişkilendirme etiketleri ekleme

Uygulamanızın günlüklerinde tanımladığınız ilişkilendirme etiketlerinin adlarının yer alması için AppOpsManager.OnOpNotedCallback geri çağırma işlevinizi güncelleyin.

Aşağıdaki kod snippet'inde, ilişkilendirme etiketlerini kaydeden güncellenmiş mantık gösterilmektedir:

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