Tạo trình cung cấp nội dung mã giả lập
Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Khung bộ điều hợp đồng bộ hoá được thiết kế để làm việc với dữ liệu thiết bị do
khung nhà cung cấp nội dung có độ bảo mật cao. Vì lý do này, khung bộ điều hợp đồng bộ hoá dự kiến
một ứng dụng sử dụng khung này đã xác định một trình cung cấp nội dung cho dữ liệu cục bộ của ứng dụng đó.
Nếu khung bộ điều hợp đồng bộ hoá cố gắng chạy bộ điều hợp đồng bộ hoá và ứng dụng của bạn không có
nhà cung cấp nội dung, bộ điều hợp đồng bộ hoá của bạn gặp sự cố.
Nếu đang phát triển một ứng dụng mới có chức năng chuyển dữ liệu từ máy chủ đến thiết bị, bạn nên
hãy cân nhắc kỹ lưỡng việc lưu trữ dữ liệu cục bộ trong trình cung cấp nội dung. Ngoài tầm quan trọng của chúng đối với
bộ điều hợp đồng bộ hoá, nhà cung cấp nội dung mang lại nhiều lợi ích về bảo mật và đặc biệt
được thiết kế để xử lý lưu trữ dữ liệu trên hệ thống Android. Để tìm hiểu thêm về việc tạo nội dung
hãy xem phần Tạo trình cung cấp nội dung.
Tuy nhiên, nếu đã lưu trữ dữ liệu cục bộ ở dạng khác, bạn vẫn có thể sử dụng tính năng đồng bộ hoá
để xử lý việc chuyển dữ liệu. Để đáp ứng yêu cầu về khung bộ điều hợp đồng bộ hoá cho một
nhà cung cấp nội dung, hãy thêm nhà cung cấp nội dung giả lập vào ứng dụng của bạn. Một trình cung cấp mã giả lập sẽ triển khai
nhưng tất cả phương thức bắt buộc đều trả về null
hoặc 0
. Nếu bạn
thêm nhà cung cấp mã giả lập, sau đó bạn có thể sử dụng bộ điều hợp đồng bộ hoá để chuyển dữ liệu từ bất kỳ bộ nhớ nào
cơ chế bạn chọn.
Nếu đã có nhà cung cấp nội dung trong ứng dụng, bạn không cần nhà cung cấp nội dung mã giả lập.
Trong trường hợp đó, bạn có thể bỏ qua bài học này và chuyển sang bài học tiếp theo.
Tạo Bộ điều hợp đồng bộ hoá. Nếu bạn chưa có
nhà cung cấp nội dung này, bài học này sẽ hướng dẫn bạn cách thêm trình cung cấp nội dung giả lập cho phép bạn
cắm bộ điều hợp đồng bộ hoá vào khung.
Thêm trình cung cấp nội dung mã giả lập
Để tạo trình cung cấp nội dung mã giả lập cho ứng dụng của bạn, hãy mở rộng lớp này
ContentProvider
và tìm ra các phương thức cần thiết. Nội dung sau đây
đoạn mã cho bạn biết cách tạo trình cung cấp mã giả lập:
Kotlin
/*
* Define an implementation of ContentProvider that stubs out
* all methods
*/
class StubProvider : ContentProvider() {
/*
* Always return true, indicating that the
* provider loaded correctly.
*/
override fun onCreate(): Boolean = true
/*
* Return no type for MIME type
*/
override fun getType(uri: Uri): String? = null
/*
* query() always returns no results
*
*/
override fun query(
uri: Uri,
projection: Array<String>,
selection: String,
selectionArgs: Array<String>,
sortOrder: String
): Cursor? = null
/*
* insert() always returns null (no URI)
*/
override fun insert(uri: Uri, values: ContentValues): Uri? = null
/*
* delete() always returns "no rows affected" (0)
*/
override fun delete(uri: Uri, selection: String, selectionArgs: Array<String>): Int = 0
/*
* update() always returns "no rows affected" (0)
*/
override fun update(
uri: Uri,
values: ContentValues,
selection: String,
selectionArgs: Array<String>
): Int = 0
}
Java
/*
* Define an implementation of ContentProvider that stubs out
* all methods
*/
public class StubProvider extends ContentProvider {
/*
* Always return true, indicating that the
* provider loaded correctly.
*/
@Override
public boolean onCreate() {
return true;
}
/*
* Return no type for MIME type
*/
@Override
public String getType(Uri uri) {
return null;
}
/*
* query() always returns no results
*
*/
@Override
public Cursor query(
Uri uri,
String[] projection,
String selection,
String[] selectionArgs,
String sortOrder) {
return null;
}
/*
* insert() always returns null (no URI)
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
/*
* delete() always returns "no rows affected" (0)
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
/*
* update() always returns "no rows affected" (0)
*/
public int update(
Uri uri,
ContentValues values,
String selection,
String[] selectionArgs) {
return 0;
}
}
Khai báo trình cung cấp trong tệp kê khai
Khung bộ điều hợp đồng bộ hoá xác minh rằng ứng dụng của bạn có nhà cung cấp nội dung bằng cách kiểm tra xem
ứng dụng đã khai báo một trình cung cấp trong tệp kê khai ứng dụng. Để khai báo trình cung cấp mã giả lập trong
tệp kê khai, hãy thêm phần tử <provider>
có các thuộc tính sau:
-
android:name="com.example.android.datasync.provider.StubProvider"
-
Chỉ định tên đủ điều kiện của lớp triển khai trình cung cấp nội dung mã giả lập.
-
android:authorities="com.example.android.datasync.provider"
-
Đơn vị quản lý URI xác định nhà cung cấp nội dung mã giả lập. Biến giá trị này thành giá trị
tên gói có chuỗi ".provider" được thêm vào từ khoá. Mặc dù bạn đang khai báo
mã giả lập vào hệ thống, không có gì cố gắng truy cập vào chính trình cung cấp đó.
-
android:exported="false"
-
Xác định xem các ứng dụng khác có thể truy cập vào trình cung cấp nội dung hay không. Đối với nội dung giả lập của bạn
nhà cung cấp dịch vụ, hãy đặt giá trị thành
false
vì không cần cho phép ứng dụng khác xem
cho nhà cung cấp. Giá trị này không ảnh hưởng đến sự tương tác giữa khung bộ điều hợp đồng bộ hoá
và trình cung cấp nội dung.
-
android:syncable="true"
-
Đặt cờ cho biết trình cung cấp có thể đồng bộ hoá. Nếu bạn đặt cờ này thành
true
, bạn không phải gọi setIsSyncable()
trong mã. Cờ này cho phép khung bộ điều hợp đồng bộ hoá tạo dữ liệu
quá trình chuyển giao với nhà cung cấp nội dung nhưng chỉ xảy ra việc chuyển giao nếu bạn thực hiện việc chuyển này một cách rõ ràng.
Đoạn mã sau đây hướng dẫn bạn cách thêm
Phần tử <provider>
vào tệp kê khai ứng dụng:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.network.sync.BasicSyncAdapter"
android:versionCode="1"
android:versionName="1.0" >
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
...
<provider
android:name="com.example.android.datasync.provider.StubProvider"
android:authorities="com.example.android.datasync.provider"
android:exported="false"
android:syncable="true"/>
...
</application>
</manifest>
Giờ đây, khi đã tạo các phần phụ thuộc theo yêu cầu của khung bộ điều hợp đồng bộ hoá, bạn có thể
tạo thành phần đóng gói mã chuyển dữ liệu. Thành phần này được gọi là
bộ điều hợp đồng bộ hoá. Bài học tiếp theo sẽ hướng dẫn bạn cách thêm thành phần này vào ứng dụng.
Nội dung và mã mẫu trên trang này phải tuân thủ các giấy phép như mô tả trong phần Giấy phép nội dung. Java và OpenJDK là nhãn hiệu hoặc nhãn hiệu đã đăng ký của Oracle và/hoặc đơn vị liên kết của Oracle.
Cập nhật lần gần đây nhất: 2025-07-27 UTC.
[[["Dễ hiểu","easyToUnderstand","thumb-up"],["Giúp tôi giải quyết được vấn đề","solvedMyProblem","thumb-up"],["Khác","otherUp","thumb-up"]],[["Thiếu thông tin tôi cần","missingTheInformationINeed","thumb-down"],["Quá phức tạp/quá nhiều bước","tooComplicatedTooManySteps","thumb-down"],["Đã lỗi thời","outOfDate","thumb-down"],["Vấn đề về bản dịch","translationIssue","thumb-down"],["Vấn đề về mẫu/mã","samplesCodeIssue","thumb-down"],["Khác","otherDown","thumb-down"]],["Cập nhật lần gần đây nhất: 2025-07-27 UTC."],[],[],null,["# Create a stub content provider\n\nThe sync adapter framework is designed to work with device data managed by the flexible and\nhighly secure content provider framework. For this reason, the sync adapter framework expects\nthat an app that uses the framework has already defined a content provider for its local data.\nIf the sync adapter framework tries to run your sync adapter, and your app doesn't have a\ncontent provider, your sync adapter crashes.\n\n\nIf you're developing a new app that transfers data from a server to the device, you should\nstrongly consider storing the local data in a content provider. Besides their importance for\nsync adapters, content providers offer a variety of security benefits and are specifically\ndesigned to handle data storage on Android systems. To learn more about creating a content\nprovider, see [Creating a Content Provider](/guide/topics/providers/content-provider-creating).\n\n\nHowever, if you're already storing local data in another form, you can still use a sync\nadapter to handle data transfer. To satisfy the sync adapter framework requirement for a\ncontent provider, add a stub content provider to your app. A stub provider implements the\ncontent provider class, but all of its required methods return `null` or `0`. If you\nadd a stub provider, you can then use a sync adapter to transfer data from any storage\nmechanism you choose.\n\n\nIf you already have a content provider in your app, you don't need a stub content provider.\nIn that case, you can skip this lesson and proceed to the lesson\n[Creating a Sync Adapter](/training/sync-adapters/creating-sync-adapter). If you don't yet have a\ncontent provider, this lesson shows you how to add a stub content provider that allows you to\nplug your sync adapter into the framework.\n\nAdd a stub content provider\n---------------------------\n\n\nTo create a stub content provider for your app, extend the class\n[ContentProvider](/reference/android/content/ContentProvider) and stub out its required methods. The following\nsnippet shows you how to create the stub provider: \n\n### Kotlin\n\n```kotlin\n/*\n * Define an implementation of ContentProvider that stubs out\n * all methods\n */\nclass StubProvider : ContentProvider() {\n /*\n * Always return true, indicating that the\n * provider loaded correctly.\n */\n override fun onCreate(): Boolean = true\n\n /*\n * Return no type for MIME type\n */\n override fun getType(uri: Uri): String? = null\n\n /*\n * query() always returns no results\n *\n */\n override fun query(\n uri: Uri,\n projection: Array\u003cString\u003e,\n selection: String,\n selectionArgs: Array\u003cString\u003e,\n sortOrder: String\n ): Cursor? = null\n\n /*\n * insert() always returns null (no URI)\n */\n override fun insert(uri: Uri, values: ContentValues): Uri? = null\n\n /*\n * delete() always returns \"no rows affected\" (0)\n */\n override fun delete(uri: Uri, selection: String, selectionArgs: Array\u003cString\u003e): Int = 0\n\n /*\n * update() always returns \"no rows affected\" (0)\n */\n override fun update(\n uri: Uri,\n values: ContentValues,\n selection: String,\n selectionArgs: Array\u003cString\u003e\n ): Int = 0\n}\n```\n\n### Java\n\n```java\n/*\n * Define an implementation of ContentProvider that stubs out\n * all methods\n */\npublic class StubProvider extends ContentProvider {\n /*\n * Always return true, indicating that the\n * provider loaded correctly.\n */\n @Override\n public boolean onCreate() {\n return true;\n }\n /*\n * Return no type for MIME type\n */\n @Override\n public String getType(Uri uri) {\n return null;\n }\n /*\n * query() always returns no results\n *\n */\n @Override\n public Cursor query(\n Uri uri,\n String[] projection,\n String selection,\n String[] selectionArgs,\n String sortOrder) {\n return null;\n }\n /*\n * insert() always returns null (no URI)\n */\n @Override\n public Uri insert(Uri uri, ContentValues values) {\n return null;\n }\n /*\n * delete() always returns \"no rows affected\" (0)\n */\n @Override\n public int delete(Uri uri, String selection, String[] selectionArgs) {\n return 0;\n }\n /*\n * update() always returns \"no rows affected\" (0)\n */\n public int update(\n Uri uri,\n ContentValues values,\n String selection,\n String[] selectionArgs) {\n return 0;\n }\n}\n```\n\nDeclare the provider in the manifest\n------------------------------------\n\n\nThe sync adapter framework verifies that your app has a content provider by checking that your\napp has declared a provider in its app manifest. To declare the stub provider in the\nmanifest, add a [\u003cprovider\u003e](/guide/topics/manifest/provider-element) element with the following attributes:\n\n\n`android:name=\"com.example.android.datasync.provider.StubProvider\"`\n:\n Specifies the fully-qualified name of the class that implements the stub content provider.\n\n\n`android:authorities=\"com.example.android.datasync.provider\"`\n:\n A URI authority that identifies the stub content provider. Make this value your app's\n package name with the string \".provider\" appended to it. Even though you're declaring your\n stub provider to the system, nothing tries to access the provider itself.\n\n\n`android:exported=\"false\"`\n:\n Determines whether other apps can access the content provider. For your stub content\n provider, set the value to `false`, since there's no need to allow other apps to see\n the provider. This value doesn't affect the interaction between the sync adapter framework\n and the content provider.\n\n\n`android:syncable=\"true\"`\n:\n Sets a flag that indicates that the provider is syncable. If you set this flag to\n `true`, you don't have to call [setIsSyncable()](/reference/android/content/ContentResolver#setIsSyncable(android.accounts.Account, java.lang.String, int)) in your code. The flag allows the sync adapter framework to make data\n transfers with the content provider, but transfers only occur if you do them explicitly.\n\n\nThe following snippet shows you how to add the\n[\u003cprovider\u003e](/guide/topics/manifest/provider-element) element to the app manifest: \n\n```xml\n\u003cmanifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.example.android.network.sync.BasicSyncAdapter\"\n android:versionCode=\"1\"\n android:versionName=\"1.0\" \u003e\n \u003capplication\n android:allowBackup=\"true\"\n android:icon=\"@drawable/ic_launcher\"\n android:label=\"@string/app_name\"\n android:theme=\"@style/AppTheme\" \u003e\n ...\n \u003cprovider\n android:name=\"com.example.android.datasync.provider.StubProvider\"\n android:authorities=\"com.example.android.datasync.provider\"\n android:exported=\"false\"\n android:syncable=\"true\"/\u003e\n ...\n \u003c/application\u003e\n\u003c/manifest\u003e\n```\n\n\nNow that you have created the dependencies required by the sync adapter framework, you can\ncreate the component that encapsulates your data transfer code. This component is called a\nsync adapter. The next lesson shows you how to add this component to your app."]]