Почему ContentResolver.requestSync не запускает синхронизацию?


Я пытаюсь реализовать шаблон адаптера Content-Provider-Sync, как описано в Google IO слайд 26. Мой контент-провайдер работает, и моя синхронизация работает, когда я запускаю его из приложения Dev Tools Sync Tester, однако когда я вызываю ContentResolver.requestSync (учетная запись, полномочия, пакет) от моего ContentProvider, моя синхронизация никогда не запускается.

ContentResolver.requestSync(
        account, 
        AUTHORITY, 
        new Bundle());

Edit -- добавлен фрагмент манифеста Моего манифеста содержит:

<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, связанный с моей службой синхронизации, содержит:

<?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"
/>

не уверен, что другой код будет полезен. Счет передан requestSync из "myaccounttype" и власть переходила к вызову соответствует моей ЦМИ адаптер с поддержкой XML.

- Это ContentResolver.requestSync правильный способ запроса синхронизации? Похоже, что инструмент sync tester привязывается непосредственно к службе и вызывает start sync, но это похоже, что это нарушает цель интеграции с архитектурой синхронизации.

Если это правильный способ запросить синхронизацию, то почему бы тестер синхронизации работать, но не мой вызов ContentResolver.requestSync? Есть ли что-то, что мне нужно передать в комплекте?

Я тестирую в эмуляторе на устройствах с ОС 2.1 и 2.2.

1 111

1 ответ:

вызов requestSync() будет работать только на паре {Account, 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>

атрибут name элемента <service> тег-это имя класса для подключения синхронизации... Я поговорю с ним через секунду.

установка exported true делает его видимым для других компонентов (необходимо так ContentResolver можно назвать это).

фильтр intent позволяет ему перехватывать запрос на синхронизацию intent. (Это Intent происходит от ContentResolver когда вы называете ContentResolver.requestSync() или связанные методы планирования.)

The <meta-data> тег будет рассматриваемый ниже.

2. Предоставляем только услуги использованы, чтобы найти ваш действие 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 или один из его подклассов, необходимо реализовать public IBinder onBind(Intent), и должен вернуть a SyncAdapterBinder когда это называется... Вам нужна переменная типа AbstractThreadedSyncAdapter. Так что, как вы можете видеть, это почти все в этом классе. Единственная причина, по которой это есть, чтобы предоставить услугу, это предлагает стандартный интерфейс для Android, чтобы запросить ваш класс о том, что ваш есть.

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 должны совпадать и совпадать с тем, что вы синхронизируете-это должна быть строка, которую вы определяете, если вы создаете свою собственную базу данных, или вы должны использовать некоторые существующие строки устройства, если вы синхронизируете известные типы данных (например, контакты или события календаря или что у вас есть.) Выше ("ком.андроид.контакты") оказывается, строка ContentAuthority для данных типа контактов (Сюрприз, сюрприз.)

accountType также должен соответствовать одному из тех известных типов учетных записей, которые уже введены, или он должен соответствовать тому, который вы создаете (это включает в себя создание подкласса AccountAuthenticator для получения auth на вашем сервере... Стоит статья, сама по себе.) Опять же, " com.google " - это определенная строка идентификации... google.com учетные данные учетной записи стиля (опять же, это не должно быть сюрприз.)

5. Включить синхронизацию для данной учетной записи / пары ContentAuthority

наконец, синхронизация должна быть включена. Вы можете сделать это на странице учетные записи и синхронизация на панели управления, перейдя в свое приложение и установив флажок рядом с вашим приложением в соответствующей учетной записи. Кроме того, вы можете сделать это в некотором коде настройки в вашем приложении:

ContentResolver.setSyncAutomatically(account, AUTHORITY, true);

для синхронизации необходимо включить синхронизацию пары учетная запись / полномочия (как показано выше) и общий флаг глобальной синхронизации в системе должен быть установлен,и устройство должно иметь подключение к сети.

если ваша учетная запись / синхронизация полномочий или глобальная синхронизация отключены, вызов RequestSync () имеет эффект-он устанавливает флаг, что синхронизация была запрошена, и будет выполняться, как только синхронизация включена.

кроме того, mgv установка ContentResolver.SYNC_EXTRAS_MANUAL к истине в дополнительном пакете ваших requestSync спросит android для принудительной синхронизации, даже если глобальная синхронизация выключена (уважайте своего пользователя здесь!)

наконец, вы можете настроить периодическую запланированную синхронизацию, снова с функциями ContentResolver.

6. Рассмотрим последствия нескольких учетных записей

можно иметь несколько учетных записей одного типа (два @gmail.com учетные записи, созданные на одном устройстве или двух учетных записях facebook, или двух учетных записях twitter и т. д...) Вы должны рассмотреть прикладные последствия этого... Если у вас есть две учетные записи, вы, вероятно, не хотите пытаться синхронизировать их в одну и ту же таблицу базы данных. Возможно, вам нужно указать, что только один может быть активен одновременно, и очистить таблицы и повторно синхронизировать, если вы переключаете учетные записи. (через страницу свойств, которая запрашивает, какие учетные записи присутствуют). Возможно, вы создаете другую базу данных для каждой учетной записи, возможно, разные таблицы, возможно, ключевой столбец в каждой таблице. Все приложения специфичны и достойны некоторая мысль. ContentResolver.setIsSyncable(Account account, String authority, int syncable) здесь может быть интересно. setSyncAutomatically() определяет, является ли пара учетная запись / полномочия проверил или unchecked, а setIsSyncable() обеспечивает способ снять флажок и серый из линии, так что пользователь не может включить его. Вы можете установить одну учетную запись Syncable, а другую не Syncable (dsabled).

7. Будьте в курсе ContentResolver.notifyChange()

одна хитрая вещь. ContentResolver.notifyChange() функция используется ContentProviders, чтобы уведомить Android, что локальная база данных была изменена. Это выполняет две функции, во-первых, это приведет к тому, что курсоры после этого uri контента будут обновляться, а в свою очередь запрашивать и аннулировать и перерисовывать a ListView и т. д... Это очень волшебно, база данных меняется и ваш ListView просто автоматически обновляет. Потрясающий. Кроме того, при изменении базы данных Android запросит синхронизацию для вас, даже вне вашего обычного расписания, чтобы эти изменения были сняты с устройства и синхронизированы с сервер как можно быстрее. Тоже потрясающе.

есть один крайний случай, хотя. Если вы тянете с сервера, и нажмите Обновление в ContentProvider, он послушно позвонит notifyChange() и android пойдет: "о, изменения в базе данных, лучше поместите их на сервер!"(Ох!) Хорошо написано ContentProviders будет иметь некоторые тесты, чтобы увидеть, если изменения пришли от сети или от пользователя, и определяют логическое syncToNetwork флаг false, если это так, чтобы предотвратить эту расточительную двойную синхронизацию. Если вы подача данных в ContentProvider, вам следует выяснить, как заставить это работать-иначе вы всегда будете выполнять две синхронизации, когда нужен только один.

8. Чувствуйте себя счастливыми!

как только у вас есть все эти метаданные xml на месте, и синхронизация включена, Android будет знать, как подключить все для вас, и синхронизация должна начать работать. В этот момент многие вещи, которые хороши, просто встанут на свои места, и это будет очень похоже на волшебство. Наслаждайтесь!