11

私はsyncAdapterがどのように機能するかを理解しようとしています.sampleSyncアダプタを例/出発点として使用し、それに基づいて最初のテストを行いました. 唯一の違いは、デフォルトの連絡先プロバイダーを使用していないことですが、独自の連絡先プロバイダーが必要です。

このメソッドは、sampleSyncAdapter デモ (AccountAuthenticatorActivity 内) と同じです。定期的な同期を追加しただけです。

    public void finishLogin(String authToken) {
    Log.i(TAG, "finishLogin()");
    final Account account = new Account(mUsername, "be.company.syncAdapterTest");
    if(mRequestNewAccount) {
        mAccountManager.addAccountExplicitly(account, mPassword, null);
        ContentResolver.setIsSyncable(account, MY_AUTHORITY, 1);

        Bundle params = new Bundle();
        params.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
        params.putBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false);
        params.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);           
        ContentResolver.addPeriodicSync(account, MY_AUTHORITY, params, 30);
        ContentResolver.setSyncAutomatically(account, MY_AUTHORITY, true);
        ContentResolver.requestSync(account,MY_AUTHORITY,params);
    } else {
        mAccountManager.setPassword(account, mPassword);
    }
    final Intent intent = new Intent();
    intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, "ACCOUNT_TEST");
    intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, "be.company.syncAdapterTest");
    setAccountAuthenticatorResult(intent.getExtras());
    setResult(RESULT_OK, intent);
    finish();
}

perfomSync() メソッドには、次のメソッドがあります。

    @Override
public void onPerformSync(Account account, Bundle extras, String authority,
        ContentProviderClient provider, SyncResult syncResult) {
    Log.d(TAG, "onPerformSync() start");
    // Testje
    try {
        final String authToken = mAccountManager.blockingGetAuthToken(account, "be.company.syncAdapterTest", NOTIFY_AUTH_FAILURE);
        Log.d(TAG, SAPNetworkUtilities.getWeek(account, authToken, getRandomDate()));
    } catch (OperationCanceledException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (AuthenticatorException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    Log.d(TAG, "onPerformSync() end");
}

ここでは、単純な SAP Web サービスを呼び出してログに表示するだけです。今、私は次の2つの質問があります:

  1. 設定でアカウントを追加しても、同期が自動的に開始されません。同期を開始するには、アカウント内に移動してチェックボックスをオンにする必要がありますか?
  2. この例では、同期は 30 秒ごとにトリガーされません... 同期が完了し、次の実行を開始できることをシステムに知らせるために、perfomSync() メソッドに何かを追加する必要がありますか?

現時点では、同期がどのように機能するかを詳細に把握しようとしているという理由だけで、contentProvider に値を書き込みません。

現在、私は Android エミュレーターでテストしています。

フィードバックをお寄せいただきありがとうございます。

敬具、

ロビン

4

7 に答える 7

13

また、同期アダプターとの定期的な同期にも苦労していました。requestSync を使用して SyncAdapter を手動で起動できましたが、addPeriodicSync は起動しませんでした。

すべての例で、Settings->Accounts に移動すると、SyncAdapter のアカウントに小さな「同期ホイール」(正常に同期している場合は通常緑色、最近同期に失敗した場合は赤色) と「Last Synced」タイムスタンプが表示されていることに気付きました。 . 私のアカウント ( Google Docsからコピーして貼り付けたダミー アカウント) には、同期ホイールやタイムスタンプのようなものがリストされていませんでした。

さらに掘り下げると、何が問題であるかが明らかになりました。コンテンツ プロバイダーの XML にラベルがありませんでした (以前は問題なく使用していたので、ドキュメントのその部分に目を通しました)。コンテンツ プロバイダーに単純なラベルを追加すると、[設定] のアカウントの下に同期ホイールとタイムスタンプと共に表示されるようになりました。

インスピレーションのために私のアプリから抜粋したコードを次に示します。うまくいけば、それはどこかで誰かを助けるでしょう!

/res/xml/sync_adapter.xml

<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.example.database"
android:allowParallelSyncs="false"
android:contentAuthority="com.example.database.data.provider"
android:isAlwaysSyncable="true"
android:supportsUploading="false"
android:userVisible="true" />

/com/example/database/data/MySyncAdapter

public class MySyncAdapter extends AbstractThreadedSyncAdapter {
    private static final String TAG = MySyncAdapter.class.getSimpleName();
    Context context;

    public MySyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
        this.context = context;
    }

    public MySyncAdapter(Context context, boolean autoInitialize, boolean allowParallelSyncs) {
        super(context, autoInitialize, allowParallelSyncs);
        this.context = context;
    }

    @Override
    public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
        Log.e(TAG, "Performing Sync");
    }
}

AndroidManifest.xml (アカウントに表示されるコンテンツ プロバイダーのラベルが必要)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.database">

    <uses-sdk tools:node="replace" />

    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="18" />

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
    <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.READ_SYNC_STATS" />


    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:logo="@drawable/chef_collection_logo_white"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <provider
            android:name="com.example.database.data.MyContentProvider"
            android:authorities="com.example.database.data.provider"
            android:label="my provider"
            android:exported="false"
            android:multiprocess="true"
            android:syncable="true" />

        <activity
            android:name=".app.MainActivity"
            android:label="@string/title_activity_main">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name="com.example.database.data.AuthenticatorService"
            android:exported="true"
            android:process=":auth">
            <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.example.database.data.MySyncAdapterService"
            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/sync_adapter" />
        </service>

    </application>

</manifest>

主な活動。このコードは、セットアップ ウィザードの初回実行後に呼び出しますが、どこでも呼び出すことができます。これにより、 30 秒ごとに同期が試行されます (テストに使用)。秒ではなくミリ秒が必要であると述べているため、これに関する Google ドキュメントは現在間違っていることに注意してください。もう 1 つの注意点は、null をバンドルとして渡すことができないことです。これを行うと、IllegalArgumentException などをスローします。

//Create Account
mAccount = createSyncAccount(this);


//Turn on periodic syncing
ContentResolver resolver = getContentResolver();
resolver.setIsSyncable(mAccount, AUTHORITY, 1);
resolver.setSyncAutomatically(mAccount, AUTHORITY, true);

resolver.addPeriodicSync(
        mAccount,
        AUTHORITY,
        Bundle.EMPTY,
        30);
于 2014-10-08T19:35:16.683 に答える
5

定期的な同期が機能しない理由を突き止めようとして、何時間も頭を壁にぶつけました。ポーリング頻度は、ミリ秒単位ではなく秒単位 (リテラル) である必要があり、ミリ秒単位ではありません。したがって、たとえば、1 分半ごとに同期する場合は、次のように呼び出す必要があります。

            ContentResolver.addPeriodicSync(
                    account,
                    authority,
                    Bundle.EMPTY,
                    90
            );

また、ドキュメントにあるように、渡されたバンドルを null にすることはできず、NullPointerException がスローされます。

于 2014-07-25T16:09:07.430 に答える