简体   繁体   English

同步适配器未运行

[英]Sync Adapter not running

This is my first time creating a Sync adapter, and i'm having issues, I followed the tutorial on the Android Developer site, https://developer.android.com/training/sync-adapters/creating-sync-adapter.html , but i can't seem to get my Sync to work. 这是我第一次创建Sync适配器,但是遇到了问题,我按照Android Developer网站https://developer.android.com/training/sync-adapters/creating-sync-adapter.html上的教程进行操作,但我似乎无法使我的同步正常工作。

I know am doing something wrong, but cannot figure it out myself. 我知道自己做错了,但我自己无法解决。

SyncAdapter. 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 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();
    }
}

my MainActivity 我的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 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 / 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"/>

Any help is appreciated, thanks. 任何帮助表示赞赏,谢谢。

You have to add the dummy account in the AccountManager in order to register the SyncAdapter in the framework. 您必须在AccountManager中添加虚拟帐户,以便在框架中注册SyncAdapter。

Just after your new Account(...) , you have to call the following : 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.
         */
    }

Also, don't forget to declare the SyncAdapter in your Manifest with the Sync Adapter MetaData file. 另外,不要忘记在清单中使用Sync Adapter MetaData文件声明SyncAdapter。

Hope this helps. 希望这可以帮助。

First create stub authenticator. 首先创建存根验证器。

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;
}
}

Bind the authenticator to the sync adapter framework using service . 使用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.create a file res/xml/authenticator.xml to add authenticator's metadata file 3.创建一个文件res / xml / authenticator.xml以添加身份验证器的元数据文件

content of authenticator.xml will be like: 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"/>

Now we need to Create a stub content provider Note:If you already have a content provider in your app, you don't need a stub content provider.Since I don't have any valid content provider, and sync adapter framework needs content provider, so creating a stub content provider.If your app doesn't have a content provider, your sync adapter crashes. 现在我们需要创建一个存根内容提供者注意:如果您的应用程序中已经有内容提供者,则不需要存根内容提供者。由于我没有任何有效的内容提供者,因此同步适配器框架需要内容提供者,因此请创建一个存根内容提供程序。如果您的应用没有内容提供程序,则同步适配器会崩溃。 1.Add a stub content provider 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.Declare the provider in the manifest: 2.在清单中声明提供者:

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

    </provider>

Create a sync adapter 1.create a sync adapter class: 创建同步适配器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.Bind the sync adapter to the sync adapter framework using service 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.now Add the sync adapter metadata file (res/xml/syncadapter.xml) 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.Declare the sync adapter in the manifest 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.Add the account required by the sync adapter framework 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;
}


}

note: Now run your application. 注意:现在运行您的应用程序。 Now go to setting, and search account.. click users &accounts. 现在转到设置,然后搜索帐户。.单击用户和帐户。 Here your dummy_account should be listed.Click dummy_account->account sync->sync now. 这里将列出您的dummy_account。单击dummy_account->帐户同步->立即同步。

sync adapter's onPerformSync will be called. 同步适配器的onPerformSync将被调用。

Now you should call ContentResolver.requestSync(mAccount, AUTHORITY, new Bundle()); 现在您应该调用ContentResolver.requestSync(mAccount,AUTHORITY,new Bundle()); as per your requirement. 根据您的要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM