summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitf0d44cd75cfa07df3c9162bc2a03884c21a7fb8f (patch)
treea6c8b7caf143dfc351a56f0f39c5768a9fb6c7e1
downloadGoogleSubscribedFeedsProvider-f0d44cd75cfa07df3c9162bc2a03884c21a7fb8f.tar.gz
-rw-r--r--Android.mk20
-rw-r--r--AndroidManifest.xml61
-rw-r--r--MODULE_LICENSE_APACHE20
-rw-r--r--NOTICE190
-rw-r--r--res/drawable/app_icon.pngbin0 -> 4001 bytes
-rw-r--r--res/drawable/ic_list_sync_anim.xml28
-rw-r--r--res/drawable/ic_list_sync_anim0.pngbin0 -> 1862 bytes
-rw-r--r--res/drawable/ic_list_sync_anim1.pngbin0 -> 1872 bytes
-rw-r--r--res/drawable/ic_list_sync_anim2.pngbin0 -> 1917 bytes
-rw-r--r--res/drawable/ic_list_sync_anim3.pngbin0 -> 1848 bytes
-rw-r--r--res/drawable/ic_list_syncerror.pngbin0 -> 2063 bytes
-rw-r--r--res/drawable/ic_menu_refresh.pngbin0 -> 2450 bytes
-rw-r--r--res/layout/preference_widget_sync_toggle.xml56
-rw-r--r--res/layout/sync_settings_list_content.xml35
-rw-r--r--res/values-cs/strings.xml12
-rw-r--r--res/values-de-rDE/strings.xml20
-rw-r--r--res/values-en-rGB/strings.xml23
-rw-r--r--res/values-es-rUS/strings.xml20
-rw-r--r--res/values-fr-rFR/strings.xml20
-rw-r--r--res/values-it-rIT/strings.xml20
-rw-r--r--res/values-nl-rNL/strings.xml12
-rw-r--r--res/values-zh-rTW/strings.xml20
-rw-r--r--res/values/strings.xml38
-rw-r--r--res/xml/sync_settings.xml44
-rw-r--r--src/com/android/providers/subscribedfeeds/GoogleSubscribedFeedsProvider.java31
-rw-r--r--src/com/android/providers/subscribedfeeds/SubscribedFeedsSyncAdapter.java244
-rw-r--r--src/com/android/settings/SyncActivityTooManyDeletes.java120
-rw-r--r--src/com/android/settings/SyncSettings.java391
-rw-r--r--src/com/android/settings/SyncStateCheckBoxPreference.java95
29 files changed, 1500 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..5e01e84
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := user
+
+base_packages := ../../../frameworks/base/packages
+source_files := $(base_packages)/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsProvider.java
+source_files += $(base_packages)/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsService.java
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files) $(source_files)
+
+# We depend on googlelogin-client also, but that is already being included by google-framework
+LOCAL_STATIC_JAVA_LIBRARIES := google-framework
+
+LOCAL_OVERRIDES_PACKAGES := SubscribedFeedsProvider
+
+LOCAL_PACKAGE_NAME := GoogleSubscribedFeedsProvider
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..62c0731
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,61 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.providers.subscribedfeeds"
+ android:sharedUserId="android.uid.system">
+
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.cp" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.cl" />
+ <uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.mail" />
+ <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
+ <uses-permission android:name="android.permission.READ_SYNC_STATS" />
+ <uses-permission android:name="android.permission.SUBSCRIBED_FEEDS_READ" />
+ <uses-permission android:name="android.permission.SUBSCRIBED_FEEDS_WRITE" />
+
+ <application android:process="system"
+ android:allowClearUserData="false"
+ android:icon="@drawable/app_icon"
+ android:label="Sync Feeds">
+
+ <uses-library android:name="com.google.android.gtalkservice" />
+
+ <activity android:name="com.android.settings.SyncSettings" android:label="@string/sync_settings"
+ android:theme="@android:style/Theme.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.settings.SYNC_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="com.android.settings.SyncActivityTooManyDeletes"
+ android:theme="@android:style/Theme.Dialog"
+ android:label="@string/sync_too_many_deletes">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <provider android:name="SubscribedFeedsProvider"
+ android:authorities="subscribedfeeds" android:syncable="true"
+ android:multiprocess="false"
+ android:readPermission="android.permission.SUBSCRIBED_FEEDS_READ"
+ android:writePermission="android.permission.SUBSCRIBED_FEEDS_WRITE" />
+
+ <receiver android:name="SubscribedFeedsService">
+ <intent-filter>
+ <action android:name="android.intent.action.GTALK_DATA_MESSAGE_RECEIVED" />
+ <category android:name="GSYNC_TICKLE"/>
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="com.android.subscribedfeeds.action.REFRESH" />
+ </intent-filter>
+ </receiver>
+
+ </application>
+</manifest>
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/res/drawable/app_icon.png b/res/drawable/app_icon.png
new file mode 100644
index 0000000..13d8cdd
--- /dev/null
+++ b/res/drawable/app_icon.png
Binary files differ
diff --git a/res/drawable/ic_list_sync_anim.xml b/res/drawable/ic_list_sync_anim.xml
new file mode 100644
index 0000000..b6965c5
--- /dev/null
+++ b/res/drawable/ic_list_sync_anim.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/drawable/status_icon_background.xml
+**
+** Copyright 2007, 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.
+*/
+-->
+<animation-list
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false">
+ <item android:drawable="@drawable/ic_list_sync_anim0" android:duration="150" />
+ <item android:drawable="@drawable/ic_list_sync_anim1" android:duration="150" />
+ <item android:drawable="@drawable/ic_list_sync_anim2" android:duration="150" />
+ <item android:drawable="@drawable/ic_list_sync_anim3" android:duration="150" />
+</animation-list>
+
diff --git a/res/drawable/ic_list_sync_anim0.png b/res/drawable/ic_list_sync_anim0.png
new file mode 100644
index 0000000..981a72e
--- /dev/null
+++ b/res/drawable/ic_list_sync_anim0.png
Binary files differ
diff --git a/res/drawable/ic_list_sync_anim1.png b/res/drawable/ic_list_sync_anim1.png
new file mode 100644
index 0000000..4581ba2
--- /dev/null
+++ b/res/drawable/ic_list_sync_anim1.png
Binary files differ
diff --git a/res/drawable/ic_list_sync_anim2.png b/res/drawable/ic_list_sync_anim2.png
new file mode 100644
index 0000000..b745916
--- /dev/null
+++ b/res/drawable/ic_list_sync_anim2.png
Binary files differ
diff --git a/res/drawable/ic_list_sync_anim3.png b/res/drawable/ic_list_sync_anim3.png
new file mode 100644
index 0000000..43e453d
--- /dev/null
+++ b/res/drawable/ic_list_sync_anim3.png
Binary files differ
diff --git a/res/drawable/ic_list_syncerror.png b/res/drawable/ic_list_syncerror.png
new file mode 100644
index 0000000..328b6a7
--- /dev/null
+++ b/res/drawable/ic_list_syncerror.png
Binary files differ
diff --git a/res/drawable/ic_menu_refresh.png b/res/drawable/ic_menu_refresh.png
new file mode 100644
index 0000000..77d70dd
--- /dev/null
+++ b/res/drawable/ic_menu_refresh.png
Binary files differ
diff --git a/res/layout/preference_widget_sync_toggle.xml b/res/layout/preference_widget_sync_toggle.xml
new file mode 100644
index 0000000..94f4065
--- /dev/null
+++ b/res/layout/preference_widget_sync_toggle.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 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.
+-->
+
+<!-- Layout used by SyncStateCheckBoxPreference. This is inflated
+ inside android.R.layout.preference. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical">
+
+ <ImageView
+ android:id="@+android:id/sync_failed"
+ android:src="@drawable/ic_list_syncerror"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="6sp"
+ android:layout_marginBottom="2sp"
+ android:layout_height="wrap_content" />
+
+ <ImageView
+ android:id="@+android:id/sync_active"
+ android:src="@drawable/ic_list_sync_anim"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="6sp"
+ android:layout_marginBottom="2sp"
+ android:layout_height="wrap_content" />
+
+ <ImageView
+ android:id="@+android:id/sync_pending"
+ android:src="@drawable/ic_list_sync_anim0"
+ android:layout_width="wrap_content"
+ android:layout_marginLeft="6sp"
+ android:layout_marginBottom="2sp"
+ android:layout_height="wrap_content" />
+
+ <CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+android:id/checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="4sp"
+ android:layout_gravity="center_vertical"
+ android:focusable="false"
+ android:clickable="false" />
+</LinearLayout>
diff --git a/res/layout/sync_settings_list_content.xml b/res/layout/sync_settings_list_content.xml
new file mode 100644
index 0000000..9573d36
--- /dev/null
+++ b/res/layout/sync_settings_list_content.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/layout/list_content.xml
+**
+** Copyright 2006, 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:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:drawSelectorOnTop="false"
+ android:scrollbarAlwaysDrawVerticalTrack="true"
+ />
+ <TextView android:id="@+id/sync_settings_error_info"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/sync_is_failing" />
+</LinearLayout>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
new file mode 100644
index 0000000..0220f2b
--- /dev/null
+++ b/res/values-cs/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sync_calendar">Kalendář</string>
+ <string name="sync_contacts">Kontakty</string>
+ <string name="sync_disabled">Vypnuto</string>
+ <string name="sync_enabled">Synchronizace se serverem Google povolena</string>
+ <string name="sync_gmail">Gmail</string>
+ <string name="sync_menu_sync_cancel">Zrušit synchronizaci</string>
+ <string name="sync_menu_sync_now">Synchronizovat</string>
+ <string name="sync_settings">Synchronizace</string>
+</resources>
diff --git a/res/values-de-rDE/strings.xml b/res/values-de-rDE/strings.xml
new file mode 100644
index 0000000..c4b6564
--- /dev/null
+++ b/res/values-de-rDE/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sync_automatically">Automatische Synchronisierung</string>
+ <string name="sync_calendar">Kalender</string>
+ <string name="sync_contacts">Kontakte</string>
+ <string name="sync_disabled">Auswählen, um Daten automatisch zu synchronisieren</string>
+ <string name="sync_do_nothing">Diesmal nichts tun.</string>
+ <string name="sync_enabled">Daten automatisch synchronisieren</string>
+ <string name="sync_gmail">Gmail</string>
+ <string name="sync_is_failing">Bei der Synchronisierung gibt es derzeit Probleme. Wird in Kürze fortgesetzt.</string>
+ <string name="sync_menu_sync_cancel">Synchr. abbrechen</string>
+ <string name="sync_menu_sync_now">Jetzt synchronisieren</string>
+ <string name="sync_really_delete">Diese Elemente löschen.</string>
+ <string name="sync_settings">Datensynchronisierung</string>
+ <string name="sync_settings_summary">Auswählen, welche Anwendungen synchronisiert werden</string>
+ <string name="sync_too_many_deletes">Limit für Löschung überschritten</string>
+ <string name="sync_too_many_deletes_desc">Es gibt %d gelöschte Elemente für %s, Konto %s. Was möchten Sie tun?</string>
+ <string name="sync_undo_deletes">Löschungen rückgängig machen.</string>
+</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..db6f9a7
--- /dev/null
+++ b/res/values-en-rGB/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2007 Google Inc.
+ *
+ * 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.
+ */
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Sync settings -->
+ <string name="sync_gmail">Google Mail</string>
+</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..e52853c
--- /dev/null
+++ b/res/values-es-rUS/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sync_automatically">Sincronización automática</string>
+ <string name="sync_calendar">Calendario</string>
+ <string name="sync_contacts">Contactos</string>
+ <string name="sync_disabled">Seleccione la sincronización automática de datos</string>
+ <string name="sync_do_nothing">No hacer nada por el momento.</string>
+ <string name="sync_enabled">Sincronización automática de datos</string>
+ <string name="sync_gmail">Gmail</string>
+ <string name="sync_is_failing">La sincronización presenta algunos problemas. Se solucionarán en breve. </string>
+ <string name="sync_menu_sync_cancel">Cancelar sincronización</string>
+ <string name="sync_menu_sync_now">Sincronizar ahora</string>
+ <string name="sync_really_delete">Eliminar los elementos.</string>
+ <string name="sync_settings">Sincronización de datos</string>
+ <string name="sync_settings_summary">Seleccionar qué aplicaciones están sincronizadas</string>
+ <string name="sync_too_many_deletes">Eliminar límite excedido</string>
+ <string name="sync_too_many_deletes_desc">Hay %d elementos eliminados en %s, cuenta %s. ¿Qué quiere hacer?</string>
+ <string name="sync_undo_deletes">Deshacer lo eliminado.</string>
+</resources>
diff --git a/res/values-fr-rFR/strings.xml b/res/values-fr-rFR/strings.xml
new file mode 100644
index 0000000..3b2dfa1
--- /dev/null
+++ b/res/values-fr-rFR/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sync_automatically">Auto-synchroniser</string>
+ <string name="sync_calendar">Agenda</string>
+ <string name="sync_contacts">Contacts</string>
+ <string name="sync_disabled">Sélectionner pour synchroniser automatiquement les données</string>
+ <string name="sync_do_nothing">Ne rien faire maintenant.</string>
+ <string name="sync_enabled">Synchroniser automatiquement les données</string>
+ <string name="sync_gmail">Gmail</string>
+ <string name="sync_is_failing">Il y a actuellement des problèmes de synchronisation. Elle sera de retour rapidement.</string>
+ <string name="sync_menu_sync_cancel">Annuler la synchronisation</string>
+ <string name="sync_menu_sync_now">Synchroniser maintenant</string>
+ <string name="sync_really_delete">Supprimez les éléments.</string>
+ <string name="sync_settings">Synchronisation données</string>
+ <string name="sync_settings_summary">Sélectionnez les applications à synchroniser</string>
+ <string name="sync_too_many_deletes">Limite de suppression dépassée</string>
+ <string name="sync_too_many_deletes_desc">Il y a %d éléments supprimés pour %s, compte %s. Que souhaitez-vous faire ?</string>
+ <string name="sync_undo_deletes">Annulez les suppressions.</string>
+</resources>
diff --git a/res/values-it-rIT/strings.xml b/res/values-it-rIT/strings.xml
new file mode 100644
index 0000000..98389c4
--- /dev/null
+++ b/res/values-it-rIT/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sync_automatically">Sincronizzazione automatica</string>
+ <string name="sync_calendar">Calendario</string>
+ <string name="sync_contacts">Contatti</string>
+ <string name="sync_disabled">Selezionare per sincronizzare i dati automaticamente</string>
+ <string name="sync_do_nothing">Non eseguire alcuna operazione per ora.</string>
+ <string name="sync_enabled">Sincronizza dati automaticamente</string>
+ <string name="sync_gmail">Gmail</string>
+ <string name="sync_is_failing">La sincronizzazione presenta dei problemi. L'operazione verrà presto ripristinata.</string>
+ <string name="sync_menu_sync_cancel">Annulla sincronizzazione</string>
+ <string name="sync_menu_sync_now">Sincronizza ora</string>
+ <string name="sync_really_delete">Eliminare gli elementi.</string>
+ <string name="sync_settings">Sincronizzazione dati</string>
+ <string name="sync_settings_summary">Scegliere le applicazioni sincronizzate</string>
+ <string name="sync_too_many_deletes">Limite di eliminazioni superato</string>
+ <string name="sync_too_many_deletes_desc">Esistono %d elementi eliminati per %s, account %s. Specificare l'operazione da eseguire.</string>
+ <string name="sync_undo_deletes">Annullare le eliminazioni.</string>
+</resources>
diff --git a/res/values-nl-rNL/strings.xml b/res/values-nl-rNL/strings.xml
new file mode 100644
index 0000000..dc566da
--- /dev/null
+++ b/res/values-nl-rNL/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sync_calendar">Agenda</string>
+ <string name="sync_contacts">Contacten</string>
+ <string name="sync_disabled">Uit</string>
+ <string name="sync_enabled">Synchroniseren met Google-server ingeschakeld</string>
+ <string name="sync_gmail">Gmail</string>
+ <string name="sync_menu_sync_cancel">Synchroniseren annuleren</string>
+ <string name="sync_menu_sync_now">Nu synchroniseren</string>
+ <string name="sync_settings">Synchronisatie</string>
+</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..b66d294
--- /dev/null
+++ b/res/values-zh-rTW/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sync_automatically">自動同步</string>
+ <string name="sync_calendar">行事曆</string>
+ <string name="sync_contacts">連絡人</string>
+ <string name="sync_disabled">選取自動同步資料</string>
+ <string name="sync_do_nothing">目前不執行任何動作。</string>
+ <string name="sync_enabled">自動同步資料</string>
+ <string name="sync_gmail">Gmail</string>
+ <string name="sync_is_failing">同步目前發生問題。將會立即恢復正常。</string>
+ <string name="sync_menu_sync_cancel">取消同步</string>
+ <string name="sync_menu_sync_now">立即同步</string>
+ <string name="sync_really_delete">刪除項目。</string>
+ <string name="sync_settings">資料同步</string>
+ <string name="sync_settings_summary">選取要同步的應用程式</string>
+ <string name="sync_too_many_deletes">已經超過刪除上限</string>
+ <string name="sync_too_many_deletes_desc">%d 個 %s 刪除的項目,來自 %s 帳號。處理的方式為?</string>
+ <string name="sync_undo_deletes">復原刪除的項目。</string>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..9413a67
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2007 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.
+ */
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Sync settings -->
+ <string name="sync_settings">Data synchronization</string>
+ <string name="sync_settings_summary">Select which applications are synchronized</string>
+ <string name="sync_too_many_deletes">Delete limit exceeded</string>
+ <string name="sync_automatically">Auto-sync</string>
+ <string name="sync_enabled">Automatically sync data</string>
+ <string name="sync_disabled">Select to automatically sync data</string>
+ <string name="sync_menu_sync_now">Sync now</string>
+ <string name="sync_menu_sync_cancel">Cancel sync</string>
+ <string name="sync_gmail">Gmail</string>
+ <string name="sync_calendar">Calendar</string>
+ <string name="sync_contacts">Contacts</string>
+ <string name="sync_too_many_deletes_desc">There are %d deleted items for %s, account %s. What would you like to do?</string>
+ <string name="sync_really_delete">Delete the items.</string>
+ <string name="sync_undo_deletes">Undo the deletes.</string>
+ <string name="sync_do_nothing">Do nothing for now.</string>
+ <string name="sync_is_failing">Sync is currently experiencing problems. It will be back shortly.</string>
+</resources>
diff --git a/res/xml/sync_settings.xml b/res/xml/sync_settings.xml
new file mode 100644
index 0000000..1bc3421
--- /dev/null
+++ b/res/xml/sync_settings.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceCategory
+ android:title="@string/sync_settings" />
+
+ <CheckBoxPreference android:key="autoSyncCheckBox"
+ android:persistent="false"
+ android:title="@string/sync_automatically"
+ android:summaryOn="@string/sync_enabled"
+ android:summaryOff="@string/sync_disabled"/>
+ <!-- The following keys are special. They correspond to
+ content providers sans the "sync_" prefix. This is
+ because very specific content providers are being
+ enabled for sync in this release.
+ -->
+ <com.android.settings.SyncStateCheckBoxPreference android:key="sync_gmail-ls"
+ android:persistent="false"
+ android:title="@string/sync_gmail"
+ android:summary="" />
+ <com.android.settings.SyncStateCheckBoxPreference android:key="sync_calendar"
+ android:persistent="false"
+ android:title="@string/sync_calendar"
+ android:summary="" />
+ <com.android.settings.SyncStateCheckBoxPreference android:key="sync_contacts"
+ android:persistent="false"
+ android:title="@string/sync_contacts"
+ android:summary="" />
+</PreferenceScreen>
diff --git a/src/com/android/providers/subscribedfeeds/GoogleSubscribedFeedsProvider.java b/src/com/android/providers/subscribedfeeds/GoogleSubscribedFeedsProvider.java
new file mode 100644
index 0000000..87e6364
--- /dev/null
+++ b/src/com/android/providers/subscribedfeeds/GoogleSubscribedFeedsProvider.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 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.providers.subscribedfeeds;
+
+import android.content.SyncAdapter;
+
+public class GoogleSubscribedFeedsProvider extends SubscribedFeedsProvider {
+ private SubscribedFeedsSyncAdapter mSyncAdapter;
+
+ @Override
+ public synchronized SyncAdapter getSyncAdapter() {
+ if (mSyncAdapter == null) {
+ mSyncAdapter = new SubscribedFeedsSyncAdapter(getContext(), this);
+ }
+ return mSyncAdapter;
+ }
+} \ No newline at end of file
diff --git a/src/com/android/providers/subscribedfeeds/SubscribedFeedsSyncAdapter.java b/src/com/android/providers/subscribedfeeds/SubscribedFeedsSyncAdapter.java
new file mode 100644
index 0000000..355b95e
--- /dev/null
+++ b/src/com/android/providers/subscribedfeeds/SubscribedFeedsSyncAdapter.java
@@ -0,0 +1,244 @@
+/*
+** Copyright 2007, 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,
+** See the License for the specific language governing permissions and
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** limitations under the License.
+*/
+
+package com.android.providers.subscribedfeeds;
+
+import com.google.android.gdata.client.AndroidGDataClient;
+import com.google.android.gdata.client.AndroidXmlParserFactory;
+import com.google.android.googlelogin.GoogleLoginServiceBlockingHelper;
+import com.google.android.googlelogin.GoogleLoginServiceNotFoundException;
+import com.google.android.providers.AbstractGDataSyncAdapter;
+import com.google.wireless.gdata.client.GDataServiceClient;
+import com.google.wireless.gdata.client.QueryParams;
+import com.google.wireless.gdata.data.Entry;
+import com.google.wireless.gdata.data.Feed;
+import com.google.wireless.gdata.parser.ParseException;
+import com.google.wireless.gdata.subscribedfeeds.client.SubscribedFeedsClient;
+import com.google.wireless.gdata.subscribedfeeds.data.FeedUrl;
+import com.google.wireless.gdata.subscribedfeeds.data.SubscribedFeedsEntry;
+import com.google.wireless.gdata.subscribedfeeds.parser.xml.XmlSubscribedFeedsGDataParserFactory;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SyncContext;
+import android.content.SyncResult;
+import android.content.SyncStats;
+import android.content.SyncableContentProvider;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.provider.SubscribedFeeds;
+import android.util.Log;
+
+/**
+ * Implements a SyncAdapter for SubscribedFeeds
+ */
+public class SubscribedFeedsSyncAdapter extends AbstractGDataSyncAdapter {
+ private final SubscribedFeedsClient mSubscribedFeedsClient;
+
+ private final static String FEED_URL = "https://android.clients.google.com/gsync/sub";
+
+ private static final String ROUTINGINFO_PARAMETER = "routinginfo";
+
+ protected SubscribedFeedsSyncAdapter(Context context, SyncableContentProvider provider) {
+ super(context, provider);
+ mSubscribedFeedsClient =
+ new SubscribedFeedsClient(
+ new AndroidGDataClient(context.getContentResolver()),
+ new XmlSubscribedFeedsGDataParserFactory(
+ new AndroidXmlParserFactory()));
+ }
+
+ @Override
+ protected GDataServiceClient getGDataServiceClient() {
+ return mSubscribedFeedsClient;
+ }
+
+ protected boolean handleAllDeletedUnavailable(GDataSyncData syncData, String feed) {
+ Log.w(TAG, "subscribed feeds don't use tombstones");
+
+ // this should never happen, but if it does pretend that we are able to handle it.
+ return true;
+ }
+
+ /*
+ * Takes the entry, casts it to a SubscribedFeedsEntry and executes the
+ * appropriate actions on the ContentProvider to represent the entry.
+ */
+ @Override
+ protected void updateProvider(Feed feed,
+ long syncLocalId,
+ boolean forceDelete, Entry baseEntry,
+ ContentProvider provider,
+ Object syncInfo) throws ParseException {
+
+ final SubscribedFeedsEntry entry = (SubscribedFeedsEntry) baseEntry;
+ final String editUri = entry.getEditUri();
+
+ if (forceDelete) {
+ final String serverId =
+ editUri.substring(editUri.lastIndexOf('/') + 1);
+ // Store the info about the subscribed feed
+ ContentValues values = new ContentValues();
+ values.put(SubscribedFeeds.Feeds._SYNC_ID, serverId);
+ provider.insert(SubscribedFeeds.Feeds.DELETED_CONTENT_URI, values);
+ return;
+ }
+
+ final String serverId = entry.getId().substring(entry.getId().lastIndexOf('/') + 1);
+ final String version = editUri.substring(editUri.lastIndexOf('/') + 1);
+
+ // Store the info about the person
+ ContentValues values = new ContentValues();
+ values.put(SubscribedFeeds.Feeds.FEED, entry.getSubscribedFeed().getFeed());
+ values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT, getAccount());
+ values.put(SubscribedFeeds.Feeds._SYNC_ID, serverId);
+ values.put(SubscribedFeeds.Feeds._SYNC_DIRTY, "0");
+ values.put(SubscribedFeeds.Feeds._SYNC_LOCAL_ID, syncLocalId);
+ values.put(SubscribedFeeds.Feeds._SYNC_TIME, version);
+ values.put(SubscribedFeeds.Feeds._SYNC_VERSION, version);
+ provider.insert(SubscribedFeeds.Feeds.CONTENT_URI, values);
+ }
+
+ @Override
+ protected String getFeedUrl(String account) {
+ return FEED_URL;
+ }
+
+ protected Class getFeedEntryClass() {
+ return SubscribedFeedsEntry.class;
+ }
+
+ @Override
+ protected void updateQueryParameters(QueryParams params) {
+ params.setParamValue(ROUTINGINFO_PARAMETER, getRoutingInfoForAccount(getAccount()));
+ }
+
+ @Override
+ protected Entry newEntry() {
+ return new SubscribedFeedsEntry();
+ }
+
+ /* (non-Javadoc)
+ * @see android.content.SyncAdapter#getServerDiffs
+ */
+ @Override
+ public void getServerDiffs(SyncContext context, SyncData syncData,
+ SyncableContentProvider tempProvider,
+ Bundle extras, Object syncInfo, SyncResult syncResult) {
+ tempProvider.setContainsDiffs(false /* the server returns all records, not just diffs */);
+ super.getServerDiffs(context, syncData, tempProvider, extras, syncInfo, syncResult);
+ }
+
+ public void onAccountsChanged(String[] accounts) {
+ // no need to do anything
+ }
+
+ @Override
+ protected Cursor getCursorForTable(ContentProvider cp, Class entryClass) {
+ if (entryClass != SubscribedFeedsEntry.class) {
+ throw new IllegalArgumentException("unexpected entry class, " + entryClass.getName());
+ }
+ return cp.query(SubscribedFeeds.Feeds.CONTENT_URI, null, null, null, null);
+ }
+
+ @Override
+ protected Cursor getCursorForDeletedTable(ContentProvider cp, Class entryClass) {
+ if (entryClass != SubscribedFeedsEntry.class) {
+ throw new IllegalArgumentException("unexpected entry class, " + entryClass.getName());
+ }
+ return cp.query(SubscribedFeeds.Feeds.DELETED_CONTENT_URI, null, null, null, null);
+ }
+
+ @Override
+ protected String cursorToEntry(SyncContext context,
+ Cursor c, Entry baseEntry, Object syncInfo) throws ParseException {
+ final String account = c.getString(c.getColumnIndex(SubscribedFeeds.Feeds._SYNC_ACCOUNT));
+ final String service = c.getString(c.getColumnIndex(SubscribedFeeds.Feeds.SERVICE));
+ final String id = c.getString(c.getColumnIndex(SubscribedFeeds.Feeds._SYNC_ID));
+ final String feed = c.getString(c.getColumnIndex(SubscribedFeeds.Feeds.FEED));
+
+ String authToken;
+ try {
+ authToken =
+ GoogleLoginServiceBlockingHelper.getAuthToken(getContext(), account, service);
+ } catch (GoogleLoginServiceBlockingHelper.AuthenticationException e) {
+ Log.e("Sync", "caught exception while attempting to get an " +
+ "authtoken for account " + account +
+ ", service " + service + ": " + e.toString());
+ throw new ParseException(e.getMessage(), e);
+ } catch (GoogleLoginServiceNotFoundException e) {
+ Log.e("Sync", "caught exception while attempting to get an " +
+ "authtoken for account " + account +
+ ", service " + service + ": " + e.toString());
+ throw new ParseException(e.getMessage(), e);
+ }
+
+ FeedUrl subscribedFeedUrl = new FeedUrl(feed, service, authToken);
+ SubscribedFeedsEntry entry = (SubscribedFeedsEntry) baseEntry;
+ if (id != null) {
+ entry.setId(getFeedUrl(account) + "/" + id);
+ entry.setEditUri(entry.getId());
+ }
+ entry.setRoutingInfo(getRoutingInfoForAccount(account));
+ entry.setSubscribedFeed(subscribedFeedUrl);
+ entry.setClientToken(subscribedFeedUrl.getFeed());
+
+ String createUrl = null;
+ if (id == null) {
+ createUrl = getFeedUrl(account);
+ }
+ return createUrl;
+ }
+
+ @Override
+ protected void deletedCursorToEntry(SyncContext context, Cursor c, Entry entry) {
+ final String id = c.getString(c.getColumnIndexOrThrow(SubscribedFeeds.Feeds._SYNC_ID));
+ entry.setId(id);
+ entry.setEditUri(getFeedUrl(getAccount()) + "/" + id);
+ }
+
+ /**
+ * Returns a string that can be used by the GSyncSubscriptionServer to
+ * route messages back to this account via GTalkService.
+ * TODO: this should eventually move into a general place so that others
+ * can use it.
+ *
+ * @param account the account whose routing info we want
+ * @return the GSyncSubscriptionServer routing string for this account
+ */
+ public String getRoutingInfoForAccount(String account) {
+ long androidId;
+ try {
+ androidId = GoogleLoginServiceBlockingHelper.getAndroidId(getContext());
+ } catch (GoogleLoginServiceNotFoundException e) {
+ Log.e(TAG, "Could not get routing info for account", e);
+ return null;
+ }
+ return Uri.parse("gtalk://" + account
+ + "#" + Settings.getGTalkDeviceId(androidId)).toString();
+ }
+
+ @Override
+ protected boolean hasTooManyDeletions(SyncStats stats) {
+ // allow subscribed feeds to delete any number of entries,
+ // since the client is the authority on which entries
+ // should exist.
+ return false;
+ }
+}
diff --git a/src/com/android/settings/SyncActivityTooManyDeletes.java b/src/com/android/settings/SyncActivityTooManyDeletes.java
new file mode 100644
index 0000000..3195ea3
--- /dev/null
+++ b/src/com/android/settings/SyncActivityTooManyDeletes.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2007 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.settings;
+
+import com.android.providers.subscribedfeeds.R;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+/**
+ * Presents multiple options for handling the case where a sync was aborted because there
+ * were too many pending deletes. One option is to force the delete, another is to rollback
+ * the deletes, the third is to do nothing.
+ */
+public class SyncActivityTooManyDeletes extends Activity
+ implements AdapterView.OnItemClickListener {
+
+ private long mNumDeletes;
+ private String mAccount;
+ private String mProvider;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Bundle extras = getIntent().getExtras();
+ if (extras == null) {
+ finish();
+ return;
+ }
+
+ mNumDeletes = extras.getLong("numDeletes");
+ mAccount = extras.getString("account");
+ mProvider = extras.getString("provider");
+
+ // the order of these must match up with the constants for position used in onItemClick
+ CharSequence[] options = new CharSequence[]{
+ getResources().getText(R.string.sync_really_delete),
+ getResources().getText(R.string.sync_undo_deletes),
+ getResources().getText(R.string.sync_do_nothing)
+ };
+
+ ListAdapter adapter = new ArrayAdapter<CharSequence>(this,
+ android.R.layout.simple_list_item_1,
+ android.R.id.text1,
+ options);
+
+ ListView listView = new ListView(this);
+ listView.setAdapter(adapter);
+ listView.setItemsCanFocus(true);
+ listView.setOnItemClickListener(this);
+
+ TextView textView = new TextView(this);
+ CharSequence tooManyDeletesDescFormat =
+ getResources().getText(R.string.sync_too_many_deletes_desc);
+ textView.setText(String.format(tooManyDeletesDescFormat.toString(),
+ mNumDeletes, mProvider, mAccount));
+
+ final LinearLayout ll = new LinearLayout(this);
+ ll.setOrientation(LinearLayout.VERTICAL);
+ final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0);
+ ll.addView(textView, lp);
+ ll.addView(listView, lp);
+ setContentView(ll);
+ }
+
+ public void onItemClick(AdapterView parent, View view, int position, long id) {
+ // the contants for position correspond to the items options array in onCreate()
+ if (position == 0) startSyncReallyDelete();
+ else if (position == 1) startSyncUndoDeletes();
+ finish();
+ }
+
+ private void startSyncReallyDelete() {
+ Uri uri = Uri.parse("content://" + mProvider);
+ Bundle extras = new Bundle();
+ extras.putString(ContentResolver.SYNC_EXTRAS_ACCOUNT, mAccount);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS, true);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_FORCE, true);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
+ getContentResolver().startSync(uri, extras);
+ }
+
+ private void startSyncUndoDeletes() {
+ Uri uri = Uri.parse("content://" + mProvider);
+ Bundle extras = new Bundle();
+ extras.putString(ContentResolver.SYNC_EXTRAS_ACCOUNT, mAccount);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS, true);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_FORCE, true);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
+ getContentResolver().startSync(uri, extras);
+ }
+}
diff --git a/src/com/android/settings/SyncSettings.java b/src/com/android/settings/SyncSettings.java
new file mode 100644
index 0000000..ec2c365
--- /dev/null
+++ b/src/com/android/settings/SyncSettings.java
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2008 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.settings;
+
+import com.android.providers.subscribedfeeds.R;
+
+import android.app.ActivityThread;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Intent;
+import android.content.pm.ProviderInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.pim.DateFormat;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceScreen;
+import android.provider.Sync;
+import android.provider.SubscribedFeeds;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Observable;
+import java.util.Observer;
+
+public class SyncSettings
+ extends PreferenceActivity
+ implements Observer {
+
+ List<String> mProviderNames;
+ List<ProviderInfo> mProviderInfos;
+
+ CheckBoxPreference mAutoSyncCheckBox;
+ TextView mErrorInfoView;
+
+ java.text.DateFormat mDateFormat;
+ java.text.DateFormat mTimeFormat;
+
+ private static final String SYNC_CONNECTION_SETTING_CHANGED
+ = "com.android.sync.SYNC_CONN_STATUS_CHANGED";
+
+ private static final String SYNC_KEY_PREFIX = "sync_";
+ private static final String SYNC_CHECKBOX_KEY = "autoSyncCheckBox";
+
+ Sync.Settings.QueryMap mSyncSettings;
+
+ private static final int MENU_SYNC_NOW_ID = Menu.FIRST;
+ private static final int MENU_SYNC_CANCEL_ID = Menu.FIRST + 1;
+
+ private Sync.Active.QueryMap mActiveSyncQueryMap = null;
+ private Sync.Status.QueryMap mStatusSyncQueryMap = null;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.sync_settings_list_content);
+ addPreferencesFromResource(R.xml.sync_settings);
+
+ mErrorInfoView = (TextView)findViewById(R.id.sync_settings_error_info);
+ mErrorInfoView.setVisibility(View.GONE);
+ mErrorInfoView.setCompoundDrawablesWithIntrinsicBounds(
+ getResources().getDrawable(R.drawable.ic_list_syncerror), null, null, null);
+
+ mDateFormat = DateFormat.getDateFormat(this);
+ mTimeFormat = DateFormat.getTimeFormat(this);
+
+ mStatusSyncQueryMap = new Sync.Status.QueryMap(getContentResolver(),
+ false /* don't keep updated yet, we will change this in onResume()/onPause() */,
+ null /* use this thread's handler for notifications */);
+ mStatusSyncQueryMap.addObserver(mSyncSuccessesObserver);
+
+ mActiveSyncQueryMap = new Sync.Active.QueryMap(getContentResolver(),
+ false /* don't keep updated yet, we will change this in onResume()/onPause() */,
+ null /* use this thread's handler for notifications */);
+ mActiveSyncQueryMap.addObserver(mSyncActiveObserver);
+
+ mSyncSettings = new Sync.Settings.QueryMap(getContentResolver(),
+ true /* keep updated */, null);
+ mSyncSettings.addObserver(this);
+
+ mAutoSyncCheckBox = (CheckBoxPreference) findPreference(SYNC_CHECKBOX_KEY);
+ initProviders();
+ initUI();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ menu.add(0, MENU_SYNC_NOW_ID, 0, getString(R.string.sync_menu_sync_now))
+ .setIcon(R.drawable.ic_menu_refresh);
+ menu.add(0, MENU_SYNC_CANCEL_ID, 0, getString(R.string.sync_menu_sync_cancel))
+ .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ final boolean syncActive = mActiveSyncQueryMap.getActiveSyncInfo() != null;
+ menu.findItem(MENU_SYNC_NOW_ID).setVisible(!syncActive);
+ menu.findItem(MENU_SYNC_CANCEL_ID).setVisible(syncActive);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_SYNC_NOW_ID:
+ startSyncForEnabledProviders();
+ return true;
+ case MENU_SYNC_CANCEL_ID:
+ cancelSyncForEnabledProviders();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void initProviders() {
+ mProviderNames = new ArrayList<String>();
+ mProviderInfos = new ArrayList<ProviderInfo>();
+
+ try {
+ ActivityThread.getPackageManager().querySyncProviders(mProviderNames,
+ mProviderInfos);
+ } catch (RemoteException e) {
+ }
+ /*
+ for (int i = 0; i < mProviderNames.size(); i++) {
+ Log.i("SyncProviders", mProviderNames.get(i));
+ }
+ */
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mActiveSyncQueryMap.setKeepUpdated(true);
+ mStatusSyncQueryMap.setKeepUpdated(true);
+ onSyncStateUpdated();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mActiveSyncQueryMap.setKeepUpdated(false);
+ mStatusSyncQueryMap.setKeepUpdated(false);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mSyncSettings != null) {
+ mSyncSettings.close();
+ mSyncSettings = null;
+ }
+ if (mActiveSyncQueryMap != null) {
+ mActiveSyncQueryMap.close();
+ mActiveSyncQueryMap = null;
+ }
+ if (mStatusSyncQueryMap != null) {
+ mStatusSyncQueryMap.close();
+ mStatusSyncQueryMap = null;
+ }
+ }
+
+ private void initUI() {
+ // Set the Auto Sync toggle state
+ CheckBoxPreference autoSync = (CheckBoxPreference) findPreference(SYNC_CHECKBOX_KEY);
+ autoSync.setChecked(mSyncSettings.getListenForNetworkTickles());
+
+ // Find individual sync provider's states and initialize the toggles
+ for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
+ Preference pref = getPreferenceScreen().getPreference(i);
+ if (pref.hasKey() && pref.getKey().startsWith(SYNC_KEY_PREFIX)) {
+ CheckBoxPreference toggle = (CheckBoxPreference) pref;
+ String providerName = toggle.getKey().substring(SYNC_KEY_PREFIX.length());
+ boolean enabled =
+ mSyncSettings.getSyncProviderAutomatically(providerName);
+ toggle.setChecked(enabled);
+ }
+ }
+
+ }
+
+ public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) {
+ CheckBoxPreference togglePreference = (CheckBoxPreference) preference;
+ String key = preference.getKey();
+ if (key.equals(SYNC_CHECKBOX_KEY)) {
+ boolean oldListenForTickles = mSyncSettings.getListenForNetworkTickles();
+ boolean listenForTickles = togglePreference.isChecked();
+ if (oldListenForTickles != listenForTickles) {
+ mSyncSettings.setListenForNetworkTickles(listenForTickles);
+ Intent intent = new Intent();
+ intent.setAction(SYNC_CONNECTION_SETTING_CHANGED);
+ sendBroadcast(intent);
+ if (listenForTickles) {
+ startSyncForEnabledProviders();
+ }
+ }
+ if (!listenForTickles) {
+ cancelSyncForEnabledProviders();
+ }
+ } else if (key.startsWith(SYNC_KEY_PREFIX)) {
+ String providerName = key.substring(SYNC_KEY_PREFIX.length());
+ boolean syncOn = togglePreference.isChecked();
+
+ boolean oldSyncState = mSyncSettings.getSyncProviderAutomatically(providerName);
+ if (syncOn != oldSyncState) {
+ mSyncSettings.setSyncProviderAutomatically(providerName, syncOn);
+ if (syncOn) {
+ startSync(providerName);
+ } else {
+ cancelSync(providerName);
+ }
+ }
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ private void startSyncForEnabledProviders() {
+ cancelOrStartSyncForEnabledProviders(true /* start them */);
+ }
+
+ private void cancelSyncForEnabledProviders() {
+ cancelOrStartSyncForEnabledProviders(false /* cancel them */);
+ }
+
+ private void cancelOrStartSyncForEnabledProviders(boolean startSync) {
+ for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
+ Preference pref = getPreferenceScreen().getPreference(i);
+ if (pref.hasKey() && pref.getKey().startsWith(SYNC_KEY_PREFIX)) {
+ CheckBoxPreference toggle = (CheckBoxPreference) pref;
+ if (!toggle.isChecked()) {
+ continue;
+ }
+ final String authority = toggle.getKey().substring(SYNC_KEY_PREFIX.length());
+ if (startSync) {
+ startSync(authority);
+ } else {
+ cancelSync(authority);
+ }
+ }
+ }
+
+ // treat SubscribedFeeds as an enabled provider
+ final String authority = SubscribedFeeds.Feeds.CONTENT_URI.getAuthority();
+ if (startSync) {
+ startSync(authority);
+ } else {
+ cancelSync(authority);
+ }
+ }
+
+ private void startSync(String providerName) {
+ Uri uriToSync = (providerName != null) ? Uri.parse("content://" + providerName) : null;
+ Bundle extras = new Bundle();
+ extras.putBoolean(ContentResolver.SYNC_EXTRAS_FORCE, true);
+ getContentResolver().startSync(uriToSync, extras);
+ }
+
+ private void cancelSync(String authority) {
+ getContentResolver().cancelSync(Uri.parse("content://" + authority));
+ }
+
+ private Observer mSyncSuccessesObserver = new Observer() {
+ public void update(Observable o, Object arg) {
+ onSyncStateUpdated();
+ }
+ };
+
+ private Observer mSyncActiveObserver = new Observer() {
+ public void update(Observable o, Object arg) {
+ onSyncStateUpdated();
+ }
+ };
+
+ /**
+ * Returns the status row that matches the authority. If there are multiples accounts for
+ * the authority, the row with the latest LAST_SUCCESS_TIME column is returned.
+ * @param authority the authority whose row should be selected
+ * @return the ContentValues for the authority, or null if none exists
+ */
+ private ContentValues getStatusByAuthority(String authority) {
+ ContentValues row = null;
+ Map<String, ContentValues> rows = mStatusSyncQueryMap.getRows();
+ for (ContentValues values : rows.values()) {
+ if (values.getAsString(Sync.Status.AUTHORITY).equals(authority)) {
+ if (row == null) {
+ row = values;
+ continue;
+ }
+ final Long curTime = row.getAsLong(Sync.Status.LAST_SUCCESS_TIME);
+ if (curTime == null) {
+ row = values;
+ continue;
+ }
+ final Long newTime = values.getAsLong(Sync.Status.LAST_SUCCESS_TIME);
+ if (newTime == null) continue;
+ if (newTime > curTime) {
+ row = values;
+ }
+ }
+ }
+ return row;
+ }
+
+ boolean isAuthorityPending(String authority) {
+ Map<String, ContentValues> rows = mStatusSyncQueryMap.getRows();
+ for (ContentValues values : rows.values()) {
+ if (values.getAsString(Sync.Status.AUTHORITY).equals(authority)
+ && values.getAsLong(Sync.Status.PENDING) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void onSyncStateUpdated() {
+ // iterate over all the preferences, setting the state properly for each
+ Date date = new Date();
+ ContentValues activeSyncValues = mActiveSyncQueryMap.getActiveSyncInfo();
+ boolean syncIsFailing = false;
+ for (int i = 0; i < getPreferenceScreen().getPreferenceCount(); i++) {
+ Preference pref = getPreferenceScreen().getPreference(i);
+ final String prefKey = pref.getKey();
+ if (!TextUtils.isEmpty(prefKey) && prefKey.startsWith(SYNC_KEY_PREFIX)) {
+ String authority = prefKey.substring(SYNC_KEY_PREFIX.length());
+ SyncStateCheckBoxPreference toggle = (SyncStateCheckBoxPreference)pref;
+ ContentValues status = getStatusByAuthority(authority);
+
+ boolean syncEnabled = mSyncSettings.getSyncProviderAutomatically(authority);
+
+ boolean authorityIsPending = isAuthorityPending(authority);
+ boolean activelySyncing = activeSyncValues != null
+ && activeSyncValues.getAsString(Sync.Active.AUTHORITY).equals(authority);
+ boolean lastSyncFailed = status != null
+ && status.getAsString(Sync.Status.LAST_FAILURE_MESG) != null
+ && status.getAsLong(Sync.Status.LAST_FAILURE_MESG)
+ != Sync.Status.ERROR_SYNC_ALREADY_IN_PROGRESS;
+ if (!syncEnabled) lastSyncFailed = false;
+ if (lastSyncFailed && !activelySyncing && !authorityIsPending) {
+ syncIsFailing = true;
+ }
+ final Long successEndTime =
+ status == null ? null : status.getAsLong(Sync.Status.LAST_SUCCESS_TIME);
+ if (successEndTime != null) {
+ date.setTime(successEndTime);
+ final String timeString = mDateFormat.format(date) + " "
+ + mTimeFormat.format(date);
+ toggle.setSummary(timeString);
+ } else {
+ toggle.setSummary("");
+ }
+ toggle.setActive(activelySyncing);
+ toggle.setPending(authorityIsPending);
+ toggle.setFailed(lastSyncFailed);
+ }
+ }
+ mErrorInfoView.setVisibility(syncIsFailing ? View.VISIBLE : View.GONE);
+ }
+
+ /** called when the sync settings change */
+ public void update(Observable o, Object arg) {
+ onSyncStateUpdated();
+ }
+}
diff --git a/src/com/android/settings/SyncStateCheckBoxPreference.java b/src/com/android/settings/SyncStateCheckBoxPreference.java
new file mode 100644
index 0000000..387c37d
--- /dev/null
+++ b/src/com/android/settings/SyncStateCheckBoxPreference.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2008 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.settings;
+
+import com.android.providers.subscribedfeeds.R;
+
+import android.content.Context;
+import android.graphics.drawable.AnimationDrawable;
+import android.preference.CheckBoxPreference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+
+public class SyncStateCheckBoxPreference extends CheckBoxPreference {
+
+ private boolean mIsActive = false;
+ private boolean mIsPending = false;
+ private boolean mFailed = false;
+
+ public SyncStateCheckBoxPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setWidgetLayoutResource(R.layout.preference_widget_sync_toggle);
+ }
+
+ @Override
+ public void onBindView(View view) {
+ super.onBindView(view);
+ ImageView syncActiveView = (ImageView) view.findViewById(R.id.sync_active);
+ View syncPendingView = view.findViewById(R.id.sync_pending);
+ View syncFailedView = view.findViewById(R.id.sync_failed);
+
+ syncActiveView.setVisibility(mIsActive ? View.VISIBLE : View.GONE);
+ AnimationDrawable anim = (AnimationDrawable) syncActiveView.getDrawable();
+ boolean showError;
+ boolean showPending;
+ if (mIsActive) {
+ anim.start();
+ showPending = false;
+ showError = false;
+ } else {
+ anim.stop();
+ if (mIsPending) {
+ showPending = true;
+ showError = false;
+ } else {
+ showPending = false;
+ showError = mFailed;
+ }
+ }
+
+ syncFailedView.setVisibility(showError ? View.VISIBLE : View.GONE);
+ syncPendingView.setVisibility((showPending && !mIsActive) ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Set whether the sync is active.
+ * @param isActive whether or not the sync is active
+ */
+ public void setActive(boolean isActive) {
+ mIsActive = isActive;
+ notifyChanged();
+ }
+
+ /**
+ * Set whether a sync is pending.
+ * @param isPending whether or not the sync is pending
+ */
+ public void setPending(boolean isPending) {
+ mIsPending = isPending;
+ notifyChanged();
+ }
+
+ /**
+ * Set whether the corresponding sync failed.
+ * @param failed whether or not the sync failed
+ */
+ public void setFailed(boolean failed) {
+ mFailed = failed;
+ notifyChanged();
+ }
+}