我正在尝试通过电话号码将我的Firestore用户与用户“联系人”同步。 由于解析电话号码并与db匹配的过程需要时间(仅3个用户大约需要20秒),并且由于该应用程序也应该脱机工作,即在应用程序不活动时进行同步,因此似乎我需要使用SyncAdapter,但这非常复杂。
我主要(不仅是)关注了下一个教程:
https://developer.android.com/training/sync-adapters
我最初的困境是:
我是否仍需要创建Stub-Provider或可以使用android Contacts?如果是这样,如何在清单中定义它?
联系人更改时如何触发syncAdapter?
在这段代码中,我离开了Stub Provider,并试图通过创建观察者来触发syncadapter,但是我可以看到吐司消息“ Contacts Changed!”。 (例如删除联系人)仅在应用程序处于活动状态时。如果我关闭了该应用程序,则看不到吐司。我不确定这是因为Toast没有上下文,还是因为观察者没有激活。
public class MainActivity extends AppCompatActivity {
private static final String TAG = "[MainActivity]: ";
private Context mContext = this;
Account mAccount;
public class TableObserver extends ContentObserver {
public TableObserver(Handler handler) {
super( handler );
}
@Override
public void onChange(boolean selfChange) {
runOnUiThread( new Runnable() {
@Override
public void run() {
Toast.makeText( mContext, "Contacts Changed!-1", Toast.LENGTH_SHORT ).show();
}
} );
onChange(selfChange, null);
}
@Override
public void onChange(boolean selfChange, Uri changeUri) {
runOnUiThread( new Runnable() {
@Override
public void run() {
Toast.makeText( mContext, "Contacts Changed!-2", Toast.LENGTH_SHORT ).show();
}
} );
ContentResolver.requestSync(mAccount, Constants.AUTHORITY, null);
}
@Override
public boolean deliverSelfNotifications() {
return true;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
// Create the dummy account
mAccount = CreateSyncAccount(this);
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true,
new TableObserver(null));
}
public static Account CreateSyncAccount(Context context) {
Account newAccount = new Account(
Constants.ACCOUNT, Constants.ACCOUNT_TYPE);
AccountManager accountManager =
(AccountManager) context.getSystemService(
ACCOUNT_SERVICE);
if (accountManager.addAccountExplicitly(newAccount, null, null)) {
Toast.makeText( context, "i think account created successful", Toast.LENGTH_SHORT ).show();
return newAccount;
} else {
Toast.makeText( context, "some error in account creation", Toast.LENGTH_SHORT ).show();
//TODO: handle errors
return newAccount;
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ranslist.android.ranslist">
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
....
<provider
android:name=".sync.StubProvider"
android:authorities="com.ranslist.android.ranslist.provider"
android:exported="false"
android:syncable="true"/>
<service android:name=".sync.AuthenticationService" >
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
</service>
<service
android:name=".sync.SyncService"
android:exported="true"
android:process=":sync">
<intent-filter>
<action android:name="android.content.SyncAdapter"/>
</intent-filter>
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
...
<service
android:name="com.google.android.gms.measurement.AppMeasurementJobService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
....
</application>
</manifest>
authenticator.xml
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="example.com"
android:icon="@drawable/ic_launcher_foreground"
android:smallIcon="@drawable/ic_launcher_foreground"
android:label="@string/app_name"/>
syncadapter.xml
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="example.com"
android:userVisible="false"
android:supportsUploading="false"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="false"/>
常量
public class Constants {
public static final String AUTHORITY = "com.example.android.datasync.provider";
public static final String ACCOUNT_TYPE = "example.com";
public static final String ACCOUNT = "dummyaccount";
}