所以我按照教程创建了一个没有真正的ContentProvider和一个帐户的SyncAdapter(来自here),但遇到了一个我无法解决的问题。
当调用ContentResolver.requestSync()手动强制同步时,似乎我实现的SyncAdapter不会被调用。 请注意,我在所提到的教程中创建了所有存根类(StubAuthenticator,StubProvider,AuthenticatorService)和SyncService。如果您需要我以任何方式发布代码,我将编辑此帖子。
Android Manifest.xml
<application
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_SYNC_STATS"/>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
...
<service
android:name=".datasync.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>
<service
android:name=".datasync.AuthenticatorService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator"/>
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator"/>
</service>
<provider
android:name=".datasync.StubProvider"
android:authorities="myexample.com.provider"
android:enabled="true"
android:exported="false"
android:label="DataSyncContentProvider"
android:syncable="true"/>
</application>
sync_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="myexample.com.provider"
android:accountType="myexample.com.account"
android:userVisible="false"
android:allowParallelSyncs="false"
android:isAlwaysSyncable="true"/>
authenticator.xml
<?xml version="1.0" encoding="utf-8"?>
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="myexample.com.account"
android:label="MyExampleApp"/>
DataSyncAdapter.java
public class DataSyncAdapter extends AbstractThreadedSyncAdapter{
public DataSyncAdapter(Context context, boolean autoInitialize) {
super(context, autoInitialize);
}
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
SyncResult syncResult) {
Log.d(MainActivity.TAG, "onPerformSync: Called");
//do sync stuff here
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity{
/**
* Tag for own application.
*/
public static final String TAG = "com.myexample";
@Override
protected final void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//create UI here...
Bundle syncExtras = new Bundle();
//add additional sync stuff (internal)
DataSyncUtil.createSyncRequest(this, syncExtras);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
grantResults) {
switch (requestCode) {
case PERMISSIONS_GET_ACCOUNTS:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Bundle syncExtras = new Bundle();
//add additional sync stuff (internal)
DataSyncUtil.createSyncRequest(this, syncExtras);
} else {
//TODO handle permission denied
}
return;
}
}
}
DataSyncUtil.java
public class DataSyncUtil {
public static void createSyncRequest(Activity activity, Bundle extras) {
Log.d(MainActivity.TAG, "createSyncRequest: Called");
String authority = "myexample.com.provider";
Account dummy = getDummySyncAccount(activity);
if (dummy != null) {
if (ContentResolver.isSyncPending(dummy, authority) ||
ContentResolver.isSyncActive(dummy, authority)) {
Log.i(MainActivity.TAG, "SyncPending, canceling");
ContentResolver.cancelSync(dummy, authority);
}
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
ContentResolver.requestSync(dummy, authority, extras);
}
}
public static Account getDummySyncAccount(Activity activity) {
String auth_type = "myexample.com.account;
Account dummy = null;
AccountManager accountManager = (AccountManager) activity.getSystemService(ACCOUNT_SERVICE);
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.GET_ACCOUNTS) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.GET_ACCOUNTS},
MainActivity.PERMISSIONS_GET_ACCOUNTS);
} else {
Account[] existing = accountManager.getAccountsByType(auth_type);
if (existing != null && existing.length > 0) {
//TODO handle more than one account
Log.d(MainActivity.TAG, "getDummySyncAccount: Account already exists and is getting returned");
dummy = existing[0];
} else {
Log.d(MainActivity.TAG, "getDummySyncAccount: Account has to be created");
// Create the account type and default account
dummy = new Account(ACCOUNT, auth_type);
// Get an instance of the Android account manager
/*
* Add the account and account type, no password or user data
* If successful, return the Account object, otherwise report an error.
*/
if (accountManager.addAccountExplicitly(dummy, null, null)) {
ContentResolver.setIsSyncable(dummy, "myexample.com.content", 1);
ContentResolver.setSyncAutomatically(dummy, "myexample.com.content", true);
} else {
/*
* The account exists or some other error occurred.Log this, report it,
* or handle it internally.
*/
}
}
}
Log.d(MainActivity.TAG, "getDummySyncAccount: "+dummy.name);
return dummy;
}
}
代码执行得非常好,直到DataSyncUtil类中的ContentResolver.requestSync(),但DataSyncAdapter永远不会被调用。
我很感激任何帮助:)
仅供参考:这是我的第一个大型Android项目,所以我很缺乏经验。
答案 0 :(得分:2)
看来我犯了一个菜鸟错误。确实调用了onPerformSync()。但我在我的android监视器集中有过滤器“仅显示选定的应用程序”,因此后台同步服务中的Log.d没有显示。 This回答帮助了我。