A chamada requestSync()
só funcionará em um par {Account, ContentAuthority} conhecido pelo sistema. Seu aplicativo precisa passar por uma série de etapas para informar ao Android que você é capaz de sincronizar um tipo específico de conteúdo usando um tipo específico de conta. Ele faz isso no AndroidManifest.
1. Notifique o Android de que o pacote do seu aplicativo fornece sincronização
Em primeiro lugar, no AndroidManifest.xml, você deve declarar que possui um serviço de sincronização:
<service android:name=".sync.mySyncService" android:exported="true">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/sync_myapp" />
</service>
O atributo name da <service>
tag é o nome da sua classe para conectar a sincronização ... Falarei sobre isso em um segundo.
Definir exportado como verdadeiro o torna visível para outros componentes (necessário para ContentResolver
poder chamá-lo).
O filtro de intent permite capturar uma sincronização de solicitação de intent. (Isso Intent
vem ContentResolver
quando você liga ContentResolver.requestSync()
ou métodos de agendamento relacionados).
A <meta-data>
tag será discutida abaixo.
2. Fornece ao Android um serviço usado para encontrar seu SyncAdapter
Portanto, a própria classe ... Aqui está um exemplo:
public class mySyncService extends Service {
private static mySyncAdapter mSyncAdapter = null;
public SyncService() {
super();
}
@Override
public void onCreate() {
super.onCreate();
if (mSyncAdapter == null) {
mSyncAdapter = new mySyncAdapter(getApplicationContext(), true);
}
}
@Override
public IBinder onBind(Intent arg0) {
return mSyncAdapter.getSyncAdapterBinder();
}
}
Sua classe deve estender Service
ou uma de suas subclasses, deve implementar public IBinder onBind(Intent)
e deve retornar um SyncAdapterBinder
quando for chamado ... Você precisa de uma variável do tipo AbstractThreadedSyncAdapter
. Como você pode ver, isso é praticamente tudo nessa classe. A única razão pela qual está lá é para fornecer um serviço, que oferece uma interface padrão para Android para consultar sua classe sobre o que você SyncAdapter
é.
3. Forneça um class SyncAdapter
para realmente executar a sincronização.
mySyncAdapter é onde a própria lógica de sincronização real é armazenada. Seu onPerformSync()
método é chamado quando é hora de sincronizar. Eu acho que você já tem isso no lugar.
4. Estabeleça uma ligação entre um tipo de conta e uma autoridade de conteúdo
Olhando novamente para AndroidManifest, aquela <meta-data>
tag estranha em nosso serviço é a peça-chave que estabelece a ligação entre um ContentAuthority e uma conta. Ele faz referência externa a outro arquivo xml (chame-o do que quiser, algo relevante para o seu aplicativo). Vejamos sync_myapp.xml:
<?xml version="1.0" encoding="utf-8" ?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="com.google"
android:userVisible="true" />
Ok, então o que isso faz? Diz ao Android que o adaptador de sincronização que definimos (a classe que foi chamada no elemento de nome da <service>
tag que inclui a <meta-data>
tag que faz referência a este arquivo ...) sincronizará os contatos usando uma conta do estilo com.google.
Todas as suas strings contentAuthority devem corresponder e combinar com o que você está sincronizando - Deve ser uma string que você define, se estiver criando seu próprio banco de dados, ou deve usar algumas strings de dispositivo existentes se estiver sincronizando conhecido tipos de dados (como contatos ou eventos de calendário ou o que for.) O acima ("com.android.contacts") passa a ser a string ContentAuthority para dados de tipo de contato (surpresa, surpresa.)
accountType também deve corresponder a um daqueles tipos de conta conhecidos que já foram inseridos, ou deve corresponder a um que você está criando (isso envolve a criação de uma subclasse de AccountAuthenticator para obter autenticação em seu servidor ... Vale um artigo, por si só.) Novamente, "com.google" é a string definida que identifica ... credenciais da conta no estilo google.com (novamente, isso não deve ser uma surpresa).
5. Ative a sincronização em um determinado par de conta / autoridade de conteúdo
Finalmente, a sincronização deve ser ativada. Você pode fazer isso na página Contas e sincronização no painel de controle acessando seu aplicativo e marcando a caixa de seleção ao lado de seu aplicativo na conta correspondente. Como alternativa, você pode fazer isso em algum código de configuração em seu aplicativo:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Para que a sincronização ocorra, seu par conta / autoridade deve estar habilitado para sincronizar (como acima) e o sinalizador de sincronização global geral no sistema deve ser definido, e o dispositivo deve ter conectividade de rede.
Se sua sincronização de conta / autoridade ou a sincronização global estiverem desabilitadas, chamar RequestSync () tem um efeito - define um sinalizador de que a sincronização foi solicitada e será executada assim que a sincronização for habilitada.
Além disso, por mgv , definir ContentResolver.SYNC_EXTRAS_MANUAL
como verdadeiro no pacote de extras do seu requestSync pedirá ao Android para forçar uma sincronização, mesmo se a sincronização global estiver desligada (seja respeitoso com seu usuário aqui!)
Finalmente, você pode configurar uma sincronização agendada periódica, novamente com funções ContentResolver.
6. Considere as implicações de várias contas
É possível ter mais de uma conta do mesmo tipo (duas contas @ gmail.com configuradas em um dispositivo ou duas contas do Facebook, ou duas contas do Twitter, etc ...). Você deve considerar as implicações do aplicativo ao fazer isso. .. Se você tem duas contas, provavelmente não deseja sincronizar as duas nas mesmas tabelas do banco de dados. Talvez você precise especificar que apenas um pode estar ativo por vez, esvaziar as tabelas e sincronizar novamente se você trocar de conta. (por meio de uma página de propriedade que consulta quais contas estão presentes). Talvez você crie um banco de dados diferente para cada conta, talvez tabelas diferentes, talvez uma coluna-chave em cada tabela. Todo aplicativo específico e digno de alguma reflexão. ContentResolver.setIsSyncable(Account account, String authority, int syncable)
pode ser de interesse aqui. setSyncAutomatically()
controla se um par de conta / autoridade é verificado oudesmarcado , enquanto setIsSyncable()
fornece uma maneira de desmarcar e esmaecer a linha para que o usuário não possa ativá-la. Você pode definir uma conta sincronizável e a outra não sincronizável (desativada).
7. Esteja ciente de ContentResolver.notifyChange ()
Uma coisa complicada. ContentResolver.notifyChange()
é uma função usada por ContentProvider
s para notificar o Android de que o banco de dados local foi alterado. Isso tem duas funções, primeiro, fará com que os cursores seguindo esse conteúdo uri sejam atualizados e, por sua vez, consulte novamente e invalide e redesenhe um ListView
, etc ... É muito mágico, o banco de dados muda e você ListView
apenas atualiza automaticamente. Impressionante. Além disso, quando o banco de dados muda, o Android irá solicitar a sincronização para você, mesmo fora de sua programação normal, para que essas alterações sejam retiradas do dispositivo e sincronizadas com o servidor o mais rápido possível. Também incrível.
Porém, há um caso extremo. Se você puxar do servidor e enviar uma atualização para o ContentProvider
, ele será devidamente chamado notifyChange()
e o Android dirá: "Oh, alterações no banco de dados, melhor colocá-las no servidor!" (Doh!) Bem escrito ContentProviders
fará alguns testes para ver se as mudanças vieram da rede ou do usuário, e definirá o syncToNetwork
sinalizador booleano como falso em caso afirmativo, para evitar esse desperdício de sincronização dupla. Se você estiver alimentando dados em um ContentProvider
, cabe a você descobrir como fazer isso funcionar - caso contrário, você acabará sempre executando duas sincronizações quando apenas uma for necessária.
8. Sinta-se feliz!
Depois de ter todos esses metadados xml no lugar e a sincronização ativada, o Android saberá como conectar tudo para você e a sincronização deve começar a funcionar. Nesse ponto, muitas coisas legais simplesmente se encaixarão no lugar e parecerão mágica. Aproveitar!