我已关注Google's tutorial使用带有 dummyAccount 的SyncAdapter和 no ContentProvider。
本教程非常简单,我知道使用帐户和ContentProvider的存根的限制。我实现了它,当在模拟器上运行时,它工作得非常好。我在日志中看到了periodicSync(..)
定期调用的消息,以及我特意要求requestSync(..)
调用的消息。
这是令人兴奋的部分,当我在我的BQ 5 HD(Android 4.1.2)上运行应用程序时,SyncAdapter 从未调用。如果重新安装了应用程序,但似乎没有发生任何事情。我浪费了几个星期的时间,我无法理解。
这是我的 manifestFile
<?xml version="1.0" encoding="utf-8"?>
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
....Whole bunch of activities...
<provider
android:name="com.sf.app_name.stubs.StubProvider"
android:authorities="com.sf.app_name.provider"
android:exported="false"
android:syncable="true" />
<service android:name="com.sf.app_name.stubs.AuthenticatorService"
android:exported="false">
<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="com.sf.app_name.sync.SyncService"
android:exported="false"
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>
</application>
authenticator.xml
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.sf.app_name"
android:userVisible="false" />
syncadapter.xml
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.sf.app_name.provider"
android:accountType="com.sf.app_name"
android:userVisible="false"
android:supportsUploading="false"
android:allowParallelSyncs="true"
android:isAlwaysSyncable="true"/>
非常感谢输入。
答案 0 :(得分:4)
感谢老忠实的Log.d(...)
,终于找出了什么是错的。这是一个明确的noob错误,我发布了答案,以防止其他初学者犯同样的错误。
在我创建和添加SyncAdapter框架所需的“dummyAccount”的代码中,我执行了以下操作:
Account[] accounts = accountManager.getAccounts();
if(accounts.length == 0){
Account newAccount = new Account(ACCOUNT, ACCOUNT_TYPE);
ContentResolver.setIsSyncable(newAccount, AUTHORITY, 1);
ContentResolver.setSyncAutomatically(newAccount, AUTHORITY, true);
ContentResolver.addPeriodicSync(newAccount, AUTHORITY, new Bundle(), 40l);
accountManager.addAccountExplicitly(newAccount, null, null);
Log.d("serverSync", "ContetResolver set periodic sync");
}
方法getAccounts()
会返回与设备关联的所有帐户。 显然它会在模拟器中运行时返回ZERO,因为模拟器没有任何关联的帐户。所以我认为除此之外要做到这一点。我创建了ACCOUNT_TYPE
类型的帐户添加它,然后快速地沿着我的方向前进。 (顺便说一下,addPeriodicSync
和setIsSyncable
之上setSyncAutomatially
的原因是解决与另一事项有关的problem。
当然,我的APP的SyncAdapter在执行以下操作时被调用:
ContentResolver.requestSync(signedInAccountInstance.getDummyAccount(),
AccountManagerActivity.AUTHORITY, bundle);
他们getDummyAccount(..)
被这样得到了:
Account[] accounts = accountManager.getAccounts();
return accounts[0];
当在实际的物理设备上运行时,我应该已经意识到 getAccounts(..)也会返回(至少)与我的Android设备关联的Gmail帐户。因此当我做的时候
ContentResolver.requestSync(signedInAccountInstance.getDummyAccount(),
AccountManagerActivity.AUTHORITY, bundle);
发送的“dummyAccount”将是Google的AccountType,因此我的应用 SyncAdapter 永远不会被调用。相反,是gmail应用程序的SyncAdapter被我的捆绑调用。 我怎么发现这个?通过在设置&gt;帐户下查看我的物理设备的帐户后在日志中打印出我的dummyAccount,并意识到由于某些原因我在移动设备上执行我的应用程序时,我的Gmail帐户会显示“同步错误”。
第一次做正确的事情可以防止这一切:
Account[] accounts = accountManager.getAccountsByType(ACCOUNT_TYPE);
ACCOUNT_TYPE
是我的应用中使用的静态最终变量。
// An account type, in the form of a domain name
public static final String ACCOUNT_TYPE = "com.sf.app_name";
希望这有助于拯救某些人头痛。