編輯:關於Android編程
關鍵組件:
ContentResolver
ContentService
SyncManager
SyncManager.ActiveSyncContext
SyncManager.SyncOperation
SyncManager.SyncHandler
ContentResolver
外部的應用程序通過調用ContentResolve.requestSync()靜態方法發起同步:
[java]
/**
* @param account which account should be synced
* @param authority which authority should be synced
* @param extras any extras to pass to the SyncAdapter.
*/
public static void requestSync(Account account, String authority, Bundle extras) {
validateSyncExtrasBundle(extras);
try {
getContentService().requestSync(account, authority, extras);
} catch (RemoteException e) {
}
}
/**
* @param account which account should be synced
* @param authority which authority should be synced
* @param extras any extras to pass to the SyncAdapter.
*/
public static void requestSync(Account account, String authority, Bundle extras) {
validateSyncExtrasBundle(extras);
try {
getContentService().requestSync(account, authority, extras);
} catch (RemoteException e) {
}
}
方法接收三個參數:
- account:需要同步的帳號
- authority:需要進行同步的authority
- extras:需要傳遞給sync adapter的附加數據
在這裡,getContentService()方法返回系統服務ContentService的代理對象,然後通過它遠程調用ContentService.requestSync()。
ContentService
ContentService是Android的系統服務,它提供一系列數據同步及數據訪問等相關的操作。它的行為在IContentService.aidl中描述。
這裡,通過遠程調用ContentService.requestSync()方法來啟動針對指定帳號(account)的指定內容(authority)的同步:
[java]
public void requestSync(Account account, String authority, Bundle extras) {
...
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleSync(account, userId, authority, extras, 0 /* no delay */,
false /* onlyThoseWithUnkownSyncableState */);
}
}
...
}
public void requestSync(Account account, String authority, Bundle extras) {
...
try {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleSync(account, userId, authority, extras, 0 /* no delay */,
false /* onlyThoseWithUnkownSyncableState */);
}
}
...
}
在這個方法中,會獲取一個SyncManager類的實例。顧名思義,SyncManager管理與同步相關的處理。
SyncManager
[java]
public void scheduleSync(Account requestedAccount, int userId, String requestedAuthority,
Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) {
...
final boolean backgroundDataUsageAllowed = !mBootCompleted ||
getConnectivityManager().getBackgroundDataSetting();
...
// 產生一個同步帳戶列表。對於手動同步,列表中僅有一個AccountUser元素,它封裝了需要同步的帳號以及對應的應用程序(userId)
AccountAndUser[] accounts;
if (requestedAccount != null && userId != UserHandle.USER_ALL) {
accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) };
}
...
for (AccountAndUser account : accounts) {
// 在這裡,會掃描系統中所有提供了sync adapter的service:根據intent filter
// 然後從得到service info中取得各自的authority。service info從對應服務的meta-data標簽中指定的sync adapter描述文件中解析出來。
final HashSet<String> syncableAuthorities = new HashSet<String>();
for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :
mSyncAdapters.getAllServices(account.userId)) {
syncableAuthorities.add(syncAdapter.type.authority);
}
...
for (String authority : syncableAuthorities) {
// 檢查帳戶是否能夠同步
int isSyncable = mSyncStorageEngine.getIsSyncable(account.account, account.userId,
authority);
if (isSyncable == 0) {
continue;
}
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(
SyncAdapterType.newKey(authority, account.account.type), account.userId);
...
if (isSyncable < 0) {
Bundle newExtras = new Bundle();
newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
...
// 部署同步操作
scheduleSyncOperation(
new SyncOperation(account.account, account.userId, source, authority,
newExtras, 0, backoffTime, delayUntil, allowParallelSyncs));
}
...
}
}
}
public void scheduleSync(Account requestedAccount, int userId, String requestedAuthority,
Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) {
...
final boolean backgroundDataUsageAllowed = !mBootCompleted ||
getConnectivityManager().getBackgroundDataSetting();
...
// 產生一個同步帳戶列表。對於手動同步,列表中僅有一個AccountUser元素,它封裝了需要同步的帳號以及對應的應用程序(userId)
AccountAndUser[] accounts;
if (requestedAccount != null && userId != UserHandle.USER_ALL) {
accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) };
}
...
for (AccountAndUser account : accounts) {
// 在這裡,會掃描系統中所有提供了sync adapter的service:根據intent filter
// 然後從得到service info中取得各自的authority。service info從對應服務的meta-data標簽中指定的sync adapter描述文件中解析出來。
final HashSet<String> syncableAuthorities = new HashSet<String>();
for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :
mSyncAdapters.getAllServices(account.userId)) {
syncableAuthorities.add(syncAdapter.type.authority);
}
...
for (String authority : syncableAuthorities) {
// 檢查帳戶是否能夠同步
int isSyncable = mSyncStorageEngine.getIsSyncable(account.account, account.userId,
authority);
if (isSyncable == 0) {
continue;
}
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(
SyncAdapterType.newKey(authority, account.account.type), account.userId);
...
if (isSyncable < 0) {
Bundle newExtras = new Bundle();
newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
...
// 部署同步操作
scheduleSyncOperation(
new SyncOperation(account.account, account.userId, source, authority,
newExtras, 0, backoffTime, delayUntil, allowParallelSyncs));
}
...
}
}
}
這裡,首先從系統中篩選出符合限定條件的service的信息,然後發起對應的同步。
首先為每一個同步操作生成一個SyncOperation實例,它封裝了同步操作需要的全部信息:
[java]
public class SyncOperation implements Comparable {
public final Account account;
public final int userId;
public int syncSource;
public String authority;
public final boolean allowParallelSyncs;
public Bundle extras;
public final String key;
public long earliestRunTime;
public boolean expedited;
public SyncStorageEngine.PendingOperation pendingOperation;
public Long backoff;
public long delayUntil;
public long effectiveRunTime;
public class SyncOperation implements Comparable {
public final Account account;
public final int userId;
public int syncSource;
public String authority;
public final boolean allowParallelSyncs;
public Bundle extras;
public final String key;
public long earliestRunTime;
public boolean expedited;
public SyncStorageEngine.PendingOperation pendingOperation;
public Long backoff;
public long delayUntil;
public long effectiveRunTime;
然後調用scheduleSyncOperation方法:
[java]
public void scheduleSyncOperation(SyncOperation syncOperation) {
boolean queueChanged;
synchronized (mSyncQueue) {
queueChanged = mSyncQueue.add(syncOperation);
}
if (queueChanged) {
...
sendCheckAlarmsMessage();
}
...
}
public void scheduleSyncOperation(SyncOperation syncOperation) {
boolean queueChanged;
synchronized (mSyncQueue) {
queueChanged = mSyncQueue.add(syncOperation);
}
if (queueChanged) {
...
sendCheckAlarmsMessage();
}
...
}
首先將SyncOperation實例插入隊列mSyncQueue然後向SyncManager中定義的SyncHandler發送消息,通知其隊列發生變化:
[java]
private void sendCheckAlarmsMessage() {
...
mSyncHandler.removeMessages(SyncHandler.MESSAGE_CHECK_ALARMS);
mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS);
}
private void sendCheckAlarmsMessage() {
...
mSyncHandler.removeMessages(SyncHandler.MESSAGE_CHECK_ALARMS);
mSyncHandler.sendEmptyMessage(SyncHandler.MESSAGE_CHECK_ALARMS);
}
隨後,SyncHandler處理這個消息:
[java] v
public void handleMessage(Message msg) {
...
try {
...
switch (msg.what) {
...
case SyncHandler.MESSAGE_CHECK_ALARMS:
...
nextPendingSyncTime = maybeStartNextSyncLocked();
break;
}
}
...
}
public void handleMessage(Message msg) {
...
try {
...
switch (msg.what) {
...
case SyncHandler.MESSAGE_CHECK_ALARMS:
...
nextPendingSyncTime = maybeStartNextSyncLocked();
break;
}
}
...
}
這裡,maybeStartNextSyncLocked()方法經過一系列的檢查,確認執行同步的全部條件已經達到之後,對SyncOperation進行分發:
[java]
private long maybeStartNextSyncLocked() {
...
dispatchSyncOperation(candidate);
}
return nextReadyToRunTime;
}
private long maybeStartNextSyncLocked() {
...
dispatchSyncOperation(candidate);
}
return nextReadyToRunTime;
}
接下來,將綁定到提供sync adapter的應用程序中對應的service:
[java]
private boolean dispatchSyncOperation(SyncOperation op) {
...
// connect to the sync adapter
SyncAdapterType syncAdapterType = SyncAdapterType.newKey(op.authority, op.account.type);
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, op.userId);
...
ActiveSyncContext activeSyncContext =
new ActiveSyncContext(op, insertStartSyncEvent(op), syncAdapterInfo.uid);
activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
mActiveSyncContexts.add(activeSyncContext);
...
if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo, op.userId)) {
Log.e(TAG, "Bind attempt failed to " + syncAdapterInfo);
closeActiveSyncContext(activeSyncContext);
return false;
}
return true;
}
private boolean dispatchSyncOperation(SyncOperation op) {
...
// connect to the sync adapter
SyncAdapterType syncAdapterType = SyncAdapterType.newKey(op.authority, op.account.type);
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(syncAdapterType, op.userId);
...
ActiveSyncContext activeSyncContext =
new ActiveSyncContext(op, insertStartSyncEvent(op), syncAdapterInfo.uid);
activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
mActiveSyncContexts.add(activeSyncContext);
...
if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo, op.userId)) {
Log.e(TAG, "Bind attempt failed to " + syncAdapterInfo);
closeActiveSyncContext(activeSyncContext);
return false;
}
return true;
}
與前面的AccountManager非常的雷同,這裡通過ActiveSyncContext類來完成service的綁定:
[java]
class ActiveSyncContext extends ISyncContext.Stub
implements ServiceConnection, IBinder.DeathRecipient {
...
public void onServiceConnected(ComponentName name, IBinder service) {
Message msg = mSyncHandler.obtainMessage();
msg.what = SyncHandler.MESSAGE_SERVICE_CONNECTED;
msg.obj = new ServiceConnectionData(this, ISyncAdapter.Stub.asInterface(service));
mSyncHandler.sendMessage(msg);
}
...
boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info, int userId) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "bindToSyncAdapter: " + info.componentName + ", connection " + this);
}
Intent intent = new Intent();
intent.setAction("android.content.SyncAdapter");
intent.setComponent(info.componentName);
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.sync_binding_label);
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0,
null, new UserHandle(userId)));
mBound = true;
final boolean bindResult = mContext.bindService(intent, this,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
| Context.BIND_ALLOW_OOM_MANAGEMENT,
mSyncOperation.userId);
if (!bindResult) {
mBound = false;
}
return bindResult;
}
...
}
class ActiveSyncContext extends ISyncContext.Stub
implements ServiceConnection, IBinder.DeathRecipient {
...
public void onServiceConnected(ComponentName name, IBinder service) {
Message msg = mSyncHandler.obtainMessage();
msg.what = SyncHandler.MESSAGE_SERVICE_CONNECTED;
msg.obj = new ServiceConnectionData(this, ISyncAdapter.Stub.asInterface(service));
mSyncHandler.sendMessage(msg);
}
...
boolean bindToSyncAdapter(RegisteredServicesCache.ServiceInfo info, int userId) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "bindToSyncAdapter: " + info.componentName + ", connection " + this);
}
Intent intent = new Intent();
intent.setAction("android.content.SyncAdapter");
intent.setComponent(info.componentName);
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
com.android.internal.R.string.sync_binding_label);
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0,
null, new UserHandle(userId)));
mBound = true;
final boolean bindResult = mContext.bindService(intent, this,
Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND
| Context.BIND_ALLOW_OOM_MANAGEMENT,
mSyncOperation.userId);
if (!bindResult) {
mBound = false;
}
return bindResult;
}
...
}其中,bindToSyncAdapter()中創建相應的Intent,發起綁定。
然後,因為本類實現了ServiceConnection接口,所以當綁定成功時,將回調本類的onServiceConnected()方法。在這個回調中,向SyncHandler發送一條MESSAGE_SERVICE_CONNECTED消息。
緊接著,輪到SyncHandler來處理消息:
case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
ServiceConnectionData msgData = (ServiceConnectionData)msg.obj;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CONNECTED: "
+ msgData.activeSyncContext);
}
// check that this isn't an old message
if (isSyncStillActive(msgData.activeSyncContext)) {
runBoundToSyncAdapter(msgData.activeSyncContext, msgData.syncAdapter);
}
break;
}
case SyncHandler.MESSAGE_SERVICE_CONNECTED: {
ServiceConnectionData msgData = (ServiceConnectionData)msg.obj;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CONNECTED: "
+ msgData.activeSyncContext);
}
// check that this isn't an old message
if (isSyncStillActive(msgData.activeSyncContext)) {
runBoundToSyncAdapter(msgData.activeSyncContext, msgData.syncAdapter);
}
break;
}
這裡主要就是調用了runBoundToSyncAdapter()方法:
[java]
private void runBoundToSyncAdapter(final ActiveSyncContext activeSyncContext,
ISyncAdapter syncAdapter) {
activeSyncContext.mSyncAdapter = syncAdapter;
final SyncOperation syncOperation = activeSyncContext.mSyncOperation;
try {
...
syncAdapter.startSync(activeSyncContext, syncOperation.authority,
syncOperation.account, syncOperation.extras);
}
...
}
在Android開發過程中,ListView的Adapter是我們最常見的類型之一,我們需要使用Adapter加載Item View的布局,並且進行數據綁定、緩存復用等操
Android手機的碎片化問題不用贅述,在此對適配什麼及適配方法進行一次總結。我們先來看被適配的對象。 第一類是操作系統適配,即適配Android 2.X,4.X,5.X
需求分析:很多時候,我們需要在視圖中顯示不同樣式的文字,但是為了減少viewgroup層級,不想新增很多個TextView控件來實現不同樣式的文字。那麼有沒有一種方式能夠
學習Android到現在估計應該還不到一個月的時間,我很激動能夠在自己的努力還有奮斗下開發一個自己想要的App,雖然這個App的功能還不夠完善,界面很丑陋,Bug很存在很