[英]ContentResolver.requestSync in Sync Adapter is not working in Android
我正在嘗試使用“StubProvider”和“StubAuthenticator”編寫同步適配器,我遵循了官方指南,我的代碼運行沒有任何錯誤,但沒有調用“onPerformSync()”,我嘗試了所有方法但沒有用。
我的完整項目可以從https://www.dropbox.com/s/48bgj3wweehaieu/MyApplication.zip?dl=0下載
以下是我正在使用的課程:
類 MainActivity
public class MainActivity extends FragmentActivity implements View.OnClickListener {
// Constants
// The authority for the sync adapter's content provider
public static final String AUTHORITY = "com.syncadaptertest.StubProvider";
// An account type, in the form of a domain name
public static final String ACCOUNT_TYPE = "com.syncadaptertest";
// The account name
public static final String ACCOUNT = "dummyaccount";
// Instance fields
Account mAccount;
private ImageButton mRefreshBtn = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRefreshBtn = (ImageButton) findViewById(R.id.refreshBtn);
mRefreshBtn.setOnClickListener(this);
// Create the dummy account
mAccount = CreateSyncAccount(this);
}
/**
* Create a new dummy account for the sync adapter
*
* @param context The application context
*/
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.
*/
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.
*/
} else {
/*
* The account exists or some other error occurred. Log this, report it,
* or handle it internally.
*/
}
return newAccount;
}
@Override
public void onClick(View v){
onRefreshButtonClick(v);
}
/**
* Respond to a button click by calling requestSync(). This is an
* asynchronous operation.
*
* This method is attached to the refresh button in the layout
* XML file
*
* @param v The View associated with the method call,
* in this case a Button
*/
public void onRefreshButtonClick(View v) {
// Pass the settings flags by inserting them in a bundle
Bundle settingsBundle = new Bundle();
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
/*
* Request the sync for the default account, authority, and
* manual sync settings
*/
ContentResolver.setIsSyncable(mAccount, AUTHORITY, 1);
ContentResolver.requestSync(mAccount, AUTHORITY, settingsBundle);
if(ContentResolver.isSyncActive(mAccount, AUTHORITY))
{
Log.d("testing1","testttt");
}
if(ContentResolver.isSyncPending(mAccount, AUTHORITY))
{
Log.d("testing2","testttt2");
}
List<SyncInfo> myList = ContentResolver.getCurrentSyncs();
}
}
存根驗證器類
public class Authenticator extends AbstractAccountAuthenticator {
// Simple constructor
public Authenticator(Context context) {
super(context);
}
// Editing properties is not supported
@Override
public Bundle editProperties(
AccountAuthenticatorResponse r, String s) {
throw new UnsupportedOperationException();
}
// Don't add additional accounts
@Override
public Bundle addAccount(
AccountAuthenticatorResponse r,
String s,
String s2,
String[] strings,
Bundle bundle) throws NetworkErrorException {
return null;
}
// Ignore attempts to confirm credentials
@Override
public Bundle confirmCredentials(
AccountAuthenticatorResponse r,
Account account,
Bundle bundle) throws NetworkErrorException {
return null;
}
// Getting an authentication token is not supported
@Override
public Bundle getAuthToken(
AccountAuthenticatorResponse r,
Account account,
String s,
Bundle bundle) throws NetworkErrorException {
throw new UnsupportedOperationException();
}
// Getting a label for the auth token is not supported
@Override
public String getAuthTokenLabel(String s) {
throw new UnsupportedOperationException();
}
// Updating user credentials is not supported
@Override
public Bundle updateCredentials(
AccountAuthenticatorResponse r,
Account account,
String s, Bundle bundle) throws NetworkErrorException {
throw new UnsupportedOperationException();
}
// Checking features for the account is not supported
@Override
public Bundle hasFeatures(
AccountAuthenticatorResponse r,
Account account, String[] strings) throws NetworkErrorException {
throw new UnsupportedOperationException();
}
}
類 AuthenticatorService
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.
*/
@Override
public IBinder onBind(Intent intent) {
return mAuthenticator.getIBinder();
}
}
類同步服務
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();
}
}
類 StubProvider
public class StubProvider extends ContentProvider {
/*
* Always return true, indicating that the
* provider loaded correctly.
*/
@Override
public boolean onCreate() {
return true;
}
/*
* Return no type for MIME type
*/
@Override
public String getType(Uri uri) {
return null;
}
/*
* query() always returns no results
*
*/
@Override
public Cursor query(
Uri uri,
String[] projection,
String selection,
String[] selectionArgs,
String sortOrder) {
return null;
}
/*
* insert() always returns null (no URI)
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
/*
* delete() always returns "no rows affected" (0)
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
/*
* update() always returns "no rows affected" (0)
*/
public int update(
Uri uri,
ContentValues values,
String selection,
String[] selectionArgs) {
return 0;
}
}
類同步適配器
public class SyncAdapter extends AbstractThreadedSyncAdapter {
private final AccountManager mAccountManager;
public SyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
mAccountManager = AccountManager.get(context);
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
Log.d("udinic", "onPerformSync for account[" + account.name + "]");
try {
// TODO Updating local tv shows
} catch (Exception e) {
e.printStackTrace();
}
}
}
你確定它不起作用?
請記住,同步適配器運行在不在同一進程中的綁定服務上,因此 onPerformSync() 中的 Log.d() 不會顯示在應用主進程下的 LogCat 中,而是顯示在同步適配器正在使用的進程中.
嘗試刪除 LogCat 中的過濾器:選擇“無過濾器”而不是“僅顯示選定的應用程序”。
您是否在同步適配器的元數據 xml 上指定了您的 account_type?
你的 xml 描述符應該是這樣的
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="com.android.contacts"
android:accountType="com.syncadaptertest"
android:userVisible="true"
android:supportsUploading="false"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"/>
最重要的是它應該在你的 AndroidManifest 文件中聲明
<service
android:name=".sync.ContactSyncService"
android:exported="true">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/sync_contact" />
</service>
從 android 清單中刪除 android:process=":sync"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.