呼び出す requestSync()
は、システムに認識されている{アカウント、ContentAuthority}ペアでのみ機能します。特定の種類のアカウントを使用して特定の種類のコンテンツを同期できることをAndroidに伝えるには、アプリでいくつかの手順を実行する必要があります。AndroidManifestでこれを行います。
1.アプリケーションパッケージが同期を提供することをAndroidに通知する
まず、AndroidManifest.xmlで、同期サービスがあることを宣言する必要があります。
<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>
<service>
タグのname属性は、同期を接続するクラスの名前です...これについては後で説明します。
export trueを設定すると、他のコンポーネントから見えるようになります(必要なため、ContentResolver
呼び出すことができます)。
インテントフィルターを使用すると、同期をリクエストするインテントをキャッチできます。(このIntent
はContentResolver
あなたが電話したときから来ますContentResolver.requestSync()
または関連するスケジューリングメソッド取得されます。)
の <meta-data>
タグは、以下に説明します。
2. AndroidにSyncAdapterを見つけるために使用するサービスを提供します
クラス自体...これが例です:
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();
}
}
クラスは、Service
またはそのサブクラスの1つを拡張して実装しpublic IBinder onBind(Intent)
、SyncAdapterBinder
それが呼び出されたときにを返す必要があります...タイプの変数が必要AbstractThreadedSyncAdapter
です。ご覧のとおり、それはそのクラスのほとんどすべてです。それが存在する唯一の理由は、サービスを提供することです。これは、Androidがクラスについてクエリするための標準インターフェイスを提供します。SyncAdapter
自身がことです。
3.提供する class SyncAdapter
実際に同期を実行ためにをます。
mySyncAdapterは、実際の同期ロジック自体が格納される場所です。そのonPerformSync()
メソッドは、同期するときに呼び出されます。私はあなたがすでにこれを配置していると思います。
4.アカウントタイプとコンテンツ機関間のバインディングを確立する
AndroidManifestをもう一度振り返ってみる<meta-data>
と、サービス内のその奇妙なタグが、ContentAuthorityとアカウント間のバインディングを確立する重要な要素です。外部から別のxmlファイルを参照します(好きなように、アプリに関連する何かを呼び出します)。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" />
さて、これは何をしますか?これは、Androidに、定義した同期アダプター(の名前要素で呼び出されたクラス)を通知します。<service>
を含むタグの通知します<meta-data>
このファイルを参照)がcom.googleスタイルのアカウントを使用して連絡先を同期する通知します。
すべてのcontentAuthority文字列はすべて一致し、同期しているものと一致する必要があります-これは、独自のデータベースを作成している場合は定義した文字列であるか、既知の同期している場合はいくつかの既存のデバイス文字列を使用する必要がありますデータタイプ(連絡先やカレンダーのイベントなど)。上記(「com.android.contacts」)は、たまたま連絡先タイプのデータのContentAuthority文字列です(驚き、驚き)。
accountTypeは、すでに入力されている既知のアカウントタイプのいずれかと一致する必要があります。または、作成中のアカウントタイプと一致する必要があります(これには、サーバーで認証を取得するためのAccountAuthenticatorのサブクラスの作成が含まれます...記事自体に価値があります)。繰り返しになりますが、「com.google」は、定義された文字列を識別する... google.comスタイルのアカウント認証情報です(これも驚きではありません)。
5.指定されたアカウントとContentAuthorityのペアで同期を有効にします
最後に、同期を有効にする必要があります。これを行うには、コントロールパネルの[アカウントと同期]ページで、アプリに移動し、一致するアカウント内のアプリの横にあるチェックボックスをオンにします。または、アプリのいくつかのセットアップコードで行うこともできます。
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
同期が発生するために、アカウント/権限のペアは同期に有効にする必要があります(上記のような)と、システムの全体的なグローバル同期フラグがセットでなければならない、とデバイスがネットワーク接続を持っている必要があります。
アカウント/権限の同期またはグローバル同期が無効になっている場合、RequestSync()を呼び出すと効果があります-同期が要求されたことを示すフラグが設定され、同期が有効になるとすぐに実行されます。
また、mgvあたり、設定ContentResolver.SYNC_EXTRAS_MANUAL
に、requestSyncのextrasバンドルでtrueにすると、グローバル同期がオフの場合でもAndroidに同期を強制するように要求します(ここでユーザーに注意してください!)
最後に、ContentResolver関数を使用して、定期的にスケジュールされた同期をセットアップできます。
6.複数のアカウントの影響を考慮する
同じタイプのアカウントを複数持つことができます(1つのデバイスに2つの@ gmail.comアカウントが設定されているか、2つのFacebookアカウント、または2つのTwitterアカウントなど)。アプリケーションの影響を考慮する必要があります。 .. 2つのアカウントがある場合、両方を同じデータベーステーブルに同期しようとは思わないでしょう。一度にアクティブにできるのは1つだけであることを指定し、アカウントを切り替えた場合はテーブルをフラッシュして再同期する必要があるかもしれません。(存在するアカウントを照会するプロパティページを介して)。たぶん、アカウントごとに異なるデータベースを作成したり、異なるテーブルを作成したり、各テーブルのキー列を作成したりできます。すべてのアプリケーション固有で、いくつかの検討に値します。 ContentResolver.setIsSyncable(Account account, String authority, int syncable)
ここで興味深いかもしれません。 setSyncAutomatically()
アカウント/権限ペアがかどうかを制御しますがチェックますかunchecked、setIsSyncable()
ユーザーがオンにできないようにラインのチェックを外して灰色にする方法を提供します。1つのアカウントを同期可能に設定し、もう1つを同期不可能(dsabled)に設定する場合があります。
7. ContentResolver.notifyChange()に注意してください
1つのトリッキーなこと。ローカルデータベースが変更されたことをAndroidに通知するためにsがContentResolver.notifyChange()
使用する関数ContentProvider
です。これは2つの機能を提供します。最初に、そのコンテンツURIに続くカーソルを更新し、次にを再クエリして無効化して再描画しListView
ます。...データベースの変更とListView
です。自動的に更新されます。驚くばかり。また、データベースが変更されると、Androidは通常のスケジュール外であっても同期を要求します。これにより、これらの変更がデバイスから取得され、サーバーにできるだけ迅速に同期されます。また素晴らしい。
ただし、エッジケースが1つあります。サーバーからプルしてアップデートをにプッシュするとContentProvider
、それが忠実に呼び出されnotifyChange()
、Androidは「ああ、データベースの変更、サーバーに配置するほうがいい!」(ドー!)よく書かれているContentProviders
ている場合、変更がネットワークからのものかユーザーからのものかを確認するためのテストがいくつかあり、ブール値syncToNetwork
フラグをfalseに設定して、無駄な二重同期を防止します。データをにフィードする場合ContentProvider
、これを機能させる方法を理解する必要があります。そうしないと、1つだけ必要なときに常に2つの同期を実行することになります。
8.幸せを感じてください。
このすべてのxmlメタデータを配置し、同期を有効にすると、Androidがすべてを接続する方法を認識し、同期が機能するようになります。この時点で、多くの優れた点がクリックされるだけで、まるで魔法のように感じられます。楽しい!