设置
如需实现 Topics API,您需要先设置开发环境。执行以下设置步骤:
使用最新版 Android Privacy Sandbox SDK 获取最新 可保护隐私的 API 版本
将以下内容添加到您的清单中:
权限:添加
ACCESS_ADSERVICES_TOPICS
权限,以允许您的应用访问 Topics API:<uses-permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS" />
广告服务配置:在清单的
<application>
元素中引用广告服务配置文件。<property android:name="android.adservices.AD_SERVICES_CONFIG" android:resource="@xml/ad_services_config" />
指定清单中引用的广告服务 XML 资源,例如
res/xml/ad_services_config.xml
。您可以使用allowAllToAccess
属性授予对所有 SDK 的访问权限,也可以使用allowSdksToAccess
属性授予对各个 SDK 的访问权限:详细了解广告服务权限和 SDK 访问权限控制。<ad-services-config> <topics allowAllToAccess="true"/> </ad-services-config>
在 Privacy Sandbox 中注册您的广告技术平台,以便在您的 SDK 中调用 Topics API。如需在本地进行测试,您可以使用以下命令停用 Topics 注册检查:
adb shell setprop debug.adservices.disable_topics_enrollment_check true
启用对 Topics API 的访问权限。默认情况下,Topics API 处于停用状态。您需要使用 ADB 命令启用它:
adb shell device_config put adservices ppapi_app_signature_allow_list \"\*\"
adb shell setprop debug.adservices.disable_topics_enrollment_check true
请求一组主题
Topics API 的主要功能位于 getTopics()
方法中
在TopicsManager
内
对象,如以下示例中所示:
fun getTopics(
getTopicsRequest: GetTopicsRequest,
executor: Executor,
callback: OutcomeReceiver<GetTopicsResponse, Exception>
) { }
public void getTopics (@NonNull GetTopicsRequest getTopicsRequest,
@NonNull Executor executor,
@NonNull OutcomeReceiver<GetTopicsResponse, Exception> callback)
如需使用此方法,请初始化 TopicsManager
对象以及接收主题数据所需的参数。GetTopicsRequest
用于传递所需信息以检索 Topics API 数据,其中包括一个用于指示调用方是否作为观察者的标志。不作为观察者时,getTopics
调用将返回上一个周期的主题,但不会影响下一个周期的主题数据。OutcomeReceiver
回调会异步处理结果。例如:
private fun topicGetter() {
val mContext = baseContext
val mTopicsManager = mContext.getSystemService(TopicsManager::class.java)
val mExecutor: Executor = Executors.newCachedThreadPool()
val shouldRecordObservation = false
val mTopicsRequestBuilder: GetTopicsRequest.Builder = GetTopicsRequest.Builder()
mTopicsRequestBuilder.setAdsSdkName(baseContext.packageName)
mTopicsRequestBuilder.setShouldRecordObservation(shouldRecordObservation)
mTopicsManager.getTopics(mTopicsRequestBuilder.build(), mExecutor,
mCallback as OutcomeReceiver<GetTopicsResponse, Exception>)
}
private var mCallback: OutcomeReceiver<GetTopicsResponse, java.lang.Exception> =
object : OutcomeReceiver<GetTopicsResponse, java.lang.Exception> {
override fun onResult(result: GetTopicsResponse) {
// handle successful result
val topicsResult = result.topics
for (i in topicsResult.indices) {
Log.i("Topic", topicsResult[i].getTopicId().toString())
}
if (topicsResult.size == 0) {
Log.i("Topic", "Returned Empty")
}
}
override fun onError(error: java.lang.Exception) {
// handle error
Log.i("Topic", "Error, did not return successfully")
}
}
public void TopicGetter() {
@NonNull Context mContext = getBaseContext();
TopicsManager mTopicsManager = mContext.getSystemService(TopicsManager.class);
Executor mExecutor = Executors.newCachedThreadPool();
boolean shouldRecordObservation = false;
GetTopicsRequest.Builder mTopicsRequestBuilder = new GetTopicsRequest.Builder();
mTopicsRequestBuilder.setAdsSdkName(getBaseContext().getPackageName());
mTopicsRequestBuilder.setShouldRecordObservation(shouldRecordObservation);
mTopicsManager.getTopics(mTopicsRequestBuilder.build(), mExecutor, mCallback);
}
OutcomeReceiver mCallback = new OutcomeReceiver<GetTopicsResponse, Exception>() {
@Override
public void onResult(@NonNull GetTopicsResponse result) {
//Handle Successful Result
List<Topic> topicsResult = result.getTopics();
for (int i = 0; i < topicsResult.size(); i++) {
Log.i("Topic", topicsResult.get(i).getTopicId().toString());
}
if (topicsResult.size() == 0) {
Log.i("Topic", "Returned Empty");
}
}
@Override
public void onError(@NonNull Exception error) {
// Handle error
Log.i("Topic", "Experienced an error, and did not return successfully");
}
};
设置就绪后,您就可以调用 getTopics()
方法来接收 GetTopicsResponse
结果:
mTopicsManager.getTopics(mTopicsRequestBuilder.build(), mExecutor,
mCallback as OutcomeReceiver<GetTopicsResponse, java.lang.Exception>)
mTopicsManager.getTopics(mTopicsRequestBuilder.build(), mExecutor, mCallback);
此调用会提供包含 ID 值的 Topics 对象列表 开源分类中与以下主题相关的主题: 或相关错误。这些主题对象列表将类似于以下示例:
/Internet & Telecom/Text & Instant Messaging
如需查看可能返回的主题列表,请参阅分类。此分类是开源的,您可以使用此页面顶部的反馈按钮提交建议的更改。
测试
Topics API 会根据应用使用情况提供最新的相关主题。此早期版本可预览 API 行为,我们会在将来的版本中提高主题的质量。
为了获得最充分的体验,建议您使用含有多个应用的测试环境,在该环境中调用 getTopics()
来查看如何选择主题。通过
SDK 运行时和隐私保护 API 代码库
包含一组独立的 Android Studio 项目,以帮助您
,其中包括展示如何初始化和调用 Topics API 的示例。
主题的计算在一个周期结束时进行。默认情况下,每个周期为 7 天,但您可以修改获取结果的这一时间间隔。以下 Android 调试桥 shell 命令可以将周期长度缩短为 5 分钟:
adb shell device_config put adservices topics_epoch_job_period_ms 300000
您可以使用 get
确认 topics_epoch_job_period_ms
值:
adb shell device_config get adservices topics_epoch_job_period_ms
如需手动触发周期计算,请执行以下命令:
adb shell cmd jobscheduler run -f com.google.android.adservices.api 2
除了使用示例应用之外,您还可以使用 Colab 针对主题分类器测试不同的应用信息组合。使用此 Colab 查看您的应用在调用 getTopics
时可能会获得的结果类型。
加密详细信息
随着加密功能的引入,调用 GetTopics()
现在会生成
包含 EncryptedTopic
对象列表的响应。解密这些结果将会
生成的对象与前一个 Topic
对象具有相同的 JSON 格式。
Topics API 支持 HPKE(混合公钥)的一次性实现 加密)。我们希望已注册的调用方在注册期间提供的公共加密网址端点上托管 32 位公钥。这些密钥应采用 Base64 编码。
EncryptedTopic
对象有 3 个字段。返回的主题列表可以是
获取此值。
出于开发目的,您可以通过停用注册检查来测试 Topics API 加密。这会强制 API 使用测试公钥来加密您的响应。您可以使用 相应的私钥。
限制
有关 Topics API 的正在开发中的功能列表,请查看版本说明。
报告 bug 和问题
您的反馈对 Privacy Sandbox on Android 至关重要。如果发现任何问题或有任何关于改进 Privacy Sandbox on Android 的想法,欢迎告诉我们。
Next steps
Control & transparency
Topics on Android overview
另请参阅
查看我们的资源,更好地了解 Android 上的 Topics API。
- 查看 Topics 示例应用、协作和演示视频。
- 了解用户和开发者如何控制该 API。
- 查看支持资源,提问、互动和分享反馈。