我正在尝试为我的应用实现同步适配器,我遇到了这个问题:
org.xmlpull.v1.XmlPullParserException:没有android.content.SyncAdapter 元数据
由于这个(我希望),我的同步适配器没有调用onPerformSync()。我知道之前曾问过这个问题,但答案对我的情况没有帮助。我必须提到我在谷歌示例中使用StubContentProvider,这里有一些配置文件:
清单:
<service android:name=".sync.AuthenticatorService">
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator" />
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
</service>
<provider
android:name=".sync.StubContentProvider"
android:authorities="${applicationId}.sync.StubContentProvider"
android:exported="false"
android:label="@string/app_name"
android:syncable="true" />
<!-- Sync Adapter -->
<service
android:name=".sync.SyncDataService"
android:label="@string/app_name"
android:exported="false">
<intent-filter>
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>
syncadapter.xml
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="@string/account_authorities"
android:accountType="one.random.net"
android:allowParallelSyncs="true"
android:isAlwaysSyncable="true"
android:supportsUploading="false"
android:userVisible="true" />
authenticator.xml:
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="one.random.net"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:smallIcon="@mipmap/ic_launcher"/>
SyncSupport.kt:
fun setupSyncAdapter(context: Context) {
// Create the account type and default account
val accountName = context.getString(R.string.account_name)
val accountType = ACCOUNT_TYPE
val newAccount = Account(accountName, accountType)
Log.d("Sync", "Account is $newAccount")
// Get an instance of the account manager
val accountManager = context.getSystemService(Context.ACCOUNT_SERVICE) as AccountManager
Log.d("Sync", "Account manager")
// Add the account and account type, no password or user data
// If successful, return the Account object, otherwise report an error.
Log.d("Sync", "Account manager size ${accountManager.getAccountsByType(accountType).size}")
/* ContentResolver.setSyncAutomatically(newAccount, AUTHORITY, true)
ContentResolver.setIsSyncable(newAccount, AUTHORITY, 1)*/
try {
if (accountManager.addAccountExplicitly(newAccount, null, null)) {
// If you don't set android:syncable="true" in your <provider> element in the
// manifest, then call context.setIsSyncable(account, AUTHORITY, 1) here
Log.d("Sync", "Sync Account added")
} else {
// The account exists or some other error occurred. Log this, report it,
// or handle it internally.
Log.d("Sync", "Sync Account not added or error")
}
} catch(e: Exception) {
Log.e("SyncSupport", e.message, e)
return
}
periodicSync(context)
}
/**
* Expedite a sync request, this will run even if there is sync queued up.
*
* **Remember this does IO, and should be threaded**
* @param context
*/
fun requestSyncNow(context: Context) {
val account = getAccount(context) ?: return
// Pass the settings flags by inserting them in a bundle
val settingsBundle = Bundle()
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
settingsBundle.putBoolean(KEY_SYNC, true)
// Request the sync for the default account, authority, and manual sync settings
/* ContentResolver.setSyncAutomatically(account, AUTHORITY, true)
ContentResolver.setIsSyncable(account, AUTHORITY, 1)*/
ContentResolver.requestSync(account, AUTHORITY, settingsBundle)
}
/**
* Requests a sync, at the next opportunity.
*
*
* **This does IO, remember to call it off the UI thread.**
* @param context
*/
fun requestSync(context: Context) {
val account = getAccount(context) ?: return
val settingsBundle = Bundle()
settingsBundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true
settingsBundle.putBoolean(KEY_SYNC, true)
/*
* Signal the framework to run your sync adapter. Assume that
* app initialization has already created the account.
*/
ContentResolver.setSyncAutomatically(account, AUTHORITY, true)
ContentResolver.setIsSyncable(account, AUTHORITY, 1)
ContentResolver.requestSync(account, AUTHORITY, settingsBundle)
}
fun periodicSync(context: Context) {
val account = getAccount(context) ?: return
Log.d("Sync", "Periodic sync triggered")
ContentResolver.setSyncAutomatically(account, AUTHORITY, true)
// ContentResolver.setIsSyncable(account, AUTHORITY, 1)
// We run the Sync Adapter every 12 hours normally or every 5 min's on dev to test.
//noinspection ConstantConditions
val pollPeriod = if (BuildConfig.DEBUG) TimeUnit.MINUTES.toSeconds(5L) else TimeUnit.HOURS.toSeconds(12L)
val settingsBundle = Bundle()
settingsBundle.putBoolean(KEY_SYNC, true)
val b = SyncRequest.Builder().syncPeriodic(pollPeriod, pollPeriod)
b.setSyncAdapter(account, AUTHORITY)
b.setExtras(settingsBundle)
ContentResolver.requestSync(b.build())
//Timber.i("Sync: PeriodicSync: %ss", pollPeriod.toString())
}
fun getAccount(context: Context): Account? {
val accountManager = context.applicationContext.getSystemService(Context.ACCOUNT_SERVICE) as AccountManager
val accountsByType = accountManager.getAccountsByType(ACCOUNT_TYPE)
for (account in accountsByType) return account
return null
}
从我多次检查的字符串是可以的但由于某种原因我仍然得到这个错误。