我一直试图让SyncAdapter
工作。男人,多么荒谬的复杂一团糟。我甚至不知道从哪里开始,所以我想我只是转储所有相关的代码。如果我在下面的代码中随处可见断点,那么在启动时会调用以下两个东西(按此顺序):
StubContentProvider.OnCreate()
AndroidApp.InitSyncService()
(我的应用启动时显式调用)。就是这样。没有任何与SyncAdapter
相关的内容被调用(严重的是,我已经将断点放在与其相关的每个类的每个方法的顶部。)
我已经在应用程序的这个方面工作了大约一个半月,并且在不同的时间使它比现在更具功能性,但我不确定我是如何制作它的功能较少。我试过调整它的每个方面。我已将ACCOUNT_TYPE
和AUTHORITY
更改为各种值。当我阅读文档并学到更多知识时,我会在这里和那里进行调整,但它似乎并不想为我聚集在一起。
这是我们应用的最后一项主要功能,所以我再也不能把它放在一边了。
AndroidApp.cs
public static class AndroidApp
{
public static string ACCOUNT_TYPE = "georgesmobile.android.backgroundservice";
public static string ACCOUNT = "mobile";
public static string AUTHORITY = "georgesmobile.android.provider";
public static Account SyncAccount { get; private set; }
public static void InitSyncService(Context context)
{
if (SyncAccount == null)
{
CreateSyncAccount(context);
ContentResolver.SetIsSyncable(AndroidApp.SyncAccount, AndroidApp.AUTHORITY, 1);
ContentResolver.SetSyncAutomatically(AndroidApp.SyncAccount, AndroidApp.AUTHORITY, true);
Bundle bund = new Bundle();
ContentResolver.AddPeriodicSync(AndroidApp.SyncAccount, AndroidApp.AUTHORITY, bund, 2);
}
}
private static Account CreateSyncAccount(Context context)
{
SyncAccount = new Account(ACCOUNT, ACCOUNT_TYPE);
AccountManager accountManager = (AccountManager)context.GetSystemService(Context.AccountService);
return SyncAccount;
}
}
StubContentProvider.cs
[ContentProvider(new[] { "georgesmobile.android.provider" },
Name = "georgesmobile.android.backgroundservice.StubContentProvider",
Exported = false,
Syncable = true)]
public class StubContentProvider : ContentProvider
{
public override int Delete(global::Android.Net.Uri uri, string selection, string[] selectionArgs)
{
return 0;
}
public override string GetType(global::Android.Net.Uri uri)
{
return "";
}
public override global::Android.Net.Uri Insert(global::Android.Net.Uri uri, ContentValues values)
{
return null;
}
public override bool OnCreate()
{
return true;
}
public override global::Android.Database.ICursor Query(global::Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
{
return null;
}
public override int Update(global::Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs)
{
return 0;
}
}
GenericAccountService.cs
[Service(Name = "georgesmobile.android.backgroundservice.GenericAccountService")]
[IntentFilter(new string[] { "android.accounts.AccountAuthenticator" })]
[MetaData("android.accounts.AccountAuthenticator", Resource = "@xml/authenticator")]
public class GenericAccountService : Service
{
private Authenticator _authenticator;
public static Account GetAccount(string accountType)
{
return new Account(AndroidApp.ACCOUNT, AndroidApp.ACCOUNT_TYPE);
}
public override void OnCreate()
{
base.OnCreate();
_authenticator = new Authenticator(this);
}
public override IBinder OnBind(Intent intent)
{
return _authenticator.IBinder;
}
}
SyncAdapter.cs
[MetaData("android.content.SyncAdapter", Resource = "@xml/syncadapter")]
public class SyncAdapter : AbstractThreadedSyncAdapter
{
public override void OnPerformSync(global::Android.Accounts.Account account, Bundle extras, string authority, ContentProviderClient provider, SyncResult syncResult)
{
BackgroundDataSync.Synchronize();
}
}
SyncService.cs
[Service(Name = "georgesmobile.android.backgroundservice.SyncService", Exported = true)]
public class SyncService : Service
{
private static SyncAdapter _syncAdapter;
private static object _syncLock = new object();
public override void OnCreate()
{
base.OnCreate();
lock (_syncLock)
{
_syncAdapter = new SyncAdapter(ApplicationContext, true);
}
}
public override IBinder OnBind(Intent intent)
{
return _syncAdapter.SyncAdapterBinder;
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
return base.OnStartCommand(intent, flags, startId);
}
}
syncadapter.xml
<?xml version="1.0" encoding="utf-8" ?>
<sync-adapter
xmlns:android="http://schemas.android.com/apk/res/android"
android:contentAuthority="georgesmobile.android.provider"
android:accountType="georgesmobile.android.backgroundservice"
android:userVisible="true"
android:supportsUploading="true"
android:allowParallelSyncs="true"
android:isAlwaysSyncable="true"/>
authenticator.xml
<?xml version="1.0" encoding="utf-8" ?>
<account-authenticator
xmlns:android="http://schemas.android.com/apk/res/android"
android:icon="@drawable/georgeslogo_icon"
android:smallIcon="@drawable/georgeslogo_icon"
android:label="@string/AppName"
android:accountType="georgesmobile.android.backgroundservice"/>
相关AndroidManifest.xml
(由编译器生成)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="georgesmobile.android" android:versionCode="1" android:versionName="Crackerjack">
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" />
<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.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.ACCOUNT_MANAGER" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<application android:label="GeorgesMobile" android:icon="@drawable/georgeslogo_icon" android:theme="@android:style/Theme.Light" android:name="mono.android.app.Application" android:debuggable="true">
<receiver android:name="georgesmobile.android.backgroundservice.BootupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name="georgesmobile.android.backgroundservice.GenericAccountService">
<meta-data android:name="android.accounts.AccountAuthenticator" android:resource="@xml/authenticator" />
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
</service>
<provider android:authorities="georgesmobile.android.provider" android:exported="false" android:name="georgesmobile.android.backgroundservice.StubContentProvider" android:syncable="true" />
<service android:exported="true" android:name="georgesmobile.android.backgroundservice.SyncService">
<meta-data android:name="android.content.SyncAdapter" android:resource="@xml/syncadapter" />
</service>
<activity android:icon="@drawable/georgeslogo_icon" android:label="George's Inc" android:name="georgesmobile.android.views.HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:icon="@drawable/georgeslogo_icon" android:label="George's Login" android:name="georgesmobile.android.views.LoginActivity" />
<provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="2147483647" android:authorities="georgesmobile.android.mono.MonoRuntimeProvider.__mono_init__" />
<receiver android:name="mono.android.Seppuku">
<intent-filter>
<action android:name="mono.android.intent.action.SEPPUKU" />
<category android:name="mono.android.intent.category.SEPPUKU.georgesmobile.android" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>