Tính năng gọi requestSync()
sẽ chỉ hoạt động trên một cặp {Account, ContentAuthority} mà hệ thống đã biết. Ứng dụng của bạn cần phải thực hiện một số bước để cho Android biết rằng bạn có khả năng đồng bộ hóa một loại nội dung cụ thể bằng một loại tài khoản cụ thể. Nó thực hiện điều này trong AndroidManifest.
1. Thông báo cho Android biết rằng gói ứng dụng của bạn cung cấp đồng bộ hóa
Trước hết, trong AndroidManifest.xml, bạn phải khai báo rằng bạn có Dịch vụ đồng bộ hóa:
<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>
Thuộc tính name của <service>
thẻ là tên lớp của bạn để kết nối đồng bộ hóa ... Tôi sẽ nói chuyện với điều đó trong giây lát.
Cài đặt được xuất true làm cho nó hiển thị với các thành phần khác (cần thiết để ContentResolver
có thể gọi nó).
Bộ lọc ý định cho phép nó bắt một ý định yêu cầu đồng bộ hóa. (Điều này Intent
đến từ ContentResolver
khi bạn gọi ContentResolver.requestSync()
hoặc các phương pháp lập lịch liên quan.)
Các <meta-data>
thẻ sẽ được thảo luận dưới đây.
2. Cung cấp cho Android một dịch vụ được sử dụng để tìm SyncAdapter của bạn
Vì vậy, chính lớp ... Đây là một ví dụ:
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();
}
}
Lớp của bạn phải mở rộng Service
hoặc một trong các lớp con của nó, phải triển khai public IBinder onBind(Intent)
, và phải trả về một SyncAdapterBinder
khi được gọi ... Bạn cần một biến kiểu AbstractThreadedSyncAdapter
. Vì vậy, như bạn có thể thấy, đó là khá nhiều thứ trong lớp đó. Lý do duy nhất để nó cung cấp một Dịch vụ, cung cấp một giao diện tiêu chuẩn cho Android để truy vấn lớp học của bạn xem SyncAdapter
bản thân bạn là gì.
3. Cung cấp một class SyncAdapter
để thực sự thực hiện đồng bộ hóa.
mySyncAdapter là nơi lưu trữ logic đồng bộ thực. onPerformSync()
Phương thức của nó được gọi khi đến lúc đồng bộ hóa. Tôi nghĩ bạn đã có cái này tại chỗ.
4. Thiết lập ràng buộc giữa Loại tài khoản và Cơ quan nội dung
Nhìn lại AndroidManifest một lần nữa, <meta-data>
thẻ kỳ lạ đó trong dịch vụ của chúng tôi là phần quan trọng thiết lập ràng buộc giữa ContentAuthority và tài khoản. Nó tham chiếu bên ngoài một tệp xml khác (gọi nó là bất cứ thứ gì bạn thích, một cái gì đó liên quan đến ứng dụng của bạn.) Hãy xem 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" />
Được rồi, vậy cái này làm được gì? Nó cho Android biết rằng bộ điều hợp đồng bộ mà chúng tôi đã xác định (lớp được gọi ra trong phần tử tên của <service>
thẻ bao gồm <meta-data>
thẻ tham chiếu đến tệp này ...) sẽ đồng bộ hóa các liên hệ bằng tài khoản kiểu com.google.
Tất cả nội dung của bạn Chuỗi quyền hạn phải khớp và khớp với những gì bạn đang đồng bộ hóa - Đây phải là chuỗi bạn xác định, nếu bạn đang tạo cơ sở dữ liệu của riêng mình hoặc bạn nên sử dụng một số chuỗi thiết bị hiện có nếu bạn đang đồng bộ hóa. loại dữ liệu (như danh bạ hoặc sự kiện lịch hoặc những gì có bạn.) Ở trên ("com.android.contacts") là chuỗi ContentAuthority cho dữ liệu loại liên hệ (bất ngờ, ngạc nhiên.)
accountType cũng phải khớp với một trong những loại tài khoản đã biết đã được nhập hoặc nó phải khớp với loại tài khoản bạn đang tạo (Điều này liên quan đến việc tạo một lớp con của AccountAuthenticator để nhận xác thực trên máy chủ của bạn ... Bản thân nó cũng đáng là một bài báo.) Một lần nữa, "com.google" là chuỗi được xác định xác định ... thông tin đăng nhập tài khoản kiểu google.com (một lần nữa, điều này không gây ngạc nhiên.)
5. Bật Đồng bộ hóa trên một cặp Tài khoản / Nội dungAuthority nhất định
Cuối cùng, đồng bộ hóa phải được bật. Bạn có thể thực hiện việc này trong trang Tài khoản và đồng bộ hóa trong bảng điều khiển bằng cách đi tới ứng dụng của bạn và đặt hộp kiểm bên cạnh ứng dụng của bạn trong tài khoản phù hợp. Ngoài ra, bạn có thể làm điều đó trong một số mã thiết lập trong ứng dụng của mình:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
Để đồng bộ hóa diễn ra, cặp tài khoản / quyền hạn của bạn phải được bật để đồng bộ hóa (như ở trên) và cờ đồng bộ hóa toàn cầu tổng thể trên hệ thống phải được đặt và thiết bị phải có kết nối mạng.
Nếu đồng bộ hóa tài khoản / quyền hạn của bạn hoặc đồng bộ hóa toàn cầu bị vô hiệu hóa, việc gọi RequestSync () sẽ có tác dụng - Nó đặt cờ cho biết đồng bộ hóa đã được yêu cầu và sẽ được thực hiện ngay sau khi đồng bộ hóa được bật.
Ngoài ra, theo mgv , đặt ContentResolver.SYNC_EXTRAS_MANUAL
thành true trong gói bổ sung của requestSync của bạn sẽ yêu cầu android buộc đồng bộ hóa ngay cả khi đồng bộ hóa toàn cầu đang tắt (hãy tôn trọng người dùng của bạn tại đây!)
Cuối cùng, bạn có thể thiết lập đồng bộ hóa theo lịch định kỳ, một lần nữa với các chức năng ContentResolver.
6. Xem xét tác động của nhiều tài khoản
Có thể có nhiều tài khoản cùng loại (hai tài khoản @ gmail.com được thiết lập trên một thiết bị hoặc hai tài khoản facebook, hoặc hai tài khoản twitter, v.v.) Bạn nên xem xét ứng dụng của việc làm đó. .. Nếu bạn có hai tài khoản, bạn có thể không muốn cố gắng đồng bộ cả hai tài khoản vào cùng một bảng cơ sở dữ liệu. Có thể bạn cần chỉ định rằng mỗi lần chỉ có thể hoạt động một bảng và xóa các bảng và đồng bộ hóa lại nếu bạn chuyển đổi tài khoản. (thông qua trang thuộc tính truy vấn tài khoản nào hiện có). Có thể bạn tạo một cơ sở dữ liệu khác nhau cho mỗi tài khoản, có thể các bảng khác nhau, có thể một cột chính trong mỗi bảng. Tất cả các ứng dụng cụ thể và xứng đáng với một số suy nghĩ. ContentResolver.setIsSyncable(Account account, String authority, int syncable)
có thể được quan tâm ở đây. setSyncAutomatically()
kiểm soát xem cặp tài khoản / quyền hạn có được kiểm tra hay khôngbỏ chọn , ngược lại setIsSyncable()
cung cấp một cách để bỏ chọn và tô màu xám dòng để người dùng không thể bật nó lên. Bạn có thể đặt một tài khoản Syncable và tài khoản kia không Syncable (bị vô hiệu hóa).
7. Lưu ý về ContentResolver.notifyChange ()
Một điều khó khăn. ContentResolver.notifyChange()
là một chức năng được sử dụng bởi ContentProvider
s để thông báo cho Android rằng cơ sở dữ liệu cục bộ đã bị thay đổi. Điều này phục vụ hai chức năng, đầu tiên, nó sẽ khiến các con trỏ theo sau nội dung đó phải cập nhật, và lần lượt yêu cầu và làm mất hiệu lực và vẽ lại a ListView
, v.v. Nó rất kỳ diệu, cơ sở dữ liệu thay đổi và bạn ListView
chỉ cập nhật tự động. Tuyệt vời. Ngoài ra, khi cơ sở dữ liệu thay đổi, Android sẽ yêu cầu Đồng bộ hóa cho bạn, ngay cả ngoài lịch trình bình thường của bạn, để những thay đổi đó được đưa ra khỏi thiết bị và đồng bộ hóa với máy chủ nhanh nhất có thể. Cũng tuyệt vời.
Tuy nhiên, có một trường hợp cạnh. Nếu bạn kéo từ máy chủ và đẩy bản cập nhật vào ContentProvider
, nó sẽ gọi notifyChange()
và android sẽ kêu , "Ồ, những thay đổi trong cơ sở dữ liệu, tốt hơn là hãy đưa chúng vào máy chủ!" (Doh!) Được viết tốt ContentProviders
sẽ có một số bài kiểm tra để xem liệu các thay đổi đến từ mạng hay từ người dùng và sẽ đặt syncToNetwork
cờ boolean là false nếu vậy, để ngăn chặn đồng bộ kép lãng phí này. Nếu bạn đang cung cấp dữ liệu vào a ContentProvider
, bạn phải tìm cách làm cho điều này hoạt động - Nếu không, bạn sẽ luôn thực hiện đồng bộ hóa hai lần khi chỉ cần một lần đồng bộ.
8. Cảm thấy hạnh phúc!
Khi bạn có tất cả siêu dữ liệu xml này và đồng bộ hóa được bật, Android sẽ biết cách kết nối mọi thứ cho bạn và đồng bộ hóa sẽ bắt đầu hoạt động. Tại thời điểm này, rất nhiều thứ tốt đẹp sẽ chỉ cần nhấp vào vị trí và nó sẽ cảm thấy rất giống như ma thuật. Thưởng thức!