스터브 콘텐츠 제공업체 만들기
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
동기화 어댑터 프레임워크는 유연하고 확장 가능한 방식으로 관리되는 기기 데이터와
매우 안전한 콘텐츠 제공자 프레임워크입니다. 따라서 동기화 어댑터 프레임워크에서는
이미 로컬 데이터에 대해 콘텐츠 제공자를 정의했는지 확인합니다.
동기화 어댑터 프레임워크가 동기화 어댑터를 실행하려고 하지만 앱에
동기화 어댑터가 다운됩니다.
서버에서 기기로 데이터를 전송하는 새로운 앱을 개발하는 경우
로컬 데이터를 콘텐츠 제공자에 저장하는 것을 적극 권장합니다. 이해관계자와의 협업에 있어
콘텐츠 제공자들은 다양한 보안 이점을 제공하며 특히
Android 시스템의 데이터 저장소를 처리하도록 설계되었습니다. 콘텐츠 제작에 대해 자세히 알아보기
제공자에 관한 자세한 내용은 콘텐츠 제공자 만들기를 참조하세요.
하지만 로컬 데이터를 이미 다른 형식으로 저장하고 있는 경우에도
데이터 전송을 처리하기 위한 어댑터입니다. 모든 클라이언트 측의 동기화 어댑터 프레임워크 요구사항을
스터브 콘텐츠 제공업체를 앱에 추가합니다. 스텁 제공업체가
콘텐츠 제공자 클래스와 같지만 필요한 모든 메서드에서 null
또는 0
를 반환합니다. 만약
스텁 제공업체를 추가한 다음 동기화 어댑터를 사용하여 모든 스토리지에서 데이터를 전송할 수 있습니다.
선택할 수 있습니다
앱에 이미 콘텐츠 제공업체가 있다면 스터브 콘텐츠 제공업체가 필요 없습니다.
이 경우 이 강의를 건너뛰고
동기화 어댑터 만들기 아직
이 강의에서는 스터브 콘텐츠 제공업체를 추가하여
동기화 어댑터를 프레임워크에 연결합니다.
스터브 콘텐츠 제공업체 추가
앱의 스터브 콘텐츠 제공업체를 만들려면 클래스를 확장합니다.
ContentProvider
하고 필요한 메서드를 스텁 아웃합니다. 다음
스니펫은 스텁 제공업체를 만드는 방법을 보여줍니다.
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
}
자바
/*
* 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;
}
}
매니페스트에서 제공업체 선언
동기화 어댑터 프레임워크는
앱이 앱 매니페스트에서 제공자를 선언했습니다. 에서 스텁 제공업체를 선언하려면
매니페스트에 다음 속성을 가진 <provider>
요소를 추가합니다.
-
android:name="com.example.android.datasync.provider.StubProvider"
-
스텁 콘텐츠 제공업체를 구현하는 클래스의 정규화된 이름을 지정합니다.
-
android:authorities="com.example.android.datasync.provider"
-
스텁 콘텐츠 제공업체를 식별하는 URI 권한입니다. 이 값을 앱의
문자열 '.provider'가 포함된 패키지 이름 추가됩니다. 비록
스텁 제공업체를 시스템에 보내면 어떠한 것도 제공업체 자체에 액세스하려고 시도하지 않습니다.
-
android:exported="false"
-
다른 앱이 콘텐츠 제공자에 액세스할 수 있는지 결정합니다. 스텁 콘텐츠
다른 앱에서 볼 수 있도록 허용할 필요가 없으므로 값을
false
로 설정합니다.
지정할 수 있습니다 이 값은 동기화 어댑터 프레임워크 간의 상호작용에 영향을 주지 않습니다.
콘텐츠 제공자 등입니다.
-
android:syncable="true"
-
제공자를 동기화할 수 있음을 나타내는 플래그를 설정합니다. 이 플래그를
true
를 사용하면 코드에서 setIsSyncable()
를 호출할 필요가 없습니다. 이 플래그를 통해 동기화 어댑터 프레임워크가 데이터를
콘텐츠 제공업체와 함께 전송되지만 명시적으로 수행하는 경우에만 전송이 이루어집니다.
다음 스니펫은
<provider>
요소를 앱 매니페스트에 추가합니다.
<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>
이제 동기화 어댑터 프레임워크에 필요한 종속 항목을 만들었으므로
데이터 전송 코드를 캡슐화하는 구성요소를 만듭니다. 이 구성 요소를
동기화 어댑터입니다. 다음 과정에서는 이 구성요소를 앱에 추가하는 방법을 안내합니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[null,null,["최종 업데이트: 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."]]