Las llamadas requestSync()
solo funcionarán en un par {Account, ContentAuthority} que sea conocido por el sistema. Tu aplicación debe seguir una serie de pasos para indicarle a Android que eres capaz de sincronizar un tipo específico de contenido usando un tipo específico de cuenta. Hace esto en el AndroidManifest.
1. Notifique a Android que el paquete de su aplicación proporciona sincronización
En primer lugar, en AndroidManifest.xml, debe declarar que tiene un Servicio de sincronización:
<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>
El atributo de nombre de la <service>
etiqueta es el nombre de su clase para conectar la sincronización ... Hablaré de eso en un segundo.
Establecer exported true lo hace visible para otros componentes (necesario para ContentResolver
poder llamarlo).
El filtro de intención le permite detectar una intención que solicita sincronización. (Esto Intent
proviene de ContentResolver
cuando llama ContentResolver.requestSync()
o de métodos de programación relacionados).
La <meta-data>
etiqueta se discutirá a continuación.
2. Proporcione a Android un servicio utilizado para encontrar su SyncAdapter
Entonces, la clase en sí ... Aquí hay un ejemplo:
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();
}
}
Su clase debe extender Service
o una de sus subclases, debe implementar public IBinder onBind(Intent)
y debe devolver un SyncAdapterBinder
cuando se llama ... Necesita una variable de tipo AbstractThreadedSyncAdapter
. Como puede ver, eso es prácticamente todo en esa clase. La única razón por la que está ahí es para proporcionar un Servicio, que ofrece una interfaz estándar para Android para consultar a su clase sobre lo que es usted SyncAdapter
mismo.
3. Proporcione una class SyncAdapter
para realizar la sincronización.
mySyncAdapter es donde se almacena la lógica de sincronización real. Se onPerformSync()
llama a su método cuando llega el momento de sincronizar. Supongo que ya tiene esto en su lugar.
4. Establecer un vínculo entre un tipo de cuenta y una autoridad de contenido.
Mirando hacia atrás de nuevo en AndroidManifest, esa extraña <meta-data>
etiqueta en nuestro servicio es la pieza clave que establece el vínculo entre ContentAuthority y una cuenta. Hace referencia externamente a otro archivo xml (llámelo como quiera, algo relevante para su aplicación). Veamos 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" />
Bien, entonces, ¿qué hace esto? Le dice a Android que el adaptador de sincronización que hemos definido (la clase que se llamó en el elemento de nombre de la <service>
etiqueta que incluye la <meta-data>
etiqueta que hace referencia a este archivo ...) sincronizará los contactos usando una cuenta de estilo com.google.
Todas las cadenas de contenido de la autoridad deben coincidir y coincidir con lo que está sincronizando: esta debe ser una cadena que defina, si está creando su propia base de datos, o debe usar algunas cadenas de dispositivos existentes si está sincronizando. tipos de datos (como contactos o eventos de calendario o lo que sea). Lo anterior ("com.android.contacts") resulta ser la cadena ContentAuthority para los datos del tipo de contactos (sorpresa, sorpresa).
accountType también tiene que coincidir con uno de esos tipos de cuenta conocidos que ya están ingresados, o tiene que coincidir con uno que está creando (esto implica crear una subclase de AccountAuthenticator para obtener la autenticación en su servidor ... Vale la pena un artículo en sí). Nuevamente, "com.google" es la cadena definida que identifica ... las credenciales de la cuenta de estilo google.com (nuevamente, esto no debería ser una sorpresa).
5. Habilite la sincronización en un par de cuenta / autoridad de contenido determinado
Finalmente, la sincronización debe estar habilitada. Puede hacer esto en la página Cuentas y sincronización en el panel de control yendo a su aplicación y configurando la casilla de verificación junto a su aplicación dentro de la cuenta correspondiente. Alternativamente, puede hacerlo en algún código de configuración en su aplicación:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Para que se produzca la sincronización, su par de cuenta / autoridad debe estar habilitado para sincronizar (como arriba) y la marca de sincronización global general en el sistema debe estar configurada, y el dispositivo debe tener conectividad de red.
Si la sincronización de su cuenta / autoridad o la sincronización global están deshabilitadas, llamar a RequestSync () tiene un efecto: establece una marca de que se ha solicitado la sincronización y se realizará tan pronto como se habilite la sincronización.
Además, por mgv , si se establece ContentResolver.SYNC_EXTRAS_MANUAL
en verdadero en el paquete de extras de su solicitud , Sync le pedirá a Android que fuerce una sincronización incluso si la sincronización global está desactivada (¡sea respetuoso con su usuario aquí!)
Finalmente, puede configurar una sincronización programada periódica, nuevamente con las funciones de ContentResolver.
6. Considere las implicaciones de múltiples cuentas
Es posible tener más de una cuenta del mismo tipo (dos cuentas @ gmail.com configuradas en un dispositivo o dos cuentas de Facebook, o dos cuentas de Twitter, etc.). Debe considerar las implicaciones de aplicación de hacerlo. .. Si tiene dos cuentas, probablemente no quiera intentar sincronizar ambas en las mismas tablas de la base de datos. Tal vez necesite especificar que solo uno puede estar activo a la vez, y vaciar las tablas y resincronizar si cambia de cuenta. (a través de una página de propiedades que consulta qué cuentas están presentes). Tal vez cree una base de datos diferente para cada cuenta, tal vez tablas diferentes, tal vez una columna clave en cada tabla. Toda aplicación específica y digna de reflexión. ContentResolver.setIsSyncable(Account account, String authority, int syncable)
podría ser de interés aquí. setSyncAutomatically()
controla si un par de cuenta / autoridad está verificado odesmarcado , mientras que setIsSyncable()
proporciona una forma de desmarcar y atenuar la línea para que el usuario no pueda activarla. Puede configurar una cuenta Syncable y la otra no Syncable (dsabled).
7. Tenga en cuenta ContentResolver.notifyChange ()
Una cosa complicada. ContentResolver.notifyChange()
es una función utilizada por ContentProvider
s para notificar a Android que se ha cambiado la base de datos local. Esto tiene dos funciones, primero, hará que los cursores que siguen ese contenido uri se actualicen y, a su vez, vuelvan a consultar, invaliden y vuelvan a dibujar ListView
, etc. Es muy mágico, la base de datos cambia y tu ListView
solo se actualiza automáticamente. Increíble. Además, cuando la base de datos cambie, Android solicitará la sincronización por usted, incluso fuera de su horario normal, para que esos cambios se eliminen del dispositivo y se sincronicen con el servidor lo más rápido posible. También impresionante.
Sin embargo, hay un caso de borde. Si extrae del servidor e inserta una actualización en el ContentProvider
, automáticamente llamará notifyChange()
y Android dirá: "¡Oh, cambios en la base de datos, mejor colóquelos en el servidor!" (¡Doh!) Bien escrito ContentProviders
tendrá algunas pruebas para ver si los cambios provienen de la red o del usuario, y establecerá la syncToNetwork
bandera booleana como falsa si es así, para evitar esta doble sincronización innecesaria. Si está introduciendo datos en un ContentProvider
, le conviene averiguar cómo hacer que esto funcione; de lo contrario, siempre terminará realizando dos sincronizaciones cuando solo se necesita una.
8. ¡Siéntete feliz!
Una vez que tenga todos estos metadatos XML en su lugar y la sincronización habilitada, Android sabrá cómo conectar todo por usted, y la sincronización debería comenzar a funcionar. En este punto, muchas cosas que son agradables simplemente encajarán en su lugar y se sentirán como magia. ¡Disfrutar!