【问题标题】:SyncAdapter onPerformSync() gets called on emulator but NOT when run on physical deviceSyncAdapter onPerformSync() 在模拟器上被调用,但在物理设备上运行时不会
【发布时间】:2014-03-26 23:37:08
【问题描述】:

我已跟随 Google's tutorial 使用带有 dummyAccount无 ContentProvider 的 SyncAdapter。

本教程非常简单明了,而且我知道为 Account 和 ContentProvider 使用存根的局限性。我实现了它,当在模拟器上运行时,它工作得非常好。我在 Log 中看到了有关何时使用periodicSync(..) 定期调用它以及何时我专门请求使用requestSync(..) 调用它的消息。

这是令人兴奋的部分,当我在我的 BQ 5 HD (Android 4.1.2) 上运行该应用程序时,SyncAdapter 永远不会被调用。如果重新安装了该应用程序,但似乎没有任何反应。我已经为此浪费了数周时间,但我无法弄清楚。

这是我的ma​​nifestFile

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

非常感谢您的输入。

【问题讨论】:

    标签: android-syncadapter


    【解决方案1】:

    感谢你们老忠实的Log.d(...),终于弄清楚出了什么问题。这是一个明确的菜鸟错误,我发布答案是为了防止其他初学者犯同样的错误。

    在我创建并添加 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() 返回与设备关联的所有帐户显然它会在模拟器中运行时返回零,因为模拟器没有任何关联的帐户。所以我认为这样做很省钱。我创建了ACCOUNT_TYPE 类型的帐户,添加它,然后愉快地前进。 (顺便说一句,addPeriodicSyncsetIsSyncablesetSyncAutomatially 之上的原因是为了解决与另一件事有关的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。 我是怎么发现这个的?通过在“设置”>“帐户”下查看我的物理设备的帐户后在日志中打印出我的 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";
    

    希望这有助于避免一些人头疼。

    【讨论】:

      猜你喜欢
      • 2014-12-24
      • 2020-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-17
      • 1970-01-01
      相关资源
      最近更新 更多