Saya mencoba menerapkan pola Adaptor Sinkronisasi Penyedia Konten seperti yang dibahas di Google IO - slide 26. Penyedia konten saya berfungsi, dan sinkronisasi saya berfungsi saat saya memicunya dari aplikasi Penguji Sinkronisasi Alat Dev, namun saat saya memanggil ContentResolver. requestSync (akun, otoritas, bundel) dari ContentProvider saya, sinkronisasi saya tidak pernah terpicu.
ContentResolver.requestSync(
account,
AUTHORITY,
new Bundle());
Edit - menambahkan cuplikan manifes Xml manifes saya berisi:
<service
android:name=".sync.SyncService"
android:exported="true">
<intent-filter>
<action
android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
--Edit
Syncadapter.xml saya yang terkait dengan layanan sinkronisasi saya berisi:
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="AUTHORITY"
android:accountType="myaccounttype"
android:supportsUploading="true"
/>
Tidak yakin kode lain apa yang akan berguna. Akun yang diteruskan ke requestSync adalah "myaccounttype" dan KEWENANGAN yang diteruskan ke panggilan tersebut cocok dengan adaptor syc saya xml.
Apakah ContentResolver.requestSync cara yang benar untuk meminta sinkronisasi? Sepertinya alat penguji sinkronisasi mengikat langsung ke layanan dan panggilan mulai sinkronisasi, tetapi tampaknya itu mengalahkan tujuan integrasi dengan arsitektur sinkronisasi.
Jika itu adalah cara yang benar untuk meminta sinkronisasi, mengapa penguji sinkronisasi berfungsi, tetapi bukan panggilan saya ke ContentResolver.requestSync? Apakah ada sesuatu yang harus saya berikan dalam bundel?
Saya menguji di emulator pada perangkat yang menjalankan 2.1 dan 2.2.
android:process=":sync"
dari layanan sinkronisasi biarkan debugger mencapai titik paruh. Layanan sinkronisasi itu sendiri berfungsi sebelumnya, karena saya bisa melihat pesan log darionPerformSync
metode atas nama proses lain.Jawaban:
Panggilan
requestSync()
hanya akan berfungsi pada pasangan {Account, ContentAuthority} yang dikenal oleh sistem. Aplikasi Anda perlu melalui sejumlah langkah untuk memberi tahu Android bahwa Anda mampu menyinkronkan jenis konten tertentu menggunakan jenis akun tertentu. Ini dilakukan di AndroidManifest.1. Beri tahu Android bahwa paket aplikasi Anda menyediakan sinkronisasi
Pertama, di AndroidManifest.xml, Anda harus menyatakan bahwa Anda memiliki Layanan Sinkronisasi:
Atribut nama dari
<service>
tag adalah nama kelas Anda untuk menyambung sinkronisasi ... Saya akan membicarakannya sebentar lagi.Pengaturan export true membuatnya terlihat oleh komponen lain (diperlukan sehingga
ContentResolver
dapat memanggilnya).Filter maksud memungkinkannya menangkap maksud yang meminta sinkronisasi. (Ini
Intent
berasal dariContentResolver
saat Anda meneleponContentResolver.requestSync()
atau metode penjadwalan terkait.)The
<meta-data>
tag akan dibahas di bawah.2. Sediakan Android layanan yang digunakan untuk menemukan SyncAdapter Anda
Jadi kelasnya sendiri ... Berikut contohnya:
Kelas Anda harus memperpanjang
Service
atau salah satu subkelasnya, harus mengimplementasikanpublic IBinder onBind(Intent)
, dan harus mengembalikanSyncAdapterBinder
ketika dipanggil ... Anda memerlukan variabel tipeAbstractThreadedSyncAdapter
. Jadi seperti yang Anda lihat, hampir semuanya di kelas itu. Satu-satunya alasan mengapa ada untuk menyediakan Layanan, yang menawarkan antarmuka standar untuk Android untuk menanyakan kelas Anda tentang apa AndaSyncAdapter
sendiri.3. Sediakan
class SyncAdapter
untuk benar-benar melakukan sinkronisasi.mySyncAdapter adalah tempat menyimpan logika sinkronisasi yang sebenarnya. Nya
onPerformSync()
metode dipanggil ketika saatnya untuk sync. Saya pikir Anda sudah memiliki ini.4. Menetapkan ikatan antara tipe Akun dan Otoritas Konten
Melihat kembali lagi di AndroidManifest,
<meta-data>
tag aneh dalam layanan kami adalah bagian kunci yang menetapkan pengikatan antara ContentAuthority dan akun. Ini secara eksternal mereferensikan file xml lain (sebut saja sesuka Anda, sesuatu yang relevan dengan aplikasi Anda.) Mari kita lihat sync_myapp.xml:Oke, jadi apa fungsinya? Ini memberi tahu Android bahwa adaptor sinkronisasi yang telah kita tentukan (kelas yang dipanggil dalam elemen nama dari
<service>
tag yang menyertakan<meta-data>
tag yang mereferensikan file ini ...) akan menyinkronkan kontak menggunakan akun gaya com.google.Semua string contentAuthority Anda harus semuanya cocok, dan cocok dengan apa yang Anda sinkronkan - Ini harus berupa string yang Anda tentukan, jika Anda membuat database Anda sendiri, atau Anda harus menggunakan beberapa string perangkat yang ada jika Anda menyinkronkan diketahui jenis data (seperti kontak atau acara kalender atau apa saja.) Di atas ("com.android.contacts") kebetulan adalah string ContentAuthority untuk data jenis kontak (kejutan, kejutan.)
accountType juga harus cocok dengan salah satu jenis akun yang diketahui yang sudah dimasukkan, atau harus cocok dengan yang Anda buat (Ini melibatkan pembuatan subkelas AccountAuthenticator untuk mendapatkan auth di server Anda ... Layak sebuah artikel, itu sendiri.) Sekali lagi, "com.google" adalah string yang ditentukan yang mengidentifikasi kredensial akun gaya ... google.com (sekali lagi, ini seharusnya tidak mengejutkan.)
5. Aktifkan Sinkronisasi pada pasangan Akun / Otoritas Konten tertentu
Terakhir, sinkronisasi harus diaktifkan. Anda dapat melakukan ini di halaman Akun & Sinkronisasi di panel kontrol dengan membuka aplikasi Anda dan menyetel kotak centang di sebelah aplikasi Anda dalam akun yang sesuai. Sebagai alternatif, Anda dapat melakukannya di beberapa kode penyiapan di aplikasi Anda:
Agar sinkronisasi terjadi, pasangan akun / otoritas Anda harus diaktifkan untuk sinkronisasi (seperti di atas) dan keseluruhan bendera sinkronisasi global pada sistem harus disetel, dan perangkat harus memiliki konektivitas jaringan.
Jika sinkronisasi akun / otoritas Anda atau sinkronisasi global dinonaktifkan, memanggil RequestSync () memang memiliki efek - Ini menetapkan tanda bahwa sinkronisasi telah diminta, dan akan dilakukan segera setelah sinkronisasi diaktifkan.
Juga, per mgv , pengaturan
ContentResolver.SYNC_EXTRAS_MANUAL
ke true dalam paket ekstra requestSync Anda akan meminta android untuk memaksa sinkronisasi bahkan jika sinkronisasi global tidak aktif (hormati pengguna Anda di sini!)Terakhir, Anda dapat mengatur sinkronisasi terjadwal berkala, lagi-lagi dengan fungsi ContentResolver.
6. Pertimbangkan implikasi dari banyak akun
Dimungkinkan untuk memiliki lebih dari satu akun dengan jenis yang sama (dua akun @ gmail.com disiapkan pada satu perangkat atau dua akun facebook, atau dua akun twitter, dll ...) Anda harus mempertimbangkan implikasi aplikasi dari melakukan itu. .. Jika Anda memiliki dua akun, Anda mungkin tidak ingin mencoba menyinkronkan keduanya ke dalam tabel database yang sama. Mungkin Anda perlu menentukan bahwa hanya satu yang dapat aktif pada satu waktu, dan hapus tabel dan sinkronkan ulang jika Anda beralih akun. (melalui halaman properti yang menanyakan akun apa yang ada). Mungkin Anda membuat database yang berbeda untuk setiap akun, mungkin tabel yang berbeda, mungkin kolom kunci di setiap tabel. Semua aplikasi spesifik dan layak untuk dipikirkan.
ContentResolver.setIsSyncable(Account account, String authority, int syncable)
mungkin menarik di sini.setSyncAutomatically()
mengontrol apakah pasangan akun / otoritas dicentang atautidak dicentang , sedangkansetIsSyncable()
menyediakan cara untuk menghapus centang dan mengubah garis menjadi abu-abu sehingga pengguna tidak dapat mengaktifkannya. Anda dapat mengatur satu akun Syncable dan yang lainnya tidak Syncable (dsabled).7. Waspadai ContentResolver.notifyChange ()
Satu hal yang rumit.
ContentResolver.notifyChange()
adalah fungsi yang digunakan olehContentProvider
s untuk memberi tahu Android bahwa database lokal telah diubah. Ini melayani dua fungsi, pertama, ini akan menyebabkan kursor mengikuti konten uri untuk diperbarui, dan pada gilirannya meminta dan membatalkan dan menggambar ulangListView
, dll ... Sangat ajaib, database berubah dan AndaListView
hanya memperbarui secara otomatis. Hebat. Selain itu, saat database berubah, Android akan meminta Sinkronisasi untuk Anda, bahkan di luar jadwal normal Anda, sehingga perubahan tersebut diambil dari perangkat dan disinkronkan ke server secepat mungkin. Juga luar biasa.Ada satu kasus tepi. Jika Anda menarik dari server, dan mendorong pembaruan ke dalam
ContentProvider
, itu akan dengan patuh memanggilnotifyChange()
dan android akan berkata, "Oh, database berubah, lebih baik letakkan di server!" (Doh!) Penulisan yang baikContentProviders
akan memiliki beberapa pengujian untuk melihat apakah perubahan itu berasal dari jaringan atau dari pengguna, dan akan menyetel booleansyncToNetwork
flag false jika demikian, untuk mencegah sinkronisasi ganda yang sia-sia ini. Jika Anda memasukkan data ke fileContentProvider
, Anda harus mencari cara untuk membuatnya berfungsi - Jika tidak, Anda akan selalu melakukan dua sinkronisasi saat hanya satu yang diperlukan.8. Merasa senang!
Setelah Anda memiliki semua metadata xml ini, dan sinkronisasi diaktifkan, Android akan tahu cara menghubungkan semuanya untuk Anda, dan sinkronisasi akan mulai berfungsi. Pada titik ini, banyak hal yang bagus akan langsung masuk ke tempatnya dan akan terasa sangat ajaib. Nikmati!
sumber
ContentResolver.SYNC_EXTRAS_MANUAL
set ke true ke Bundel ekstra dan Anda akan memaksa sinkronisasi :)Saya menelepon
setIsSyncable
setelahsetAuthToken
metode AccountManager . TapisetAuthToken
fungsi kembali sebelumsetIsSyncable
tercapai. Setelah pesanan berubah semuanya bekerja dengan baik!sumber