SyncAdapterDriver.java revision d7a3ea819dc9bc2355446ae12b4792e6e5e899fb
1d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana/* 2d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * Copyright (C) 2009 The Android Open Source Project 3d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * 4d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * Licensed under the Apache License, Version 2.0 (the "License"); 5d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * you may not use this file except in compliance with the License. 6d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * You may obtain a copy of the License at 7d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * 8d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * http://www.apache.org/licenses/LICENSE-2.0 9d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * 10d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * Unless required by applicable law or agreed to in writing, software 11d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * distributed under the License is distributed on an "AS IS" BASIS, 12d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * See the License for the specific language governing permissions and 14d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana * limitations under the License. 15d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana */ 16d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 17d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanapackage com.android.development; 18d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 19d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.app.Activity; 20d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.app.PendingIntent; 21d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.app.Dialog; 22d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.app.AlertDialog; 23d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.res.TypedArray; 24d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.pm.RegisteredServicesCache; 25d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.pm.RegisteredServicesCacheListener; 26d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.SyncAdapterType; 27d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.ISyncAdapter; 28d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.ISyncContext; 29d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.ServiceConnection; 30d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.ComponentName; 31d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.SyncResult; 32d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.Intent; 33d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.content.Context; 34d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.os.Bundle; 35d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.os.IBinder; 36d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.os.RemoteException; 37d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.ArrayAdapter; 38d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.AdapterView; 39d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.Spinner; 40d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.Button; 41d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.TextView; 42d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.widget.ListView; 43d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.util.AttributeSet; 44d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.provider.Settings; 45d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.accounts.Account; 46d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.accounts.AccountManager; 47d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.view.View; 48d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport android.view.LayoutInflater; 49d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 50d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanaimport java.util.Collection; 51d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 52d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintanapublic class SyncAdapterDriver extends Activity 53d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana implements RegisteredServicesCacheListener, AdapterView.OnItemClickListener { 54d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Spinner mSyncAdapterSpinner; 55d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 56d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Button mBindButton; 57d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Button mUnbindButton; 58d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private TextView mBoundAdapterTextView; 59d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Button mStartSyncButton; 60d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Button mCancelSyncButton; 61d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private TextView mStatusTextView; 62d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private Object[] mSyncAdapters; 63d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private SyncAdaptersCache mSyncAdaptersCache; 64d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private final Object mSyncAdaptersLock = new Object(); 65d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 66d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private static final int DIALOG_ID_PICK_ACCOUNT = 1; 67d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private ListView mAccountPickerView = null; 68d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 69d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana @Override 70d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana protected void onCreate(Bundle savedInstanceState) { 71d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana super.onCreate(savedInstanceState); 72d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdaptersCache = new SyncAdaptersCache(this); 73d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana setContentView(R.layout.sync_adapter_driver); 74d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 75d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapterSpinner = (Spinner) findViewById(R.id.sync_adapters_spinner); 76d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBindButton = (Button) findViewById(R.id.bind_button); 77d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mUnbindButton = (Button) findViewById(R.id.unbind_button); 78d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView = (TextView) findViewById(R.id.bound_adapter_text_view); 79d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 80d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStartSyncButton = (Button) findViewById(R.id.start_sync_button); 81d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mCancelSyncButton = (Button) findViewById(R.id.cancel_sync_button); 82d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 83d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView = (TextView) findViewById(R.id.status_text_view); 84d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 85d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getSyncAdapters(); 86d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdaptersCache.setListener(this); 87d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 88d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 89d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana protected void onDestroy() { 90d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdaptersCache.close(); 91d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana super.onDestroy(); 92d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 93d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 94d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private void getSyncAdapters() { 95d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> all = 96d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdaptersCache.getAllServices(); 97d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mSyncAdaptersLock) { 98d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapters = new Object[all.size()]; 99d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana String[] names = new String[mSyncAdapters.length]; 100d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana int i = 0; 101d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> item : all) { 102d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapters[i] = item; 103d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana names[i] = item.type.authority + " - " + item.type.accountType; 104d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana i++; 105d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 106d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 107d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ArrayAdapter<String> adapter = 108d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana new ArrayAdapter<String>(this, 109d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana R.layout.sync_adapter_item, names); 110d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapterSpinner.setAdapter(adapter); 111d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 112d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 113d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 114d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana void updateUi() { 115d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana boolean isBound; 116d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana boolean hasServiceConnection; 117d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 118d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana hasServiceConnection = mActiveServiceConnection != null; 119d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana isBound = hasServiceConnection && mActiveServiceConnection.mBoundSyncAdapter != null; 120d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 121d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStartSyncButton.setEnabled(isBound); 122d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mCancelSyncButton.setEnabled(isBound); 123d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBindButton.setEnabled(!hasServiceConnection); 124d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mUnbindButton.setEnabled(hasServiceConnection); 125d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 126d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 127d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void startSyncSelected(View view) { 128d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 129d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ISyncAdapter syncAdapter = null; 130d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection != null) { 131d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter = mActiveServiceConnection.mBoundSyncAdapter; 132d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 133d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 134d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (syncAdapter != null) { 135d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana removeDialog(DIALOG_ID_PICK_ACCOUNT); 136d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 137d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mAccountPickerView = (ListView) LayoutInflater.from(this).inflate( 138d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana R.layout.account_list_view, null); 139d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mAccountPickerView.setOnItemClickListener(this); 140d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana Account accounts[] = AccountManager.get(this).getAccountsByType( 141d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection.mSyncAdapter.type.accountType); 142d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana String[] accountNames = new String[accounts.length]; 143d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana for (int i = 0; i < accounts.length; i++) { 144d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana accountNames[i] = accounts[i].name; 145d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 146d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ArrayAdapter<String> adapter = 147d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana new ArrayAdapter<String>(SyncAdapterDriver.this, 148d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana android.R.layout.simple_list_item_1, accountNames); 149d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mAccountPickerView.setAdapter(adapter); 150d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 151d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana showDialog(DIALOG_ID_PICK_ACCOUNT); 152d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 153d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 154d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 155d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 156d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 157d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private void startSync(String accountName) { 158d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 159d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ISyncAdapter syncAdapter = null; 160d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection != null) { 161d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter = mActiveServiceConnection.mBoundSyncAdapter; 162d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 163d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 164d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (syncAdapter != null) { 165d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana try { 166d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 167d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_starting_sync_format, accountName)); 168d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana Account account = new Account(accountName, 169d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection.mSyncAdapter.type.accountType); 170d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter.startSync(mActiveServiceConnection, 171d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection.mSyncAdapter.type.authority, 172d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana account, new Bundle()); 173d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } catch (RemoteException e) { 174d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 175d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_remote_exception_while_starting_sync)); 176d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 177d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 178d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 179d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 180d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 181d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 182d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void cancelSync(View view) { 183d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 184d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana ISyncAdapter syncAdapter = null; 185d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection != null) { 186d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter = mActiveServiceConnection.mBoundSyncAdapter; 187d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 188d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 189d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (syncAdapter != null) { 190d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana try { 191d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText(getString(R.string.status_canceled_sync)); 192d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana syncAdapter.cancelSync(mActiveServiceConnection); 193d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } catch (RemoteException e) { 194d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 195d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_remote_exception_while_canceling_sync)); 196d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 197d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 198d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 199d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 200d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 201d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 202d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onRegisteredServicesCacheChanged() { 203d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getSyncAdapters(); 204d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 205d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 206d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana @Override 207d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana protected Dialog onCreateDialog(final int id) { 208d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (id == DIALOG_ID_PICK_ACCOUNT) { 209d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana AlertDialog.Builder builder = new AlertDialog.Builder(this); 210d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana builder.setMessage(R.string.select_account_to_sync); 211d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana builder.setInverseBackgroundForced(true); 212d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana builder.setView(mAccountPickerView); 213d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return builder.create(); 214d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 215d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return super.onCreateDialog(id); 216d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 217d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 218d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 219d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana TextView item = (TextView) view; 220d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final String accountName = item.getText().toString(); 221d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana dismissDialog(DIALOG_ID_PICK_ACCOUNT); 222d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana startSync(accountName); 223d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 224d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 225d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private class MyServiceConnection extends ISyncContext.Stub implements ServiceConnection { 226d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private volatile ISyncAdapter mBoundSyncAdapter; 227d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final RegisteredServicesCache.ServiceInfo<SyncAdapterType> mSyncAdapter; 228d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 229d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public MyServiceConnection( 230d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter) { 231d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapter = syncAdapter; 232d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 233d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 234d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onServiceConnected(ComponentName name, IBinder service) { 235d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundSyncAdapter = ISyncAdapter.Stub.asInterface(service); 236d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final SyncAdapterType type = mActiveServiceConnection.mSyncAdapter.type; 237d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(getString(R.string.binding_connected_format, 238d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana type.authority, type.accountType)); 239d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 240d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 241d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 242d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onServiceDisconnected(ComponentName name) { 243d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(getString(R.string.binding_not_connected)); 244d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundSyncAdapter = null; 245d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 246d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 247d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 248d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void sendHeartbeat() { 249d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana runOnUiThread(new Runnable() { 250d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void run() { 251d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana uiThreadSendHeartbeat(); 252d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 253d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana }); 254d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 255d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 256d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void uiThreadSendHeartbeat() { 257d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText(getString(R.string.status_received_heartbeat)); 258d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 259d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 260d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void uiThreadOnFinished(SyncResult result) { 261d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (result.hasError()) { 262d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 263d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_sync_failed_format, result.toString())); 264d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } else { 265d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText( 266d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getString(R.string.status_sync_succeeded_format, result.toString())); 267d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 268d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 269d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 270d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void onFinished(final SyncResult result) throws RemoteException { 271d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana runOnUiThread(new Runnable() { 272d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void run() { 273d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana uiThreadOnFinished(result); 274d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 275d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana }); 276d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 277d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 278d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 279d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final Object mServiceConnectionLock = new Object(); 280d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana MyServiceConnection mActiveServiceConnection; 281d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 282d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void initiateBind(View view) { 283d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 284d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection != null) { 285d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText(getString(R.string.status_already_bound)); 286d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return; 287d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 288d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 289d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter = 290d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana getSelectedSyncAdapter(); 291d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (syncAdapter == null) { 292d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mStatusTextView.setText(getString(R.string.status_sync_adapter_not_selected)); 293d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return; 294d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 295d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 296d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection = new MyServiceConnection(syncAdapter); 297d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 298d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana Intent intent = new Intent(); 299d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana intent.setAction("android.content.SyncAdapter"); 300d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana intent.setComponent(syncAdapter.componentName); 301d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana intent.putExtra(Intent.EXTRA_CLIENT_LABEL, 302d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana com.android.internal.R.string.sync_binding_label); 303d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( 304d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana this, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0)); 305d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (!bindService(intent, mActiveServiceConnection, Context.BIND_AUTO_CREATE)) { 306d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(getString(R.string.binding_bind_failed)); 307d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection = null; 308d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return; 309d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 310d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(getString(R.string.binding_waiting_for_connection)); 311d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 312d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 313d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 314d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 315d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public void initiateUnbind(View view) { 316d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mServiceConnectionLock) { 317d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (mActiveServiceConnection == null) { 318d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return; 319d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 320d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mBoundAdapterTextView.setText(""); 321d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana unbindService(mActiveServiceConnection); 322d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mActiveServiceConnection = null; 323d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 324d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana updateUi(); 325d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 326d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 327d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private RegisteredServicesCache.ServiceInfo<SyncAdapterType> getSelectedSyncAdapter() { 328d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana synchronized (mSyncAdaptersLock) { 329d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final int position = mSyncAdapterSpinner.getSelectedItemPosition(); 330d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (position == AdapterView.INVALID_POSITION) { 331d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return null; 332d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 333d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana try { 334d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana //noinspection unchecked 335d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return (RegisteredServicesCache.ServiceInfo<SyncAdapterType>) 336d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana mSyncAdapters[position]; 337d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } catch (Exception e) { 338d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return null; 339d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 340d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 341d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 342d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 343d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana static class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> { 344d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private static final String SERVICE_INTERFACE = "android.content.SyncAdapter"; 345d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private static final String SERVICE_META_DATA = "android.content.SyncAdapter"; 346d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana private static final String ATTRIBUTES_NAME = "sync-adapter"; 347d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 348d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana SyncAdaptersCache(Context context) { 349d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME); 350d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 351d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana 352d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana public SyncAdapterType parseServiceAttributes(String packageName, AttributeSet attrs) { 353d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana TypedArray sa = mContext.getResources().obtainAttributes(attrs, 354d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana com.android.internal.R.styleable.SyncAdapter); 355d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana try { 356d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final String authority = 357d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana sa.getString(com.android.internal.R.styleable.SyncAdapter_contentAuthority); 358d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final String accountType = 359d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana sa.getString(com.android.internal.R.styleable.SyncAdapter_accountType); 360d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana if (authority == null || accountType == null) { 361d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return null; 362d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 363d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final boolean userVisible = sa.getBoolean( 364d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana com.android.internal.R.styleable.SyncAdapter_userVisible, true); 365d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana final boolean supportsUploading = sa.getBoolean( 366d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana com.android.internal.R.styleable.SyncAdapter_supportsUploading, true); 367d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana return new SyncAdapterType(authority, accountType, userVisible, supportsUploading); 368d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } finally { 369d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana sa.recycle(); 370d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 371d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 372d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana } 373d7a3ea819dc9bc2355446ae12b4792e6e5e899fbFred Quintana} 374