Criar um provedor de conteúdo stub

O framework do adaptador de sincronização foi projetado para funcionar com dados de dispositivos gerenciados pelo framework do provedor de conteúdo flexível e altamente seguro. Por esse motivo, o framework do adaptador de sincronização espera que um app que o usa já tenha definido um provedor de conteúdo para os dados locais. Se o framework tentar executar o adaptador de sincronização e o app não tiver um provedor de conteúdo, o adaptador de sincronização falhará.

Se você estiver desenvolvendo um novo app que transfere dados de um servidor para o dispositivo, considere fortemente armazenar os dados locais em um provedor de conteúdo. Além da importância para os adaptadores de sincronização, os provedores de conteúdo oferecem uma variedade de benefícios de segurança e são especificamente projetados para gerenciar o armazenamento de dados em sistemas Android. Para saber mais sobre a criação de um provedor de conteúdo, consulte Como criar um provedor de conteúdo.

No entanto, se você já estiver armazenando dados locais de outra forma, ainda poderá usar um adaptador de sincronização para lidar com a transferência de dados. Para atender ao requisito do framework do adaptador de sincronização para um provedor de conteúdo, adicione um provedor de conteúdo stub ao app. Um provedor stub implementa a classe do provedor de conteúdo, mas todos os métodos necessários retornam null ou 0. Se você adicionar um provedor de stub, poderá usar um adaptador de sincronização para transferir dados de qualquer mecanismo de armazenamento escolhido.

Se você já tem um provedor de conteúdo no app, não é necessário ter um stub. Nesse caso, você pode pular esta lição e avançar para a lição Como criar um adaptador de sincronização. Se você ainda não tem um provedor de conteúdo, esta lição mostra como adicionar um provedor de conteúdo stub para conectar o adaptador de sincronização ao framework.

Adicionar um provedor de conteúdo stub

Para criar um provedor de conteúdo stub para o app, estenda a classe ContentProvider e crie stubs para os métodos necessários. O snippet a seguir mostra como criar o provedor de stub:

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

Declarar o provedor no manifesto

O framework do adaptador de sincronização verifica se o app tem um provedor de conteúdo, verificando se o app declarou um provedor no manifesto dele. Para declarar o provedor de stub no manifesto, adicione um elemento <provider> com os seguintes atributos:

android:name="com.example.android.datasync.provider.StubProvider"
Especifica o nome totalmente qualificado da classe que implementa o provedor de conteúdo stub.
android:authorities="com.example.android.datasync.provider"
Uma autoridade de URI que identifica o provedor de conteúdo stub. Use esse valor como o nome do pacote do app com a string ".provider" anexada a ele. Mesmo que você esteja declarando o provedor stub para o sistema, nada tentará acessar o provedor em si.
android:exported="false"
Determina se outros apps podem acessar o provedor de conteúdo. Para seu provedor de conteúdo stub, defina o valor como false, já que não é necessário permitir que outros apps o vejam. Esse valor não afeta a interação entre o framework do adaptador de sincronização e o provedor de conteúdo.
android:syncable="true"
Define uma sinalização que indica que o provedor é sincronizável. Se você definir essa flag como true, não precisará chamar setIsSyncable() no código. A sinalização permite que o framework do adaptador de sincronização faça transferências de dados com o provedor de conteúdo, mas elas só ocorrerão se você as fizer explicitamente.

O snippet a seguir mostra como adicionar o elemento <provider> ao manifesto do app.

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

Agora que você criou as dependências exigidas pelo framework do adaptador de sincronização, pode criar o componente que encapsula o código de transferência de dados. Esse componente é chamado de adaptador de sincronização. A próxima lição mostra como adicionar esse componente ao app.