create a test app that allows direct control of a sync adapter for testing purposes
http://b/issue?id=2239791
This commit is contained in:
@@ -84,6 +84,14 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name="SyncAdapterDriver" android:label="Sync Tester"
|
||||||
|
android:theme="@android:style/Theme.Light">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.TEST" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
<activity android:name="DataList">
|
<activity android:name="DataList">
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name="Details">
|
<activity android:name="Details">
|
||||||
|
|||||||
20
apps/Development/res/layout/account_list_view.xml
Normal file
20
apps/Development/res/layout/account_list_view.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2009 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"/>
|
||||||
86
apps/Development/res/layout/sync_adapter_driver.xml
Normal file
86
apps/Development/res/layout/sync_adapter_driver.xml
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2009 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent">
|
||||||
|
|
||||||
|
<LinearLayout android:orientation="vertical"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<TextView android:id="@+id/sync_adapters_spinner_label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="22dip"
|
||||||
|
android:text="@string/sync_adapters_spinner_label"/>
|
||||||
|
|
||||||
|
<Spinner android:id="@+id/sync_adapters_spinner"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="52dip">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/bind_button"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/bind_button"
|
||||||
|
android:onClick="initiateBind"
|
||||||
|
android:layout_weight="2"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/unbind_button"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/unbind_button"
|
||||||
|
android:onClick="initiateUnbind"
|
||||||
|
android:layout_weight="2"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView android:id="@+id/bound_adapter_text_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:textSize="20dip"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="52dip">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/start_sync_button"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/start_sync_button"
|
||||||
|
android:onClick="startSyncSelected"
|
||||||
|
android:layout_weight="2"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/cancel_sync_button"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/cancel_sync_button"
|
||||||
|
android:onClick="cancelSync"
|
||||||
|
android:layout_weight="2"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView android:id="@+id/status_text_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
26
apps/Development/res/layout/sync_adapter_item.xml
Normal file
26
apps/Development/res/layout/sync_adapter_item.xml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2009, The Android Open Source Project
|
||||||
|
**
|
||||||
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
** you may not use this file except in compliance with the License.
|
||||||
|
** You may obtain a copy of the License at
|
||||||
|
**
|
||||||
|
** http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
**
|
||||||
|
** Unless required by applicable law or agreed to in writing, software
|
||||||
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
** See the License for the specific language governing permissions and
|
||||||
|
** limitations under the License.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@android:id/text1"
|
||||||
|
style="?android:attr/spinnerItemStyle"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="52dip"
|
||||||
|
android:ellipsize="marquee" />
|
||||||
@@ -155,4 +155,25 @@
|
|||||||
<string name="accounts_tester_edit_properties">Properties</string>
|
<string name="accounts_tester_edit_properties">Properties</string>
|
||||||
<string name="accounts_tester_desired_authtokentype_label">authtoken type:</string>
|
<string name="accounts_tester_desired_authtokentype_label">authtoken type:</string>
|
||||||
<string name="accounts_tester_desired_features_label">features:</string>
|
<string name="accounts_tester_desired_features_label">features:</string>
|
||||||
|
|
||||||
|
<!-- SyncAdapterDriver -->
|
||||||
|
<string name="bind_button">bind</string>
|
||||||
|
<string name="unbind_button">unbind</string>
|
||||||
|
<string name="start_sync_button">start sync</string>
|
||||||
|
<string name="cancel_sync_button">cancel sync</string>
|
||||||
|
<string name="sync_adapters_spinner_label">Registered Sync Adapters:</string>
|
||||||
|
<string name="status_starting_sync_format">Starting a sync of account %s...</string>
|
||||||
|
<string name="status_remote_exception_while_starting_sync">Got a RemoteException while starting the sync</string>
|
||||||
|
<string name="status_canceled_sync">Canceled the sync</string>
|
||||||
|
<string name="status_remote_exception_while_canceling_sync">Got a RemoteException while canceling the sync</string>
|
||||||
|
<string name="status_received_heartbeat">Received heartbeat</string>
|
||||||
|
<string name="status_sync_failed_format">Sync failed: %s</string>
|
||||||
|
<string name="status_sync_succeeded_format">Sync succeeded: %s</string>
|
||||||
|
<string name="status_already_bound">Already bound to sync adapter</string>
|
||||||
|
<string name="status_sync_adapter_not_selected">No selected sync adapter</string>
|
||||||
|
<string name="binding_connected_format">Connected to Sync Adapter\n\tauthority: %s\n\taccount type: %s</string>
|
||||||
|
<string name="binding_not_connected">Not connected to a sync adapter</string>
|
||||||
|
<string name="binding_bind_failed">Bind failed</string>
|
||||||
|
<string name="binding_waiting_for_connection">Waiting for service to be connected...</string>
|
||||||
|
<string name="select_account_to_sync">Select account to sync</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -0,0 +1,373 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.development;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.content.pm.RegisteredServicesCache;
|
||||||
|
import android.content.pm.RegisteredServicesCacheListener;
|
||||||
|
import android.content.SyncAdapterType;
|
||||||
|
import android.content.ISyncAdapter;
|
||||||
|
import android.content.ISyncContext;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.SyncResult;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.accounts.Account;
|
||||||
|
import android.accounts.AccountManager;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class SyncAdapterDriver extends Activity
|
||||||
|
implements RegisteredServicesCacheListener, AdapterView.OnItemClickListener {
|
||||||
|
private Spinner mSyncAdapterSpinner;
|
||||||
|
|
||||||
|
private Button mBindButton;
|
||||||
|
private Button mUnbindButton;
|
||||||
|
private TextView mBoundAdapterTextView;
|
||||||
|
private Button mStartSyncButton;
|
||||||
|
private Button mCancelSyncButton;
|
||||||
|
private TextView mStatusTextView;
|
||||||
|
private Object[] mSyncAdapters;
|
||||||
|
private SyncAdaptersCache mSyncAdaptersCache;
|
||||||
|
private final Object mSyncAdaptersLock = new Object();
|
||||||
|
|
||||||
|
private static final int DIALOG_ID_PICK_ACCOUNT = 1;
|
||||||
|
private ListView mAccountPickerView = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
mSyncAdaptersCache = new SyncAdaptersCache(this);
|
||||||
|
setContentView(R.layout.sync_adapter_driver);
|
||||||
|
|
||||||
|
mSyncAdapterSpinner = (Spinner) findViewById(R.id.sync_adapters_spinner);
|
||||||
|
mBindButton = (Button) findViewById(R.id.bind_button);
|
||||||
|
mUnbindButton = (Button) findViewById(R.id.unbind_button);
|
||||||
|
mBoundAdapterTextView = (TextView) findViewById(R.id.bound_adapter_text_view);
|
||||||
|
|
||||||
|
mStartSyncButton = (Button) findViewById(R.id.start_sync_button);
|
||||||
|
mCancelSyncButton = (Button) findViewById(R.id.cancel_sync_button);
|
||||||
|
|
||||||
|
mStatusTextView = (TextView) findViewById(R.id.status_text_view);
|
||||||
|
|
||||||
|
getSyncAdapters();
|
||||||
|
mSyncAdaptersCache.setListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onDestroy() {
|
||||||
|
mSyncAdaptersCache.close();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getSyncAdapters() {
|
||||||
|
Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> all =
|
||||||
|
mSyncAdaptersCache.getAllServices();
|
||||||
|
synchronized (mSyncAdaptersLock) {
|
||||||
|
mSyncAdapters = new Object[all.size()];
|
||||||
|
String[] names = new String[mSyncAdapters.length];
|
||||||
|
int i = 0;
|
||||||
|
for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> item : all) {
|
||||||
|
mSyncAdapters[i] = item;
|
||||||
|
names[i] = item.type.authority + " - " + item.type.accountType;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayAdapter<String> adapter =
|
||||||
|
new ArrayAdapter<String>(this,
|
||||||
|
R.layout.sync_adapter_item, names);
|
||||||
|
mSyncAdapterSpinner.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateUi() {
|
||||||
|
boolean isBound;
|
||||||
|
boolean hasServiceConnection;
|
||||||
|
synchronized (mServiceConnectionLock) {
|
||||||
|
hasServiceConnection = mActiveServiceConnection != null;
|
||||||
|
isBound = hasServiceConnection && mActiveServiceConnection.mBoundSyncAdapter != null;
|
||||||
|
}
|
||||||
|
mStartSyncButton.setEnabled(isBound);
|
||||||
|
mCancelSyncButton.setEnabled(isBound);
|
||||||
|
mBindButton.setEnabled(!hasServiceConnection);
|
||||||
|
mUnbindButton.setEnabled(hasServiceConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startSyncSelected(View view) {
|
||||||
|
synchronized (mServiceConnectionLock) {
|
||||||
|
ISyncAdapter syncAdapter = null;
|
||||||
|
if (mActiveServiceConnection != null) {
|
||||||
|
syncAdapter = mActiveServiceConnection.mBoundSyncAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncAdapter != null) {
|
||||||
|
removeDialog(DIALOG_ID_PICK_ACCOUNT);
|
||||||
|
|
||||||
|
mAccountPickerView = (ListView) LayoutInflater.from(this).inflate(
|
||||||
|
R.layout.account_list_view, null);
|
||||||
|
mAccountPickerView.setOnItemClickListener(this);
|
||||||
|
Account accounts[] = AccountManager.get(this).getAccountsByType(
|
||||||
|
mActiveServiceConnection.mSyncAdapter.type.accountType);
|
||||||
|
String[] accountNames = new String[accounts.length];
|
||||||
|
for (int i = 0; i < accounts.length; i++) {
|
||||||
|
accountNames[i] = accounts[i].name;
|
||||||
|
}
|
||||||
|
ArrayAdapter<String> adapter =
|
||||||
|
new ArrayAdapter<String>(SyncAdapterDriver.this,
|
||||||
|
android.R.layout.simple_list_item_1, accountNames);
|
||||||
|
mAccountPickerView.setAdapter(adapter);
|
||||||
|
|
||||||
|
showDialog(DIALOG_ID_PICK_ACCOUNT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startSync(String accountName) {
|
||||||
|
synchronized (mServiceConnectionLock) {
|
||||||
|
ISyncAdapter syncAdapter = null;
|
||||||
|
if (mActiveServiceConnection != null) {
|
||||||
|
syncAdapter = mActiveServiceConnection.mBoundSyncAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncAdapter != null) {
|
||||||
|
try {
|
||||||
|
mStatusTextView.setText(
|
||||||
|
getString(R.string.status_starting_sync_format, accountName));
|
||||||
|
Account account = new Account(accountName,
|
||||||
|
mActiveServiceConnection.mSyncAdapter.type.accountType);
|
||||||
|
syncAdapter.startSync(mActiveServiceConnection,
|
||||||
|
mActiveServiceConnection.mSyncAdapter.type.authority,
|
||||||
|
account, new Bundle());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
mStatusTextView.setText(
|
||||||
|
getString(R.string.status_remote_exception_while_starting_sync));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelSync(View view) {
|
||||||
|
synchronized (mServiceConnectionLock) {
|
||||||
|
ISyncAdapter syncAdapter = null;
|
||||||
|
if (mActiveServiceConnection != null) {
|
||||||
|
syncAdapter = mActiveServiceConnection.mBoundSyncAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (syncAdapter != null) {
|
||||||
|
try {
|
||||||
|
mStatusTextView.setText(getString(R.string.status_canceled_sync));
|
||||||
|
syncAdapter.cancelSync(mActiveServiceConnection);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
mStatusTextView.setText(
|
||||||
|
getString(R.string.status_remote_exception_while_canceling_sync));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onRegisteredServicesCacheChanged() {
|
||||||
|
getSyncAdapters();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Dialog onCreateDialog(final int id) {
|
||||||
|
if (id == DIALOG_ID_PICK_ACCOUNT) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setMessage(R.string.select_account_to_sync);
|
||||||
|
builder.setInverseBackgroundForced(true);
|
||||||
|
builder.setView(mAccountPickerView);
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
return super.onCreateDialog(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
TextView item = (TextView) view;
|
||||||
|
final String accountName = item.getText().toString();
|
||||||
|
dismissDialog(DIALOG_ID_PICK_ACCOUNT);
|
||||||
|
startSync(accountName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MyServiceConnection extends ISyncContext.Stub implements ServiceConnection {
|
||||||
|
private volatile ISyncAdapter mBoundSyncAdapter;
|
||||||
|
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> mSyncAdapter;
|
||||||
|
|
||||||
|
public MyServiceConnection(
|
||||||
|
RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter) {
|
||||||
|
mSyncAdapter = syncAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
mBoundSyncAdapter = ISyncAdapter.Stub.asInterface(service);
|
||||||
|
final SyncAdapterType type = mActiveServiceConnection.mSyncAdapter.type;
|
||||||
|
mBoundAdapterTextView.setText(getString(R.string.binding_connected_format,
|
||||||
|
type.authority, type.accountType));
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
mBoundAdapterTextView.setText(getString(R.string.binding_not_connected));
|
||||||
|
mBoundSyncAdapter = null;
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendHeartbeat() {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
uiThreadSendHeartbeat();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiThreadSendHeartbeat() {
|
||||||
|
mStatusTextView.setText(getString(R.string.status_received_heartbeat));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiThreadOnFinished(SyncResult result) {
|
||||||
|
if (result.hasError()) {
|
||||||
|
mStatusTextView.setText(
|
||||||
|
getString(R.string.status_sync_failed_format, result.toString()));
|
||||||
|
} else {
|
||||||
|
mStatusTextView.setText(
|
||||||
|
getString(R.string.status_sync_succeeded_format, result.toString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFinished(final SyncResult result) throws RemoteException {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
uiThreadOnFinished(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Object mServiceConnectionLock = new Object();
|
||||||
|
MyServiceConnection mActiveServiceConnection;
|
||||||
|
|
||||||
|
public void initiateBind(View view) {
|
||||||
|
synchronized (mServiceConnectionLock) {
|
||||||
|
if (mActiveServiceConnection != null) {
|
||||||
|
mStatusTextView.setText(getString(R.string.status_already_bound));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter =
|
||||||
|
getSelectedSyncAdapter();
|
||||||
|
if (syncAdapter == null) {
|
||||||
|
mStatusTextView.setText(getString(R.string.status_sync_adapter_not_selected));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mActiveServiceConnection = new MyServiceConnection(syncAdapter);
|
||||||
|
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setAction("android.content.SyncAdapter");
|
||||||
|
intent.setComponent(syncAdapter.componentName);
|
||||||
|
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
|
||||||
|
com.android.internal.R.string.sync_binding_label);
|
||||||
|
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
|
||||||
|
this, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0));
|
||||||
|
if (!bindService(intent, mActiveServiceConnection, Context.BIND_AUTO_CREATE)) {
|
||||||
|
mBoundAdapterTextView.setText(getString(R.string.binding_bind_failed));
|
||||||
|
mActiveServiceConnection = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mBoundAdapterTextView.setText(getString(R.string.binding_waiting_for_connection));
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initiateUnbind(View view) {
|
||||||
|
synchronized (mServiceConnectionLock) {
|
||||||
|
if (mActiveServiceConnection == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mBoundAdapterTextView.setText("");
|
||||||
|
unbindService(mActiveServiceConnection);
|
||||||
|
mActiveServiceConnection = null;
|
||||||
|
}
|
||||||
|
updateUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RegisteredServicesCache.ServiceInfo<SyncAdapterType> getSelectedSyncAdapter() {
|
||||||
|
synchronized (mSyncAdaptersLock) {
|
||||||
|
final int position = mSyncAdapterSpinner.getSelectedItemPosition();
|
||||||
|
if (position == AdapterView.INVALID_POSITION) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (RegisteredServicesCache.ServiceInfo<SyncAdapterType>)
|
||||||
|
mSyncAdapters[position];
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> {
|
||||||
|
private static final String SERVICE_INTERFACE = "android.content.SyncAdapter";
|
||||||
|
private static final String SERVICE_META_DATA = "android.content.SyncAdapter";
|
||||||
|
private static final String ATTRIBUTES_NAME = "sync-adapter";
|
||||||
|
|
||||||
|
SyncAdaptersCache(Context context) {
|
||||||
|
super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SyncAdapterType parseServiceAttributes(String packageName, AttributeSet attrs) {
|
||||||
|
TypedArray sa = mContext.getResources().obtainAttributes(attrs,
|
||||||
|
com.android.internal.R.styleable.SyncAdapter);
|
||||||
|
try {
|
||||||
|
final String authority =
|
||||||
|
sa.getString(com.android.internal.R.styleable.SyncAdapter_contentAuthority);
|
||||||
|
final String accountType =
|
||||||
|
sa.getString(com.android.internal.R.styleable.SyncAdapter_accountType);
|
||||||
|
if (authority == null || accountType == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final boolean userVisible = sa.getBoolean(
|
||||||
|
com.android.internal.R.styleable.SyncAdapter_userVisible, true);
|
||||||
|
final boolean supportsUploading = sa.getBoolean(
|
||||||
|
com.android.internal.R.styleable.SyncAdapter_supportsUploading, true);
|
||||||
|
return new SyncAdapterType(authority, accountType, userVisible, supportsUploading);
|
||||||
|
} finally {
|
||||||
|
sa.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user