簡體   English   中英

同步適配器未運行

[英]Sync Adapter not running

這是我第一次創建Sync適配器,但是遇到了問題,我按照Android Developer網站https://developer.android.com/training/sync-adapters/creating-sync-adapter.html上的教程進行操作,但我似乎無法使我的同步正常工作。

我知道自己做錯了,但我自己無法解決。

SyncAdapter。

    public class SyncAdapter extends AbstractThreadedSyncAdapter {
        // Global variables
        // Define a variable to contain a content resolver instance
        ContentResolver mContentResolver;

        /**
         * Set up the sync adapter
         */
        public SyncAdapter(Context context, boolean autoInitialize) {
            super(context, autoInitialize);
            /*
             * If your app uses a content resolver, get an instance of it
             * from the incoming Context
             */
            mContentResolver = context.getContentResolver();
        }

        /**
         * Set up the sync adapter. This form of the
         * constructor maintains compatibility with Android 3.0
         * and later platform versions
         */
        public SyncAdapter(
                Context context,
                boolean autoInitialize,
                boolean allowParallelSyncs) {
            super(context, autoInitialize, allowParallelSyncs);
            /*
             * If your app uses a content resolver, get an instance of it
             * from the incoming Context
             */
            mContentResolver = context.getContentResolver();

        }

        public void onPerformSync(
                Account account,
                Bundle extras,
                String authority,
                ContentProviderClient provider,
                SyncResult syncResult) {
        /*
         * Put the data transfer code here.
         */
            Log.d("Message: ", "Perform Sync Call");
            new JSONAsyncTask().execute("http://example.com?category=1");



        }
}

SyncService

public class SyncService extends Service {
    // Storage for an instance of the sync adapter
    private static SyncAdapter sSyncAdapter = null;
    // Object to use as a thread-safe lock
    private static final Object sSyncAdapterLock = new Object();
    /*
     * Instantiate the sync adapter object.
     */
    @Override
    public void onCreate() {
        /*
         * Create the sync adapter as a singleton.
         * Set the sync adapter as syncable
         * Disallow parallel syncs
         */
        synchronized (sSyncAdapterLock) {
            if (sSyncAdapter == null) {
                sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
            }
        }
    }
    /**
     * Return an object that allows the system to invoke
     * the sync adapter.
     *
     */
    @Override
    public IBinder onBind(Intent intent) {
        /*
         * Get the object that allows external processes
         * to call onPerformSync(). The object is created
         * in the base class code when the SyncAdapter
         * constructors call super()
         */
        return sSyncAdapter.getSyncAdapterBinder();
    }
}

我的MainActivity

public class MainActivity extends AppCompatActivity{

    int id = 0;
    public static String CONNECTION_STATUS="";
    String TAG ="Message: ";


    /** Sync adapter code **/
    // Constants
    // The authority for the sync adapter's content provider
    public static final String AUTHORITY = "com.example.tech6.sampleapp.contentprovider";
    // An account type, in the form of a domain name
    public static final String ACCOUNT_TYPE = "com.android.example.sampleapp";
    // The account name
    public static final String ACCOUNT = "dummyaccount";
    // Instance fields
    Account mAccount;
    ContentResolver mResolver;


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_movies);

        // Set the menu icon instead of the launcher icon.
        final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);


        ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService(getApplicationContext().CONNECTIVITY_SERVICE);
        NetworkInfo ni = cm.getActiveNetworkInfo();
        /** Check if connected, then Sync **/
        if (ni != null) {
        Account mAccount = new Account(
                           ACCOUNT, ACCOUNT_TYPE);
        Bundle extras = new Bundle();
        mResolver.setIsSyncable(mAccount, AUTHORITY, 1);
        mResolver.setSyncAutomatically(mAccount, AUTHORITY, true);
        mResolver.requestSync(mAccount, AUTHORITY, extras);
        }



    }

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Base.Theme.DesignDemo" >
    <activity
        android:name=".activity.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    <provider
        android:name=".contentprovider.CinemalistingContentProvider"
        android:authorities="com.example.tech6.providersample.contentprovider" >
    </provider>

AndroidManifest.xml中

<service
                android:name=".helpers.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/sync_adapter" />
            </service>

        </application>

    </manifest>

XML / sync_adapter.xml

<?xml version="1.0" encoding="utf-8"?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.example.tech6.sampleapp.contentprovider"
android:accountType="com.android.example.sampleapp"
android:userVisible="true"
android:supportsUploading="true"
android:allowParallelSyncs="true"
android:isAlwaysSyncable="true"/>

任何幫助表示贊賞,謝謝。

您必須在AccountManager中添加虛擬帳戶,以便在框架中注冊SyncAdapter。

new Account(...) ,您必須撥打以下電話:

    // Get an instance of the Android account manager
    AccountManager accountManager =
            (AccountManager) context.getSystemService(
                    ACCOUNT_SERVICE);
    /*
     * Add the account and account type, no password or user data
     * If successful, return the Account object, otherwise report an error.
     */
    if (accountManager.addAccountExplicitly(mAccount, null, null))) {
        /*
         * If you don't set android:syncable="true" in
         * in your <provider> element in the manifest,
         * then call context.setIsSyncable(account, AUTHORITY, 1)
         * here. 
         */
        Bundle extras = new Bundle();
        mResolver.setIsSyncable(mAccount, AUTHORITY, 1);
        mResolver.setSyncAutomatically(mAccount, AUTHORITY, true);
        mResolver.requestSync(mAccount, AUTHORITY, extras);
    } else {
        /*
         * The account exists or some other error occurred. Log this, report it,
         * or handle it internally.
         */
    }

另外,不要忘記在清單中使用Sync Adapter MetaData文件聲明SyncAdapter。

希望這可以幫助。

首先創建存根驗證器。

public class Authenticator extends AbstractAccountAuthenticator {
public Authenticator(Context context) {
    super(context);
}

@Override
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
    return null;
}

@Override
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException {
    return null;
}

@Override
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options) throws NetworkErrorException {
    return null;
}

@Override
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
    return null;
}

@Override
public String getAuthTokenLabel(String authTokenType) {
    return null;
}

@Override
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException {
    return null;
}

@Override
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features) throws NetworkErrorException {
    return null;
}
}

使用service將身份驗證器綁定到同步適配器框架。

public class AuthenticatorService extends Service {

// Instance field that stores the authenticator object
private Authenticator mAuthenticator;
@Override
public void onCreate() {
    // Create a new authenticator object
    mAuthenticator = new Authenticator(this);
}

 /*
 * When the system binds to this Service to make the RPC call
 * return the authenticator's IBinder.
 */

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return mAuthenticator.getIBinder();
}
}

3.創建一個文件res / xml / authenticator.xml以添加身份驗證器的元數據文件

authenticator.xml的內容將類似於:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="client.example.com"
android:icon="@mipmap/ic_launcher"
android:smallIcon="@mipmap/ic_launcher"
android:label="@string/app_name"/>

現在我們需要創建一個存根內容提供者注意:如果您的應用程序中已經有內容提供者,則不需要存根內容提供者。由於我沒有任何有效的內容提供者,因此同步適配器框架需要內容提供者,因此請創建一個存根內容提供程序。如果您的應用沒有內容提供程序,則同步適配器會崩潰。 1.添加存根內容提供商

public class StubProvider extends ContentProvider{

@Override
public boolean onCreate() {
    return false;
}

@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
    return null;
}

@Nullable
@Override
public String getType(@NonNull Uri uri) {
    return null;
}

@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
    return null;
}

@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
    return 0;
}

@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
    return 0;
}
}

2.在清單中聲明提供者:

<provider
        android:authorities="app_package.provider"
        android:name=".StubProvider"
        android:exported="false"
        android:syncable="true">

    </provider>

創建同步適配器1.創建一個同步適配器類:

public class SyncAdapter extends AbstractThreadedSyncAdapter {

private static final String TAG = SyncAdapter.class.getSimpleName();
// Global variables
// Define a variable to contain a content resolver instance
ContentResolver mContentResolver;

/**
 * Set up the sync adapter
 */
public SyncAdapter(Context context, boolean autoInitialize) {
    super(context, autoInitialize);
    /*
     * If your app uses a content resolver, get an instance of it
     * from the incoming Context
     */
    mContentResolver = context.getContentResolver();
    Log.d(TAG, "SyncAdapter:  ctr");
}

/**
 * Set up the sync adapter. This form of the
 * constructor maintains compatibility with Android 3.0
 * and later platform versions
 */
public SyncAdapter(
        Context context,
        boolean autoInitialize,
        boolean allowParallelSyncs) {
    super(context, autoInitialize, allowParallelSyncs);
    /*
     * If your app uses a content resolver, get an instance of it
     * from the incoming Context
     */
    mContentResolver = context.getContentResolver();
    Log.d(TAG, "SyncAdapter:  ctr");
}

/*
* Specify the code you want to run in the sync adapter. The entire
* sync adapter runs in a background thread, so you don't have to set
* up your own background processing.
*/
@Override
public void onPerformSync(Account account, Bundle extras, String authority,
                          ContentProviderClient provider, SyncResult syncResult) {
    Log.d(TAG, "onPerformSync:  + called");
   // here write your logic, what exactly you want to sync
}
}

2.使用服務將同步適配器綁定到同步適配器框架

public class SyncService extends Service {
// Storage for an instance of the sync adapter
private static SyncAdapter sSyncAdapter = null;
// Object to use as a thread-safe lock
private static final Object sSyncAdapterLock = new Object();

@Override
public void onCreate() {
    /*
     * Create the sync adapter as a singleton.
     * Set the sync adapter as syncable
     * Disallow parallel syncs
     */
    synchronized (sSyncAdapterLock) {
        if (sSyncAdapter == null) {
            sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
        }
    }
}

/**
 * Return an object that allows the system to invoke
 * the sync adapter.
 *
 */
@Nullable
@Override
public IBinder onBind(Intent intent) {
    /*
     * Get the object that allows external processes
     * to call onPerformSync(). The object is created
     * in the base class code when the SyncAdapter
     * constructors call super()
     */
    return sSyncAdapter.getSyncAdapterBinder();
}
}

3.現在添加同步適配器元數據文件(res / xml / syncadapter.xml)

<?xml version="1.0" encoding="utf-8"?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="app_package.provider"
android:accountType="client.example.com"
android:userVisible="false"
android:supportsUploading="false"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"/>

4.在清單中聲明同步適配器

<service
        android:name=".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>

5,添加同步適配器框架所需的帳戶

public class MainActivity extends FragmentActivity{

   // Constants
// The authority for the sync adapter's content provider
public static final String AUTHORITY = "app_package.provider";
// An account type, in the form of a domain name
public static final String ACCOUNT_TYPE = "client.example.com";
// The account name
public static final String ACCOUNT = "dummy_account";
// Instance fields
public  Account mAccount;
 @Override
protected void onCreate(Bundle savedInstanceState) {
  mAccount = CreateSyncAccount(this);
}


public static Account CreateSyncAccount(Context context) {
    // Create the account type and default account
    Account newAccount = new Account(
            ACCOUNT, ACCOUNT_TYPE);
    // Get an instance of the Android account manager
    AccountManager accountManager =
            (AccountManager) context.getSystemService(
                    ACCOUNT_SERVICE);
    /*
     * Add the account and account type, no password or user data
     * If successful, return the Account object, otherwise report an error.
     */
    accountManager.removeAccountExplicitly(newAccount);
    if (accountManager.addAccountExplicitly(newAccount, null, null)) {
        /*
         * If you don't set android:syncable="true" in
         * in your <provider> element in the manifest,
         * then call context.setIsSyncable(account, AUTHORITY, 1)
         * here.
         */
        Log.d(TAG, "*******CreateSyncAccount: successful ");
        ContentResolver.setSyncAutomatically(newAccount, AUTHORITY, true);
    } else {
        /*
         * The account exists or some other error occurred. Log this, report it,
         * or handle it internally.
         */
        Log.d(TAG, "*******CreateSyncAccount: error occured ");
    }
    return newAccount;
}


}

注意:現在運行您的應用程序。 現在轉到設置,然后搜索帳戶。.單擊用戶和帳戶。 這里將列出您的dummy_account。單擊dummy_account->帳戶同步->立即同步。

同步適配器的onPerformSync將被調用。

現在您應該調用ContentResolver.requestSync(mAccount,AUTHORITY,new Bundle()); 根據您的要求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM