Khi bạn đọc tài liệu Hộp cát về quyền riêng tư trên Android, hãy sử dụng nút Bản dùng thử cho nhà phát triển hoặc Beta để chọn phiên bản chương trình bạn đang làm việc, vì hướng dẫn có thể khác nhau.
Thời gian chạy SDK cho phép SDK chạy trong một hộp cát riêng, tách biệt với ứng dụng gọi. Thời gian chạy SDK cung cấp các biện pháp bảo vệ và bảo đảm nâng cao cho việc thu thập dữ liệu người dùng. Việc này được thực hiện thông qua môi trường thực thi đã sửa đổi nhằm giới hạn quyền truy cập dữ liệu và tập hợp các quyền được phép. Tìm hiểu thêm về Thời gian chạy SDK trong đề xuất thiết kế.
Các bước trên trang này sẽ hướng dẫn bạn thực hiện quy trình tạo SDK hỗ trợ thời gian chạy để xác định khung hiển thị dựa trên nền tảng web có thể kết xuất từ xa vào ứng dụng gọi.
Các hạn chế đã biết
Để biết danh sách các tính năng đang trong quá trình phát triển cho Thời gian chạy SDK, vui lòng xem ghi chú phát hành.
Chúng tôi dự kiến sẽ khắc phục các hạn chế sau đây trong bản phát hành chính tiếp theo cho nền tảng Android.
- Hiển thị quảng cáo trong khung hiển thị có thể cuộn. Ví dụ:
RecyclerView
không hoạt động đúng cách.- Bạn có thể gặp phải hiện tượng giật khi thay đổi kích thước.
- Các sự kiện cuộn bằng thao tác chạm của người dùng sẽ không được chuyển đúng cách đến thời gian chạy.
- Storage API (API Bộ nhớ)
- Không có bộ nhớ cho mỗi SDK trong Android 13.
Chúng tôi sẽ khắc phục sự cố sau đây vào năm 2023:
- API
getAdId
vàgetAppSetId
chưa hoạt động đúng cách vì chức năng hỗ trợ những API này chưa được kích hoạt.
Trước khi bắt đầu
Trước khi bắt đầu, hãy hoàn thành các bước sau:
Thiết lập môi trường phát triển cho Hộp cát về quyền riêng tư trên Android. Công cụ hỗ trợ Thời gian chạy SDK đang phát triển nhanh chóng, nên hướng dẫn này sẽ yêu cầu bạn sử dụng phiên bản Canary mới nhất của Android Studio. Bạn có thể chạy phiên bản Android Studio này song song với các phiên bản khác mà bạn sử dụng. Vì vậy, vui lòng cho chúng tôi biết nếu yêu cầu này không phù hợp với bạn.
Hãy cài đặt hình ảnh hệ thống trên một thiết bị được hỗ trợ hoặc thiết lập trình mô phỏng có chức năng hỗ trợ cho Hộp cát về quyền riêng tư trên Android.
Thiết lập dự án trong Android Studio
Để dùng thử Thời gian chạy SDK, hãy sử dụng một mô hình tương tự như mô hình máy khách – máy chủ. Điểm khác biệt chính yếu là các ứng dụng (máy khách) và SDK ("máy chủ") chạy trên cùng một thiết bị.
- Thêm một mô-đun ứng dụng vào dự án. Mô-đun này đóng vai trò ứng dụng điều khiển SDK.
- Trong mô-đun ứng dụng, hãy bật Thời gian chạy SDK, khai báo các quyền cần thiết và định cấu hình các dịch vụ quảng cáo cho API cụ thể.
- Thêm một mô-đun thư viện vào dự án. Mô-đun này có chứa mã SDK của bạn.
- Trong mô-đun SDK, hãy khai báo các quyền cần thiết. Bạn không cần định cấu hình các dịch vụ quảng cáo dành riêng cho API trong mô-đun này.
- Xoá
dependencies
trong tệpbuild.gradle
của mô-đun thư viện mà SDK của bạn không sử dụng. Trong hầu hết mọi trường hợp, bạn có thể xoá tất cả các phần phụ thuộc. Bạn có thể thực hiện việc này bằng cách tạo một thư mục mới có tên tương ứng với SDK của bạn. Tạo thủ công một mô-đun mới bằng loại
com.android.privacy-sandbox-sdk
. Mô-đun này đi kèm với mã SDK để tạo một APK có thể triển khai cho thiết bị của bạn. Bạn có thể thực hiện việc này bằng cách tạo một thư mục mới có tên tương ứng với SDK của bạn. Thêm một tệpbuild.gradle
trống. Nội dung của tệp này sẽ được điền sau trong hướng dẫn này.Thêm đoạn mã sau vào tệp
gradle.properties
:android.experimental.privacysandboxsdk.enable=true
Tải hình ảnh trình mô phỏng Tiramisu (Tiện ích cấp độ 4) xuống rồi tạo một trình mô phỏng với hình ảnh này chứa Cửa hàng Play.
Tuỳ thuộc vào việc bạn là nhà phát triển SDK hay nhà phát triển ứng dụng, bạn có thể có cách thiết lập cuối cùng khác với cách thiết lập đã mô tả trong đoạn trước.
Dùng Android Studio hoặc Cầu gỡ lỗi Android (ADB) để cài đặt SDK trên thiết bị kiểm thử, tương tự như cách bạn cài đặt ứng dụng. Để giúp bạn bắt đầu, chúng tôi đã tạo các ứng dụng mẫu bằng ngôn ngữ lập trình Kotlin và Java. Bạn có thể tìm thấy các ứng dụng này trong kho lưu trữ GitHub. Tệp README và tệp kê khai có nhận xét mô tả những gì cần thay đổi để chạy mẫu trong các phiên bản Android Studio ổn định.
Chuẩn bị SDK của bạn
Tạo thư mục ở cấp mô-đun theo cách thủ công. Thư mục này đóng vai trò là trình bao bọc xung quanh mã triển khai của bạn để tạo APK SDK. Trong thư mục mới, hãy thêm tệp
build.gradle
rồi điền đoạn mã sau vào tệp đó. Sử dụng một tên riêng biệt cho SDK hỗ trợ thời gian chạy (RE-SDK) và cung cấp một phiên bản. Đưa mô-đun thư viện của bạn vào mụcdependencies
.plugins { id 'com.android.privacy-sandbox-sdk' } android { compileSdk 33 compileSdkExtension 4 minSdk 33 targetSdk 33 namespace = "com.example.example-sdk" bundle { packageName = "com.example.privacysandbox.provider" sdkProviderClassName = "com.example.sdk_implementation.SdkProviderImpl" setVersion(1, 0, 0) } } dependencies { include project(':<your-library-here>') }
Tạo một lớp trong thư viện triển khai để đóng vai trò là điểm truy cập cho SDK. Tên của lớp phải ánh xạ tới giá trị của
sdkProviderClassName
và mở rộngSandboxedSdkProvider
.
Điểm truy cập cho SDK của bạn sẽ mở rộng SandboxedSdkProvider
. SandboxedSdkProvider
chứa đối tượng Context
cho SDK mà bạn có thể truy cập bằng cách gọi getContext()
. Bạn chỉ có thể truy cập vào ngữ cảnh này sau khi gọi onLoadSdk()
.
Để biên dịch ứng dụng SDK, bạn cần phải ghi đè lên các phương thức để xử lý vòng đời SDK:
onLoadSdk()
Tải SDK vào hộp cát, đồng thời thông báo cho ứng dụng gọi khi SDK đã sẵn sàng xử lý yêu cầu bằng cách truyền giao diện của SDK dưới dạng đối tượng
IBinder
được bao bọc bên trong đối tượngSandboxedSdk
mới. Hướng dẫn về dịch vụ ràng buộc giới thiệu nhiều cách để cung cấpIBinder
. Bạn có thể linh hoạt chọn cách cung cấp nhưng phải nhất quán với SDK và ứng dụng gọi.Lấy AIDL làm ví dụ, bạn nên xác định tệp AIDL để hiển thị
IBinder
mà ứng dụng sẽ chia sẻ và sử dụng:// ISdkInterface.aidl interface ISdkInterface { // the public functions to share with the App. int doSomthing(); }
getView()
Tạo và thiết lập khung hiển thị cho quảng cáo của bạn, khởi tạo khung hiển thị giống như mọi khung hiển thị khác của Android và trả về khung hiển thị để kết xuất từ xa trong một cửa sổ có chiều rộng và chiều cao cho trước tính bằng pixel.
Đoạn mã sau đây minh hoạ cách ghi đè lên các phương thức này:
Kotlin
class SdkProviderImpl : SandboxedSdkProvider() { override fun onLoadSdk(params: Bundle?): SandboxedSdk { // Returns a SandboxedSdk, passed back to the client. The IBinder used // to create the SandboxedSdk object is used by the app to call into the // SDK. return SandboxedSdk(SdkInterfaceProxy()) } override fun getView(windowContext: Context, bundle: Bundle, width: Int, height: Int): View { val webView = WebView(windowContext) val layoutParams = LinearLayout.LayoutParams(width, height) webView.setLayoutParams(layoutParams) webView.loadUrl("https://developer.android.com/privacy-sandbox") return webView } private class SdkInterfaceProxy : ISdkInterface.Stub() { fun doSomething() { // Implementation of the API. } } }
Java
public class SdkProviderImpl extends SandboxedSdkProvider { @Override public SandboxedSdk onLoadSdk(Bundle params) { // Returns a SandboxedSdk, passed back to the client. The IBinder used // to create the SandboxedSdk object is used by the app to call into the // SDK. return new SandboxedSdk(new SdkInterfaceProxy()); } @Override public View getView(Context windowContext, Bundle bundle, int width, int height) { WebView webView = new WebView(windowContext); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(width, height); webView.setLayoutParams(layoutParams); webView.loadUrl("https://developer.android.com/privacy-sandbox"); return webView; } private static class SdkInterfaceProxy extends ISdkInterface.Stub { @Override public void doSomething() { // Implementation of the API. } } }
Kiểm thử trình phát video trong Thời gian chạy SDK
Ngoài việc hỗ trợ quảng cáo biểu ngữ, Hộp cát về quyền riêng tư còn cam kết hỗ trợ các trình phát video chạy trong Thời gian chạy SDK.
Quy trình thử nghiệm trình phát video tương tự như thử nghiệm quảng cáo biểu ngữ. Thay đổi phương thức
getView()
của điểm truy cập SDK của bạn để đưa trình phát video vào đối tượng View
được trả về. Kiểm thử tất cả các luồng của trình phát video mà bạn mong muốn Hộp cát về quyền riêng tư hỗ trợ. Lưu ý rằng hoạt động giao tiếp giữa SDK và ứng dụng về vòng đời của video hiện nằm ngoài phạm vi, do đó, chưa cần phải đưa ra ý kiến phản hồi về chức năng này.
Hoạt động kiểm thử và ý kiến phản hồi của bạn sẽ đảm bảo Thời gian chạy SDK hỗ trợ tất cả các trường hợp sử dụng của trình phát video mà bạn ưa thích.
Đoạn mã sau đây minh hoạ cách trả về một lượt xem video đơn giản tải từ một URL.
Kotlin
class SdkProviderImpl : SandboxedSdkProvider() { override fun getView(windowContext: Context, bundle: Bundle, width: Int, height: Int): View { val videoView = VideoView(windowContext) val layoutParams = LinearLayout.LayoutParams(width, height) videoView.setLayoutParams(layoutParams) videoView.setVideoURI(Uri.parse("https://test.website/video.mp4")) videoView.setOnPreparedListener { mp -> mp.start() } return videoView } }
Java
public class SdkProviderImpl extends SandboxedSdkProvider { @Override public View getView(Context windowContext, Bundle bundle, int width, int height) { VideoView videoView = new VideoView(windowContext); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(width, height); videoView.setLayoutParams(layoutParams); videoView.setVideoURI(Uri.parse("https://test.website/video.mp4")); videoView.setOnPreparedListener(mp -> { mp.start(); }); return videoView; } }
Sử dụng API lưu trữ trong SDK của bạn
Các SDK trong Thời gian chạy SDK không còn truy cập, đọc hoặc ghi trong bộ nhớ trong của ứng dụng nữa và ngược lại. Thời gian chạy SDK sẽ được phân bổ vào vùng bộ nhớ trong riêng biệt, đảm bảo tách biệt với ứng dụng.
Các SDK có thể truy cập vào bộ nhớ trong riêng biệt này thông qua các API lưu trữ tệp trên đối tượng Context
do SandboxedSdkProvider#getContext()
trả về. SDK chỉ có thể dùng bộ nhớ trong nên chỉ các API bộ nhớ trong, chẳng hạn như Context.getFilesDir()
hoặc Context.getCacheDir()
, mới hoạt động. Vui lòng tham khảo thêm ví dụ ở bài viết Quyền truy cập vào bộ nhớ trong.
Không hỗ trợ quyền truy cập vào bộ nhớ ngoài trong Thời gian chạy SDK. Việc gọi các API để truy cập vào bộ nhớ ngoài sẽ gửi một ngoại lệ hoặc trả về null
. Dưới đây là một số ví dụ:
- Việc truy cập các tệp bằng Khung truy cập bộ nhớ sẽ tạo ra
SecurityException
. getExternalFilsDir()
sẽ luôn trả vềnull
.
Trong Android 13, tất cả các SDK trong Thời gian chạy SDK sẽ dùng chung bộ nhớ trong được phân bổ cho Thời gian chạy SDK. Bộ nhớ sẽ được duy trì cho đến khi gỡ cài đặt, hoặc xoá dữ liệu của ứng dụng.
Bạn phải sử dụng Context
do SandboxedSdkProvider.getContext()
trả về để lưu trữ. Việc sử dụng API lưu trữ tệp trên mọi thực thể đối tượng Context
nào khác, chẳng hạn như ngữ cảnh của ứng dụng, không được đảm bảo sẽ hoạt động như mong đợi trong mọi tình huống hoặc trong tương lai.
Đoạn mã sau đây minh hoạ cách sử dụng bộ nhớ trong Thời gian chạy SDK:
Kotlin
private static class SdkInterfaceStorage extends ISdkInterface.Stub { override fun doSomething() { val filename = "myfile" val fileContents = "content" try { getContext().openFileOutput(filename, Context.MODE_PRIVATE).use { it.write(fileContents.toByteArray()) } catch (e: Exception) { throw RuntimeException(e) } } } }
Java
private static class SdkInterfaceStorage extends ISdkInterface.Stub { @Override public void doSomething() { final filename = "myFile"; final String fileContents = "content"; try (FileOutputStream fos = getContext().openFileOutput(filename, Context.MODE_PRIVATE)) { fos.write(fileContents.toByteArray()); } catch (Exception e) { throw new RuntimeException(e); } } }
Bộ nhớ trên mỗi SDK
Ở bộ nhớ trong riêng biệt của từng Thời gian chạy SDK, mỗi SDK có một thư mục bộ nhớ riêng. Bộ nhớ trên mỗi SDK là sự phân tách theo logic bộ nhớ trong của Thời gian chạy SDK, giúp tính toán dung lượng bộ nhớ mà mỗi SDK sử dụng.
Trên Android 13, chỉ có một API trả về đường dẫn đến bộ nhớ trên mỗi SDK: Context#getDataDir()
.
Trên Android 14, tất cả các Internal Storage API (API Bộ nhớ trong) trên đối tượng Context
đều trả về một đường dẫn bộ nhớ cho từng SDK. Bạn có thể cần bật tính năng này bằng cách chạy lệnh adb sau đây:
adb shell device_config put adservices sdksandbox_customized_sdk_context_enabled true
Truy cập vào mã nhận dạng cho quảng cáo do Dịch vụ Google Play cung cấp
Nếu SDK của bạn cần quyền truy cập vào mã nhận dạng cho quảng cáo do Dịch vụ Google Play cung cấp:
- Khai báo quyền
android.permission.ACCESS_ADSERVICES_AD_ID
trong tệp kê khai của SDK. - Sử dụng
AdIdManager#getAdId()
để truy xuất giá trị không đồng bộ.
Truy cập vào mã nhóm ứng dụng do Dịch vụ Google Play cung cấp
Nếu SDK của bạn cần quyền truy cập vào mã nhóm ứng dụng do Dịch vụ Google Play cung cấp:
- Sử dụng
AppSetIdManager#getAppSetId()
để truy xuất giá trị không đồng bộ.
Cập nhật ứng dụng
Để gọi vào một SDK đang chạy trong Thời gian chạy SDK, hãy thực hiện những thay đổi sau đây đối với ứng dụng khách dùng để gọi:
Thêm quyền
INTERNET
vàACCESS_NETWORK_STATE
vào tệp kê khai của ứng dụng:<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Trong hoạt động của ứng dụng bao gồm một quảng cáo, hãy khai báo thông tin tham chiếu đến
SdkSandboxManager
(là boolean cho biết liệu SDK có được tải hay không) và một đối tượngSurfaceView
để kết xuất từ xa:Kotlin
private lateinit var mSdkSandboxManager: SdkSandboxManager private lateinit var mClientView: SurfaceView private var mSdkLoaded = false companion object { private const val SDK_NAME = "com.example.privacysandbox.provider" }
Java
private static final String SDK_NAME = "com.example.privacysandbox.provider"; private SdkSandboxManager mSdkSandboxManager; private SurfaceView mClientView; private boolean mSdkLoaded = false;
Kiểm tra xem thiết bị có quy trình Thời gian chạy SDK hay không.
Kiểm tra hằng số
SdkSandboxState
(getSdkSandboxState()
).SDK_SANDBOX_STATE_ENABLED_PROCESS_ISOLATION
có nghĩa là Thời gian chạy SDK có sẵn.Kiểm tra để đảm bảo rằng đã gọi
loadSdk()
thành công. Nếu không có ngoại lệ nào được gửi thì nghĩa là đã gọi thành công, và trình thu nhận là thực thể củaSandboxedSdk
.Gọi
loadSdk()
từ nền trước. Nếu được gọi từ nền, hệ thống sẽ gửiSecurityException
.Kiểm tra
OutcomeReceiver
cho thực thể củaSandboxedSdk
để xác minh xem có xảy raLoadSdkException
hay không. Nếu xảy ra ngoại lệ thì có thể Thời gian chạy SDK không có sẵn.
Nếu lệnh gọi
SdkSandboxState
hoặcloadSdk
không thành công, thì Thời gian chạy SDK không có sẵn và lệnh gọi sẽ quay lại SDK hiện có.Xác định lớp gọi lại bằng cách triển khai
OutcomeReceiver
để tương tác với SDK trong thời gian chạy sau khi được tải. Trong ví dụ sau, máy khách sử dụng lệnh gọi lại để chờ đến khi SDK được tải thành công, sau đó cố gắng kết xuất khung hiển thị web từ SDK. Các lệnh gọi lại được xác định sau trong bước này.Kotlin
private inner class LoadSdkOutcomeReceiverImpl private constructor() : OutcomeReceiver
{ override fun onResult(sandboxedSdk: SandboxedSdk) { mSdkLoaded = true val binder: IBinder = sandboxedSdk.getInterface() if (!binderInterface.isPresent()) { // SDK is not loaded anymore. return } val sdkInterface: ISdkInterface = ISdkInterface.Stub.asInterface(binder) sdkInterface.doSomething() Handler(Looper.getMainLooper()).post { val bundle = Bundle() bundle.putInt(SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth()) bundle.putInt(SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight()) bundle.putInt(SdkSandboxManager.EXTRA_DISPLAY_ID, display!!.displayId) bundle.putInt(SdkSandboxManager.EXTRA_HOST_TOKEN, mClientView.getHostToken()) mSdkSandboxManager!!.requestSurfacePackage( SDK_NAME, bundle, { obj: Runnable -> obj.run() }, RequestSurfacePackageOutcomeReceiverImpl()) } } override fun onError(error: LoadSdkException) { // Log or show error. } } Java
import static android.app.sdksandbox.SdkSandboxManager.EXTRA_DISPLAY_ID; import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HEIGHT_IN_PIXELS; import static android.app.sdksandbox.SdkSandboxManager.EXTRA_HOST_TOKEN; import static android.app.sdksandbox.SdkSandboxManager.EXTRA_WIDTH_IN_PIXELS; private class LoadSdkOutcomeReceiverImpl implements OutcomeReceiver
{ private LoadSdkOutcomeReceiverImpl() {} @Override public void onResult(@NonNull SandboxedSdk sandboxedSdk) { mSdkLoaded = true; IBinder binder = sandboxedSdk.getInterface(); if (!binderInterface.isPresent()) { // SDK is not loaded anymore. return; } ISdkInterface sdkInterface = ISdkInterface.Stub.asInterface(binder); sdkInterface.doSomething(); new Handler(Looper.getMainLooper()).post(() -> { Bundle bundle = new Bundle(); bundle.putInt(EXTRA_WIDTH_IN_PIXELS, mClientView.getWidth()); bundle.putInt(EXTRA_HEIGHT_IN_PIXELS, mClientView.getHeight()); bundle.putInt(EXTRA_DISPLAY_ID, getDisplay().getDisplayId()); bundle.putInt(EXTRA_HOST_TOKEN, mClientView.getHostToken()); mSdkSandboxManager.requestSurfacePackage( SDK_NAME, bundle, Runnable::run, new RequestSurfacePackageOutcomeReceiverImpl()); }); } @Override public void onError(@NonNull LoadSdkException error) { // Log or show error. } } Để quay lại khung hiển thị từ xa của SDK trong thời gian chạy khi đang gọi
requestSurfacePackage()
, hãy triển khai giao diệnOutcomeReceiver<Bundle, RequestSurfacePackageException>
:Kotlin
private inner class RequestSurfacePackageOutcomeReceiverImpl : OutcomeReceiver
{ fun onResult(@NonNull result: Bundle) { Handler(Looper.getMainLooper()) .post { val surfacePackage: SurfacePackage = result.getParcelable( EXTRA_SURFACE_PACKAGE, SurfacePackage::class.java) mRenderedView.setChildSurfacePackage(surfacePackage) mRenderedView.setVisibility(View.VISIBLE) } } fun onError(@NonNull error: RequestSurfacePackageException?) { // Error handling } } Java
import static android.app.sdksandbox.SdkSandboxManager.EXTRA_SURFACE_PACKAGE; private class RequestSurfacePackageOutcomeReceiverImpl implements OutcomeReceiver
{ @Override public void onResult(@NonNull Bundle result) { new Handler(Looper.getMainLooper()) .post( () -> { SurfacePackage surfacePackage = result.getParcelable( EXTRA_SURFACE_PACKAGE, SurfacePackage.class); mRenderedView.setChildSurfacePackage(surfacePackage); mRenderedView.setVisibility(View.VISIBLE); }); } @Override public void onError(@NonNull RequestSurfacePackageException error) { // Error handling } } Khi hiện xong khung hiển thị, hãy nhớ thả
SurfacePackage
bằng cách gọi:surfacePackage.notifyDetachedFromWindow()
Trong
onCreate()
, hãy khởi chạySdkSandboxManager
, các lệnh gọi lại cần thiết, sau đó đưa ra yêu cầu tải SDK:Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mSdkSandboxManager = applicationContext.getSystemService( SdkSandboxManager::class.java ) mClientView = findViewById(R.id.rendered_view) mClientView.setZOrderOnTop(true) val loadSdkCallback = LoadSdkCallbackImpl() mSdkSandboxManager.loadSdk( SDK_NAME, Bundle(), { obj: Runnable -> obj.run() }, loadSdkCallback ) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSdkSandboxManager = getApplicationContext().getSystemService( SdkSandboxManager.class); mClientView = findViewById(R.id.rendered_view); mClientView.setZOrderOnTop(true); LoadSdkCallbackImpl loadSdkCallback = new LoadSdkCallbackImpl(); mSdkSandboxManager.loadSdk( SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback); }
Để xử lý trường hợp khi quy trình hộp cát SDK bị chấm dứt đột ngột, hãy xác định phương thức triển khai cho giao diện
SdkSandboxProcessDeathCallback
:Kotlin
private inner class SdkSandboxLifecycleCallbackImpl() : SdkSandboxProcessDeathCallback { override fun onSdkSandboxDied() { // The SDK runtime process has terminated. To bring back up the // sandbox and continue using SDKs, load the SDKs again. val loadSdkCallback = LoadSdkOutcomeReceiverImpl() mSdkSandboxManager.loadSdk( SDK_NAME, Bundle(), { obj: Runnable -> obj.run() }, loadSdkCallback) } }
Java
private class SdkSandboxLifecycleCallbackImpl implements SdkSandboxProcessDeathCallback { @Override public void onSdkSandboxDied() { // The SDK runtime process has terminated. To bring back up // the sandbox and continue using SDKs, load the SDKs again. LoadSdkOutcomeReceiverImpl loadSdkCallback = new LoadSdkOutcomeReceiverImpl(); mSdkSandboxManager.loadSdk( SDK_NAME, new Bundle(), Runnable::run, loadSdkCallback); } }
Để đăng ký lệnh gọi lại này nhằm nhận thông tin về thời điểm hộp cát SDK bị chấm dứt, hãy thêm dòng sau bất kỳ lúc nào:
Kotlin
mSdkSandboxManager.addSdkSandboxProcessDeathCallback({ obj: Runnable -> obj.run() }, SdkSandboxLifecycleCallbackImpl())
Java
mSdkSandboxManager.addSdkSandboxProcessDeathCallback(Runnable::run, new SdkSandboxLifecycleCallbackImpl());
Vì trạng thái của hộp cát bị mất khi quy trình xử lý của nó kết thúc, nên các chế độ xem do SDK kết xuất từ xa có thể không còn hoạt động chính xác nữa. Để tiếp tục tương tác với các SDK, các khung hiển thị này phải được tải lại để bắt đầu một quy trình hộp cát mới.
Thêm phần phụ thuộc trên mô-đun SDK vào
build.gradle
của ứng dụng khách:dependencies { ... implementation project(':<your-sdk-module>') ... }
Kiểm thử ứng dụng
Để chạy ứng dụng, hãy cài đặt ứng dụng SDK và ứng dụng trên thiết bị kiểm thử của bạn thông qua Android Studio hoặc dòng lệnh.
Triển khai thông qua Android Studio
Khi triển khai thông qua Android Studio, hãy hoàn thành các bước sau:
- Mở dự án Android Studio cho ứng dụng khách của bạn.
- Chuyển đến Run > Edit Configurations (Chạy > Chỉnh sửa cấu hình). Cửa sổ Run/Debug Configuration (Cấu hình chạy/gỡ lỗi) sẽ xuất hiện.
- Trong phần Launch Options (Tuỳ chọn khởi chạy), hãy đặt Launch (Khởi chạy) thành Specified Activity (Hoạt động đã chỉ định).
- Nhấp vào trình đơn có biểu tượng ba dấu chấm bên cạnh Activity (Hoạt động) rồi chọn Main Activity (Hoạt động chính) cho ứng dụng khách của bạn.
- Nhấp vào Apply (Áp dụng) rồi nhấp vào OK.
- Nhấp vào biểu tượng Run (Chạy)
để cài đặt ứng dụng và SDK trên thiết bị kiểm thử của bạn.
Triển khai trên dòng lệnh
Khi triển khai bằng dòng lệnh, hãy hoàn tất các bước trong danh sách sau.
Phần này giả định rằng tên mô-đun ứng dụng SDK của bạn là sdk-app
và tên mô-đun ứng dụng khách là client-app
.
Trên một thiết bị đầu cuối của dòng lệnh, hãy tạo các APK SDK Hộp cát về quyền riêng tư:
./gradlew :client-app:buildPrivacySandboxSdkApksForDebug
Thao tác này sẽ tạo ra vị trí cho các APK đã tạo. Các APK này được ký bằng khoá gỡ lỗi cục bộ của bạn. Bạn cần có đường dẫn này trong lệnh tiếp theo.
Cài đặt APK trên thiết bị:
adb install -t /path/to/your/standalone.apk
Trong Android Studio, hãy nhấp vào Run > Edit Configurations (Chạy > Chỉnh sửa cấu hình). Cửa sổ Run/Debug Configuration (Cấu hình chạy/gỡ lỗi) sẽ hiện ra.
Trong mục Installation Options (Các tuỳ chọn cài đặt), hãy đặt Deploy (Triển khai) thành Default APK (APK mặc định).
Nhấp vào Apply (Áp dụng) rồi nhấp vào OK.
Nhấp vào Run (Chạy) để cài đặt gói APK trên thiết bị kiểm thử của bạn.
Gỡ lỗi ứng dụng
Để gỡ lỗi ứng dụng, hãy nhấp vào nút Debug (Gỡ lỗi) trong Android Studio.
Để gỡ lỗi ứng dụng SDK, hãy chuyển đến Run > Attach to Process (Chạy > Đính kèm quy trình). Thao tác này sẽ cho bạn thấy màn hình bật lên (hình 1). Đánh dấu vào hộp Show all processes (Hiển thị tất cả quy trình). Trong danh sách xuất hiện, hãy tìm quy trình có tên CLIENT_APP_PROCESS_sdk_sandbox
. Chọn tuỳ chọn này và thêm các điểm ngắt vào mã của ứng dụng SDK để bắt đầu gỡ lỗi SDK của bạn.

Bắt đầu và dừng thời gian chạy SDK từ dòng lệnh
Để bắt đầu quy trình thời gian chạy SDK cho ứng dụng, hãy sử dụng lệnh shell sau:
adb shell cmd sdk_sandbox start [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>
Tương tự như vậy, để dừng quy trình thời gian chạy SDK, hãy chạy lệnh sau:
adb shell cmd sdk_sandbox stop [--user <USER_ID> | current] <CLIENT_APP_PACKAGE>
Các điểm hạn chế
Để biết danh sách các tính năng đang tiến hành cho Thời gian chạy SDK, vui lòng xem ghi chú phát hành.
Mã mẫu
Trang Kho lưu trữ API Thời gian chạy SDK và Bảo đảm quyền riêng tư trên GitHub chứa một tập hợp các dự án Android Studio riêng lẻ để giúp bạn bắt đầu, trong đó có các mẫu minh hoạ cách khởi động và gọi Thời gian chạy SDK.Báo cáo lỗi và vấn đề
Phản hồi của bạn có vai trò quan trọng trong Hộp cát về quyền riêng tư trên Android! Hãy cho chúng tôi biết mọi vấn đề bạn tìm thấy hoặc ý tưởng để cải thiện Hộp cát về quyền riêng tư trên Android.
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Thời gian chạy SDK
- Ghi chú phát hành
- Hướng dẫn cho nhà phát triển về Protected Audience API