호출 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>
<service>
태그 의 이름 속성은 동기화를 연결하는 클래스의 이름입니다. 잠시 후에 이에 대해 설명하겠습니다.
내보내기를 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
또는 하위 클래스 중 하나를 확장해야하며을 구현 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의 추가 번들에서 true로 설정 하면 전역 동기화가 꺼져 있어도 Android에 강제로 동기화하도록 요청합니다 (여기에서 사용자를 존중하십시오!).
마지막으로 ContentResolver 기능을 사용하여 정기적으로 예약 된 동기화를 설정할 수 있습니다.
6. 여러 계정의 의미 고려
동일한 유형의 계정을 두 개 이상 가질 수 있습니다 (하나의 기기에 두 개의 @ gmail.com 계정이 설정되어 있거나 두 개의 페이스 북 계정 또는 두 개의 트위터 계정 등 ...).이를 수행하는 애플리케이션의 의미를 고려해야합니다. .. 두 개의 계정이있는 경우 두 계정을 동일한 데이터베이스 테이블에 동기화하고 싶지 않을 것입니다. 한 번에 하나만 활성화되도록 지정하고 계정을 전환하면 테이블을 비우고 다시 동기화해야 할 수 있습니다. (어떤 계정이 있는지 쿼리하는 속성 페이지를 통해). 각 계정에 대해 다른 데이터베이스를 만들거나 다른 테이블을 만들거나 각 테이블의 키 열을 만들 수 있습니다. 모든 응용 프로그램은 특정하고 생각할만한 가치가 있습니다. ContentResolver.setIsSyncable(Account account, String authority, int syncable)
여기에 관심이있을 수 있습니다. setSyncAutomatically()
제어 계정 / 권한 쌍이되어 있는지 확인 하거나선택하지 않은 반면 setIsSyncable()
해제하고 사용자가 컴퓨터를 켭 할 수 있도록 라인을 회색으로 할 수있는 방법을 제공합니다. 하나의 계정을 동기화 가능으로 설정하고 다른 하나는 동기화 불가능 (dsabled)으로 설정할 수 있습니다.
7. ContentResolver.notifyChange ()에 유의하십시오.
까다로운 한 가지. s가 로컬 데이터베이스가 변경되었음을 Android에 알리는 ContentResolver.notifyChange()
데 사용하는 함수 ContentProvider
입니다. 이것은 두 가지 기능을 제공합니다. 첫째, 해당 콘텐츠 uri를 따르는 커서가 업데이트되고 차례로 다시 쿼리하고 무효화하고 다시 그리는 ListView
등 ... 매우 마술 적이며 데이터베이스가 변경되고 ListView
자동으로 업데이트됩니다. 대박. 또한 데이터베이스가 변경되면 Android는 정상적인 일정을 벗어난 경우에도 동기화를 요청하므로 이러한 변경 사항이 장치에서 제거되고 가능한 한 빨리 서버에 동기화됩니다. 또한 굉장합니다.
하지만 하나의 엣지 케이스가 있습니다. 서버에서 가져 와서에 업데이트를 푸시 ContentProvider
하면 성실하게 전화를 걸고 notifyChange()
Android는 "오, 데이터베이스 변경 사항, 서버에 추가하는 것이 좋습니다!"라고합니다. (Doh!) Well-written ContentProviders
은 변경 사항이 네트워크 또는 사용자로부터 왔는지 확인하기위한 몇 가지 테스트를 거치며, syncToNetwork
그렇다면이 낭비적인 이중 동기화를 방지하기 위해 부울 플래그를 false로 설정합니다 . 에 데이터를 제공하는 ContentProvider
경우이 작업을 수행하는 방법을 알아 내야합니다. 그렇지 않으면 하나만 필요할 때 항상 두 개의 동기화를 수행하게됩니다.
8. 행복하세요!
이 모든 XML 메타 데이터를 제자리에두고 동기화를 활성화하면 Android가 모든 것을 연결하는 방법을 알고 동기화가 작동하기 시작합니다. 이 시점에서 멋진 많은 것들이 제자리에 고정되어 마치 마법처럼 느껴질 것입니다. 즐겨!