summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2009-11-15 12:06:49 -0800
committerJean-Baptiste Queru <jbq@google.com>2009-11-15 12:06:49 -0800
commitbd659ddf395a60bcfb7c795afd36a6e90e28ab76 (patch)
tree0877137a524c3dbf23e0bf635833e6ead5fa10d2
parentb8a837fced3211a3f63ce080331a5085ff83939a (diff)
parent1f33de9100788a56a02d1abbc28f15385329b068 (diff)
downloadIM-bd659ddf395a60bcfb7c795afd36a6e90e28ab76.tar.gz
merge from eclair
-rw-r--r--Android.mk19
-rw-r--r--AndroidManifest.xml91
-rw-r--r--libwbxml/Android.mk16
-rw-r--r--libwbxml/include/imps_encoder.h18
-rw-r--r--libwbxml/include/wbxml_encoder.h40
-rw-r--r--libwbxml/src/imps_encoder.cpp130
-rw-r--r--libwbxml/src/wbxml_encoder.cpp173
-rw-r--r--plugin/Android.mk31
-rw-r--r--plugin/com/android/im/plugin/BrandingResourceIDs.java32
-rw-r--r--plugin/com/android/im/plugin/ImPlugin.java (renamed from plugin/com/android/im/plugin/IImPlugin.aidl)8
-rw-r--r--plugin/com/android/im/plugin/ImPluginConstants.java2
-rw-r--r--plugin/com/android/im/plugin/PasswordDigest.java (renamed from plugin/com/android/im/plugin/IPasswordDigest.aidl)7
-rw-r--r--plugin/com/android/im/plugin/PresenceMapping.java (renamed from plugin/com/android/im/plugin/IPresenceMapping.aidl)8
-rw-r--r--res/color/landing_page_text.xml22
-rw-r--r--res/color/landing_page_text_secondary.xml22
-rw-r--r--res/drawable-hdpi/avatar_unknown.pngbin0 -> 1487 bytes
-rw-r--r--res/drawable-hdpi/background_textfield.9.pngbin0 -> 482 bytes
-rw-r--r--res/drawable-hdpi/dashboard_highlight_selected.9.pngbin0 -> 2358 bytes
-rw-r--r--res/drawable-hdpi/dialog_im_switch_chats_strip.9.pngbin0 -> 218 bytes
-rw-r--r--res/drawable-hdpi/droid_watermark.pngbin0 -> 1132 bytes
-rw-r--r--res/drawable-hdpi/group_chat.pngbin0 -> 1017 bytes
-rw-r--r--res/drawable-hdpi/group_chat_new.pngbin0 -> 1016 bytes
-rw-r--r--res/drawable-hdpi/ic_im_block.pngbin0 -> 1975 bytes
-rw-r--r--res/drawable-hdpi/ic_im_message_not_sent.pngbin0 -> 658 bytes
-rw-r--r--res/drawable-hdpi/ic_launcher_im.pngbin0 -> 4675 bytes
-rw-r--r--res/drawable-hdpi/ic_menu_my_profile.pngbin0 -> 2746 bytes
-rw-r--r--res/drawable-hdpi/ic_menu_view_profile.pngbin0 -> 3616 bytes
-rw-r--r--res/drawable-hdpi/im_avatar_picture_border_normal.9.pngbin0 -> 578 bytes
-rw-r--r--res/drawable-hdpi/im_logo.pngbin0 -> 7388 bytes
-rw-r--r--res/drawable-hdpi/imlogo_s.pngbin0 -> 2706 bytes
-rw-r--r--res/drawable-hdpi/list_item_im_bubble_default.9.pngbin0 -> 1507 bytes
-rw-r--r--res/drawable-hdpi/list_item_im_bubble_pressed.9.pngbin0 -> 1673 bytes
-rw-r--r--res/drawable-hdpi/list_item_im_bubble_selected.9.pngbin0 -> 1719 bytes
-rw-r--r--res/drawable-hdpi/picture_frame_background.9.pngbin0 -> 546 bytes
-rw-r--r--res/drawable-hdpi/status_chat.pngbin0 -> 867 bytes
-rw-r--r--res/drawable-hdpi/status_chat_new.pngbin0 -> 568 bytes
-rw-r--r--res/drawable-hdpi/text_divider_horizontal.9.pngbin0 -> 543 bytes
-rw-r--r--res/drawable-hdpi/textfield_im_pressed.9.pngbin0 -> 518 bytes
-rw-r--r--res/drawable-hdpi/textfield_im_received.9.pngbin0 -> 275 bytes
-rw-r--r--res/drawable-hdpi/textfield_im_selected.9.pngbin0 -> 514 bytes
-rw-r--r--res/drawable-mdpi/avatar_unknown.png (renamed from res/drawable/avatar_unknown.png)bin1719 -> 1719 bytes
-rw-r--r--res/drawable-mdpi/background_textfield.9.png (renamed from res/drawable/background_textfield.9.png)bin286 -> 286 bytes
-rw-r--r--res/drawable-mdpi/dashboard_highlight_selected.9.png (renamed from res/drawable/dashboard_highlight_selected.9.png)bin1226 -> 1226 bytes
-rw-r--r--res/drawable-mdpi/dialog_im_switch_chats_strip.9.png (renamed from res/drawable/dialog_im_switch_chats_strip.9.png)bin259 -> 259 bytes
-rw-r--r--res/drawable-mdpi/droid_watermark.png (renamed from res/drawable/droid_watermark.png)bin767 -> 767 bytes
-rw-r--r--res/drawable-mdpi/group_chat.png (renamed from res/drawable/group_chat.png)bin632 -> 632 bytes
-rw-r--r--res/drawable-mdpi/group_chat_new.png (renamed from res/drawable/group_chat_new.png)bin624 -> 624 bytes
-rw-r--r--res/drawable-mdpi/ic_im_block.png (renamed from res/drawable/ic_im_block.png)bin1331 -> 1331 bytes
-rw-r--r--res/drawable-mdpi/ic_im_message_not_sent.png (renamed from res/drawable/ic_im_message_not_sent.png)bin275 -> 275 bytes
-rw-r--r--res/drawable-mdpi/ic_launcher_im.png (renamed from res/drawable/ic_launcher_im.png)bin2951 -> 2951 bytes
-rw-r--r--res/drawable-mdpi/ic_menu_my_profile.png (renamed from res/drawable/ic_menu_my_profile.png)bin1999 -> 1999 bytes
-rw-r--r--res/drawable-mdpi/ic_menu_view_profile.png (renamed from res/drawable/ic_menu_view_profile.png)bin2232 -> 2232 bytes
-rw-r--r--res/drawable-mdpi/im_avatar_picture_border_normal.9.png (renamed from res/drawable/im_avatar_picture_border_normal.9.png)bin390 -> 390 bytes
-rw-r--r--res/drawable-mdpi/im_logo.png (renamed from res/drawable/im_logo.png)bin5967 -> 5967 bytes
-rw-r--r--res/drawable-mdpi/imlogo_s.png (renamed from res/drawable/imlogo_s.png)bin1912 -> 1912 bytes
-rw-r--r--res/drawable-mdpi/list_item_im_bubble_default.9.png (renamed from res/drawable/list_item_im_bubble_default.9.png)bin1225 -> 1225 bytes
-rw-r--r--res/drawable-mdpi/list_item_im_bubble_pressed.9.png (renamed from res/drawable/list_item_im_bubble_pressed.9.png)bin1186 -> 1186 bytes
-rw-r--r--res/drawable-mdpi/list_item_im_bubble_selected.9.png (renamed from res/drawable/list_item_im_bubble_selected.9.png)bin1029 -> 1029 bytes
-rw-r--r--res/drawable-mdpi/picture_frame_background.9.png (renamed from res/drawable/picture_frame_background.9.png)bin3225 -> 3225 bytes
-rw-r--r--res/drawable-mdpi/status_chat.png (renamed from res/drawable/status_chat.png)bin616 -> 616 bytes
-rw-r--r--res/drawable-mdpi/status_chat_new.png (renamed from res/drawable/status_chat_new.png)bin614 -> 614 bytes
-rw-r--r--res/drawable-mdpi/text_divider_horizontal.9.png (renamed from res/drawable/text_divider_horizontal.9.png)bin626 -> 626 bytes
-rw-r--r--res/drawable-mdpi/textfield_im_pressed.9.png (renamed from res/drawable/textfield_im_pressed.9.png)bin315 -> 315 bytes
-rw-r--r--res/drawable-mdpi/textfield_im_received.9.png (renamed from res/drawable/textfield_im_received.9.png)bin242 -> 242 bytes
-rw-r--r--res/drawable-mdpi/textfield_im_selected.9.png (renamed from res/drawable/textfield_im_selected.9.png)bin394 -> 394 bytes
-rw-r--r--res/drawable/default_background.9.png (renamed from samples/PluginDemo/res/drawable/emo_im_cool.png)bin3466 -> 2893 bytes
-rw-r--r--res/layout/account_view.xml91
-rw-r--r--res/layout/contact_list_view.xml3
-rw-r--r--res/layout/contact_view.xml4
-rw-r--r--res/layout/group_view.xml5
-rw-r--r--res/values-cs/strings.xml12
-rw-r--r--res/values-da/strings.xml12
-rw-r--r--res/values-de/strings.xml12
-rw-r--r--res/values-el/strings.xml12
-rw-r--r--res/values-es-rUS/strings.xml12
-rw-r--r--res/values-es/strings.xml12
-rw-r--r--res/values-fr/strings.xml12
-rw-r--r--res/values-it/strings.xml12
-rw-r--r--res/values-ja/strings.xml12
-rw-r--r--res/values-ko/strings.xml12
-rw-r--r--res/values-nb/strings.xml48
-rw-r--r--res/values-nl/strings.xml12
-rw-r--r--res/values-pl/strings.xml12
-rw-r--r--res/values-pt-rPT/strings.xml12
-rw-r--r--res/values-pt/strings.xml12
-rw-r--r--res/values-ru/strings.xml12
-rw-r--r--res/values-sv/strings.xml12
-rw-r--r--res/values-tr/strings.xml12
-rw-r--r--res/values-zh-rCN/strings.xml14
-rw-r--r--res/values-zh-rTW/strings.xml12
-rw-r--r--res/values/strings.xml32
-rw-r--r--samples/PluginDemo/Android.mk12
-rw-r--r--samples/PluginDemo/AndroidManifest.xml41
-rwxr-xr-xsamples/PluginDemo/res/drawable/chat.pngbin615 -> 0 bytes
-rwxr-xr-xsamples/PluginDemo/res/drawable/chat_new.pngbin656 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_angel.pngbin3592 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_crying.pngbin3558 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_embarrassed.pngbin3619 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_foot_in_mouth.pngbin3603 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_happy.pngbin3591 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_kissing.pngbin3492 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_laughing.pngbin3624 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_lips_are_sealed.pngbin3670 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_money_mouth.pngbin3649 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_sad.pngbin3572 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_surprised.pngbin3490 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_tongue_sticking_out.pngbin3653 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_undecided.pngbin3552 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_winking.pngbin3568 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_wtf.pngbin3591 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/emo_im_yelling.pngbin3575 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/im_logo.pngbin2572 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/drawable/im_logo_splashscr.pngbin16280 -> 0 bytes
-rw-r--r--samples/PluginDemo/res/values-cs/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-da/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-de/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-el/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-es-rUS/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-es/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-fr/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-it/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-ja/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-ko/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-nb/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-nl/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-pl/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-pt-rPT/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-pt/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-ru/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-sv/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-tr/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-zh-rCN/strings.xml75
-rw-r--r--samples/PluginDemo/res/values-zh-rTW/strings.xml75
-rw-r--r--samples/PluginDemo/res/values/strings.xml80
-rw-r--r--samples/PluginDemo/src/com/android/im/plugin/demo/DemoImPlugin.java173
-rw-r--r--samples/PluginDemo/src/com/android/im/plugin/demo/DemoPresenceMapping.java4
-rw-r--r--src/com/android/im/app/AccountActivity.java20
-rw-r--r--src/com/android/im/app/AddContactActivity.java12
-rw-r--r--src/com/android/im/app/BlockedContactsActivity.java22
-rw-r--r--src/com/android/im/app/BrandingResources.java17
-rw-r--r--src/com/android/im/app/ChatBackgroundMaker.java8
-rw-r--r--src/com/android/im/app/ChatSwitcher.java34
-rw-r--r--src/com/android/im/app/ChatView.java75
-rw-r--r--src/com/android/im/app/ChooseAccountActivity.java5
-rw-r--r--src/com/android/im/app/ContactListActivity.java36
-rw-r--r--src/com/android/im/app/ContactListFilterView.java8
-rw-r--r--src/com/android/im/app/ContactListTreeAdapter.java46
-rw-r--r--src/com/android/im/app/ContactListView.java30
-rw-r--r--src/com/android/im/app/ContactPresenceActivity.java18
-rw-r--r--src/com/android/im/app/ContactView.java38
-rw-r--r--src/com/android/im/app/ContactsPickerActivity.java10
-rw-r--r--src/com/android/im/app/DatabaseUtils.java46
-rw-r--r--src/com/android/im/app/FrontDoorPlugin.java363
-rw-r--r--src/com/android/im/app/ImApp.java121
-rw-r--r--src/com/android/im/app/ImPluginHelper.java278
-rw-r--r--src/com/android/im/app/ImRingtonePreference.java6
-rw-r--r--src/com/android/im/app/ImUrlActivity.java37
-rw-r--r--src/com/android/im/app/LandingPage.java459
-rw-r--r--src/com/android/im/app/MessageView.java10
-rw-r--r--src/com/android/im/app/NewChatActivity.java12
-rw-r--r--src/com/android/im/app/PreferenceActivity.java14
-rw-r--r--src/com/android/im/app/PresenceUtils.java36
-rw-r--r--src/com/android/im/app/ProviderListItem.java216
-rw-r--r--src/com/android/im/app/SettingActivity.java6
-rw-r--r--src/com/android/im/app/SigningInActivity.java24
-rw-r--r--src/com/android/im/app/SignoutActivity.java22
-rw-r--r--src/com/android/im/app/UserPresenceView.java12
-rw-r--r--src/com/android/im/engine/SmsService.java2
-rw-r--r--src/com/android/im/imps/CirChannel.java8
-rw-r--r--src/com/android/im/imps/CustomPasswordDigest.java22
-rw-r--r--src/com/android/im/imps/CustomPresenceMapping.java52
-rw-r--r--src/com/android/im/imps/DefaultPresenceMapping.java1
-rw-r--r--src/com/android/im/imps/HttpCirChannel.java9
-rw-r--r--src/com/android/im/imps/ImpsConnectionConfig.java2
-rw-r--r--src/com/android/im/imps/ImpsContactListManager.java1
-rw-r--r--src/com/android/im/imps/ImpsPresenceUtils.java4
-rw-r--r--src/com/android/im/imps/PasswordDigest.java35
-rw-r--r--src/com/android/im/imps/PresenceMapping.java81
-rw-r--r--src/com/android/im/imps/PresencePollingManager.java4
-rw-r--r--src/com/android/im/imps/SmsCirChannel.java34
-rw-r--r--src/com/android/im/imps/StandardPasswordDigest.java1
-rw-r--r--src/com/android/im/imps/TcpCirChannel.java9
-rw-r--r--src/com/android/im/provider/Imps.java2333
-rw-r--r--src/com/android/im/provider/ImpsProvider.java3332
-rw-r--r--src/com/android/im/receiver/ImServiceAutoStarter.java10
-rw-r--r--src/com/android/im/service/AndroidHeartBeatService.java64
-rw-r--r--src/com/android/im/service/AndroidSmsService.java24
-rw-r--r--src/com/android/im/service/ChatSessionAdapter.java104
-rw-r--r--src/com/android/im/service/ContactListManagerAdapter.java205
-rw-r--r--src/com/android/im/service/ImConnectionAdapter.java58
-rw-r--r--src/com/android/im/service/RemoteImService.java116
-rw-r--r--src/com/android/im/service/StatusBarNotifier.java28
192 files changed, 8209 insertions, 3213 deletions
diff --git a/Android.mk b/Android.mk
index a3a1856..4eecd43 100644
--- a/Android.mk
+++ b/Android.mk
@@ -16,22 +16,13 @@ LOCAL_SRC_FILES := $(call all-subdir-java-files) \
src/com/android/im/ISubscriptionListener.aidl \
src/com/android/im/IConnectionCreationListener.aidl \
-# Filter out the plugin and samples when build IM.apk
-LOCAL_SRC_FILES := $(filter-out \
- plugin/% samples/% \
- ,$(LOCAL_SRC_FILES))
-
LOCAL_PACKAGE_NAME := IM
-# TODO: Remove dependency of application on the test runner (android.test.runner)
-# library.
-LOCAL_JAVA_LIBRARIES := android.test.runner \
- com.android.im.plugin \
-# com.android.providers.im.plugin
-
-# LOCAL_REQUIRED_MODULES must go before BUILD_PACKAGE
-LOCAL_REQUIRED_MODULES := libwbxml libwbxml_jni ImProvider
+LOCAL_JNI_SHARED_LIBRARIES := libwbxml_jni
-include $(BUILD_PACKAGE)
+#Disable building the APK; we are checking in the pre-built version which
+#contains the credential plug-in instead. Note the libwbxml_jni has to be
+#enabled because so won't be extracted from the system APK
+#include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c0b26aa..cec0a6b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -22,8 +22,8 @@
package="com.android.im" android:sharedUserId="android.uid.im"
android:sharedUserLabel="@string/perm_label">
- <uses-permission android:name="com.android.providers.im.permission.READ_ONLY" />
- <uses-permission android:name="com.android.providers.im.permission.WRITE_ONLY" />
+ <uses-permission android:name="com.android.providers.imps.permission.READ_ONLY" />
+ <uses-permission android:name="com.android.providers.imps.permission.WRITE_ONLY" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
@@ -40,20 +40,22 @@
android:label="@string/perm_label"
android:description="@string/perm_desc" />
+ <permission android:name="com.android.providers.imps.permission.READ_ONLY"
+ android:permissionGroup="android.permission-group.MESSAGES"
+ android:protectionLevel="dangerous"
+ android:label="@string/ro_perm_label"
+ android:description="@string/ro_perm_desc" />
+
+ <permission android:name="com.android.providers.imps.permission.WRITE_ONLY"
+ android:permissionGroup="android.permission-group.MESSAGES"
+ android:protectionLevel="dangerous"
+ android:label="@string/wo_perm_label"
+ android:description="@string/wo_perm_desc" />
+
<application android:name=".app.ImApp"
android:label="@string/im_label"
android:icon="@drawable/ic_launcher_im"
android:taskAffinity="android.task.im">
- <uses-library android:name="com.android.im.plugin" />
- <!-- TODO: Remove dependency of application on the test runner
- (android.test) library. -->
- <uses-library android:name="android.test.runner" />
-
- <service android:name=".app.FrontDoorPlugin">
- <intent-filter>
- <action android:name="android.im.plugin" />
- </intent-filter>
- </service>
<service android:name=".service.RemoteImService"
android:process="android.process.im"
@@ -65,6 +67,14 @@
</intent-filter>
</service>
+ <provider android:name=".provider.ImpsProvider"
+ android:authorities="imps"
+ android:process="android.process.im"
+ android:multiprocess="false"
+ android:readPermission="com.android.providers.imps.permission.READ_ONLY"
+ android:writePermission="com.android.providers.imps.permission.WRITE_ONLY"
+ android:grantUriPermissions="true" />
+
<activity android:name=".app.ChooseAccountActivity"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
@@ -93,22 +103,39 @@
</intent-filter>
</activity>
- <activity android:name=".app.AccountActivity">
+ <activity android:name=".app.LandingPage">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.dir/imps-providers" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name=".app.AccountActivity"
+ android:configChanges="orientation|keyboardHidden"
+ android:windowSoftInputMode="stateUnchanged">
<intent-filter>
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.android.im.IMPS_CATEGORY" />
- <data android:mimeType="vnd.android.cursor.item/im-accounts" />
+ <data android:mimeType="vnd.android.cursor.item/imps-accounts" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.android.im.IMPS_CATEGORY" />
- <data android:mimeType="vnd.android.cursor.item/im-providers" />
+ <data android:mimeType="vnd.android.cursor.item/imps-providers" />
</intent-filter>
</activity>
- <activity android:name=".app.SigningInActivity">
+ <activity android:name=".app.SigningInActivity"
+ android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
@@ -127,7 +154,7 @@
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.android.im.IMPS_CATEGORY" />
- <data android:mimeType="vnd.android.cursor.dir/im-contacts"/>
+ <data android:mimeType="vnd.android.cursor.dir/imps-contacts"/>
</intent-filter>
</activity>
@@ -141,17 +168,17 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.android.im.IMPS_CATEGORY" />
- <data android:mimeType="vnd.android.cursor.item/im-chats" />
+ <data android:mimeType="vnd.android.cursor.item/imps-chats" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.item/im-invitations" />
+ <data android:mimeType="vnd.android.cursor.item/imps-invitations" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.IM_MANAGE_SUBSCRIPTION"/>
<category android:name="android.intent.category.DEFAULT"/>
- <data android:mimeType="vnd.android.cursor.item/im-contacts"/>
+ <data android:mimeType="vnd.android.cursor.item/imps-contacts"/>
</intent-filter>
</activity>
@@ -159,7 +186,7 @@
<intent-filter>
<action android:name="android.intent.action.PICK" />
<category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.dir/im-contacts" />
+ <data android:mimeType="vnd.android.cursor.dir/imps-contacts" />
</intent-filter>
</activity>
@@ -167,7 +194,7 @@
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.dir/im-blockedList" />
+ <data android:mimeType="vnd.android.cursor.dir/imps-blockedList" />
</intent-filter>
</activity>
@@ -175,7 +202,7 @@
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.item/im-contacts" />
+ <data android:mimeType="vnd.android.cursor.item/imps-contacts" />
</intent-filter>
</activity>
@@ -190,7 +217,7 @@
<action android:name="android.intent.action.VIEW" />
<category android:name="com.android.im.IMPS_CATEGORY" />
<category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android-dir/im-providerSettings" />
+ <data android:mimeType="vnd.android-dir/imps-providerSettings" />
</intent-filter>
</activity>
@@ -207,6 +234,22 @@
</intent-filter>
</receiver>
+ <!--Plug-in Sevice started-->
+ <!--
+ <service android:name="com.android.im.plugin.demo.DemoImPlugin">
+ <intent-filter>
+ <action android:name="com.android.im.plugin" />
+ </intent-filter>
+ <meta-data android:name="com.android.im.provider_name"
+ android:value="Demo"/>
+ <meta-data android:name="com.android.im.provider_full_name"
+ android:value="Demo IM Provider"/>
+ <meta-data android:name="com.android.im.signup_url"
+ android:value="http://xxx.xxx.xxx"/>
+ </service>
+ -->
+ <!--Plug-in Service end-->
+
</application>
</manifest>
diff --git a/libwbxml/Android.mk b/libwbxml/Android.mk
index 4836f0d..c9450c1 100644
--- a/libwbxml/Android.mk
+++ b/libwbxml/Android.mk
@@ -9,6 +9,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
src/wbxml_parser.cpp \
+ src/wbxml_encoder.cpp \
src/imps_encoder.cpp \
src/csp13tags_hash.c \
src/csp13values_hash.c \
@@ -29,7 +30,7 @@ LOCAL_MODULE_TAGS := $(wbxml_module_tags)
LOCAL_MODULE := libwbxml
-include $(BUILD_SHARED_LIBRARY)
+include $(BUILD_STATIC_LIBRARY)
# xml2wbxml library: libxml2wbxml.so
# ---------------------------------------
@@ -49,9 +50,10 @@ LOCAL_CFLAGS += -DPLATFORM_ANDROID
LOCAL_SHARED_LIBRARIES += \
libutils \
- libwbxml \
libexpat
+LOCAL_STATIC_LIBRARIES := libwbxml
+
LOCAL_MODULE_TAGS := $(wbxml_module_tags)
LOCAL_MODULE := libxml2wbxml
@@ -79,13 +81,14 @@ LOCAL_CFLAGS += -DSUPPORT_SYNCML
LOCAL_SRC_FILES += test/syncml_parser_test.cpp
LOCAL_SHARED_LIBRARIES += \
- libwbxml \
libxml2wbxml \
libembunit \
libutils \
libexpat
-LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_LIBRARIES := libwbxml
+
+LOCAL_MODULE_TAGS := tests
LOCAL_MODULE := wbxmltest
@@ -100,16 +103,15 @@ LOCAL_SRC_FILES := \
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include \
- external/expat/lib \
$(JNI_H_INCLUDE)
LOCAL_CFLAGS += -DPLATFORM_ANDROID
LOCAL_SHARED_LIBRARIES += \
- libwbxml \
libutils \
libcutils \
- libexpat
+
+LOCAL_STATIC_LIBRARIES := libwbxml
LOCAL_MODULE_TAGS := $(wbxml_module_tags)
diff --git a/libwbxml/include/imps_encoder.h b/libwbxml/include/imps_encoder.h
index c7300b0..fda9651 100644
--- a/libwbxml/include/imps_encoder.h
+++ b/libwbxml/include/imps_encoder.h
@@ -25,7 +25,7 @@ class ImpsWbxmlEncoder : public WbxmlEncoder
{
public:
ImpsWbxmlEncoder(int publicid) :
- mPublicId(publicid)
+ WbxmlEncoder(publicid)
{
reset();
}
@@ -53,28 +53,12 @@ public:
EncoderError endElement();
private:
- int mPublicId;
int mTagCodePage;
- string mResult;
string mCurrElement;
int mDepth;
- EncoderError encodeInteger(const char *chars, int len);
- EncoderError encodeDatetime(const char *chars, int len);
EncoderError encodeString(const char *chars, int len);
EncoderError encodeAttrib(const char *name, const char *value);
- void encodeInlinedStr(const char *s, int len);
- void encodeMbuint(uint32_t i);
-
- void appendResult(int ch)
- {
- mResult += (char)ch;
- }
-
- void appendResult(const char *s, int len)
- {
- mResult.append(s, len);
- }
};
#endif
diff --git a/libwbxml/include/wbxml_encoder.h b/libwbxml/include/wbxml_encoder.h
index a1b653a..bbd21c8 100644
--- a/libwbxml/include/wbxml_encoder.h
+++ b/libwbxml/include/wbxml_encoder.h
@@ -20,6 +20,8 @@
#include <stdint.h>
#include "wbxml_const.h"
+#include "wbxml_stl.h"
+
class WbxmlHandler
{
@@ -43,6 +45,8 @@ enum EncoderError {
class WbxmlEncoder
{
public:
+ WbxmlEncoder(int publicId):mPublicId(publicId) {}
+
virtual ~WbxmlEncoder() {}
void setWbxmlHandler(WbxmlHandler * handler)
@@ -60,8 +64,44 @@ public:
*/
virtual void reset() = 0;
+ static bool isXmlWhitespace(int ch);
+ static bool parseUint(const char * s, int len, uint32_t *res);
+
protected:
WbxmlHandler * mHandler;
+ int mPublicId;
+
+ EncoderError encodeInteger(const char *chars, int len);
+ EncoderError encodeDatetime(const char *chars, int len);
+ void encodeInlinedStr(const char *s, int len);
+ void encodeMbuint(uint32_t i);
+
+ void clearResult()
+ {
+ mResult.clear();
+ }
+
+ void appendResult(int ch)
+ {
+ mResult += (char)ch;
+ }
+
+ void appendResult(const char *s, int len)
+ {
+ mResult.append(s, len);
+ }
+
+ void sendResult();
+
+ /**
+ * Append a string into the string table, return the index of the string in
+ * the string table.
+ */
+ int appendToStringTable(const char *s);
+
+private:
+ string mResult;
+ vector<string> mStringTable;
};
#endif
diff --git a/libwbxml/src/imps_encoder.cpp b/libwbxml/src/imps_encoder.cpp
index 959486c..26a30ee 100644
--- a/libwbxml/src/imps_encoder.cpp
+++ b/libwbxml/src/imps_encoder.cpp
@@ -42,34 +42,14 @@ static const XmlnsPrefix csp13xmlns[] = {
{ "http://www.openmobilealliance.org/DTD/IMPS-TRC", 0x0d },
};
-static bool isXmlWhitespace(int ch)
-{
- return ch == ' ' || ch == 9 || ch == 0xd || ch == 0xa;
-}
-
static bool isDatetimeElement(const char *name)
{
return (strcmp("DateTime", name) == 0 || strcmp("DeliveryTime", name) == 0);
}
-static bool parseUint(const char * s, int len, uint32_t *res)
-{
- string str(s, len);
- char *end;
- long long val = strtoll(str.c_str(), &end, 10);
- if (*end != 0 || val < 0 || val > 0xFFFFFFFFU) {
- return false;
- }
- *res = (uint32_t)val;
- return true;
-}
-
void ImpsWbxmlEncoder::reset()
{
- // WBXML 1.3, UTF-8, no string table
- char header[4] = {0x03, (char)mPublicId, 0x6A, 0x00};
- mResult.clear();
- mResult.append(header, sizeof(header));
+ clearResult();
mTagCodePage = 0;
mCurrElement.clear();
@@ -82,9 +62,11 @@ EncoderError ImpsWbxmlEncoder::startElement(const char *name, const char **atts)
return ERROR_INVALID_DATA;
}
+ bool isUnknownTag = false;
int stag = csp13TagNameToKey(name);
if (stag == -1) {
- return ERROR_UNSUPPORTED_TAG;
+ stag = TOKEN_LITERAL;
+ isUnknownTag = true;
}
mDepth++;
mCurrElement = name;
@@ -102,6 +84,11 @@ EncoderError ImpsWbxmlEncoder::startElement(const char *name, const char **atts)
stag |= 0x80; // has attribute
}
appendResult(stag);
+
+ if (isUnknownTag) {
+ int index = appendToStringTable(name);
+ encodeMbuint(index);
+ }
if (stag & 0x80) {
for (size_t i = 0; atts[i]; i += 2) {
EncoderError err = encodeAttrib(atts[i], atts[i + 1]);
@@ -164,69 +151,9 @@ EncoderError ImpsWbxmlEncoder::endElement()
}
appendResult(TOKEN_END);
mCurrElement.clear();
- if (mDepth == 0 && mHandler) {
- mHandler->wbxmlData(mResult.c_str(), mResult.size());
- }
- return NO_ERROR;
-}
-
-EncoderError ImpsWbxmlEncoder::encodeInteger(const char *chars, int len)
-{
- uint32_t val;
- if (!parseUint(chars, len, &val)) {
- return ERROR_INVALID_INTEGER_VALUE;
- }
-
- appendResult(TOKEN_OPAQUE);
- uint32_t mask = 0xff000000U;
- int numBytes = 4;
- while (!(val & mask) && mask) {
- numBytes--;
- mask >>= 8;
- }
- if (!numBytes) {
- // Zero value. We generate at least 1 byte OPAQUE data.
- // libwbxml2 generates 0 byte long OPAQUE data (0xC3 0x00) in this case.
- numBytes = 1;
- }
-
- appendResult(numBytes);
- while (numBytes) {
- numBytes--;
- appendResult((val >> (numBytes * 8)) & 0xff);
- }
-
- return NO_ERROR;
-}
-
-EncoderError ImpsWbxmlEncoder::encodeDatetime(const char *chars, int len)
-{
- // to make life easier we accept only yyyymmddThhmmssZ
- if (len != 16 || chars[8] != 'T' || chars[15] != 'Z') {
- return ERROR_INVALID_DATETIME_VALUE;
+ if (mDepth == 0) {
+ sendResult();
}
- appendResult(TOKEN_OPAQUE);
- appendResult(6);
-
- uint32_t year, month, day, hour, min, sec;
- if (!parseUint(chars, 4, &year)
- || !parseUint(chars + 4, 2, &month)
- || !parseUint(chars + 6, 2, &day)
- || !parseUint(chars + 9, 2, &hour)
- || !parseUint(chars + 11,2, &min)
- || !parseUint(chars + 13,2, &sec)) {
- return ERROR_INVALID_DATETIME_VALUE;
- }
- if (year > 4095 || month > 12 || day > 31 || hour > 23 || min > 59 || sec > 59) {
- return ERROR_INVALID_DATETIME_VALUE;
- }
-
- appendResult(year >> 6);
- appendResult(((year & 0x3f) << 2) | (month >> 2));
- appendResult(((month & 0x3) << 6) | (day << 1) | (hour >> 4));
- appendResult(((hour & 0xf) << 4) | (min >> 2));
- appendResult(((min & 0x2) << 6) | sec);
- appendResult('Z');
return NO_ERROR;
}
@@ -251,7 +178,9 @@ EncoderError ImpsWbxmlEncoder::encodeAttrib(const char *name, const char *value)
return ERROR_UNSUPPORTED_ATTR;
}
int valueLen = strlen(value);
- for (size_t i = 0; i < sizeof(csp13xmlns) / sizeof(csp13xmlns[0]); i++) {
+ size_t csp13xmlnsCount = sizeof(csp13xmlns) / sizeof(csp13xmlns[0]);
+ size_t i;
+ for (i = 0; i < csp13xmlnsCount; i++) {
const char * prefix = csp13xmlns[i].prefix;
int prefixLen = strlen(csp13xmlns[i].prefix);
if (strncmp(prefix, value, prefixLen) == 0) {
@@ -262,31 +191,12 @@ EncoderError ImpsWbxmlEncoder::encodeAttrib(const char *name, const char *value)
return NO_ERROR;
}
}
+ if (i == csp13xmlnsCount) {
+ // not predefined attribute
+ appendResult(TOKEN_LITERAL);
+ int index = appendToStringTable(name);
+ encodeMbuint(index);
+ }
encodeInlinedStr(value, valueLen);
return NO_ERROR;
}
-
-void ImpsWbxmlEncoder::encodeInlinedStr(const char *s, int len)
-{
- // TODO: move this to WbxmlEncoder
- // TODO: handle ENTITY
- appendResult(TOKEN_STR_I);
- appendResult(s, len);
- appendResult('\0');
-}
-
-void ImpsWbxmlEncoder::encodeMbuint(uint32_t val)
-{
- char buf[32 / 7 + 1]; // each byte holds up to 7 bits
- int i = sizeof(buf);
-
- buf[--i] = val & 0x7f;
- val >>= 7;
- while ((i > 0) && (val & 0x7f)) {
- buf[--i] = 0x80 | (val & 0x7f);
- val >>= 7;
- }
-
- appendResult(buf + i, sizeof(buf) - i);
-}
-
diff --git a/libwbxml/src/wbxml_encoder.cpp b/libwbxml/src/wbxml_encoder.cpp
new file mode 100644
index 0000000..c84b90e
--- /dev/null
+++ b/libwbxml/src/wbxml_encoder.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2009 Esmertec AG.
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "imps_encoder.h"
+
+bool WbxmlEncoder::isXmlWhitespace(int ch)
+{
+ return ch == ' ' || ch == 9 || ch == 0xd || ch == 0xa;
+}
+
+bool WbxmlEncoder::parseUint(const char * s, int len, uint32_t *res)
+{
+ string str(s, len);
+ char *end;
+ long long val = strtoll(str.c_str(), &end, 10);
+ if (*end != 0 || val < 0 || val > 0xFFFFFFFFU) {
+ return false;
+ }
+ *res = (uint32_t)val;
+ return true;
+}
+
+EncoderError WbxmlEncoder::encodeInteger(const char *chars, int len)
+{
+ uint32_t val;
+ if (!parseUint(chars, len, &val)) {
+ return ERROR_INVALID_INTEGER_VALUE;
+ }
+
+ appendResult(TOKEN_OPAQUE);
+ uint32_t mask = 0xff000000U;
+ int numBytes = 4;
+ while (!(val & mask) && mask) {
+ numBytes--;
+ mask >>= 8;
+ }
+ if (!numBytes) {
+ // Zero value. We generate at least 1 byte OPAQUE data.
+ // libwbxml2 generates 0 byte long OPAQUE data (0xC3 0x00) in this case.
+ numBytes = 1;
+ }
+
+ appendResult(numBytes);
+ while (numBytes) {
+ numBytes--;
+ appendResult((val >> (numBytes * 8)) & 0xff);
+ }
+
+ return NO_ERROR;
+}
+
+EncoderError WbxmlEncoder::encodeDatetime(const char *chars, int len)
+{
+ // to make life easier we accept only yyyymmddThhmmssZ
+ if (len != 16 || chars[8] != 'T' || chars[15] != 'Z') {
+ return ERROR_INVALID_DATETIME_VALUE;
+ }
+ appendResult(TOKEN_OPAQUE);
+ appendResult(6);
+
+ uint32_t year, month, day, hour, min, sec;
+ if (!parseUint(chars, 4, &year)
+ || !parseUint(chars + 4, 2, &month)
+ || !parseUint(chars + 6, 2, &day)
+ || !parseUint(chars + 9, 2, &hour)
+ || !parseUint(chars + 11,2, &min)
+ || !parseUint(chars + 13,2, &sec)) {
+ return ERROR_INVALID_DATETIME_VALUE;
+ }
+ if (year > 4095 || month > 12 || day > 31 || hour > 23 || min > 59 || sec > 59) {
+ return ERROR_INVALID_DATETIME_VALUE;
+ }
+
+ appendResult(year >> 6);
+ appendResult(((year & 0x3f) << 2) | (month >> 2));
+ appendResult(((month & 0x3) << 6) | (day << 1) | (hour >> 4));
+ appendResult(((hour & 0xf) << 4) | (min >> 2));
+ appendResult(((min & 0x2) << 6) | sec);
+ appendResult('Z');
+ return NO_ERROR;
+}
+
+void WbxmlEncoder::encodeInlinedStr(const char *s, int len)
+{
+ // TODO: handle ENTITY
+ appendResult(TOKEN_STR_I);
+ appendResult(s, len);
+ appendResult('\0');
+}
+
+void WbxmlEncoder::encodeMbuint(uint32_t val)
+{
+ char buf[32 / 7 + 1]; // each byte holds up to 7 bits
+ int i = sizeof(buf);
+
+ buf[--i] = val & 0x7f;
+ val >>= 7;
+ while ((i > 0) && (val & 0x7f)) {
+ buf[--i] = 0x80 | (val & 0x7f);
+ val >>= 7;
+ }
+
+ appendResult(buf + i, sizeof(buf) - i);
+}
+
+int WbxmlEncoder::appendToStringTable(const char *s)
+{
+ int stringTableSize = mStringTable.size();
+ int offset = 0;
+
+ // search the string table to find if the string already exist
+ int index = 0;
+ for (; index < stringTableSize; index++) {
+ if (mStringTable[index] == s) {
+ break;
+ }
+ offset += mStringTable[index].length();
+ ++offset; // '\0' for each string in the table
+ }
+ if (index == stringTableSize) {
+ // not found, insert a new one
+ mStringTable.push_back(s);
+ }
+ return offset;
+}
+
+void WbxmlEncoder::sendResult()
+{
+ if (mHandler) {
+ string data;
+ string tmp = mResult;
+ mResult = data;
+
+ // WBXML 1.3, UTF-8
+ char header[3] = { 0x03, (char) mPublicId, 0x6A };
+ appendResult(header, 3);
+
+ // calculate the length of string table
+ int len = 0;
+ for (int i = 0; i < mStringTable.size(); i++) {
+ len += mStringTable[i].length();
+ ++len;
+ }
+
+ encodeMbuint(len);
+
+ // encode each string in the table
+ for (int i = 0; i < mStringTable.size(); i++) {
+ mResult += mStringTable[i];
+ mResult += '\0';
+ }
+
+ mResult += tmp;
+
+ mHandler->wbxmlData(mResult.c_str(), mResult.size());
+ }
+}
diff --git a/plugin/Android.mk b/plugin/Android.mk
deleted file mode 100644
index 28ccd21..0000000
--- a/plugin/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (C) 2008 Esmertec AG.
-# 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.
-#
-LOCAL_PATH := $(call my-dir)
-
-# the library
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- $(call all-subdir-java-files) \
- com/android/im/plugin/IImPlugin.aidl \
- com/android/im/plugin/IPasswordDigest.aidl \
- com/android/im/plugin/IPresenceMapping.aidl \
-
-LOCAL_MODULE:= com.android.im.plugin
-
-include $(BUILD_JAVA_LIBRARY)
diff --git a/plugin/com/android/im/plugin/BrandingResourceIDs.java b/plugin/com/android/im/plugin/BrandingResourceIDs.java
index b53c143..70b48c6 100644
--- a/plugin/com/android/im/plugin/BrandingResourceIDs.java
+++ b/plugin/com/android/im/plugin/BrandingResourceIDs.java
@@ -20,7 +20,37 @@ package com.android.im.plugin;
* Defines the IDs of branding resources.
*
*/
-public interface BrandingResourceIDs extends android.im.BrandingResourceIDs {
+public interface BrandingResourceIDs {
+
+ /**
+ * The logo icon of the provider which is displayed in the landing page.
+ */
+ public static final int DRAWABLE_LOGO = 100;
+ /**
+ * The icon of online presence status.
+ */
+ public static final int DRAWABLE_PRESENCE_ONLINE = 102;
+ /**
+ * The icon of busy presence status.
+ */
+ public static final int DRAWABLE_PRESENCE_BUSY = 103;
+ /**
+ * The icon of away presence status.
+ */
+ public static final int DRAWABLE_PRESENCE_AWAY = 104;
+ /**
+ * The icon of invisible presence status.
+ */
+ public static final int DRAWABLE_PRESENCE_INVISIBLE = 105;
+ /**
+ * The icon of offline presence status.
+ */
+ public static final int DRAWABLE_PRESENCE_OFFLINE = 106;
+ /**
+ * The label of the menu to go to the contact list screen.
+ */
+ public static final int STRING_MENU_CONTACT_LIST = 107;
+
/**
* The image displayed on the splash screen while logging in.
*/
diff --git a/plugin/com/android/im/plugin/IImPlugin.aidl b/plugin/com/android/im/plugin/ImPlugin.java
index b641e86..27ad319 100644
--- a/plugin/com/android/im/plugin/IImPlugin.aidl
+++ b/plugin/com/android/im/plugin/ImPlugin.java
@@ -16,7 +16,9 @@
*/
package com.android.im.plugin;
-interface IImPlugin {
+import java.util.Map;
+
+public interface ImPlugin {
/**
* Gets a map of branding resources for the provider. The keys are defined
* in {@link com.android.im.plugin.BrandingResourceIDs}. The values are the
@@ -24,7 +26,7 @@ interface IImPlugin {
*
* @return The map of branding resources.
*/
- Map getResourceMap();
+ Map<Integer, Integer> getResourceMap();
/**
* Gets an array of IDs of the smiley icons. The sequence of the IDs must
@@ -42,5 +44,5 @@ interface IImPlugin {
*
* @return the configuration for the provider.
*/
- Map getProviderConfig();
+ Map<String, String> getProviderConfig();
}
diff --git a/plugin/com/android/im/plugin/ImPluginConstants.java b/plugin/com/android/im/plugin/ImPluginConstants.java
index a512744..d51e5ec 100644
--- a/plugin/com/android/im/plugin/ImPluginConstants.java
+++ b/plugin/com/android/im/plugin/ImPluginConstants.java
@@ -25,7 +25,7 @@ public class ImPluginConstants {
/**
* The name of the provider. It should match the values defined in
- * {@link android.provider.Im.ProviderNames}.
+ * {@link com.android.im.provider.Imps.ProviderNames}.
*/
public static final String METADATA_PROVIDER_NAME = "com.android.im.provider_name";
diff --git a/plugin/com/android/im/plugin/IPasswordDigest.aidl b/plugin/com/android/im/plugin/PasswordDigest.java
index f6bed17..1a03243 100644
--- a/plugin/com/android/im/plugin/IPasswordDigest.aidl
+++ b/plugin/com/android/im/plugin/PasswordDigest.java
@@ -17,10 +17,12 @@
package com.android.im.plugin;
+import com.android.im.engine.ImException;
+
/**
* The password digest method used in IMPS login transaction.
*/
-interface IPasswordDigest {
+public interface PasswordDigest {
/**
* Gets an array of supported digest schema.
*
@@ -35,6 +37,7 @@ interface IPasswordDigest {
* @param nonce The nonce string returned by the server.
* @param password The user password.
* @return The digest bytes of the password.
+ * @throws ImException
*/
- String digest(String schema, String nonce, String password);
+ String digest(String schema, String nonce, String password) throws ImException;
}
diff --git a/plugin/com/android/im/plugin/IPresenceMapping.aidl b/plugin/com/android/im/plugin/PresenceMapping.java
index 3b6ffc4..74e0fd6 100644
--- a/plugin/com/android/im/plugin/IPresenceMapping.aidl
+++ b/plugin/com/android/im/plugin/PresenceMapping.java
@@ -16,11 +16,13 @@
*/
package com.android.im.plugin;
+import java.util.Map;
+
/**
* The methods used to map presence value sent in protocol to predefined
* presence status.
*/
-interface IPresenceMapping {
+public interface PresenceMapping {
/**
* Tells if the mapping needs all presence values sent in protocol. If this
* method returns true, the framework will pass all the presence values
@@ -43,7 +45,7 @@ interface IPresenceMapping {
* @see #requireAllPresenceValues()
*/
int getPresenceStatus(boolean onlineStatus, String userAvailability,
- in Map allValues);
+ Map<String, Object> allValues);
/**
* Gets the value of &lt;OnlineStatus&gt; will be sent to the server when
@@ -71,7 +73,7 @@ interface IPresenceMapping {
* @param status the predefined status.
* @return The extra values that will be sent to the server.
*/
- Map getExtra(int status);
+ Map<String, Object> getExtra(int status);
/**
* Gets an array of the supported presence status. The client can only update
diff --git a/res/color/landing_page_text.xml b/res/color/landing_page_text.xml
new file mode 100644
index 0000000..6e967d9
--- /dev/null
+++ b/res/color/landing_page_text.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:color="#ff000000"/>
+ <item android:state_selected="true" android:color="#ff000000"/>
+ <item android:state_pressed="true" android:color="#ff000000"/>
+ <item android:color="#ffffffff"/>
+</selector>
diff --git a/res/color/landing_page_text_secondary.xml b/res/color/landing_page_text_secondary.xml
new file mode 100644
index 0000000..78cc390
--- /dev/null
+++ b/res/color/landing_page_text_secondary.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:color="#ff000000"/>
+ <item android:state_selected="true" android:color="#ff000000"/>
+ <item android:state_pressed="true" android:color="#ff000000"/>
+ <item android:color="#ffbebebe"/>
+</selector>
diff --git a/res/drawable-hdpi/avatar_unknown.png b/res/drawable-hdpi/avatar_unknown.png
new file mode 100644
index 0000000..7c34f5c
--- /dev/null
+++ b/res/drawable-hdpi/avatar_unknown.png
Binary files differ
diff --git a/res/drawable-hdpi/background_textfield.9.png b/res/drawable-hdpi/background_textfield.9.png
new file mode 100644
index 0000000..6c101ac
--- /dev/null
+++ b/res/drawable-hdpi/background_textfield.9.png
Binary files differ
diff --git a/res/drawable-hdpi/dashboard_highlight_selected.9.png b/res/drawable-hdpi/dashboard_highlight_selected.9.png
new file mode 100644
index 0000000..483fe3b
--- /dev/null
+++ b/res/drawable-hdpi/dashboard_highlight_selected.9.png
Binary files differ
diff --git a/res/drawable-hdpi/dialog_im_switch_chats_strip.9.png b/res/drawable-hdpi/dialog_im_switch_chats_strip.9.png
new file mode 100644
index 0000000..262ab2d
--- /dev/null
+++ b/res/drawable-hdpi/dialog_im_switch_chats_strip.9.png
Binary files differ
diff --git a/res/drawable-hdpi/droid_watermark.png b/res/drawable-hdpi/droid_watermark.png
new file mode 100644
index 0000000..7aeb550
--- /dev/null
+++ b/res/drawable-hdpi/droid_watermark.png
Binary files differ
diff --git a/res/drawable-hdpi/group_chat.png b/res/drawable-hdpi/group_chat.png
new file mode 100644
index 0000000..09b8944
--- /dev/null
+++ b/res/drawable-hdpi/group_chat.png
Binary files differ
diff --git a/res/drawable-hdpi/group_chat_new.png b/res/drawable-hdpi/group_chat_new.png
new file mode 100644
index 0000000..49807bf
--- /dev/null
+++ b/res/drawable-hdpi/group_chat_new.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_im_block.png b/res/drawable-hdpi/ic_im_block.png
new file mode 100644
index 0000000..1854e82
--- /dev/null
+++ b/res/drawable-hdpi/ic_im_block.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_im_message_not_sent.png b/res/drawable-hdpi/ic_im_message_not_sent.png
new file mode 100644
index 0000000..aba1b56
--- /dev/null
+++ b/res/drawable-hdpi/ic_im_message_not_sent.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_launcher_im.png b/res/drawable-hdpi/ic_launcher_im.png
new file mode 100644
index 0000000..3ea3b70
--- /dev/null
+++ b/res/drawable-hdpi/ic_launcher_im.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_my_profile.png b/res/drawable-hdpi/ic_menu_my_profile.png
new file mode 100644
index 0000000..ed9a563
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_my_profile.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_view_profile.png b/res/drawable-hdpi/ic_menu_view_profile.png
new file mode 100644
index 0000000..96e20c4
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_view_profile.png
Binary files differ
diff --git a/res/drawable-hdpi/im_avatar_picture_border_normal.9.png b/res/drawable-hdpi/im_avatar_picture_border_normal.9.png
new file mode 100644
index 0000000..2367f98
--- /dev/null
+++ b/res/drawable-hdpi/im_avatar_picture_border_normal.9.png
Binary files differ
diff --git a/res/drawable-hdpi/im_logo.png b/res/drawable-hdpi/im_logo.png
new file mode 100644
index 0000000..8681c8c
--- /dev/null
+++ b/res/drawable-hdpi/im_logo.png
Binary files differ
diff --git a/res/drawable-hdpi/imlogo_s.png b/res/drawable-hdpi/imlogo_s.png
new file mode 100644
index 0000000..064cdbf
--- /dev/null
+++ b/res/drawable-hdpi/imlogo_s.png
Binary files differ
diff --git a/res/drawable-hdpi/list_item_im_bubble_default.9.png b/res/drawable-hdpi/list_item_im_bubble_default.9.png
new file mode 100644
index 0000000..048409d
--- /dev/null
+++ b/res/drawable-hdpi/list_item_im_bubble_default.9.png
Binary files differ
diff --git a/res/drawable-hdpi/list_item_im_bubble_pressed.9.png b/res/drawable-hdpi/list_item_im_bubble_pressed.9.png
new file mode 100644
index 0000000..29b3bfc
--- /dev/null
+++ b/res/drawable-hdpi/list_item_im_bubble_pressed.9.png
Binary files differ
diff --git a/res/drawable-hdpi/list_item_im_bubble_selected.9.png b/res/drawable-hdpi/list_item_im_bubble_selected.9.png
new file mode 100644
index 0000000..fbd0914
--- /dev/null
+++ b/res/drawable-hdpi/list_item_im_bubble_selected.9.png
Binary files differ
diff --git a/res/drawable-hdpi/picture_frame_background.9.png b/res/drawable-hdpi/picture_frame_background.9.png
new file mode 100644
index 0000000..45858df
--- /dev/null
+++ b/res/drawable-hdpi/picture_frame_background.9.png
Binary files differ
diff --git a/res/drawable-hdpi/status_chat.png b/res/drawable-hdpi/status_chat.png
new file mode 100644
index 0000000..a1d7f53
--- /dev/null
+++ b/res/drawable-hdpi/status_chat.png
Binary files differ
diff --git a/res/drawable-hdpi/status_chat_new.png b/res/drawable-hdpi/status_chat_new.png
new file mode 100644
index 0000000..f8e829a
--- /dev/null
+++ b/res/drawable-hdpi/status_chat_new.png
Binary files differ
diff --git a/res/drawable-hdpi/text_divider_horizontal.9.png b/res/drawable-hdpi/text_divider_horizontal.9.png
new file mode 100644
index 0000000..3ea9e90
--- /dev/null
+++ b/res/drawable-hdpi/text_divider_horizontal.9.png
Binary files differ
diff --git a/res/drawable-hdpi/textfield_im_pressed.9.png b/res/drawable-hdpi/textfield_im_pressed.9.png
new file mode 100644
index 0000000..660b138
--- /dev/null
+++ b/res/drawable-hdpi/textfield_im_pressed.9.png
Binary files differ
diff --git a/res/drawable-hdpi/textfield_im_received.9.png b/res/drawable-hdpi/textfield_im_received.9.png
new file mode 100644
index 0000000..4ee6baa
--- /dev/null
+++ b/res/drawable-hdpi/textfield_im_received.9.png
Binary files differ
diff --git a/res/drawable-hdpi/textfield_im_selected.9.png b/res/drawable-hdpi/textfield_im_selected.9.png
new file mode 100644
index 0000000..efbc26a
--- /dev/null
+++ b/res/drawable-hdpi/textfield_im_selected.9.png
Binary files differ
diff --git a/res/drawable/avatar_unknown.png b/res/drawable-mdpi/avatar_unknown.png
index 3a338e8..3a338e8 100644
--- a/res/drawable/avatar_unknown.png
+++ b/res/drawable-mdpi/avatar_unknown.png
Binary files differ
diff --git a/res/drawable/background_textfield.9.png b/res/drawable-mdpi/background_textfield.9.png
index 679e00f..679e00f 100644
--- a/res/drawable/background_textfield.9.png
+++ b/res/drawable-mdpi/background_textfield.9.png
Binary files differ
diff --git a/res/drawable/dashboard_highlight_selected.9.png b/res/drawable-mdpi/dashboard_highlight_selected.9.png
index 473e059..473e059 100644
--- a/res/drawable/dashboard_highlight_selected.9.png
+++ b/res/drawable-mdpi/dashboard_highlight_selected.9.png
Binary files differ
diff --git a/res/drawable/dialog_im_switch_chats_strip.9.png b/res/drawable-mdpi/dialog_im_switch_chats_strip.9.png
index 1fe2c11..1fe2c11 100644
--- a/res/drawable/dialog_im_switch_chats_strip.9.png
+++ b/res/drawable-mdpi/dialog_im_switch_chats_strip.9.png
Binary files differ
diff --git a/res/drawable/droid_watermark.png b/res/drawable-mdpi/droid_watermark.png
index 785f7b9..785f7b9 100644
--- a/res/drawable/droid_watermark.png
+++ b/res/drawable-mdpi/droid_watermark.png
Binary files differ
diff --git a/res/drawable/group_chat.png b/res/drawable-mdpi/group_chat.png
index c08d822..c08d822 100644
--- a/res/drawable/group_chat.png
+++ b/res/drawable-mdpi/group_chat.png
Binary files differ
diff --git a/res/drawable/group_chat_new.png b/res/drawable-mdpi/group_chat_new.png
index 6490d77..6490d77 100644
--- a/res/drawable/group_chat_new.png
+++ b/res/drawable-mdpi/group_chat_new.png
Binary files differ
diff --git a/res/drawable/ic_im_block.png b/res/drawable-mdpi/ic_im_block.png
index 36b3c03..36b3c03 100644
--- a/res/drawable/ic_im_block.png
+++ b/res/drawable-mdpi/ic_im_block.png
Binary files differ
diff --git a/res/drawable/ic_im_message_not_sent.png b/res/drawable-mdpi/ic_im_message_not_sent.png
index 477b575..477b575 100644
--- a/res/drawable/ic_im_message_not_sent.png
+++ b/res/drawable-mdpi/ic_im_message_not_sent.png
Binary files differ
diff --git a/res/drawable/ic_launcher_im.png b/res/drawable-mdpi/ic_launcher_im.png
index afc35a2..afc35a2 100644
--- a/res/drawable/ic_launcher_im.png
+++ b/res/drawable-mdpi/ic_launcher_im.png
Binary files differ
diff --git a/res/drawable/ic_menu_my_profile.png b/res/drawable-mdpi/ic_menu_my_profile.png
index 6f9caf7..6f9caf7 100644
--- a/res/drawable/ic_menu_my_profile.png
+++ b/res/drawable-mdpi/ic_menu_my_profile.png
Binary files differ
diff --git a/res/drawable/ic_menu_view_profile.png b/res/drawable-mdpi/ic_menu_view_profile.png
index afc18aa..afc18aa 100644
--- a/res/drawable/ic_menu_view_profile.png
+++ b/res/drawable-mdpi/ic_menu_view_profile.png
Binary files differ
diff --git a/res/drawable/im_avatar_picture_border_normal.9.png b/res/drawable-mdpi/im_avatar_picture_border_normal.9.png
index 01cc9dc..01cc9dc 100644
--- a/res/drawable/im_avatar_picture_border_normal.9.png
+++ b/res/drawable-mdpi/im_avatar_picture_border_normal.9.png
Binary files differ
diff --git a/res/drawable/im_logo.png b/res/drawable-mdpi/im_logo.png
index 3bd8ca0..3bd8ca0 100644
--- a/res/drawable/im_logo.png
+++ b/res/drawable-mdpi/im_logo.png
Binary files differ
diff --git a/res/drawable/imlogo_s.png b/res/drawable-mdpi/imlogo_s.png
index b7aa43a..b7aa43a 100644
--- a/res/drawable/imlogo_s.png
+++ b/res/drawable-mdpi/imlogo_s.png
Binary files differ
diff --git a/res/drawable/list_item_im_bubble_default.9.png b/res/drawable-mdpi/list_item_im_bubble_default.9.png
index 92f7058..92f7058 100644
--- a/res/drawable/list_item_im_bubble_default.9.png
+++ b/res/drawable-mdpi/list_item_im_bubble_default.9.png
Binary files differ
diff --git a/res/drawable/list_item_im_bubble_pressed.9.png b/res/drawable-mdpi/list_item_im_bubble_pressed.9.png
index 2032bc0..2032bc0 100644
--- a/res/drawable/list_item_im_bubble_pressed.9.png
+++ b/res/drawable-mdpi/list_item_im_bubble_pressed.9.png
Binary files differ
diff --git a/res/drawable/list_item_im_bubble_selected.9.png b/res/drawable-mdpi/list_item_im_bubble_selected.9.png
index bd0a1e2..bd0a1e2 100644
--- a/res/drawable/list_item_im_bubble_selected.9.png
+++ b/res/drawable-mdpi/list_item_im_bubble_selected.9.png
Binary files differ
diff --git a/res/drawable/picture_frame_background.9.png b/res/drawable-mdpi/picture_frame_background.9.png
index 8ecddcd..8ecddcd 100644
--- a/res/drawable/picture_frame_background.9.png
+++ b/res/drawable-mdpi/picture_frame_background.9.png
Binary files differ
diff --git a/res/drawable/status_chat.png b/res/drawable-mdpi/status_chat.png
index abfb6fa..abfb6fa 100644
--- a/res/drawable/status_chat.png
+++ b/res/drawable-mdpi/status_chat.png
Binary files differ
diff --git a/res/drawable/status_chat_new.png b/res/drawable-mdpi/status_chat_new.png
index 564b38b..564b38b 100644
--- a/res/drawable/status_chat_new.png
+++ b/res/drawable-mdpi/status_chat_new.png
Binary files differ
diff --git a/res/drawable/text_divider_horizontal.9.png b/res/drawable-mdpi/text_divider_horizontal.9.png
index 21b11a3..21b11a3 100644
--- a/res/drawable/text_divider_horizontal.9.png
+++ b/res/drawable-mdpi/text_divider_horizontal.9.png
Binary files differ
diff --git a/res/drawable/textfield_im_pressed.9.png b/res/drawable-mdpi/textfield_im_pressed.9.png
index a768cb4..a768cb4 100644
--- a/res/drawable/textfield_im_pressed.9.png
+++ b/res/drawable-mdpi/textfield_im_pressed.9.png
Binary files differ
diff --git a/res/drawable/textfield_im_received.9.png b/res/drawable-mdpi/textfield_im_received.9.png
index bde8fc3..bde8fc3 100644
--- a/res/drawable/textfield_im_received.9.png
+++ b/res/drawable-mdpi/textfield_im_received.9.png
Binary files differ
diff --git a/res/drawable/textfield_im_selected.9.png b/res/drawable-mdpi/textfield_im_selected.9.png
index ba958c8..ba958c8 100644
--- a/res/drawable/textfield_im_selected.9.png
+++ b/res/drawable-mdpi/textfield_im_selected.9.png
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_cool.png b/res/drawable/default_background.9.png
index d8eeb34..33cb551 100644
--- a/samples/PluginDemo/res/drawable/emo_im_cool.png
+++ b/res/drawable/default_background.9.png
Binary files differ
diff --git a/res/layout/account_view.xml b/res/layout/account_view.xml
new file mode 100644
index 0000000..411c844
--- /dev/null
+++ b/res/layout/account_view.xml
@@ -0,0 +1,91 @@
+<?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.
+ */
+-->
+
+<com.android.im.app.ProviderListItem
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight">
+
+ <ImageView
+ android:id="@+id/providerIcon"
+ android:layout_gravity="center_vertical"
+ android:scaleType="fitXY"
+ android:paddingLeft="5dip"
+ android:paddingRight="2dip"
+ android:layout_width="39dip"
+ android:layout_height="32dip"/>
+
+ <LinearLayout
+ android:id="@+id/underBubble"
+ android:orientation="horizontal"
+ android:layout_weight="1"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_weight="1"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TextView android:id="@+id/providerName"
+ android:textColor="@color/landing_page_text"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textStyle="bold"
+ android:singleLine="true"
+ android:layout_weight="1.0"
+ android:ellipsize="marquee"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/conversations"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/landing_page_text_secondary"
+ android:singleLine="true"
+ android:paddingRight="3dip"
+ android:paddingLeft="5dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+
+ <TextView android:id="@+id/loginName"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="@color/landing_page_text"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+ <ImageView
+ android:id="@+id/statusIcon"
+ android:scaleType="fitXY"
+ android:paddingRight="6dip"
+ android:paddingLeft="6dip"
+ android:layout_weight="0"
+ android:layout_gravity="center_vertical"
+ android:layout_width="30dip"
+ android:layout_height="18dip"/>
+ </LinearLayout>
+</com.android.im.app.ProviderListItem> \ No newline at end of file
diff --git a/res/layout/contact_list_view.xml b/res/layout/contact_list_view.xml
index 01e3b50..619dff1 100644
--- a/res/layout/contact_list_view.xml
+++ b/res/layout/contact_list_view.xml
@@ -76,6 +76,7 @@
<ExpandableListView android:id="@+id/contactsList"
android:layout_width="fill_parent"
- android:layout_height="fill_parent" />
+ android:layout_height="fill_parent"
+ android:nextFocusUp="@id/statusDropDownButton" />
</com.android.im.app.ContactListView>
diff --git a/res/layout/contact_view.xml b/res/layout/contact_view.xml
index b64d990..00dc0b9 100644
--- a/res/layout/contact_view.xml
+++ b/res/layout/contact_view.xml
@@ -58,7 +58,7 @@
android:layout_height="wrap_content">
<TextView android:id="@+id/line1"
- android:maxLines="1"
+ android:singleLine="true"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="wrap_content"
@@ -76,7 +76,7 @@
</LinearLayout>
<TextView android:id="@+id/line2"
- android:maxLines="1"
+ android:singleLine="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
diff --git a/res/layout/group_view.xml b/res/layout/group_view.xml
index a8bfad1..6bf5768 100644
--- a/res/layout/group_view.xml
+++ b/res/layout/group_view.xml
@@ -25,15 +25,16 @@
android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft">
<TextView android:id="@+id/text1"
- android:maxLines="1"
+ android:singleLine="true"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
+ android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView android:id="@+id/text2"
- android:maxLines="1"
+ android:singleLine="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 5c687b7..7d5e716 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"čtení zpráv chatu"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Povoluje aplikacím číst data od poskytovatele chatu."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"psaní zpráv chatu"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Povoluje aplikacím psát data poskytovateli chatu."</string>
<string name="im_label" msgid="6289028202073124911">"Chat"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chat – vybrat účet"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Přidat účet"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Upravit účet"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Odebrat účet"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Odhlásit se ze všech služeb"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chat – vybrat účet"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Zrušit přihlašování"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Přidat kontakt"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Smazat kontakt"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Vstup"</string>
<string name="confirm" msgid="3229086014444547636">"Potvrdit"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Chcete se odhlásit ze všech služeb?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Kontakt <xliff:g id="USER">%1$s</xliff:g> bude smazán."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Kontakt <xliff:g id="USER">%1$s</xliff:g> bude blokován."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Kontakt <xliff:g id="USER">%1$s</xliff:g> bude odblokován."</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index c83e272..07661dc 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"læs chatbeskeder"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Tillader programmer at læse data fra IM-indholdsleverandøren."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"skriv chatbeskeder"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Tillader programmer at skrive data til IM-indholdsleverandøren."</string>
<string name="im_label" msgid="6289028202073124911">"IM"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chat – Vælg en konto"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Tilføj konto"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Rediger konto"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Fjern konto"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Log alle ud"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chat – Vælg en konto"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Annuller login"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Tilføj kontakt"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Slet kontakt"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Input"</string>
<string name="confirm" msgid="3229086014444547636">"Bekræft"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Vil du logge ud af alle tjenester?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Kontakten \"<xliff:g id="USER">%1$s</xliff:g>\" slettes."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Kontakten \"<xliff:g id="USER">%1$s</xliff:g>\" blokeres."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Blokeringen af kontakten \"<xliff:g id="USER">%1$s</xliff:g>\" ophæves."</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index d9aa1f9..749cb3a 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"Chat-Nachrichten lesen"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Ermöglicht Anwendungen das Lesen von Daten des IM-Content-Providers."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"Chat-Nachrichten verfassen"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Ermöglicht Anwendungen das Schreiben von Daten an den IM-Content-Provider."</string>
<string name="im_label" msgid="6289028202073124911">"Chat"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chat – Konto auswählen"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Konto hinzufügen"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Konto bearbeiten"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Konto entfernen"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Alle abmelden"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chat – Konto auswählen"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Anmeldung abbrechen"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Kontakt hinzufügen"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Kontakt löschen"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menü +"</string>
<string name="default_input_title" msgid="6182729628894599563">"Eingabe"</string>
<string name="confirm" msgid="3229086014444547636">"Bestätigen"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Möchten Sie alle Dienste abmelden?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Kontakt \"<xliff:g id="USER">%1$s</xliff:g>\" wird gelöscht."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Kontakt \"<xliff:g id="USER">%1$s</xliff:g>\" wird gesperrt."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Blockierung des Kontakts \"<xliff:g id="USER">%1$s</xliff:g>\" wird aufgehoben."</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index ade72df..e539860 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"ανάγνωση άμεσων μηνυμάτων"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Επιτρέπει στις εφαρμογές την ανάγνωση δεδομένων από τον πάροχο περιεχομένου ανταλλαγής άμεσων μηνυμάτων (IM)."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"εγγραφή άμεσων μηνυμάτων"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Επιτρέπει στις εφαρμογές την εγγραφή δεδομένων από τον πάροχο της υπηρεσίας άμεσων μηνυμάτων (IM)."</string>
<string name="im_label" msgid="6289028202073124911">"Ανταλ.άμεσων μην.(IM)"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Συζήτηση - Επιλογή λογαριασμού"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Προσθήκη λογαριασμού"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Επεξεργασία λογαριασμού"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Κατάργηση λογαριασμού"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Αποσύνδεση όλων"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Συζήτηση - Επιλογή λογαριασμού"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Ακύρωση σύνδεσης"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Προσθήκη επαφής"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Διαγραφή επαφής"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Μενού+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Είσοδος"</string>
<string name="confirm" msgid="3229086014444547636">"Επιβεβαίωση"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Θέλετε να πραγματοποιήσετε αποσύνδεση από όλες τις υπηρεσίες;"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Η επαφή \"<xliff:g id="USER">%1$s</xliff:g>\" θα διαγραφεί."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Θα γίνει αποκλεισμός της επαφής \"<xliff:g id="USER">%1$s</xliff:g>\"."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Θα γίνει κατάργηση αποκλεισμού της επαφής \"<xliff:g id="USER">%1$s</xliff:g>\"."</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 649d27b..6226606 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"leer mensajes instantáneos"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Permite que las aplicaciones lean datos del proveedor de contenido de mensajería instantánea"</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"escribir mensajes instantáneos"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Permite que las aplicaciones ingresen datos en el proveedor de contenido de mensajería instantánea"</string>
<string name="im_label" msgid="6289028202073124911">"Mensajería instantánea"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chat - Seleccionar una cuenta"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Agregar cuenta"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Editar cuenta"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Eliminar cuenta"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Cerrar sesión de todo"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chat - Seleccionar una cuenta"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Cancelar inicio de sesión"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Agregar contacto"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Eliminar contacto"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menú+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Entrada"</string>
<string name="confirm" msgid="3229086014444547636">"Confirmar"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"¿Deseas salir de todos los servicios?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"El contacto \"<xliff:g id="USER">%1$s</xliff:g>\" se eliminará."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"El contacto \"<xliff:g id="USER">%1$s</xliff:g>\" se bloqueará."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"El contacto \"<xliff:g id="USER">%1$s</xliff:g>\" se desbloqueará."</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 2b38f77..98c2e2e 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"leer mensajes instantáneos"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Permite que las aplicaciones lean datos del proveedor de contenido de MI."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"escribir mensajes instantáneos"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Permite que las aplicaciones escriban datos en el proveedor de contenido de MI."</string>
<string name="im_label" msgid="6289028202073124911">"MI"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chat: seleccionar una cuenta"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Añadir cuenta"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Editar cuenta"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Eliminar cuenta"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Salir de todo"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chat: seleccionar una cuenta"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Cancelar acceso"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Añadir contacto"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Eliminar contacto"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"MENU+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Introducción de texto"</string>
<string name="confirm" msgid="3229086014444547636">"Confirmar"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"¿Quieres salir de todos los servicios?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"El contacto \"<xliff:g id="USER">%1$s</xliff:g>\" se eliminará."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"El contacto \"<xliff:g id="USER">%1$s</xliff:g>\" se bloqueará."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"El contacto \"<xliff:g id="USER">%1$s</xliff:g>\" se desbloqueará."</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 0c431bc..2226521 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"Lire des messages instantanés"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Permet aux applications de lire les données du fournisseur de service de messagerie instantanée."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"Écrire des messages instantanés"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Permet aux applications d\'écrire des données du fournisseur de service de messagerie instantanée."</string>
<string name="im_label" msgid="6289028202073124911">"Chat"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chat : sélectionner un compte"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Ajouter un compte"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Modifier un compte"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Supprimer le compte"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Se déconnecter de tout"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chat : sélectionner un compte"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Annuler la connexion"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Ajouter un contact"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Supprimer le contact"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Entrée"</string>
<string name="confirm" msgid="3229086014444547636">"Confirmer"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Voulez-vous vous déconnecter de tous les services ?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Le contact \"<xliff:g id="USER">%1$s</xliff:g>\" sera supprimé."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Le contact \"<xliff:g id="USER">%1$s</xliff:g>\" sera bloqué."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Le contact \"<xliff:g id="USER">%1$s</xliff:g>\" sera débloqué."</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 999edba..6832ec5 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"lettura di messaggi immediati"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Consente alle applicazioni di leggere dati del provider di contenuti IM."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"scrittura di messaggi immediati"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Consente alle applicazioni di scrivere dati per il provider di contenuti IM."</string>
<string name="im_label" msgid="6289028202073124911">"Chat"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chat - Seleziona un account"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Aggiungi account"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Modifica account"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Rimuovi account"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Esci da tutto"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chat - Seleziona un account"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Annulla accesso"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Aggiungi contatto"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Elimina contatto"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Input"</string>
<string name="confirm" msgid="3229086014444547636">"Conferma"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Uscire da tutti i servizi?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Il contatto \"<xliff:g id="USER">%1$s</xliff:g>\" sarà eliminato."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Il contatto \"<xliff:g id="USER">%1$s</xliff:g>\" sarà bloccato."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Il contatto \"<xliff:g id="USER">%1$s</xliff:g>\" sarà sbloccato."</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 954cffc..61deb67 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"インスタントメッセージを表示"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"アプリケーションでIMコンテンツプロバイダからデータを読み取れるようにします。"</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"インスタントメッセージを作成"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"アプリケーションからIMコンテンツプロバイダにデータを書き込めるようにします。"</string>
<string name="im_label" msgid="6289028202073124911">"チャット"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"チャット: アカウントを選択"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"アカウントを追加"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"アカウントを編集"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"アカウントを削除"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"すべてログアウト"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"チャット: アカウントを選択"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>件)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"ログインをキャンセル"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"連絡先を追加"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"連絡先を削除"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"入力"</string>
<string name="confirm" msgid="3229086014444547636">"確認"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"すべてのアカウントからログアウトしますか?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"連絡先「<xliff:g id="USER">%1$s</xliff:g>」を削除します。"</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"連絡先「<xliff:g id="USER">%1$s</xliff:g>」をブロックします。"</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"連絡先「<xliff:g id="USER">%1$s</xliff:g>」のブロックを解除します。"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index b92adca..cf98293 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"인스턴트 메시지 읽기"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"응용프로그램이 메신저 콘텐츠 제공업체에서 제공한 데이터를 읽을 수 있도록 합니다."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"인스턴트 메시지 쓰기"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"응용프로그램이 메신저 콘텐츠 제공업체에 데이터를 쓸 수 있도록 합니다."</string>
<string name="im_label" msgid="6289028202073124911">"메신저"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"채팅 - 계정 선택"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"계정 추가"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"계정 수정"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"계정 삭제"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"모두 로그아웃"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"채팅 - 계정 선택"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"로그인 취소"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"연락처 추가"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"연락처 삭제"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"입력"</string>
<string name="confirm" msgid="3229086014444547636">"확인"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"모든 서비스에서 로그아웃하시겠습니까?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"연락처 \'<xliff:g id="USER">%1$s</xliff:g>\'이(가) 삭제됩니다."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"연락처 \'<xliff:g id="USER">%1$s</xliff:g>\'이(가) 차단됩니다."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"연락처 \'<xliff:g id="USER">%1$s</xliff:g>\'이(가) 차단 해제됩니다."</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index d0b10cf..2ce18fd 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -15,8 +15,19 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"lese nettpratmeldinger"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Lar applikasjoner lese data fra innholdsleverandøren for nettprat."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"skrive nettpratmeldinger"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Lar applikasjoner skrive data til innholdsleverandøren for nettprat."</string>
<string name="im_label" msgid="6289028202073124911">"Nettprat"</string>
- <string name="menu_cancel_signin" msgid="146078926243968887">"Avbryt innlogging"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Nettprat – velg en konto"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Legg til konto"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Rediger konto"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Fjern konto"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Logg av alle"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Nettprat – velg en konto"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
+ <string name="menu_cancel_signin" msgid="146078926243968887">"Avbryt pålogging"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Legg til kontakt"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Fjern kontakt"</string>
<string name="menu_block_contact" msgid="727204732836017804">"Blokker kontakt"</string>
@@ -24,7 +35,7 @@
<string name="menu_view_accounts" msgid="2876518557188672305">"Kontoliste"</string>
<string name="menu_settings" msgid="4609084900756093288">"Innstillinger"</string>
<string name="menu_start_chat" msgid="6188262479212139863">"Start samtale"</string>
- <string name="menu_sign_out" msgid="2456603636849489202">"Logg ut"</string>
+ <string name="menu_sign_out" msgid="2456603636849489202">"Logg av"</string>
<string name="menu_view_profile" msgid="5883288134525529119">"Vis profil"</string>
<string name="menu_end_conversation" msgid="3556567768336552622">"Avslutt samtale"</string>
<string name="menu_view_contact_list" msgid="4630377976475003130">"Kontaktliste"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Meny+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Inndata"</string>
<string name="confirm" msgid="3229086014444547636">"Bekreft"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Vil du logge deg av alle tjenester?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Kontakten «<xliff:g id="USER">%1$s</xliff:g>» vil bli slettet."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Kontakten «<xliff:g id="USER">%1$s</xliff:g>» vil bli blokkert."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Kontakten «<xliff:g id="USER">%1$s</xliff:g>» vil bli avblokkert."</string>
@@ -41,18 +53,18 @@
<string name="cancel" msgid="5115511021657936211">"Avbryt"</string>
<string name="yes" msgid="4042588907115698888">"OK"</string>
<string name="no" msgid="1791024164361629713">"Avbryt"</string>
- <string name="signed_out_prompt" msgid="8832702403969474634">"De er blitt logget ut fra <xliff:g id="ACCOUNT">%1$s</xliff:g>."</string>
- <string name="signed_out_prompt_with_error" msgid="7747094436931805456">"Du er blitt logget ut fra <xliff:g id="ACCOUNT">%1$s</xliff:g> fordi <xliff:g id="REASON">%2$s</xliff:g>."</string>
+ <string name="signed_out_prompt" msgid="8832702403969474634">"De er blitt logget av <xliff:g id="ACCOUNT">%1$s</xliff:g>."</string>
+ <string name="signed_out_prompt_with_error" msgid="7747094436931805456">"Du er blitt logget av <xliff:g id="ACCOUNT">%1$s</xliff:g> fordi <xliff:g id="REASON">%2$s</xliff:g>."</string>
<string name="add_account" msgid="3402105687785864337">"Legg til <xliff:g id="ACCOUNT">%1$s</xliff:g>-konto"</string>
<string name="label_username" msgid="8704597829337399952">"Brukernavn:"</string>
<string name="label_password" msgid="7809879599377131899">"Passord:"</string>
<string name="remember_password" msgid="4090719436666073946">"Husk passord."</string>
- <string name="keep_me_signed_in" msgid="2883914867912933061">"Logg inn automatisk."</string>
+ <string name="keep_me_signed_in" msgid="2883914867912933061">"Logg på automatisk."</string>
<string name="sign_up" msgid="7071654280992136839">"Mangler du konto?"</string>
- <string name="check_auto_sign_in" msgid="308461891031463647">"Dette valget logger deg automatisk inn hver gang du åpner applikasjonen. For å avmerke valget, logg ut og fjern så haken ved «Logg inn automatisk»."</string>
- <string name="sign_in" msgid="6204326200860136567">"Logg inn"</string>
- <string name="signing_in_to" msgid="2689649632858697221">"Logger inn på <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
- <string name="signing_in_wait" msgid="987357161364666888">"Logger inn…"</string>
+ <string name="check_auto_sign_in" msgid="308461891031463647">"Dette valget logger deg automatisk på hver gang du åpner applikasjonen. For å avmerke valget, logg av og fjern så haken ved «Logg på automatisk»."</string>
+ <string name="sign_in" msgid="6204326200860136567">"Logg på"</string>
+ <string name="signing_in_to" msgid="2689649632858697221">"Logger på <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
+ <string name="signing_in_wait" msgid="987357161364666888">"Logger på…"</string>
<string name="bg_data_prompt_title" msgid="4861800723853178111">"Bakgrunnsdata deaktivert"</string>
<string name="bg_data_prompt_message" msgid="2343305645142823544">"<xliff:g id="PROVIDER">%1$s</xliff:g> trenger at bakgrunnsdata er aktivert."</string>
<string name="bg_data_prompt_ok" msgid="3443385427882751532">"Aktiver"</string>
@@ -77,7 +89,7 @@
<string name="presence_busy" msgid="3425926873862063910">"Opptatt"</string>
<string name="presence_away" msgid="2893687249265559744">"Borte"</string>
<string name="presence_idle" msgid="3127526059878228229">"Inaktiv"</string>
- <string name="presence_offline" msgid="7946842914359044731">"Avlogget"</string>
+ <string name="presence_offline" msgid="7946842914359044731">"Frakoblet"</string>
<string name="presence_invisible" msgid="1485652711495491831">"Usynlig"</string>
<string name="chat_with" msgid="8562954189958846831">"Samtale med <xliff:g id="USER">%1$s</xliff:g>"</string>
<string name="me" msgid="8421609599685404593">"Meg"</string>
@@ -85,16 +97,16 @@
<string name="contact_online" msgid="4241843267436748586">"<xliff:g id="USER">%1$s</xliff:g> er tilgjengelig"</string>
<string name="contact_away" msgid="2333627320542883164">"<xliff:g id="USER">%1$s</xliff:g> er borte"</string>
<string name="contact_busy" msgid="9175172991334146704">"<xliff:g id="USER">%1$s</xliff:g> er opptatt"</string>
- <string name="contact_offline" msgid="7054903259540426223">"<xliff:g id="USER">%1$s</xliff:g> er avlogget"</string>
+ <string name="contact_offline" msgid="7054903259540426223">"<xliff:g id="USER">%1$s</xliff:g> er frakoblet"</string>
<string name="contact_joined" msgid="6713312815095658394">"<xliff:g id="USER">%1$s</xliff:g> har blitt med i samtalen"</string>
<string name="contact_left" msgid="3020686291216941829">"<xliff:g id="USER">%1$s</xliff:g> har forlatt samtalen"</string>
<string name="time_stamp" format="date" msgid="8952691401963972802">"'Sendt '<xliff:g id="HOUR">hh</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>', '<xliff:g id="DATE">EEEE</xliff:g>"</string>
<string name="send" msgid="2726588254020771734">"Send"</string>
<string name="msg_sent_failed" msgid="4209970218075996979">"Kunne ikke sende meldingen."</string>
<string name="disconnected_warning" msgid="6798248948843269795">"Mistet tilkoblingen til tjeneren. Meldingen vil bli sendt ved tilkobling."</string>
- <string name="contact_offline_warning" msgid="8822964251595561504">"<xliff:g id="USER_0">%1$s</xliff:g> er avlogget. Meldinger du sender vil bli levert når <xliff:g id="USER_1">%1$s</xliff:g> kobler til."</string>
+ <string name="contact_offline_warning" msgid="8822964251595561504">"<xliff:g id="USER_0">%1$s</xliff:g> er frakoblet. Meldinger du sender vil bli levert når <xliff:g id="USER_1">%1$s</xliff:g> kobler til."</string>
<string name="contact_not_in_list_warning" msgid="2411313232707156524">"<xliff:g id="USER">%1$s</xliff:g> er ikke i kontaktlisten."</string>
- <string name="select_link_title" msgid="5020179468567358399">"Velg lenke"</string>
+ <string name="select_link_title" msgid="5020179468567358399">"Velg kobling"</string>
<string name="empty_chat_list" msgid="7268903855432844937">"Ingen aktive samtaler."</string>
<string name="add_contact_title" msgid="8541795892456911186">"Legg til kontakt"</string>
<string name="input_contact_label" msgid="395294356081431462">"E-postadresse til den du ønsker å invitere:"</string>
@@ -132,7 +144,7 @@
<string name="perm_label" msgid="203411797893865789">"start lynmeldingstjeneste"</string>
<string name="perm_desc" msgid="6978187394092498941">"Tillater applikasjoner å starte lynmeldingstjenesten."</string>
<string name="error" msgid="4778856523246532623">"NB"</string>
- <string name="login_service_failed" msgid="3883751713470046349">"Kunne ikke logge inn på <xliff:g id="SERVICE">%1$s</xliff:g>. Prøv igjen senere."\n"(Detaljer: <xliff:g id="DESCRIPTION">%2$s</xliff:g>)"</string>
+ <string name="login_service_failed" msgid="3883751713470046349">"Kunne ikke logge på <xliff:g id="SERVICE">%1$s</xliff:g>. Prøv igjen senere."\n"(Detaljer: <xliff:g id="DESCRIPTION">%2$s</xliff:g>)"</string>
<string name="add_list_failed" msgid="5659371594032378190">"Listen ble ikke lagt til."</string>
<string name="block_contact_failed" msgid="5870952543258608424">"Kontakten ble ikke blokkert."</string>
<string name="unblock_contact_failed" msgid="7761060327693183076">"Kontakten ble ikke avblokkert."</string>
@@ -156,11 +168,11 @@
<string name="domain_not_supported" msgid="7715663042901606605">"Tjeneren støtter ikke videresending til domenet."</string>
<string name="unknown_user" msgid="6680215792586778118">"Brukernavnet du skrev inn ble ikke gjenkjent."</string>
<string name="recipient_blocked_the_user" msgid="8438323314518151118">"Beklager, du er blokkert av brukeren."</string>
- <string name="session_expired" msgid="1999103420742299764">"Sesjonen har gått ut, logg inn på nytt."</string>
- <string name="forced_logout" msgid="4914497176506037105">"du er logget inn på en annen klient."</string>
- <string name="already_logged_in" msgid="1907391913706263174">"du allerede er logget inn på en annen klient."</string>
+ <string name="session_expired" msgid="1999103420742299764">"Sesjonen har gått ut, logg på på nytt."</string>
+ <string name="forced_logout" msgid="4914497176506037105">"du er pålogget med en annen klient."</string>
+ <string name="already_logged_in" msgid="1907391913706263174">"du allerede er pålogget med en annen klient."</string>
<string name="msisdn_error" msgid="1477099919088266968">"Beklager, kan ikke lese telefonnummeret fra SIM-kortet. Kontakt operatøren for hjelp."</string>
- <string name="not_signed_in" msgid="8894662143178849906">"Du er ikke logget inn."</string>
+ <string name="not_signed_in" msgid="8894662143178849906">"Du er ikke pålogget."</string>
<string name="general_error" msgid="2784900425265121080">"Feilkode <xliff:g id="CODE">%1$d</xliff:g>"</string>
<string-array name="default_smiley_names">
<item msgid="1496436377093882868">"Glad"</item>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 9f635a5..a6e115f 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"chatberichten lezen"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Toepassingen toestaan gegevens te lezen van de provider van chatinhoud."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"chatberichten schrijven"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Toepassingen toestaan gegevens te schrijven naar de provider van chatinhoud."</string>
<string name="im_label" msgid="6289028202073124911">"Chat"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chatten - Een account selecteren"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Account toevoegen"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Account bewerken"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Account verwijderen"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Overal afmelden"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chatten - Een account selecteren"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Aanmelding annuleren"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Contact toevoegen"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Contact verwijderen"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Invoer"</string>
<string name="confirm" msgid="3229086014444547636">"Bevestigen"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Wilt u zich afmelden bij alle services?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Contact \'<xliff:g id="USER">%1$s</xliff:g>\' wordt verwijderd."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Contact \'<xliff:g id="USER">%1$s</xliff:g>\' wordt geblokkeerd."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Contact \'<xliff:g id="USER">%1$s</xliff:g>\' wordt gedeblokkeerd."</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index be9e375..0da89a3 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"odczytaj wiadomości czatu"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Zezwala aplikacjom na odczytywanie danych z dostawcy zawartości czatu."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"zapisz wiadomości czatu"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Zezwala aplikacjom na zapisywanie danych do dostawcy zawartości czatu."</string>
<string name="im_label" msgid="6289028202073124911">"Czat"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Czat: wybierz konto"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Dodaj konto"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Edytuj konto"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Usuń konto"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Wyloguj się ze wszystkich"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Czat: wybierz konto"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Anuluj logowanie"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Dodaj kontakt"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Usuń kontakt"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Katalog wejściowy"</string>
<string name="confirm" msgid="3229086014444547636">"Potwierdź"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Czy chcesz wylogować się ze wszystkich usług?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Kontakt „<xliff:g id="USER">%1$s</xliff:g>” zostanie usunięty."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Kontakt „<xliff:g id="USER">%1$s</xliff:g>” zostanie zablokowany."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Kontakt „<xliff:g id="USER">%1$s</xliff:g>” zostanie odblokowany."</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index a511d55..fa04a40 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"ler mensagens instantâneas"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Permite que as aplicações leiam dados a partir do fornecedor de conteúdo de MI."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"escrever mensagens instantâneas"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Permite que as aplicações escrevam dados para o fornecedor de conteúdo de MI."</string>
<string name="im_label" msgid="6289028202073124911">"MI"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chat - Seleccione uma conta"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Adicionar conta"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Editar conta"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Remover conta"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Terminar sessão em todos"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chat - Seleccione uma conta"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Cancelar início de sessão"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Adicionar contacto"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Eliminar contacto"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Entrada"</string>
<string name="confirm" msgid="3229086014444547636">"Confirmar"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Pretende terminar sessão em todos os serviços?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"O contacto \"<xliff:g id="USER">%1$s</xliff:g>\" será eliminado."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"O contacto \"<xliff:g id="USER">%1$s</xliff:g>\" será bloqueado."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"O contacto \"<xliff:g id="USER">%1$s</xliff:g>\" será desbloqueado."</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index bd334a1..a01bb6b 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"ler mensagens instantâneas"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Permite que os aplicativos leiam os dados do provedor de conteúdo de mensagem instantânea."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"gravar mensagens instantâneas"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Permite que os aplicativos gravem os dados no provedor de conteúdo de mensagem instantânea."</string>
<string name="im_label" msgid="6289028202073124911">"Mensagem instantânea"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Bate-papo - Selecione uma conta"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Adicionar conta"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Editar conta"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Remover conta"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Sair de todos"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Bate-papo - Selecione uma conta"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Cancelar login"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Adicionar contato"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Excluir contato"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Entrada"</string>
<string name="confirm" msgid="3229086014444547636">"Confirmar"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Deseja sair de todos os serviços?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"O contato \"<xliff:g id="USER">%1$s</xliff:g>\" será excluído."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"O contato \"<xliff:g id="USER">%1$s</xliff:g>\" será bloqueado."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"O contato \"<xliff:g id="USER">%1$s</xliff:g>\" será desbloqueado."</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index a0e029d..c243a82 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"читать мгновенные сообщения"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Позволяет приложениям считывать данные из провайдера чата."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"писать мгновенные сообщения"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Позволяет приложениям отправлять данные провайдеру чата."</string>
<string name="im_label" msgid="6289028202073124911">"Чат"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Чат – выберите аккаунт"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Добавить аккаунт"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Изменить аккаунт"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Удалить аккаунт"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Выйти отовсюду"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Чат – выберите аккаунт"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Отмена входа"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Добавить контакт"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Удалить контакт"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Мenu+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Ввод"</string>
<string name="confirm" msgid="3229086014444547636">"Подтвердить"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Выйти из всех служб?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Контакт \"<xliff:g id="USER">%1$s</xliff:g>\" будет удален."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Контакт \"<xliff:g id="USER">%1$s</xliff:g>\" будет заблокирован."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Контакт \"<xliff:g id="USER">%1$s</xliff:g>\" будет разблокирован."</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index d3bb2b8..ed23f4e 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"läsa snabbmeddelanden"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Tillåter att ett program läser data från snabbmeddelandeleverantören."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"skriva snabbmeddelanden"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Tillåter att ett program skriver data till snabbmeddelandeleverantören."</string>
<string name="im_label" msgid="6289028202073124911">"Chatt"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Chatt – välj ett konto"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Lägg till konto"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Redigera konto"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Ta bort konto"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Logga ut från alla"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Chatt – välj ett konto"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Avbryt inloggning"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Lägg till kontakt"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Ta bort kontakt"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Meny+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Indata"</string>
<string name="confirm" msgid="3229086014444547636">"Bekräfta"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Vill du logga ut från alla tjänster?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"Kontakten <xliff:g id="USER">%1$s</xliff:g> tas bort."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"Kontakten <xliff:g id="USER">%1$s</xliff:g> blockeras."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"Blockering hävs för kontakten <xliff:g id="USER">%1$s</xliff:g>."</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index d0e2c8f..420fdc2 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"anlık iletileri oku"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"Uygulamalara, IM içerik sağlayıcısından gelen verileri okuma izni verir."</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"anlık iletiler yazın"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"Uygulamalara, IM içerik sağlayıcısına veri yazma izni verir."</string>
<string name="im_label" msgid="6289028202073124911">"IM"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"Sohbet - Bir hesap seçin"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"Hesap ekle"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"Hesabı düzenle"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"Hesabı kaldır"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"Tüm hizmetlerden çık"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"Sohbet - Bir hesap seçin"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"Oturum açmayı iptal et"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"Kişi ekle"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"Kişiyi sil"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"Menü+"</string>
<string name="default_input_title" msgid="6182729628894599563">"Giriş"</string>
<string name="confirm" msgid="3229086014444547636">"Doğrula"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"Tüm hizmetlerden çıkmak istiyor musunuz?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"\"<xliff:g id="USER">%1$s</xliff:g>\" kişisi silinecek."</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"\"<xliff:g id="USER">%1$s</xliff:g>\" kişisi engellenecek."</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"\"<xliff:g id="USER">%1$s</xliff:g>\" kişisinin engellemesi kaldırılacak."</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 42c2c16..ef7ae12 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"阅读即时消息"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"允许应用程序从即时消息内容提供者处读取数据。"</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"撰写即时消息"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"允许应用程序向即时消息内容提供者写入数据。"</string>
<string name="im_label" msgid="6289028202073124911">"即时消息"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"聊天 - 选择一个帐户"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"添加帐户"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"编辑帐户"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"删除帐户"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"全部退出"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"聊天 - 选择一个帐户"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"取消登录"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"添加联系人"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"删除联系人"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"MENU+"</string>
<string name="default_input_title" msgid="6182729628894599563">"输入"</string>
<string name="confirm" msgid="3229086014444547636">"确认"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"是否要退出全部服务?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"将会删除联系人“<xliff:g id="USER">%1$s</xliff:g>”。"</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"将会阻止联系人“<xliff:g id="USER">%1$s</xliff:g>”。"</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"将会解除阻止联系人“<xliff:g id="USER">%1$s</xliff:g>”。"</string>
@@ -53,7 +65,7 @@
<string name="sign_in" msgid="6204326200860136567">"登录"</string>
<string name="signing_in_to" msgid="2689649632858697221">"正在登录 <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
<string name="signing_in_wait" msgid="987357161364666888">"正在登录..."</string>
- <string name="bg_data_prompt_title" msgid="4861800723853178111">"背景数据已禁用"</string>
+ <string name="bg_data_prompt_title" msgid="4861800723853178111">"已停用背景数据"</string>
<string name="bg_data_prompt_message" msgid="2343305645142823544">"<xliff:g id="PROVIDER">%1$s</xliff:g> 需要启用背景数据。"</string>
<string name="bg_data_prompt_ok" msgid="3443385427882751532">"启用"</string>
<string name="bg_data_prompt_cancel" msgid="7206105589826174638">"退出"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index d644a6e..5ecd31f 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -15,7 +15,18 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label" msgid="4791213266570841712">"讀取即時訊息"</string>
+ <string name="ro_perm_desc" msgid="2030191017293726405">"允許應用程式讀取來自即時訊息內容提供端的資料。"</string>
+ <string name="wo_perm_label" msgid="2275102271914312340">"撰寫即時訊息"</string>
+ <string name="wo_perm_desc" msgid="4332792325927331086">"允許應用程式將資料寫入即時訊息內容提供端。"</string>
<string name="im_label" msgid="6289028202073124911">"即時訊息"</string>
+ <string name="landing_page_title" msgid="8575938257482637474">"即時通訊 - 選取帳戶"</string>
+ <string name="menu_add_account" msgid="5762363412622888397">"新增帳戶"</string>
+ <string name="menu_edit_account" msgid="2909998494159263063">"編輯帳戶"</string>
+ <string name="menu_remove_account" msgid="6821008426177540869">"移除帳戶"</string>
+ <string name="menu_sign_out_all" msgid="4796813055998684330">"全部登出"</string>
+ <string name="choose_account_title" msgid="6660096418433575680">"即時通訊 - 選取帳戶"</string>
+ <string name="conversations" msgid="7338245838564623519">"(<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
<string name="menu_cancel_signin" msgid="146078926243968887">"取消登入"</string>
<string name="menu_add_contact" msgid="6315091944808434095">"新增聯絡人"</string>
<string name="menu_remove_contact" msgid="3306468526492774925">"刪除聯絡人"</string>
@@ -34,6 +45,7 @@
<string name="menu_plus" msgid="5000617247235760106">"[Menu] +"</string>
<string name="default_input_title" msgid="6182729628894599563">"輸入"</string>
<string name="confirm" msgid="3229086014444547636">"確認"</string>
+ <string name="signout_all_confirm_message" msgid="4442995839737460513">"您要登出所有服務嗎?"</string>
<string name="confirm_delete_contact" msgid="1364595657359357114">"刪除「<xliff:g id="USER">%1$s</xliff:g>」?"</string>
<string name="confirm_block_contact" msgid="2490910366424078491">"封鎖「<xliff:g id="USER">%1$s</xliff:g>」。"</string>
<string name="confirm_unblock_contact" msgid="2194464819104507216">"「<xliff:g id="USER">%1$s</xliff:g>」會被解除封鎖。"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fb366b8..3fe363a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -18,10 +18,40 @@
*/
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="ro_perm_label">read instant messages</string>
+ <string name="ro_perm_desc">
+ Allows applications to read data from the IM content provider.
+ </string>
+
+ <string name="wo_perm_label">write instant messages</string>
+ <string name="wo_perm_desc">
+ Allows applications to write data to the IM content provider.
+ </string>
+
<!-- The application label. This appears in the application launcher on the
Home screen. This is a noun. -->
<string name="im_label">IM</string>
+ <!-- These strings displayed on the landing page. -->
+ <!-- The title of the landing page.-->
+ <string name="landing_page_title">Chat - Select an account</string>
+
+ <!-- Landing page screen menu and context menu items. -->
+ <!-- Conext menu item: add a new account.-->
+ <string name="menu_add_account">Add account</string>
+ <!-- Conext menu item: edit an account.-->
+ <string name="menu_edit_account">Edit account</string>
+ <!-- Conext menu item: remove an account.-->
+ <string name="menu_remove_account">Remove account</string>
+ <!-- Screen menu item: sign out all service.-->
+ <string name="menu_sign_out_all">Sign out all</string>
+
+ <!-- These strings displayed on the landing page. -->
+ <!-- The title of the landing page.-->
+ <string name="choose_account_title">Chat - Select an account</string>
+ <!-- Displays the number of ongoing chats on the landing page.-->
+ <string name="conversations">(<xliff:g id="number" example="27">%1$d</xliff:g>)</string>
+
<!-- Sign in progress screen menu items.-->
<!-- Screen menu item on the sign-in progress screen. It allows the user to cancel signing in.-->
<string name="menu_cancel_signin">Cancel signin</string>
@@ -86,6 +116,8 @@
<!-- Strings for the confirm dialogs-->
<!-- The title of the confirm dialog which asks the user to continue or cancel an operation such as block a contact, remove a contact.-->
<string name="confirm">Confirm</string>
+ <!-- This is the message displayed in the confirm dialog when the user choose to sign out all service -->
+ <string name="signout_all_confirm_message">Do you want to sign out all services?</string>
<!-- This is the message displayed in the confirm dialog that opens when user clicks to delete a contact in the contact list screen.-->
<string name="confirm_delete_contact">The contact \"<xliff:g id="user">%1$s</xliff:g>\" will be deleted.</string>
<!-- This is the message displayed in the confirm dialog that opens when user clicks to block a contact in the contact list screen.-->
diff --git a/samples/PluginDemo/Android.mk b/samples/PluginDemo/Android.mk
deleted file mode 100644
index 46fe534..0000000
--- a/samples/PluginDemo/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := samples
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files) \
-
-LOCAL_PACKAGE_NAME := ImPluginDemo
-
-LOCAL_JAVA_LIBRARIES := com.android.im.plugin
-
-include $(BUILD_PACKAGE)
diff --git a/samples/PluginDemo/AndroidManifest.xml b/samples/PluginDemo/AndroidManifest.xml
deleted file mode 100644
index eaebd68..0000000
--- a/samples/PluginDemo/AndroidManifest.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2008 Esmertec Inc.
- * 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.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.im.plugin.demo" android:sharedUserId="android.uid.im">
-
- <application android:taskAffinity="android.task.im">
-
- <uses-library android:name="com.android.im.plugin" />
-
- <service android:name=".DemoImPlugin">
- <intent-filter>
- <action android:name="com.android.im.plugin" />
- </intent-filter>
- <meta-data android:name="com.android.im.provider_name"
- android:value="Demo"/>
- <meta-data android:name="com.android.im.provider_full_name"
- android:value="Demo IM Provider"/>
- <meta-data android:name="com.android.im.signup_url"
- android:value="http://xxx.xxx.xxx"/>
- </service>
-
- </application>
-
-</manifest>
diff --git a/samples/PluginDemo/res/drawable/chat.png b/samples/PluginDemo/res/drawable/chat.png
deleted file mode 100755
index be844fd..0000000
--- a/samples/PluginDemo/res/drawable/chat.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/chat_new.png b/samples/PluginDemo/res/drawable/chat_new.png
deleted file mode 100755
index f31ba59..0000000
--- a/samples/PluginDemo/res/drawable/chat_new.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_angel.png b/samples/PluginDemo/res/drawable/emo_im_angel.png
deleted file mode 100644
index c34dfa6..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_angel.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_crying.png b/samples/PluginDemo/res/drawable/emo_im_crying.png
deleted file mode 100644
index 1cafdb3..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_crying.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_embarrassed.png b/samples/PluginDemo/res/drawable/emo_im_embarrassed.png
deleted file mode 100644
index e4db963..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_embarrassed.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_foot_in_mouth.png b/samples/PluginDemo/res/drawable/emo_im_foot_in_mouth.png
deleted file mode 100644
index 09d1fba..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_foot_in_mouth.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_happy.png b/samples/PluginDemo/res/drawable/emo_im_happy.png
deleted file mode 100644
index b86602a..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_happy.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_kissing.png b/samples/PluginDemo/res/drawable/emo_im_kissing.png
deleted file mode 100644
index 56378f6..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_kissing.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_laughing.png b/samples/PluginDemo/res/drawable/emo_im_laughing.png
deleted file mode 100644
index 980bf28..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_laughing.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_lips_are_sealed.png b/samples/PluginDemo/res/drawable/emo_im_lips_are_sealed.png
deleted file mode 100644
index f2de993..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_lips_are_sealed.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_money_mouth.png b/samples/PluginDemo/res/drawable/emo_im_money_mouth.png
deleted file mode 100644
index 08c53fd..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_money_mouth.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_sad.png b/samples/PluginDemo/res/drawable/emo_im_sad.png
deleted file mode 100644
index 31c08d0..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_sad.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_surprised.png b/samples/PluginDemo/res/drawable/emo_im_surprised.png
deleted file mode 100644
index abe8c7a..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_surprised.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_tongue_sticking_out.png b/samples/PluginDemo/res/drawable/emo_im_tongue_sticking_out.png
deleted file mode 100644
index 6f0f47b..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_tongue_sticking_out.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_undecided.png b/samples/PluginDemo/res/drawable/emo_im_undecided.png
deleted file mode 100644
index eb4f8c5..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_undecided.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_winking.png b/samples/PluginDemo/res/drawable/emo_im_winking.png
deleted file mode 100644
index 568562a..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_winking.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_wtf.png b/samples/PluginDemo/res/drawable/emo_im_wtf.png
deleted file mode 100644
index 41dd47f..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_wtf.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/emo_im_yelling.png b/samples/PluginDemo/res/drawable/emo_im_yelling.png
deleted file mode 100644
index c3c8612..0000000
--- a/samples/PluginDemo/res/drawable/emo_im_yelling.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/im_logo.png b/samples/PluginDemo/res/drawable/im_logo.png
deleted file mode 100644
index 764d189..0000000
--- a/samples/PluginDemo/res/drawable/im_logo.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/drawable/im_logo_splashscr.png b/samples/PluginDemo/res/drawable/im_logo_splashscr.png
deleted file mode 100644
index 1b7ee6f..0000000
--- a/samples/PluginDemo/res/drawable/im_logo_splashscr.png
+++ /dev/null
Binary files differ
diff --git a/samples/PluginDemo/res/values-cs/strings.xml b/samples/PluginDemo/res/values-cs/strings.xml
deleted file mode 100644
index 0345b89..0000000
--- a/samples/PluginDemo/res/values-cs/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Přidat kontakt"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Smazat kontakt"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Blokovat"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Seznam kontaktů"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Odeslat zprávu"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Info o kamarádovi"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Konec konverzace"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Přepnout chat"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Vložit emotikony"</string>
- <string name="sign_up" msgid="3944276728278864333">"Zřízení nového účtu"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Pokud je váš telefon ukraden nebo jej ztratíte, přejděte v zájmu vlastní bezpečnosti na počítači na web a změňte své heslo."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Seznam kontaktů – <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Uživatelské jméno:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Konverzace (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Kontaktní informace"</string>
- <string name="presence_available" msgid="1184051402868736726">"Povoleno"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Přidat kontakt"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Jméno osoby, kterou chcete přidat:"</string>
- <string name="invite_label" msgid="907494221148096012">"Přidat kamaráda"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Happy"</item>
- <item msgid="2764363456492352853">"Smutný"</item>
- <item msgid="416624764294712159">"Mrkající"</item>
- <item msgid="7152979870122929989">"Vypláznutý jazyk"</item>
- <item msgid="5784780866600056743">"Překvapený"</item>
- <item msgid="5454185003381226454">"Pusa"</item>
- <item msgid="1413668617851210441">"Hej!"</item>
- <item msgid="232246158381043538">"Cool"</item>
- <item msgid="2440257511131202785">"Cinkání zlaťáků"</item>
- <item msgid="4571282940807190133">"Šlápota v úsměvu"</item>
- <item msgid="3260099163589753993">"V rozpacích"</item>
- <item msgid="3042531792218744865">"Andílek"</item>
- <item msgid="5227319381647888452">"Nerozhodný"</item>
- <item msgid="6952104030566994554">"Rozplakaný"</item>
- <item msgid="9199616532683270084">"Ani muk"</item>
- <item msgid="4338502150254517147">"Smějící se"</item>
- <item msgid="1014703928300075245">"Zmatený"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-da/strings.xml b/samples/PluginDemo/res/values-da/strings.xml
deleted file mode 100644
index f1c5a2f..0000000
--- a/samples/PluginDemo/res/values-da/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Tilføj kontakt"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Slet kontakt"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Bloker"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Liste over kontakter"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Send IM"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Venneoplysninger"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Afslut samtale"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Skift chats"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Indsæt humørikoner"</string>
- <string name="sign_up" msgid="3944276728278864333">"Få en ny konto"</string>
- <string name="check_save_password" msgid="3554564072443242779">"For din egen sikkerheds skyld skal du gå til webstedet på din computer og ændre din adgangskode, hvis du mister din telefon, eller den bliver stjålet."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Liste over kontakter – <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Brugernavn:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Samtaler (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Kontaktoplysninger"</string>
- <string name="presence_available" msgid="1184051402868736726">"Ledig"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Tilføj kontakt"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Skærmnavn for den person du ønsker at tilføje:"</string>
- <string name="invite_label" msgid="907494221148096012">"Tilføj ven"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Glad"</item>
- <item msgid="2764363456492352853">"Trist"</item>
- <item msgid="416624764294712159">"Blinker"</item>
- <item msgid="7152979870122929989">"Rækker tunge"</item>
- <item msgid="5784780866600056743">"Overrasket"</item>
- <item msgid="5454185003381226454">"Kysser"</item>
- <item msgid="1413668617851210441">"Råber"</item>
- <item msgid="232246158381043538">"Sej"</item>
- <item msgid="2440257511131202785">"Pengeglad"</item>
- <item msgid="4571282940807190133">"Forlegen"</item>
- <item msgid="3260099163589753993">"Flov"</item>
- <item msgid="3042531792218744865">"Engel"</item>
- <item msgid="5227319381647888452">"Uafklaret"</item>
- <item msgid="6952104030566994554">"Græder"</item>
- <item msgid="9199616532683270084">"Lukket med syv segl"</item>
- <item msgid="4338502150254517147">"Griner"</item>
- <item msgid="1014703928300075245">"Forvirret"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-de/strings.xml b/samples/PluginDemo/res/values-de/strings.xml
deleted file mode 100644
index 5a081cb..0000000
--- a/samples/PluginDemo/res/values-de/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Kontakt hinzufügen"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Kontakt löschen"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Blockieren"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Kontaktliste"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"IM senden"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Buddy Info"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Gespräch beenden"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Chats wechseln"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Emoticons einfügen"</string>
- <string name="sign_up" msgid="3944276728278864333">"Ein neues Konto erhalten"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Zu Ihrer Sicherheit: Wenn Sie Ihr Telefon verloren haben oder es gestohlen wurde, rufen Sie die Website auf Ihrem Computer auf und ändern Sie Ihr Passwort."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Kontaktliste - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Benutzername:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Gespräche (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Kontaktinformationen"</string>
- <string name="presence_available" msgid="1184051402868736726">"Verfügbar"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Kontakt hinzufügen"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Displayname der Person, die Sie hinzufügen möchten:"</string>
- <string name="invite_label" msgid="907494221148096012">"Buddy hinzufügen"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Glücklich"</item>
- <item msgid="2764363456492352853">"Traurig"</item>
- <item msgid="416624764294712159">"Zwinkern"</item>
- <item msgid="7152979870122929989">"Zunge rausstrecken"</item>
- <item msgid="5784780866600056743">"Überrascht"</item>
- <item msgid="5454185003381226454">"Kuss"</item>
- <item msgid="1413668617851210441">"Schreien"</item>
- <item msgid="232246158381043538">"Cool"</item>
- <item msgid="2440257511131202785">"Lass Taten sprechen"</item>
- <item msgid="4571282940807190133">"Fettnäpfchen"</item>
- <item msgid="3260099163589753993">"Peinlich berührt"</item>
- <item msgid="3042531792218744865">"Engel"</item>
- <item msgid="5227319381647888452">"Unentschlossen"</item>
- <item msgid="6952104030566994554">"Weinen"</item>
- <item msgid="9199616532683270084">"Versiegelte Lippen"</item>
- <item msgid="4338502150254517147">"Lachen"</item>
- <item msgid="1014703928300075245">"Verwirrt"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-el/strings.xml b/samples/PluginDemo/res/values-el/strings.xml
deleted file mode 100644
index 28501ae..0000000
--- a/samples/PluginDemo/res/values-el/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Προσθήκη επαφής"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Διαγραφή επαφής"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Αποκλεισμός"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Λίστα επαφών"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Αποστολή άμεσων μηνυμάτων (IM)"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Πληροφορίες φίλου"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Τερματισμός συνομιλίας"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Αλλαγή συζητήσεων"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Εισαγωγή εικονιδίων emoticons"</string>
- <string name="sign_up" msgid="3944276728278864333">"Αποκτήστε νέο λογαριασμό"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Για την ασφάλειά σας, εάν το τηλέφωνό σας χαθεί ή κλαπεί, μεταβείτε στον ιστότοπο στον υπολογιστή σας και αλλάξτε τον κωδικό πρόσβασης."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Λίστα επαφών - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Όνομα χρήστη:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Συνομιλίες (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Πληροφορίας επικοινωνίας"</string>
- <string name="presence_available" msgid="1184051402868736726">"Διαθέσιμος/η"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Προσθήκη επαφής"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Το ψευδώνυμο του ατόμου που θέλετε να προσθέσετε:"</string>
- <string name="invite_label" msgid="907494221148096012">"Προσθήκη φίλου"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Είμαι χαρούμενος"</item>
- <item msgid="2764363456492352853">"Είμαι λυπημένος"</item>
- <item msgid="416624764294712159">"Κλείνω το μάτι"</item>
- <item msgid="7152979870122929989">"Κοροϊδεύω"</item>
- <item msgid="5784780866600056743">"Είμαι έκπληκτος"</item>
- <item msgid="5454185003381226454">"Φιλάω"</item>
- <item msgid="1413668617851210441">"Φωνάζω"</item>
- <item msgid="232246158381043538">"Cool"</item>
- <item msgid="2440257511131202785">"Κάνω τα λόγια μου πράξη"</item>
- <item msgid="4571282940807190133">"Είπα ανοησία"</item>
- <item msgid="3260099163589753993">"Ντρέπομαι"</item>
- <item msgid="3042531792218744865">"Αγγελούδι"</item>
- <item msgid="5227319381647888452">"Δεν έχω αποφασίσει"</item>
- <item msgid="6952104030566994554">"Κλαίω"</item>
- <item msgid="9199616532683270084">"Δεν αποκαλύπτω τίποτα"</item>
- <item msgid="4338502150254517147">"Γελάω"</item>
- <item msgid="1014703928300075245">"Είμαι μπερδεμένος"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-es-rUS/strings.xml b/samples/PluginDemo/res/values-es-rUS/strings.xml
deleted file mode 100644
index c573baa..0000000
--- a/samples/PluginDemo/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Agregar contacto"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Eliminar contacto"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Bloquear"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Lista de contactos"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Enviar mensajería instantánea"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Información de Buddy"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Finalizar conversación"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Modificar chats"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Insertar emoticones"</string>
- <string name="sign_up" msgid="3944276728278864333">"Obtén una cuenta nueva"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Para tu seguridad, si pierdes o te roban el teléfono, ingresa al sitio web desde tu computadora y cambia la contraseña."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Lista de contactos - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Nombre de usuario:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Conversaciones (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Información de contacto"</string>
- <string name="presence_available" msgid="1184051402868736726">"Disponible"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Agregar contacto"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Nombre de pantalla de la persona que deseas agregar:"</string>
- <string name="invite_label" msgid="907494221148096012">"Agregar Buddy"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Feliz"</item>
- <item msgid="2764363456492352853">"Triste"</item>
- <item msgid="416624764294712159">"Guiñando un ojo"</item>
- <item msgid="7152979870122929989">"Con la lengua afuera"</item>
- <item msgid="5784780866600056743">"Sorprendido"</item>
- <item msgid="5454185003381226454">"Besando"</item>
- <item msgid="1413668617851210441">"Gritando"</item>
- <item msgid="232246158381043538">"En la onda"</item>
- <item msgid="2440257511131202785">"Dinero en boca"</item>
- <item msgid="4571282940807190133">"Meter la pata"</item>
- <item msgid="3260099163589753993">"Avergonzado"</item>
- <item msgid="3042531792218744865">"Ángel"</item>
- <item msgid="5227319381647888452">"Indeciso"</item>
- <item msgid="6952104030566994554">"Llorando"</item>
- <item msgid="9199616532683270084">"Los labios están cerrados"</item>
- <item msgid="4338502150254517147">"Riendo"</item>
- <item msgid="1014703928300075245">"Confundido"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-es/strings.xml b/samples/PluginDemo/res/values-es/strings.xml
deleted file mode 100644
index 0fcf217..0000000
--- a/samples/PluginDemo/res/values-es/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Añadir contacto"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Eliminar contacto"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Bloquear"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Lista de contactos"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Enviar MI"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Información de amigo"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Finalizar conversación"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Cambiar de chat"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Insertar emoticonos"</string>
- <string name="sign_up" msgid="3944276728278864333">"Obtener una cuenta nueva"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Si pierdes el teléfono o te lo roban, te recomendamos por seguridad que accedas al sitio web desde tu equipo y cambies la contraseña."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Lista de contactos - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Nombre de usuario:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Conversaciones (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Información de contacto"</string>
- <string name="presence_available" msgid="1184051402868736726">"Disponible"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Añadir contacto"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Nombre de pantalla de la persona que quieres añadir:"</string>
- <string name="invite_label" msgid="907494221148096012">"Añadir amigo"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Contento"</item>
- <item msgid="2764363456492352853">"Triste"</item>
- <item msgid="416624764294712159">"Guiño"</item>
- <item msgid="7152979870122929989">"Sacando la lengua"</item>
- <item msgid="5784780866600056743">"Sorprendido"</item>
- <item msgid="5454185003381226454">"Besando"</item>
- <item msgid="1413668617851210441">"Gritando"</item>
- <item msgid="232246158381043538">"Atractivo"</item>
- <item msgid="2440257511131202785">"Dinero en la boca"</item>
- <item msgid="4571282940807190133">"Metedura de pata"</item>
- <item msgid="3260099163589753993">"Avergonzado"</item>
- <item msgid="3042531792218744865">"Ángel"</item>
- <item msgid="5227319381647888452">"Indeciso"</item>
- <item msgid="6952104030566994554">"Llorando"</item>
- <item msgid="9199616532683270084">"Labios sellados"</item>
- <item msgid="4338502150254517147">"Riendo"</item>
- <item msgid="1014703928300075245">"Confuso"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-fr/strings.xml b/samples/PluginDemo/res/values-fr/strings.xml
deleted file mode 100644
index cc048ed..0000000
--- a/samples/PluginDemo/res/values-fr/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Ajouter un contact"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Supprimer un contact"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Bloquer"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Liste de contacts"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Envoyer un message instantané"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Infos sur le contact"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Terminer la conversation"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Changer de chat"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Insérer une émoticône"</string>
- <string name="sign_up" msgid="3944276728278864333">"Créer un nouveau compte"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Pour votre sécurité, en cas de vol ou de perte de votre téléphone, rendez-vous sur le site Web depuis votre ordinateur et modifiez votre mot de passe."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Liste de contacts :<xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Nom d\'utilisateur :"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Conversations (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Infos sur le contact"</string>
- <string name="presence_available" msgid="1184051402868736726">"Disponible"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Ajouter le contact"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Identifiant du contact que vous souhaitez ajouter :"</string>
- <string name="invite_label" msgid="907494221148096012">"Ajouter un contact"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Content"</item>
- <item msgid="2764363456492352853">"Triste"</item>
- <item msgid="416624764294712159">"Clin d\'œil"</item>
- <item msgid="7152979870122929989">"Tire la langue"</item>
- <item msgid="5784780866600056743">"Surpris"</item>
- <item msgid="5454185003381226454">"Bisou"</item>
- <item msgid="1413668617851210441">"Hurle"</item>
- <item msgid="232246158381043538">"Cool"</item>
- <item msgid="2440257511131202785">"Argent"</item>
- <item msgid="4571282940807190133">"Embarrassé"</item>
- <item msgid="3260099163589753993">"Gêné"</item>
- <item msgid="3042531792218744865">"Ange"</item>
- <item msgid="5227319381647888452">"Indécis"</item>
- <item msgid="6952104030566994554">"Pleure"</item>
- <item msgid="9199616532683270084">"Motus et bouche cousue"</item>
- <item msgid="4338502150254517147">"Rigole"</item>
- <item msgid="1014703928300075245">"Confus"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-it/strings.xml b/samples/PluginDemo/res/values-it/strings.xml
deleted file mode 100644
index 6745c76..0000000
--- a/samples/PluginDemo/res/values-it/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Aggiungi contatto"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Elimina contatto"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Blocca"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Elenco contatti"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Invia msg chat"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Info amico"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Termina conversazione"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Cambia conversazione"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Inserisci emoticon"</string>
- <string name="sign_up" msgid="3944276728278864333">"Ottieni un nuovo account"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Per la tua sicurezza, in caso di perdita o furto del telefono visita il sito web da un computer e cambia la password."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Elenco contatti - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Nome utente:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Conversazioni (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Info contatto"</string>
- <string name="presence_available" msgid="1184051402868736726">"Disponibile"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Aggiungi contatto"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Nome visualizzato della persona da aggiungere:"</string>
- <string name="invite_label" msgid="907494221148096012">"Aggiungi amico"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Felice"</item>
- <item msgid="2764363456492352853">"Triste"</item>
- <item msgid="416624764294712159">"Occhiolino"</item>
- <item msgid="7152979870122929989">"Linguaccia"</item>
- <item msgid="5784780866600056743">"Sorpreso"</item>
- <item msgid="5454185003381226454">"Bacio"</item>
- <item msgid="1413668617851210441">"Urlo"</item>
- <item msgid="232246158381043538">"Fico"</item>
- <item msgid="2440257511131202785">"Fatti, non parole"</item>
- <item msgid="4571282940807190133">"Gaffe"</item>
- <item msgid="3260099163589753993">"Imbarazzato"</item>
- <item msgid="3042531792218744865">"Angelo"</item>
- <item msgid="5227319381647888452">"Indeciso"</item>
- <item msgid="6952104030566994554">"Piango"</item>
- <item msgid="9199616532683270084">"Labbra cucite"</item>
- <item msgid="4338502150254517147">"Risata"</item>
- <item msgid="1014703928300075245">"Confuso"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-ja/strings.xml b/samples/PluginDemo/res/values-ja/strings.xml
deleted file mode 100644
index f59333d..0000000
--- a/samples/PluginDemo/res/values-ja/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"連絡先を追加"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"連絡先を削除"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"ブロック"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"連絡先リスト"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"チャットを送信"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"友だち情報"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"チャット終了"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"チャットを切り替え"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"絵文字を挿入"</string>
- <string name="sign_up" msgid="3944276728278864333">"新しいアカウントを取得"</string>
- <string name="check_save_password" msgid="3554564072443242779">"セキュリティ保護のため、携帯電話を紛失したり盗まれたりした場合は、パソコンからウェブサイトにアクセスしてパスワードを変更してください。"</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"連絡先リスト - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"ユーザー名:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"チャット (<xliff:g id="NUMBER">%1$d</xliff:g>件)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"連絡先情報"</string>
- <string name="presence_available" msgid="1184051402868736726">"オンライン"</string>
- <string name="add_contact_title" msgid="292217657045373736">"連絡先を追加"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"追加する人のスクリーンネーム:"</string>
- <string name="invite_label" msgid="907494221148096012">"友だちを追加"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"ハッピー"</item>
- <item msgid="2764363456492352853">"悲しい"</item>
- <item msgid="416624764294712159">"ウィンク"</item>
- <item msgid="7152979870122929989">"アッカンベー"</item>
- <item msgid="5784780866600056743">"びっくり"</item>
- <item msgid="5454185003381226454">"キス"</item>
- <item msgid="1413668617851210441">"激怒"</item>
- <item msgid="232246158381043538">"クール"</item>
- <item msgid="2440257511131202785">"気持ち悪い"</item>
- <item msgid="4571282940807190133">"しまった"</item>
- <item msgid="3260099163589753993">"恥ずかしい"</item>
- <item msgid="3042531792218744865">"天使"</item>
- <item msgid="5227319381647888452">"迷う"</item>
- <item msgid="6952104030566994554">"泣く"</item>
- <item msgid="9199616532683270084">"お口にチャック"</item>
- <item msgid="4338502150254517147">"笑顔"</item>
- <item msgid="1014703928300075245">"混乱"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-ko/strings.xml b/samples/PluginDemo/res/values-ko/strings.xml
deleted file mode 100644
index ab5cb9f..0000000
--- a/samples/PluginDemo/res/values-ko/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"연락처 추가"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"연락처 삭제"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"차단"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"연락처 목록"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"채팅하기"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"친구 정보"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"대화 종료"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"채팅 전환"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"이모티콘 삽입"</string>
- <string name="sign_up" msgid="3944276728278864333">"새 계정 만들기"</string>
- <string name="check_save_password" msgid="3554564072443242779">"휴대전화를 잃어버렸거나 도난당한 경우에는 보안을 위해 컴퓨터에서 웹사이트를 방문하여 비밀번호를 변경하세요."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"연락처 목록 - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"사용자 이름:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"대화(<xliff:g id="NUMBER">%1$d</xliff:g>개)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"연락처 정보"</string>
- <string name="presence_available" msgid="1184051402868736726">"온라인"</string>
- <string name="add_contact_title" msgid="292217657045373736">"연락처 추가"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"추가할 사람의 대화명:"</string>
- <string name="invite_label" msgid="907494221148096012">"친구 추가"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"행복해"</item>
- <item msgid="2764363456492352853">"슬퍼요"</item>
- <item msgid="416624764294712159">"윙크"</item>
- <item msgid="7152979870122929989">"메롱"</item>
- <item msgid="5784780866600056743">"헉!"</item>
- <item msgid="5454185003381226454">"키스"</item>
- <item msgid="1413668617851210441">"아악"</item>
- <item msgid="232246158381043538">"멋지네"</item>
- <item msgid="2440257511131202785">"으이구"</item>
- <item msgid="4571282940807190133">"실수했네"</item>
- <item msgid="3260099163589753993">"당황"</item>
- <item msgid="3042531792218744865">"천사"</item>
- <item msgid="5227319381647888452">"결정하기 어렵군"</item>
- <item msgid="6952104030566994554">"엉엉엉"</item>
- <item msgid="9199616532683270084">"비밀로 할게"</item>
- <item msgid="4338502150254517147">"하하하"</item>
- <item msgid="1014703928300075245">"어리둥절"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-nb/strings.xml b/samples/PluginDemo/res/values-nb/strings.xml
deleted file mode 100644
index 43d614a..0000000
--- a/samples/PluginDemo/res/values-nb/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Legg til kontakt"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Fjern kontakt"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Blokker kontakt"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Kontaktliste"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Start samtale"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Vis profil"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Avslutt samtale"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Bytt mellom samtaler"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Sett inn smilefjes"</string>
- <string name="sign_up" msgid="3944276728278864333">"Mangler du konto?"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Av sikkerhetsgrunner, gå til nettstedet og endre passordet om telefonen blir tapt eller stjåler."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Kontaktliste - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Brukernavn:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Pågående samtaler (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Kontaktprofil"</string>
- <string name="presence_available" msgid="1184051402868736726">"Tilgjengelig"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Legg til kontakt"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"E-postadresse til den du ønsker å invitere:"</string>
- <string name="invite_label" msgid="907494221148096012">"Send invitasjon"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Glad"</item>
- <item msgid="2764363456492352853">"Trist"</item>
- <item msgid="416624764294712159">"Blunker"</item>
- <item msgid="7152979870122929989">"Rekker tunge"</item>
- <item msgid="5784780866600056743">"Overrasket"</item>
- <item msgid="5454185003381226454">"Kyss"</item>
- <item msgid="1413668617851210441">"Roper"</item>
- <item msgid="232246158381043538">"Kul"</item>
- <item msgid="2440257511131202785">"Pengemunn"</item>
- <item msgid="4571282940807190133">"Fot i munnen"</item>
- <item msgid="3260099163589753993">"Flau"</item>
- <item msgid="3042531792218744865">"Engel"</item>
- <item msgid="5227319381647888452">"Usikker"</item>
- <item msgid="6952104030566994554">"Gråter"</item>
- <item msgid="9199616532683270084">"Stille som graven"</item>
- <item msgid="4338502150254517147">"Ler"</item>
- <item msgid="1014703928300075245">"Forvirret"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-nl/strings.xml b/samples/PluginDemo/res/values-nl/strings.xml
deleted file mode 100644
index ea64f04..0000000
--- a/samples/PluginDemo/res/values-nl/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Contact toevoegen"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Contact verwijderen"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Blokkeren"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Lijst met contacten"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Chat verzenden"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Buddygegevens"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Conversatie beëindigen"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Schakelen tussen chats"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Emoticons invoegen"</string>
- <string name="sign_up" msgid="3944276728278864333">"Een nieuw account verkrijgen"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Als u uw telefoon verliest of als deze wordt gestolen, moet u voor uw veiligheid naar de website gaan op uw computer en uw wachtwoord wijzigen."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Lijst met contacten - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Gebruikersnaam:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Conversaties (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Contactgegevens"</string>
- <string name="presence_available" msgid="1184051402868736726">"Beschikbaar"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Contact toevoegen"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Schermnaam van de persoon die u wilt toevoegen:"</string>
- <string name="invite_label" msgid="907494221148096012">"Buddy toevoegen"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Blij"</item>
- <item msgid="2764363456492352853">"Bedroefd"</item>
- <item msgid="416624764294712159">"Knipoog"</item>
- <item msgid="7152979870122929989">"Tong uitsteken"</item>
- <item msgid="5784780866600056743">"Verrast"</item>
- <item msgid="5454185003381226454">"Kussend"</item>
- <item msgid="1413668617851210441">"Schreeuwend"</item>
- <item msgid="232246158381043538">"Cool"</item>
- <item msgid="2440257511131202785">"Geldzoeker"</item>
- <item msgid="4571282940807190133">"Mond vol tanden"</item>
- <item msgid="3260099163589753993">"Beschaamd"</item>
- <item msgid="3042531792218744865">"Engel"</item>
- <item msgid="5227319381647888452">"Twijfelend"</item>
- <item msgid="6952104030566994554">"Huilend"</item>
- <item msgid="9199616532683270084">"Lippen op elkaar"</item>
- <item msgid="4338502150254517147">"Lachend"</item>
- <item msgid="1014703928300075245">"Verward"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"#NAME?"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-pl/strings.xml b/samples/PluginDemo/res/values-pl/strings.xml
deleted file mode 100644
index bc254bf..0000000
--- a/samples/PluginDemo/res/values-pl/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Dodaj kontakt"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Usuń kontakt"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Zablokuj"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Lista kontaktów"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Wyślij wiadomość przez czat"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Informacje o znajomym"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Zakończ rozmowę"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Przełącz czaty"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Wstaw buźkę"</string>
- <string name="sign_up" msgid="3944276728278864333">"Utwórz nowe konto"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Ze względów bezpieczeństwa w przypadku zgubienia lub kradzieży telefonu odwiedź witrynę internetową ze swojego komputera i zmień hasło."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Lista kontaktów – <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Nazwa użytkownika:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Rozmowy: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Informacje kontaktowe"</string>
- <string name="presence_available" msgid="1184051402868736726">"Dostępny"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Dodaj kontakt"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Widoczna nazwa dodawanej osoby:"</string>
- <string name="invite_label" msgid="907494221148096012">"Dodaj znajomego"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Wesoły"</item>
- <item msgid="2764363456492352853">"Smutny"</item>
- <item msgid="416624764294712159">"Mruga"</item>
- <item msgid="7152979870122929989">"Pokazuje język"</item>
- <item msgid="5784780866600056743">"Zdziwienie"</item>
- <item msgid="5454185003381226454">"Całuje"</item>
- <item msgid="1413668617851210441">"Krzyczy"</item>
- <item msgid="232246158381043538">"Na luzie"</item>
- <item msgid="2440257511131202785">"Pazerny"</item>
- <item msgid="4571282940807190133">"Nietaktowny"</item>
- <item msgid="3260099163589753993">"Zakłopotanie"</item>
- <item msgid="3042531792218744865">"Anioł"</item>
- <item msgid="5227319381647888452">"Niezdecydowany"</item>
- <item msgid="6952104030566994554">"Płacze"</item>
- <item msgid="9199616532683270084">"Milczy jak grób"</item>
- <item msgid="4338502150254517147">"Śmieje się"</item>
- <item msgid="1014703928300075245">"Zmieszany"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-pt-rPT/strings.xml b/samples/PluginDemo/res/values-pt-rPT/strings.xml
deleted file mode 100644
index ae5eefc..0000000
--- a/samples/PluginDemo/res/values-pt-rPT/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Adicionar contacto"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Eliminar contacto"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Bloquear"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Lista de contactos"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Enviar MI"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Informações do amigo"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Terminar conversa"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Trocar chats"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Inserir ícones expressivos"</string>
- <string name="sign_up" msgid="3944276728278864333">"Obter uma nova conta"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Para sua segurança, caso perca o telefone ou este seja roubado, aceda ao Web site no computador e altere a sua palavra-passe."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Lista de contactos - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Nome de utilizador:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Conversas (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Informações de contacto"</string>
- <string name="presence_available" msgid="1184051402868736726">"Disponível"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Adicionar contacto"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Pseudónimo da pessoa que pretende adicionar:"</string>
- <string name="invite_label" msgid="907494221148096012">"Adicionar amigo"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Feliz"</item>
- <item msgid="2764363456492352853">"Triste"</item>
- <item msgid="416624764294712159">"A piscar o olho"</item>
- <item msgid="7152979870122929989">"Língua de fora"</item>
- <item msgid="5784780866600056743">"Surpreendido"</item>
- <item msgid="5454185003381226454">"Beijoqueiro"</item>
- <item msgid="1413668617851210441">"A gritar"</item>
- <item msgid="232246158381043538">"Fixe"</item>
- <item msgid="2440257511131202785">"Interesseiro"</item>
- <item msgid="4571282940807190133">"Arrependido"</item>
- <item msgid="3260099163589753993">"Envergonhado"</item>
- <item msgid="3042531792218744865">"Anjo"</item>
- <item msgid="5227319381647888452">"Indeciso"</item>
- <item msgid="6952104030566994554">"Chorão"</item>
- <item msgid="9199616532683270084">"Boca fechada"</item>
- <item msgid="4338502150254517147">"Risonho"</item>
- <item msgid="1014703928300075245">"Confuso"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-pt/strings.xml b/samples/PluginDemo/res/values-pt/strings.xml
deleted file mode 100644
index 6ff3ba5..0000000
--- a/samples/PluginDemo/res/values-pt/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Adicionar contato"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Excluir contato"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Bloquear"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Lista de contatos"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Enviar mensagem instantânea"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Informações do amigo"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Encerrar conversa"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Alternar bate-papos"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Inserir emoticons"</string>
- <string name="sign_up" msgid="3944276728278864333">"Obter uma nova conta"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Para a sua segurança, se o seu telefone for perdido ou roubado, acesse o site no seu computador e altere a sua senha."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Lista de contatos - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Nome de usuário:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Conversas (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Informações de contato"</string>
- <string name="presence_available" msgid="1184051402868736726">"Disponível"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Adicionar contato"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Apelido da pessoa que você deseja adicionar:"</string>
- <string name="invite_label" msgid="907494221148096012">"Adicionar amigo"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Feliz"</item>
- <item msgid="2764363456492352853">"Triste"</item>
- <item msgid="416624764294712159">"Piscando"</item>
- <item msgid="7152979870122929989">"Mostrando a língua"</item>
- <item msgid="5784780866600056743">"Surpreso"</item>
- <item msgid="5454185003381226454">"Beijando"</item>
- <item msgid="1413668617851210441">"Gritando"</item>
- <item msgid="232246158381043538">"Tranquilo"</item>
- <item msgid="2440257511131202785">"Louco por dinheiro"</item>
- <item msgid="4571282940807190133">"Falei besteira"</item>
- <item msgid="3260099163589753993">"Envergonhado"</item>
- <item msgid="3042531792218744865">"Anjo"</item>
- <item msgid="5227319381647888452">"Indeciso"</item>
- <item msgid="6952104030566994554">"Chorando"</item>
- <item msgid="9199616532683270084">"Boca fechada"</item>
- <item msgid="4338502150254517147">"Rindo"</item>
- <item msgid="1014703928300075245">"Confuso"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-ru/strings.xml b/samples/PluginDemo/res/values-ru/strings.xml
deleted file mode 100644
index 174f7e7..0000000
--- a/samples/PluginDemo/res/values-ru/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Добавить контакт"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Удалить контакт"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Заблокировать"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Список контактов"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Отправить сообщение чата"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"О приятеле"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Закончить разговор"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Сменить чат"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Вставить значки настроений"</string>
- <string name="sign_up" msgid="3944276728278864333">"Получить новый аккаунт"</string>
- <string name="check_save_password" msgid="3554564072443242779">"В случае потери или кражи телефона для обеспечения вашей безопасности перейдите со своего компьютера на веб-сайт и поменяйте пароль."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Список контактов – <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Имя пользователя:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Разговоров: <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Сведения о контакте"</string>
- <string name="presence_available" msgid="1184051402868736726">"На месте"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Добавить контакт"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Псевдоним человека, которого необходимо добавить:"</string>
- <string name="invite_label" msgid="907494221148096012">"Добавить приятеля"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Веселый"</item>
- <item msgid="2764363456492352853">"Грустный"</item>
- <item msgid="416624764294712159">"Подмигивает"</item>
- <item msgid="7152979870122929989">"Показывает язык"</item>
- <item msgid="5784780866600056743">"Удивление"</item>
- <item msgid="5454185003381226454">"Поцелуй"</item>
- <item msgid="1413668617851210441">"Кричит"</item>
- <item msgid="232246158381043538">"Крутой"</item>
- <item msgid="2440257511131202785">"Молчание – золото"</item>
- <item msgid="4571282940807190133">"В замешательстве"</item>
- <item msgid="3260099163589753993">"Смущение"</item>
- <item msgid="3042531792218744865">"Ангел"</item>
- <item msgid="5227319381647888452">"Нерешительный"</item>
- <item msgid="6952104030566994554">"Плачет"</item>
- <item msgid="9199616532683270084">"Не скажу"</item>
- <item msgid="4338502150254517147">"Смех"</item>
- <item msgid="1014703928300075245">"Озадаченный"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-sv/strings.xml b/samples/PluginDemo/res/values-sv/strings.xml
deleted file mode 100644
index 845ecf2..0000000
--- a/samples/PluginDemo/res/values-sv/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Lägg till kontakt"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Ta bort kontakt"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Blockera"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Kontaktlista"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"Skicka chattmeddelande"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Kompisinfo"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"Avsluta konversation"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Byt chatt"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"Infoga uttryckssymboler"</string>
- <string name="sign_up" msgid="3944276728278864333">"Öppna ett nytt konto"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Om din telefon blir stulen besöker du webbplatsen via datorn och ändrar lösenordet. Detta är för din egen säkerhet."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Kontaktlista – <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Användarnamn:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Konversationer (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Kontaktinfo"</string>
- <string name="presence_available" msgid="1184051402868736726">"Tillgänglig"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Lägg till kontakt"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Signatur för den du vill lägga till:"</string>
- <string name="invite_label" msgid="907494221148096012">"Lägg till kompis"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Glad"</item>
- <item msgid="2764363456492352853">"Ledsen"</item>
- <item msgid="416624764294712159">"Blinkar"</item>
- <item msgid="7152979870122929989">"Lipar"</item>
- <item msgid="5784780866600056743">"Förvånad"</item>
- <item msgid="5454185003381226454">"Pussar"</item>
- <item msgid="1413668617851210441">"Skriker"</item>
- <item msgid="232246158381043538">"Cool"</item>
- <item msgid="2440257511131202785">"Dollarmun"</item>
- <item msgid="4571282940807190133">"Bortgjord"</item>
- <item msgid="3260099163589753993">"Generad"</item>
- <item msgid="3042531792218744865">"Ängel"</item>
- <item msgid="5227319381647888452">"Tveksam"</item>
- <item msgid="6952104030566994554">"Gråter"</item>
- <item msgid="9199616532683270084">"Hemlis"</item>
- <item msgid="4338502150254517147">"Skrattar"</item>
- <item msgid="1014703928300075245">"Förvirrad"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-tr/strings.xml b/samples/PluginDemo/res/values-tr/strings.xml
deleted file mode 100644
index e7813e6..0000000
--- a/samples/PluginDemo/res/values-tr/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"Kişi Ekle"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"Kişiyi Sil"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"Engelle"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"Kişi Listesi"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"IM Gönder"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"Arkadaş Bilgileri"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"İleti Dizisini Sonlandır"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"Sohbetler Arasında Geçiş Yap"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"İfade Ekle"</string>
- <string name="sign_up" msgid="3944276728278864333">"Yeni hesap al"</string>
- <string name="check_save_password" msgid="3554564072443242779">"Telefonunuz kaybolur veya çalınırsa, güvenliğiniz için bilgisayarınızdan Web sitesine gidin ve şifrenizi değiştirin."</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"Kişi Listesi - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"Kullanıcı adı:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"Konuşmalar (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"Kişi Bilgileri"</string>
- <string name="presence_available" msgid="1184051402868736726">"Müsait"</string>
- <string name="add_contact_title" msgid="292217657045373736">"Kişi Ekle"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"Eklemek istediğiniz kişinin ekran adı:"</string>
- <string name="invite_label" msgid="907494221148096012">"Arkadaş Ekle"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"Mutlu"</item>
- <item msgid="2764363456492352853">"Üzgün"</item>
- <item msgid="416624764294712159">"Göz Kırpma"</item>
- <item msgid="7152979870122929989">"Dil çıkarmış"</item>
- <item msgid="5784780866600056743">"Şaşırmış"</item>
- <item msgid="5454185003381226454">"Öpücük"</item>
- <item msgid="1413668617851210441">"Bağırma"</item>
- <item msgid="232246158381043538">"Sakin"</item>
- <item msgid="2440257511131202785">"Para ağızlı"</item>
- <item msgid="4571282940807190133">"Ayak ağızda"</item>
- <item msgid="3260099163589753993">"Utanmış"</item>
- <item msgid="3042531792218744865">"Melek"</item>
- <item msgid="5227319381647888452">"Kararsız"</item>
- <item msgid="6952104030566994554">"Ağlama"</item>
- <item msgid="9199616532683270084">"Dudakları mühürlü"</item>
- <item msgid="4338502150254517147">"Gülme"</item>
- <item msgid="1014703928300075245">"Kafası karışmış"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-zh-rCN/strings.xml b/samples/PluginDemo/res/values-zh-rCN/strings.xml
deleted file mode 100644
index 839f405..0000000
--- a/samples/PluginDemo/res/values-zh-rCN/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"添加联系人"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"删除联系人"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"阻止"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"联系人列表"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"发送即时消息"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"好友信息"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"结束会话"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"切换聊天"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"插入表情符"</string>
- <string name="sign_up" msgid="3944276728278864333">"获取新帐户"</string>
- <string name="check_save_password" msgid="3554564072443242779">"为了您的安全,如果您的手机遗失或被窃,请通过您的计算机访问网站并更改您的密码。"</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"联系人列表 - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"用户名:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"会话 (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"联系人信息"</string>
- <string name="presence_available" msgid="1184051402868736726">"有空"</string>
- <string name="add_contact_title" msgid="292217657045373736">"添加联系人"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"您希望添加的联系人的用户名:"</string>
- <string name="invite_label" msgid="907494221148096012">"添加好友"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"幸福"</item>
- <item msgid="2764363456492352853">"悲伤"</item>
- <item msgid="416624764294712159">"眨眼"</item>
- <item msgid="7152979870122929989">"吐舌头"</item>
- <item msgid="5784780866600056743">"惊讶"</item>
- <item msgid="5454185003381226454">"亲吻"</item>
- <item msgid="1413668617851210441">"大喊"</item>
- <item msgid="232246158381043538">"酷"</item>
- <item msgid="2440257511131202785">"财迷"</item>
- <item msgid="4571282940807190133">"说错了话"</item>
- <item msgid="3260099163589753993">"尴尬"</item>
- <item msgid="3042531792218744865">"天使"</item>
- <item msgid="5227319381647888452">"犹豫"</item>
- <item msgid="6952104030566994554">"哭泣"</item>
- <item msgid="9199616532683270084">"保密"</item>
- <item msgid="4338502150254517147">"大笑"</item>
- <item msgid="1014703928300075245">"困惑"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values-zh-rTW/strings.xml b/samples/PluginDemo/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 4412f7a..0000000
--- a/samples/PluginDemo/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-<?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.
--->
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact" msgid="1577617821180977339">"新增聯絡人"</string>
- <string name="menu_remove_contact" msgid="1438737309746209943">"刪除聯絡人"</string>
- <string name="menu_block_contact" msgid="1418576909122458824">"封鎖"</string>
- <string name="menu_contact_list" msgid="7408048984312793527">"聯絡人清單"</string>
- <string name="menu_start_chat" msgid="1942461880426180926">"傳送即時訊息"</string>
- <string name="menu_view_profile" msgid="4594617426877626560">"好友資訊"</string>
- <string name="menu_end_conversation" msgid="215067667186746690">"結束會話"</string>
- <string name="menu_switch_chats" msgid="4616221788780459133">"切換即時通訊"</string>
- <string name="menu_insert_smiley" msgid="6880772056965363205">"插入表情符號"</string>
- <string name="sign_up" msgid="3944276728278864333">"取得新帳戶"</string>
- <string name="check_save_password" msgid="3554564072443242779">"為了安全起見,如果電話遺失或遭竊,請使用電腦前往該網站並變更密碼。"</string>
- <string name="buddy_list_title" msgid="5837732412636822107">"聯絡人清單 - <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
- <string name="label_username" msgid="7905168188814604370">"使用者名稱:"</string>
- <string name="ongoing_conversation" msgid="9097832769731811986">"會話 (<xliff:g id="NUMBER">%1$d</xliff:g>)"</string>
- <string name="contact_profile_title" msgid="5203284525412697232">"聯絡人資訊"</string>
- <string name="presence_available" msgid="1184051402868736726">"可用"</string>
- <string name="add_contact_title" msgid="292217657045373736">"新增聯絡人"</string>
- <string name="input_contact_label" msgid="2583915568413164449">"要新增之聯絡人在畫面上的名稱:"</string>
- <string name="invite_label" msgid="907494221148096012">"新增好友"</string>
- <string-array name="smiley_names">
- <item msgid="811476776139578986">"開心"</item>
- <item msgid="2764363456492352853">"傷心"</item>
- <item msgid="416624764294712159">"眨眼"</item>
- <item msgid="7152979870122929989">"吐舌頭"</item>
- <item msgid="5784780866600056743">"驚訝"</item>
- <item msgid="5454185003381226454">"紅唇"</item>
- <item msgid="1413668617851210441">"大喊"</item>
- <item msgid="232246158381043538">"酷"</item>
- <item msgid="2440257511131202785">"滿嘴錢"</item>
- <item msgid="4571282940807190133">"說錯話"</item>
- <item msgid="3260099163589753993">"害羞"</item>
- <item msgid="3042531792218744865">"天使"</item>
- <item msgid="5227319381647888452">"還沒決定"</item>
- <item msgid="6952104030566994554">"嚎啕大哭"</item>
- <item msgid="9199616532683270084">"不要告訴別人"</item>
- <item msgid="4338502150254517147">"開懷大笑"</item>
- <item msgid="1014703928300075245">"疑惑"</item>
- </string-array>
- <string-array name="smiley_texts">
- <item msgid="6682271134385564589">":-)"</item>
- <item msgid="5242689844155076377">":-("</item>
- <item msgid="521632995149320343">";-)"</item>
- <item msgid="3442897533435789796">":-P"</item>
- <item msgid="682698687423187022">"=-O"</item>
- <item msgid="1531701168660725626">":-*"</item>
- <item msgid="7958357467119008619">":O"</item>
- <item msgid="4638775565490840154">"B-)"</item>
- <item msgid="6225545209385623235">":-$"</item>
- <item msgid="5725425598368680891">":-!"</item>
- <item msgid="5365880622794795497">":-["</item>
- <item msgid="8260692119195572132">"O:-)"</item>
- <item msgid="6879285154649424413">":-\\"</item>
- <item msgid="554517875650930417">":\'("</item>
- <item msgid="8169228040168187510">":-X"</item>
- <item msgid="5444890977206638254">":-D"</item>
- <item msgid="8814856019116253585">"o_O"</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/res/values/strings.xml b/samples/PluginDemo/res/values/strings.xml
deleted file mode 100644
index 7afa4ab..0000000
--- a/samples/PluginDemo/res/values/strings.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2008 Esmertec Inc.
- * 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.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="menu_add_contact">Add Contact</string>
- <string name="menu_remove_contact">Delete Contact</string>
- <string name="menu_block_contact">Block</string>
- <string name="menu_contact_list">Contact List</string>
- <string name="menu_start_chat">Send IM</string>
- <string name="menu_view_profile">Buddy Info</string>
- <string name="menu_end_conversation">End Conversation</string>
- <string name="menu_switch_chats">Switch Chats</string>
- <string name="menu_insert_smiley">Insert Emoticons</string>
- <string name="sign_up">Get a new account</string>
- <string name="check_save_password">For your security, if your phone is lost or stolen, go to the Web site on your computer and change your password.</string>
- <string name="buddy_list_title">Contact List - <xliff:g id="username">%1$s</xliff:g></string>
- <string name="label_username">Username:</string>
- <string name="ongoing_conversation">Conversations (<xliff:g id="number">%1$d</xliff:g>)</string>
- <string name="contact_profile_title">Contact Info</string>
- <string name="presence_available">Available</string>
- <string name="add_contact_title">Add Contact</string>
- <string name="input_contact_label">Screen name of person you wish to add:</string>
- <string name="invite_label">Add Buddy</string>
-
- <string-array name="smiley_names">
- <item>Happy</item>
- <item>Sad</item>
- <item>Winking</item>
- <item>Tongue sticking out</item>
- <item>Surprised</item>
- <item>Kissing</item>
- <item>Yelling</item>
- <item>Cool</item>
- <item>Money mouth</item>
- <item>Foot in mouth</item>
- <item>Embarrassed</item>
- <item>Angel</item>
- <item>Undecided</item>
- <item>Crying</item>
- <item>Lips are sealed</item>
- <item>Laughing</item>
- <item>Confused</item>
- </string-array>
-
- <string-array name="smiley_texts">
- <item>:-)</item>
- <item>:-(</item>
- <item>;-)</item>
- <item>:-P</item>
- <item>=-O</item>
- <item>:-*</item>
- <item>:O</item>
- <item>B-)</item>
- <item>:-$</item>
- <item>:-!</item>
- <item>:-[</item>
- <item>O:-)</item>
- <item>:-\\</item>
- <item>:\'(</item>
- <item>:-X</item>
- <item>:-D</item>
- <item>o_O</item>
- </string-array>
-</resources>
diff --git a/samples/PluginDemo/src/com/android/im/plugin/demo/DemoImPlugin.java b/samples/PluginDemo/src/com/android/im/plugin/demo/DemoImPlugin.java
index eb7d0c9..5fe6cc0 100644
--- a/samples/PluginDemo/src/com/android/im/plugin/demo/DemoImPlugin.java
+++ b/samples/PluginDemo/src/com/android/im/plugin/demo/DemoImPlugin.java
@@ -17,7 +17,7 @@
package com.android.im.plugin.demo;
import com.android.im.plugin.BrandingResourceIDs;
-import com.android.im.plugin.IImPlugin;
+import com.android.im.plugin.ImPlugin;
import com.android.im.plugin.ImConfigNames;
import com.android.im.plugin.ImpsConfigNames;
@@ -33,110 +33,105 @@ import java.util.Map;
* Simple example of writing a plug-in for the IM application.
*
*/
-public class DemoImPlugin extends Service {
+public class DemoImPlugin extends Service implements ImPlugin {
@Override
public IBinder onBind(Intent intent) {
- return mBinder;
+ return null;
}
- /**
- * The implementation of IImPlugin defined through AIDL.
- */
- private IBinder mBinder = new IImPlugin.Stub() {
- public Map getProviderConfig() {
- HashMap<String, String> config = new HashMap<String, String>();
- // The protocol name MUST be IMPS now.
- config.put(ImConfigNames.PROTOCOL_NAME, "IMPS");
- config.put(ImpsConfigNames.HOST, "http://xxx.xxxx.xxx");
- config.put(ImpsConfigNames.CLIENT_ID, "Jimmy");
- config.put(ImpsConfigNames.DATA_CHANNEL, "HTTP");
- config.put(ImpsConfigNames.DATA_ENCODING, "WBXML");
- config.put(ImpsConfigNames.CIR_CHANNEL, "STCP");
- config.put(ImpsConfigNames.CUSTOM_PRESENCE_MAPPING,
- "com.android.im.plugin.demo.DemoPresenceMapping");
- return config;
- }
+ public Map getProviderConfig() {
+ HashMap<String, String> config = new HashMap<String, String>();
+ // The protocol name MUST be IMPS now.
+ config.put(ImConfigNames.PROTOCOL_NAME, "IMPS");
+ config.put(ImpsConfigNames.HOST, "http://xxx.xxxx.xxx");
+ config.put(ImpsConfigNames.CLIENT_ID, "Jimmy");
+ config.put(ImpsConfigNames.DATA_CHANNEL, "HTTP");
+ config.put(ImpsConfigNames.DATA_ENCODING, "WBXML");
+ config.put(ImpsConfigNames.CIR_CHANNEL, "STCP");
+ config.put(ImpsConfigNames.CUSTOM_PRESENCE_MAPPING,
+ "com.android.im.plugin.demo.DemoPresenceMapping");
+ return config;
+ }
- public Map getResourceMap() throws RemoteException {
- HashMap<Integer, Integer> resMapping = new HashMap<Integer, Integer>();
- resMapping.put(BrandingResourceIDs.DRAWABLE_LOGO, R.drawable.im_logo);
- resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_ONLINE,
- android.R.drawable.presence_online);
- resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY,
- android.R.drawable.presence_away);
- resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_BUSY,
- android.R.drawable.presence_busy);
- resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_INVISIBLE,
- android.R.drawable.presence_invisible);
- resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_OFFLINE,
- android.R.drawable.presence_offline);
- resMapping.put(BrandingResourceIDs.DRAWABLE_SPLASH_SCREEN,
- R.drawable.im_logo_splashscr);
- resMapping.put(BrandingResourceIDs.DRAWABLE_READ_CHAT,
- R.drawable.chat);
- resMapping.put(BrandingResourceIDs.DRAWABLE_UNREAD_CHAT,
- R.drawable.chat_new);
+ public Map getResourceMap() {
+ HashMap<Integer, Integer> resMapping = new HashMap<Integer, Integer>();
+/* resMapping.put(BrandingResourceIDs.DRAWABLE_LOGO, R.drawable.im_logo);
+ resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_ONLINE,
+ android.R.drawable.presence_online);
+ resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY,
+ android.R.drawable.presence_away);
+ resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_BUSY,
+ android.R.drawable.presence_busy);
+ resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_INVISIBLE,
+ android.R.drawable.presence_invisible);
+ resMapping.put(BrandingResourceIDs.DRAWABLE_PRESENCE_OFFLINE,
+ android.R.drawable.presence_offline);
+ resMapping.put(BrandingResourceIDs.DRAWABLE_SPLASH_SCREEN,
+ R.drawable.im_logo_splashscr);
+ resMapping.put(BrandingResourceIDs.DRAWABLE_READ_CHAT,
+ R.drawable.chat);
+ resMapping.put(BrandingResourceIDs.DRAWABLE_UNREAD_CHAT,
+ R.drawable.chat_new);
- resMapping.put(BrandingResourceIDs.STRING_BUDDY_LIST_TITLE,
- R.string.buddy_list_title);
- resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_NAMES,
- R.array.smiley_names);
- resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_TEXTS,
- R.array.smiley_texts);
- resMapping.put(BrandingResourceIDs.STRING_PRESENCE_AVAILABLE,
- R.string.presence_available);
+ resMapping.put(BrandingResourceIDs.STRING_BUDDY_LIST_TITLE,
+ R.string.buddy_list_title);
+ resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_NAMES,
+ R.array.smiley_names);
+ resMapping.put(BrandingResourceIDs.STRING_ARRAY_SMILEY_TEXTS,
+ R.array.smiley_texts);
+ resMapping.put(BrandingResourceIDs.STRING_PRESENCE_AVAILABLE,
+ R.string.presence_available);
- resMapping.put(BrandingResourceIDs.STRING_LABEL_USERNAME,
- R.string.label_username);
- resMapping.put(BrandingResourceIDs.STRING_ONGOING_CONVERSATION,
- R.string.ongoing_conversation);
- resMapping.put(BrandingResourceIDs.STRING_ADD_CONTACT_TITLE,
- R.string.add_contact_title);
- resMapping.put(BrandingResourceIDs.STRING_LABEL_INPUT_CONTACT,
- R.string.input_contact_label);
- resMapping.put(BrandingResourceIDs.STRING_BUTTON_ADD_CONTACT,
- R.string.invite_label);
- resMapping.put(BrandingResourceIDs.STRING_CONTACT_INFO_TITLE,
- R.string.contact_profile_title);
+ resMapping.put(BrandingResourceIDs.STRING_LABEL_USERNAME,
+ R.string.label_username);
+ resMapping.put(BrandingResourceIDs.STRING_ONGOING_CONVERSATION,
+ R.string.ongoing_conversation);
+ resMapping.put(BrandingResourceIDs.STRING_ADD_CONTACT_TITLE,
+ R.string.add_contact_title);
+ resMapping.put(BrandingResourceIDs.STRING_LABEL_INPUT_CONTACT,
+ R.string.input_contact_label);
+ resMapping.put(BrandingResourceIDs.STRING_BUTTON_ADD_CONTACT,
+ R.string.invite_label);
+ resMapping.put(BrandingResourceIDs.STRING_CONTACT_INFO_TITLE,
+ R.string.contact_profile_title);
- resMapping.put(BrandingResourceIDs.STRING_MENU_ADD_CONTACT,
- R.string.menu_add_contact);
- resMapping.put(BrandingResourceIDs.STRING_MENU_BLOCK_CONTACT,
- R.string.menu_block_contact);
- resMapping.put(BrandingResourceIDs.STRING_MENU_CONTACT_LIST,
- R.string.menu_contact_list);
- resMapping.put(BrandingResourceIDs.STRING_MENU_DELETE_CONTACT,
- R.string.menu_remove_contact);
- resMapping.put(BrandingResourceIDs.STRING_MENU_END_CHAT,
- R.string.menu_end_conversation);
- resMapping.put(BrandingResourceIDs.STRING_MENU_INSERT_SMILEY,
- R.string.menu_insert_smiley);
- resMapping.put(BrandingResourceIDs.STRING_MENU_START_CHAT,
- R.string.menu_start_chat);
- resMapping.put(BrandingResourceIDs.STRING_MENU_VIEW_PROFILE,
- R.string.menu_view_profile);
- resMapping.put(BrandingResourceIDs.STRING_MENU_SWITCH_CHATS,
- R.string.menu_switch_chats);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_ADD_CONTACT,
+ R.string.menu_add_contact);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_BLOCK_CONTACT,
+ R.string.menu_block_contact);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_CONTACT_LIST,
+ R.string.menu_contact_list);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_DELETE_CONTACT,
+ R.string.menu_remove_contact);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_END_CHAT,
+ R.string.menu_end_conversation);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_INSERT_SMILEY,
+ R.string.menu_insert_smiley);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_START_CHAT,
+ R.string.menu_start_chat);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_VIEW_PROFILE,
+ R.string.menu_view_profile);
+ resMapping.put(BrandingResourceIDs.STRING_MENU_SWITCH_CHATS,
+ R.string.menu_switch_chats);
- resMapping.put(BrandingResourceIDs.STRING_TOAST_CHECK_SAVE_PASSWORD,
- R.string.check_save_password);
- resMapping.put(BrandingResourceIDs.STRING_LABEL_SIGN_UP,
- R.string.sign_up);
- return resMapping;
- }
+ resMapping.put(BrandingResourceIDs.STRING_TOAST_CHECK_SAVE_PASSWORD,
+ R.string.check_save_password);
+ resMapping.put(BrandingResourceIDs.STRING_LABEL_SIGN_UP,
+ R.string.sign_up);*/
+ return resMapping;
+ }
- public int[] getSmileyIconIds() throws RemoteException {
- return SMILEY_RES_IDS;
- }
- };
+ public int[] getSmileyIconIds() {
+ return SMILEY_RES_IDS;
+ }
/**
* An array of the smiley icon IDs. Note that the sequence of the array MUST
* match the smiley texts and smiley names defined in strings.xml.
*/
static final int[] SMILEY_RES_IDS = {
- R.drawable.emo_im_happy,
+/* R.drawable.emo_im_happy,
R.drawable.emo_im_sad,
R.drawable.emo_im_winking,
R.drawable.emo_im_tongue_sticking_out,
@@ -152,7 +147,7 @@ public class DemoImPlugin extends Service {
R.drawable.emo_im_crying,
R.drawable.emo_im_lips_are_sealed,
R.drawable.emo_im_laughing,
- R.drawable.emo_im_wtf
+ R.drawable.emo_im_wtf */
};
}
diff --git a/samples/PluginDemo/src/com/android/im/plugin/demo/DemoPresenceMapping.java b/samples/PluginDemo/src/com/android/im/plugin/demo/DemoPresenceMapping.java
index e8acb88..fc32984 100644
--- a/samples/PluginDemo/src/com/android/im/plugin/demo/DemoPresenceMapping.java
+++ b/samples/PluginDemo/src/com/android/im/plugin/demo/DemoPresenceMapping.java
@@ -17,7 +17,7 @@
package com.android.im.plugin.demo;
import com.android.im.plugin.ImPluginConstants;
-import com.android.im.plugin.IPresenceMapping;
+import com.android.im.plugin.PresenceMapping;
import java.util.Map;
@@ -25,7 +25,7 @@ import java.util.Map;
* A simple implementation of PresenceMaping for the provider.
*
*/
-public class DemoPresenceMapping extends IPresenceMapping.Stub {
+public class DemoPresenceMapping implements PresenceMapping {
public int[] getSupportedPresenceStatus() {
return new int[] {
diff --git a/src/com/android/im/app/AccountActivity.java b/src/com/android/im/app/AccountActivity.java
index fcd1ba3..d73f446 100644
--- a/src/com/android/im/app/AccountActivity.java
+++ b/src/com/android/im/app/AccountActivity.java
@@ -19,6 +19,7 @@ package com.android.im.app;
import com.android.im.R;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
import android.app.Activity;
import android.app.AlertDialog;
@@ -31,7 +32,6 @@ import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
-import android.provider.Im;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@@ -59,11 +59,11 @@ public class AccountActivity extends Activity {
static final int REQUEST_SIGN_IN = RESULT_FIRST_USER + 1;
private static final String[] ACCOUNT_PROJECTION = {
- Im.Account._ID,
- Im.Account.PROVIDER,
- Im.Account.USERNAME,
- Im.Account.PASSWORD,
- Im.Account.KEEP_SIGNED_IN,
+ Imps.Account._ID,
+ Imps.Account.PROVIDER,
+ Imps.Account.USERNAME,
+ Imps.Account.PASSWORD,
+ Imps.Account.KEEP_SIGNED_IN,
};
private static final int ACCOUNT_PROVIDER_COLUMN = 1;
@@ -117,7 +117,7 @@ public class AccountActivity extends Activity {
ContentResolver cr = getContentResolver();
Uri uri = i.getData();
- if ((uri == null) || !Im.Account.CONTENT_ITEM_TYPE.equals(cr.getType(uri))) {
+ if ((uri == null) || !Imps.Account.CONTENT_ITEM_TYPE.equals(cr.getType(uri))) {
Log.w(ImApp.LOG_TAG, "<AccountActivity>Bad data");
return;
}
@@ -193,7 +193,7 @@ public class AccountActivity extends Activity {
long accountId = ImApp.insertOrUpdateAccount(cr, providerId, username,
rememberPass ? pass : null);
- mAccountUri = ContentUris.withAppendedId(Im.Account.CONTENT_URI, accountId);
+ mAccountUri = ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId);
if (!origUserName.equals(username) && shouldShowTermOfUse(brandingRes)) {
comfirmTermsOfUse(brandingRes, new DialogInterface.OnClickListener() {
@@ -276,7 +276,7 @@ public class AccountActivity extends Activity {
updateKeepSignedIn(false);
mEditPass.setText("");
ContentValues values = new ContentValues();
- values.put(Im.Account.PASSWORD, (String) null);
+ values.put(Imps.Account.PASSWORD, (String) null);
getContentResolver().update(mAccountUri, values, null, null);
}
}
@@ -284,7 +284,7 @@ public class AccountActivity extends Activity {
void updateKeepSignedIn(boolean keepSignIn) {
ContentValues values = new ContentValues();
- values.put(Im.Account.KEEP_SIGNED_IN, keepSignIn ? 1 : 0);
+ values.put(Imps.Account.KEEP_SIGNED_IN, keepSignIn ? 1 : 0);
getContentResolver().update(mAccountUri, values, null, null);
}
diff --git a/src/com/android/im/app/AddContactActivity.java b/src/com/android/im/app/AddContactActivity.java
index 6e8a92d..a370d5f 100644
--- a/src/com/android/im/app/AddContactActivity.java
+++ b/src/com/android/im/app/AddContactActivity.java
@@ -29,7 +29,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.provider.Im;
import android.provider.Contacts.ContactMethods;
import android.text.Editable;
import android.text.TextUtils;
@@ -51,6 +50,7 @@ import com.android.im.R;
import com.android.im.engine.ImErrorInfo;
import com.android.im.plugin.BrandingResourceIDs;
import com.android.im.plugin.ImpsConfigNames;
+import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
import java.util.List;
@@ -58,8 +58,8 @@ import java.util.List;
public class AddContactActivity extends Activity {
private static final String[] CONTACT_LIST_PROJECTION = {
- Im.ContactList._ID,
- Im.ContactList.NAME,
+ Imps.ContactList._ID,
+ Imps.ContactList.NAME,
};
private static final int CONTACT_LIST_NAME_COLUMN = 1;
@@ -102,7 +102,7 @@ public class AddContactActivity extends Activity {
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_item,
c,
- new String[] {Im.ContactList.NAME},
+ new String[] {Imps.ContactList.NAME},
new int[] {android.R.id.text1});
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mListSpinner.setAdapter(adapter);
@@ -116,7 +116,7 @@ public class AddContactActivity extends Activity {
}
private Cursor queryContactLists() {
- Uri uri = Im.ContactList.CONTENT_URI;
+ Uri uri = Imps.ContactList.CONTENT_URI;
uri = ContentUris.withAppendedId(uri, mProviderId);
uri = ContentUris.withAppendedId(uri, mAccountId);
Cursor c = managedQuery(uri, CONTACT_LIST_PROJECTION, null, null);
@@ -141,7 +141,7 @@ public class AddContactActivity extends Activity {
ImServiceConstants.EXTRA_INTENT_PROVIDER_ID, -1);
mAccountId = intent.getLongExtra(
ImServiceConstants.EXTRA_INTENT_ACCOUNT_ID, -1);
- mDefaultDomain = Im.ProviderSettings.getStringValue(getContentResolver(),
+ mDefaultDomain = Imps.ProviderSettings.getStringValue(getContentResolver(),
mProviderId, ImpsConfigNames.DEFAULT_DOMAIN);
}
diff --git a/src/com/android/im/app/BlockedContactsActivity.java b/src/com/android/im/app/BlockedContactsActivity.java
index 014f596..c2aa495 100644
--- a/src/com/android/im/app/BlockedContactsActivity.java
+++ b/src/com/android/im/app/BlockedContactsActivity.java
@@ -28,7 +28,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
-import android.provider.Im;
import android.util.Log;
import android.view.View;
import android.view.Window;
@@ -40,18 +39,19 @@ import com.android.im.IContactListManager;
import com.android.im.IImConnection;
import com.android.im.R;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
public class BlockedContactsActivity extends ListActivity {
ImApp mApp;
SimpleAlertHandler mHandler;
private static final String[] PROJECTION = {
- Im.BlockedList._ID,
- Im.BlockedList.ACCOUNT,
- Im.BlockedList.PROVIDER,
- Im.BlockedList.NICKNAME,
- Im.BlockedList.USERNAME,
- Im.BlockedList.AVATAR_DATA,
+ Imps.BlockedList._ID,
+ Imps.BlockedList.ACCOUNT,
+ Imps.BlockedList.PROVIDER,
+ Imps.BlockedList.NICKNAME,
+ Imps.BlockedList.USERNAME,
+ Imps.BlockedList.AVATAR_DATA,
};
static final int ACCOUNT_COLUMN = 1;
@@ -99,7 +99,7 @@ public class BlockedContactsActivity extends ListActivity {
}
long accountId = ContentUris.parseId(uri);
- Uri accountUri = ContentUris.withAppendedId(Im.Account.CONTENT_URI, accountId);
+ Uri accountUri = ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId);
Cursor accountCursor = getContentResolver().query(accountUri, null, null, null, null);
if (accountCursor == null) {
warning("Bad account");
@@ -112,9 +112,9 @@ public class BlockedContactsActivity extends ListActivity {
}
long providerId = accountCursor.getLong(
- accountCursor.getColumnIndexOrThrow(Im.Account.PROVIDER));
+ accountCursor.getColumnIndexOrThrow(Imps.Account.PROVIDER));
String username = accountCursor.getString(
- accountCursor.getColumnIndexOrThrow(Im.Account.USERNAME));
+ accountCursor.getColumnIndexOrThrow(Imps.Account.USERNAME));
BrandingResources brandingRes = mApp.getBrandingResource(providerId);
getWindow().setFeatureDrawable(Window.FEATURE_LEFT_ICON,
@@ -123,7 +123,7 @@ public class BlockedContactsActivity extends ListActivity {
setTitle(getResources().getString(R.string.blocked_list_title, username));
accountCursor.close();
- Cursor c = managedQuery(uri, PROJECTION, null, Im.BlockedList.DEFAULT_SORT_ORDER);
+ Cursor c = managedQuery(uri, PROJECTION, null, Imps.BlockedList.DEFAULT_SORT_ORDER);
if (c == null) {
warning("Database error when query " + uri);
return false;
diff --git a/src/com/android/im/app/BrandingResources.java b/src/com/android/im/app/BrandingResources.java
index 97dd698..6708b9e 100644
--- a/src/com/android/im/app/BrandingResources.java
+++ b/src/com/android/im/app/BrandingResources.java
@@ -17,7 +17,7 @@
package com.android.im.app;
-import com.android.im.plugin.IImPlugin;
+import com.android.im.plugin.ImPlugin;
import com.android.im.plugin.ImPluginInfo;
import dalvik.system.PathClassLoader;
@@ -68,12 +68,11 @@ public class BrandingResources {
// Load the plug-in directly from the apk instead of binding the service
// and calling through the IPC binder API. It's more effective in this way
// and we can avoid the async behaviors of binding service.
- PathClassLoader classLoader = new PathClassLoader(pluginInfo.mSrcPath,
- context.getClassLoader());
+ ClassLoader classLoader = context.getClassLoader();
try {
Class cls = classLoader.loadClass(pluginInfo.mClassName);
Method m = cls.getMethod("onBind", Intent.class);
- IImPlugin plugin = (IImPlugin)m.invoke(cls.newInstance(), new Object[]{null});
+ ImPlugin plugin = (ImPlugin)m.invoke(cls.newInstance(), new Object[]{null});
mResMapping = plugin.getResourceMap();
mSmileyIcons = plugin.getSmileyIconIds();
} catch (ClassNotFoundException e) {
@@ -90,8 +89,6 @@ public class BrandingResources {
Log.e(TAG, "Failed load the plugin resource map", e);
} catch (InvocationTargetException e) {
Log.e(TAG, "Failed load the plugin resource map", e);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed load the plugin resource map", e);
}
}
@@ -104,8 +101,14 @@ public class BrandingResources {
*/
public BrandingResources(Context context, Map<Integer, Integer> resMapping,
BrandingResources defaultRes) {
- mPackageRes = context.getResources();
+ this(context.getResources(), resMapping, null, defaultRes);
+ }
+
+ public BrandingResources(Resources packageRes, Map<Integer, Integer> resMapping,
+ int[] smileyIcons, BrandingResources defaultRes) {
+ mPackageRes = packageRes;
mResMapping = resMapping;
+ mSmileyIcons = smileyIcons;
mDefaultRes = defaultRes;
}
diff --git a/src/com/android/im/app/ChatBackgroundMaker.java b/src/com/android/im/app/ChatBackgroundMaker.java
index fe340e5..12a9a85 100644
--- a/src/com/android/im/app/ChatBackgroundMaker.java
+++ b/src/com/android/im/app/ChatBackgroundMaker.java
@@ -18,12 +18,12 @@
package com.android.im.app;
import com.android.im.R;
+import com.android.im.provider.Imps;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.provider.Im;
import android.view.View;
public class ChatBackgroundMaker {
@@ -43,13 +43,13 @@ public class ChatBackgroundMaker {
View msgText = view.findViewById(R.id.message);
switch (type) {
- case Im.MessageType.INCOMING:
+ case Imps.MessageType.INCOMING:
// TODO: set color according different contact
msgText.setBackgroundDrawable(mIncomingBg);
break;
- case Im.MessageType.OUTGOING:
- case Im.MessageType.POSTPONED:
+ case Imps.MessageType.OUTGOING:
+ case Imps.MessageType.POSTPONED:
msgText.setBackgroundDrawable(null);
msgText.setPadding(mPadding.left, mPadding.top, mPadding.right,
mPadding.bottom);
diff --git a/src/com/android/im/app/ChatSwitcher.java b/src/com/android/im/app/ChatSwitcher.java
index 04d35e6..731128a 100644
--- a/src/com/android/im/app/ChatSwitcher.java
+++ b/src/com/android/im/app/ChatSwitcher.java
@@ -21,6 +21,7 @@ import java.util.List;
import com.android.im.R;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
import android.app.Activity;
import android.app.Dialog;
@@ -33,7 +34,6 @@ import android.content.res.Configuration;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
-import android.provider.Im;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
@@ -51,7 +51,7 @@ public class ChatSwitcher {
private static final boolean LOCAL_DEBUG = true;
private static final String[] PROVIDER_CATEGORY_PROJECTION = new String[] {
- Im.Provider.CATEGORY
+ Imps.Provider.CATEGORY
};
private static final int PROVIDER_CATEGORY_COLUMN = 0;
@@ -130,7 +130,7 @@ public class ChatSwitcher {
mQueryHandler.startQuery(
sQueryToken,
runnable,
- Im.Contacts.CONTENT_URI_CHAT_CONTACTS,
+ Imps.Contacts.CONTENT_URI_CHAT_CONTACTS,
null, /*projection*/
mQuerySelection,
mQuerySelectionArgs,
@@ -452,17 +452,17 @@ public class ChatSwitcher {
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
if (cursor != null) {
- mContactIdColumn = cursor.getColumnIndexOrThrow(Im.Contacts._ID);
- mProviderIdColumn = cursor.getColumnIndexOrThrow(Im.Contacts.PROVIDER);
- mAccountIdColumn = cursor.getColumnIndexOrThrow(Im.Contacts.ACCOUNT);
- mUsernameColumn = cursor.getColumnIndexOrThrow(Im.Contacts.USERNAME);
- mNicknameColumn = cursor.getColumnIndexOrThrow(Im.Contacts.NICKNAME);
- mPresenceStatusColumn = cursor.getColumnIndexOrThrow(Im.Contacts.PRESENCE_STATUS);
- mLastUnreadMessageColumn = cursor.getColumnIndexOrThrow(Im.Chats.LAST_UNREAD_MESSAGE);
- mAvatarDataColumn = cursor.getColumnIndexOrThrow(Im.Contacts.AVATAR_DATA);
- mShortcutColumn = cursor.getColumnIndexOrThrow(Im.Chats.SHORTCUT);
- mLastChatColumn = cursor.getColumnIndexOrThrow(Im.Chats.LAST_MESSAGE_DATE);
- mGroupChatColumn = cursor.getColumnIndexOrThrow(Im.Chats.GROUP_CHAT);
+ mContactIdColumn = cursor.getColumnIndexOrThrow(Imps.Contacts._ID);
+ mProviderIdColumn = cursor.getColumnIndexOrThrow(Imps.Contacts.PROVIDER);
+ mAccountIdColumn = cursor.getColumnIndexOrThrow(Imps.Contacts.ACCOUNT);
+ mUsernameColumn = cursor.getColumnIndexOrThrow(Imps.Contacts.USERNAME);
+ mNicknameColumn = cursor.getColumnIndexOrThrow(Imps.Contacts.NICKNAME);
+ mPresenceStatusColumn = cursor.getColumnIndexOrThrow(Imps.Contacts.PRESENCE_STATUS);
+ mLastUnreadMessageColumn = cursor.getColumnIndexOrThrow(Imps.Chats.LAST_UNREAD_MESSAGE);
+ mAvatarDataColumn = cursor.getColumnIndexOrThrow(Imps.Contacts.AVATAR_DATA);
+ mShortcutColumn = cursor.getColumnIndexOrThrow(Imps.Chats.SHORTCUT);
+ mLastChatColumn = cursor.getColumnIndexOrThrow(Imps.Chats.LAST_MESSAGE_DATE);
+ mGroupChatColumn = cursor.getColumnIndexOrThrow(Imps.Chats.GROUP_CHAT);
}
mOkToShowEmptyView = true;
@@ -496,7 +496,7 @@ public class ChatSwitcher {
buf.append(" OR ");
}
- buf.append(Im.Contacts.PROVIDER).append("=?");
+ buf.append(Imps.Contacts.PROVIDER).append("=?");
mQuerySelectionArgs[i] = String.valueOf(providerDef.mId);
i++;
}
@@ -510,7 +510,7 @@ public class ChatSwitcher {
private static String findCategory(ContentResolver resolver, long providerId) {
// find the provider category for this chat
Cursor providerCursor = resolver.query(
- Im.Provider.CONTENT_URI,
+ Imps.Provider.CONTENT_URI,
PROVIDER_CATEGORY_PROJECTION,
"_id = " + providerId,
null /* selection args */,
@@ -532,7 +532,7 @@ public class ChatSwitcher {
public static Intent makeChatIntent(ContentResolver resolver, long provider, long account,
String contact, long contactId, int groupChat) {
Intent i = new Intent(Intent.ACTION_VIEW,
- ContentUris.withAppendedId(Im.Chats.CONTENT_URI, contactId));
+ ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, contactId));
i.addCategory(findCategory(resolver, provider));
i.putExtra("from", contact);
i.putExtra("providerId", provider);
diff --git a/src/com/android/im/app/ChatView.java b/src/com/android/im/app/ChatView.java
index 665c7a5..ebc1038 100644
--- a/src/com/android/im/app/ChatView.java
+++ b/src/com/android/im/app/ChatView.java
@@ -42,7 +42,6 @@ import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Browser;
-import android.provider.Im;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -84,18 +83,19 @@ import com.android.im.engine.Contact;
import com.android.im.engine.ImConnection;
import com.android.im.engine.ImErrorInfo;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
public class ChatView extends LinearLayout {
// This projection and index are set for the query of active chats
static final String[] CHAT_PROJECTION = {
- Im.Contacts._ID,
- Im.Contacts.ACCOUNT,
- Im.Contacts.PROVIDER,
- Im.Contacts.USERNAME,
- Im.Contacts.NICKNAME,
- Im.Contacts.TYPE,
- Im.Presence.PRESENCE_STATUS,
- Im.Chats.LAST_UNREAD_MESSAGE,
+ Imps.Contacts._ID,
+ Imps.Contacts.ACCOUNT,
+ Imps.Contacts.PROVIDER,
+ Imps.Contacts.USERNAME,
+ Imps.Contacts.NICKNAME,
+ Imps.Contacts.TYPE,
+ Imps.Presence.PRESENCE_STATUS,
+ Imps.Chats.LAST_UNREAD_MESSAGE,
};
static final int CONTACT_ID_COLUMN = 0;
static final int ACCOUNT_COLUMN = 1;
@@ -107,9 +107,9 @@ public class ChatView extends LinearLayout {
static final int LAST_UNREAD_MESSAGE_COLUMN = 7;
static final String[] INVITATION_PROJECT = {
- Im.Invitation._ID,
- Im.Invitation.PROVIDER,
- Im.Invitation.SENDER,
+ Imps.Invitation._ID,
+ Imps.Invitation.PROVIDER,
+ Imps.Invitation.SENDER,
};
static final int INVITATION_ID_COLUMN = 0;
static final int INVITATION_PROVIDER_COLUMN = 1;
@@ -480,9 +480,9 @@ public class ChatView extends LinearLayout {
}
private void setTitle() {
- if (mType == Im.Contacts.TYPE_GROUP) {
- final String[] projection = {Im.GroupMembers.NICKNAME};
- Uri memberUri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, mChatId);
+ if (mType == Imps.Contacts.TYPE_GROUP) {
+ final String[] projection = {Imps.GroupMembers.NICKNAME};
+ Uri memberUri = ContentUris.withAppendedId(Imps.GroupMembers.CONTENT_URI, mChatId);
ContentResolver cr = mScreen.getContentResolver();
Cursor c = cr.query(memberUri, projection, null, null, null);
StringBuilder buf = new StringBuilder();
@@ -502,7 +502,7 @@ public class ChatView extends LinearLayout {
}
private void setStatusIcon() {
- if (mType == Im.Contacts.TYPE_GROUP) {
+ if (mType == Imps.Contacts.TYPE_GROUP) {
// hide the status icon for group chat.
mStatusIcon.setVisibility(GONE);
} else {
@@ -517,7 +517,7 @@ public class ChatView extends LinearLayout {
if (mCursor != null) {
mCursor.deactivate();
}
- Uri contactUri = ContentUris.withAppendedId(Im.Contacts.CONTENT_URI, chatId);
+ Uri contactUri = ContentUris.withAppendedId(Imps.Contacts.CONTENT_URI, chatId);
mCursor = mScreen.managedQuery(contactUri, CHAT_PROJECTION, null, null);
if (mCursor == null || !mCursor.moveToFirst()) {
if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
@@ -533,7 +533,7 @@ public class ChatView extends LinearLayout {
}
public void bindInvitation(long invitationId) {
- Uri uri = ContentUris.withAppendedId(Im.Invitation.CONTENT_URI, invitationId);
+ Uri uri = ContentUris.withAppendedId(Imps.Invitation.CONTENT_URI, invitationId);
ContentResolver cr = mScreen.getContentResolver();
Cursor cursor = cr.query(uri, INVITATION_PROJECT, null, null, null);
if (cursor == null || !cursor.moveToFirst()) {
@@ -656,12 +656,7 @@ public class ChatView extends LinearLayout {
mQueryHandler.cancelOperation(QUERY_TOKEN);
}
- Uri uri;
- if (Im.Contacts.TYPE_GROUP == mType) {
- uri = ContentUris.withAppendedId(Im.GroupMessages.CONTENT_URI_GROUP_MESSAGES_BY, mChatId);
- } else {
- uri = Im.Messages.getContentUriByContact(mProviderId, mAccountId, mUserName);
- }
+ Uri uri = Imps.Messages.getContentUriByThreadId(mChatId);
if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)){
log("queryCursor: uri=" + uri);
@@ -728,7 +723,7 @@ public class ChatView extends LinearLayout {
} else {
// the conversation is already closed, clear data in database
ContentResolver cr = mContext.getContentResolver();
- cr.delete(ContentUris.withAppendedId(Im.Chats.CONTENT_URI, mChatId),
+ cr.delete(ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, mChatId),
null, null);
}
mScreen.finish();
@@ -745,7 +740,7 @@ public class ChatView extends LinearLayout {
}
public void viewProfile() {
- Uri data = ContentUris.withAppendedId(Im.Contacts.CONTENT_URI, mChatId);
+ Uri data = ContentUris.withAppendedId(Imps.Contacts.CONTENT_URI, mChatId);
Intent intent = new Intent(Intent.ACTION_VIEW, data);
mScreen.startActivity(intent);
}
@@ -833,7 +828,7 @@ public class ChatView extends LinearLayout {
}
boolean isGroupChat() {
- return Im.Contacts.TYPE_GROUP == mType;
+ return Imps.Contacts.TYPE_GROUP == mType;
}
void sendMessage() {
@@ -943,10 +938,10 @@ public class ChatView extends LinearLayout {
}
if (isConnected) {
- if (mType == Im.Contacts.TYPE_TEMPORARY) {
+ if (mType == Imps.Contacts.TYPE_TEMPORARY) {
visibility = View.VISIBLE;
message = mContext.getString(R.string.contact_not_in_list_warning, mNickName);
- } else if (mPresenceStatus == Im.Presence.OFFLINE) {
+ } else if (mPresenceStatus == Imps.Presence.OFFLINE) {
visibility = View.VISIBLE;
message = mContext.getString(R.string.contact_offline_warning, mNickName);
}
@@ -1054,7 +1049,7 @@ public class ChatView extends LinearLayout {
for (int i = 0 ; i < len ; i++) {
mColumnNames[i] = columnNames[i];
- if (mColumnNames[i].equals(Im.BaseMessageColumns.DATE)) {
+ if (mColumnNames[i].equals(Imps.Messages.DATE)) {
mDateColumn = i;
}
}
@@ -1418,7 +1413,7 @@ public class ChatView extends LinearLayout {
private int mScrollState;
private boolean mNeedRequeryCursor;
- private int mContactColumn;
+ private int mNicknameColumn;
private int mBodyColumn;
private int mDateColumn;
private int mTypeColumn;
@@ -1438,11 +1433,11 @@ public class ChatView extends LinearLayout {
}
private void resolveColumnIndex(Cursor c) {
- mContactColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.CONTACT);
- mBodyColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.BODY);
- mDateColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.DATE);
- mTypeColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.TYPE);
- mErrCodeColumn = c.getColumnIndexOrThrow(Im.BaseMessageColumns.ERROR_CODE);
+ mNicknameColumn = c.getColumnIndexOrThrow(Imps.Messages.NICKNAME);
+ mBodyColumn = c.getColumnIndexOrThrow(Imps.Messages.BODY);
+ mDateColumn = c.getColumnIndexOrThrow(Imps.Messages.DATE);
+ mTypeColumn = c.getColumnIndexOrThrow(Imps.Messages.TYPE);
+ mErrCodeColumn = c.getColumnIndexOrThrow(Imps.Messages.ERROR_CODE);
mDeltaColumn = c.getColumnIndexOrThrow(DeltaCursor.DELTA_COLUMN_NAME);
}
@@ -1464,19 +1459,19 @@ public class ChatView extends LinearLayout {
MessageView chatMsgView = (MessageView) view;
int type = cursor.getInt(mTypeColumn);
- String contact = isGroupChat() ? cursor.getString(mContactColumn) : mNickName;
+ String contact = isGroupChat() ? cursor.getString(mNicknameColumn) : mNickName;
String body = cursor.getString(mBodyColumn);
long delta = cursor.getLong(mDeltaColumn);
boolean showTimeStamp = (delta > SHOW_TIME_STAMP_INTERVAL);
Date date = showTimeStamp ? new Date(cursor.getLong(mDateColumn)) : null;
switch (type) {
- case Im.MessageType.INCOMING:
+ case Imps.MessageType.INCOMING:
chatMsgView.bindIncomingMessage(contact, body, date, mMarkup, isScrolling());
break;
- case Im.MessageType.OUTGOING:
- case Im.MessageType.POSTPONED:
+ case Imps.MessageType.OUTGOING:
+ case Imps.MessageType.POSTPONED:
int errCode = cursor.getInt(mErrCodeColumn);
if (errCode != 0) {
chatMsgView.bindErrorMessage(errCode);
diff --git a/src/com/android/im/app/ChooseAccountActivity.java b/src/com/android/im/app/ChooseAccountActivity.java
index b18b0b2..6b0b57b 100644
--- a/src/com/android/im/app/ChooseAccountActivity.java
+++ b/src/com/android/im/app/ChooseAccountActivity.java
@@ -17,10 +17,11 @@
package com.android.im.app;
+import com.android.im.provider.Imps;
+
import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
-import android.provider.Im;
public class ChooseAccountActivity extends Activity {
@Override
@@ -28,7 +29,7 @@ public class ChooseAccountActivity extends Activity {
super.onCreate(icicle);
Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setType(Im.Provider.CONTENT_TYPE);
+ intent.setType(Imps.Provider.CONTENT_TYPE);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
diff --git a/src/com/android/im/app/ContactListActivity.java b/src/com/android/im/app/ContactListActivity.java
index 544d254..a907e25 100644
--- a/src/com/android/im/app/ContactListActivity.java
+++ b/src/com/android/im/app/ContactListActivity.java
@@ -19,6 +19,7 @@ package com.android.im.app;
import com.android.im.IImConnection;
import com.android.im.R;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
import android.app.Activity;
@@ -31,7 +32,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
-import android.provider.Im;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
@@ -72,7 +72,7 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
boolean mIsFiltering;
- Im.ProviderSettings.QueryMap mSettingMap;
+ Imps.ProviderSettings.QueryMap mSettingMap;
boolean mDestroyed;
@Override
@@ -96,7 +96,7 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
mApp = ImApp.getApplication(this);
ContentResolver cr = getContentResolver();
- Cursor c = cr.query(ContentUris.withAppendedId(Im.Account.CONTENT_URI, mAccountId),
+ Cursor c = cr.query(ContentUris.withAppendedId(Imps.Account.CONTENT_URI, mAccountId),
null, null, null, null);
if (c == null) {
finish();
@@ -108,9 +108,9 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
return;
}
- mProviderId = c.getLong(c.getColumnIndexOrThrow(Im.Account.PROVIDER));
+ mProviderId = c.getLong(c.getColumnIndexOrThrow(Imps.Account.PROVIDER));
mHandler = new MyHandler(this);
- String username = c.getString(c.getColumnIndexOrThrow(Im.Account.USERNAME));
+ String username = c.getString(c.getColumnIndexOrThrow(Imps.Account.USERNAME));
BrandingResources brandingRes = mApp.getBrandingResource(mProviderId);
setTitle(brandingRes.getString(
@@ -118,7 +118,7 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
getWindow().setFeatureDrawable(Window.FEATURE_LEFT_ICON,
brandingRes.getDrawable(BrandingResourceIDs.DRAWABLE_LOGO));
- mSettingMap = new Im.ProviderSettings.QueryMap(
+ mSettingMap = new Imps.ProviderSettings.QueryMap(
getContentResolver(), mProviderId, true, null);
mApp.callWhenServiceConnected(mHandler, new Runnable(){
@@ -177,7 +177,7 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
return true;
case R.id.menu_blocked_contacts:
- Uri.Builder builder = Im.BlockedList.CONTENT_URI.buildUpon();
+ Uri.Builder builder = Imps.BlockedList.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, mProviderId);
ContentUris.appendId(builder, mAccountId);
startActivity(new Intent(Intent.ACTION_VIEW, builder.build()));
@@ -185,7 +185,7 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
case R.id.menu_view_accounts:
Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setType(Im.Provider.CONTENT_TYPE);
+ intent.setType(Imps.Provider.CONTENT_TYPE);
startActivity(intent);
finish();
return true;
@@ -276,8 +276,8 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
R.layout.contact_list_filter_view, null);
mFilterView.getListView().setOnCreateContextMenuListener(this);
}
- Uri uri = mSettingMap.getHideOfflineContacts() ? Im.Contacts.CONTENT_URI_ONLINE_CONTACTS_BY
- : Im.Contacts.CONTENT_URI_CONTACTS_BY;
+ Uri uri = mSettingMap.getHideOfflineContacts() ? Imps.Contacts.CONTENT_URI_ONLINE_CONTACTS_BY
+ : Imps.Contacts.CONTENT_URI_CONTACTS_BY;
uri = ContentUris.withAppendedId(uri, mProviderId);
uri = ContentUris.withAppendedId(uri, mAccountId);
mFilterView.doFilter(uri, null);
@@ -346,12 +346,12 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
if (contactCursor != null) {
//XXX HACK: Yahoo! doesn't allow to block a friend. We can only block a temporary contact.
ProviderDef provider = mApp.getProvider(mProviderId);
- if (Im.ProviderNames.YAHOO.equals(provider.mName)) {
- int type = contactCursor.getInt(contactCursor.getColumnIndexOrThrow(Im.Contacts.TYPE));
- allowBlock = (type == Im.Contacts.TYPE_TEMPORARY);
+ if (Imps.ProviderNames.YAHOO.equals(provider.mName)) {
+ int type = contactCursor.getInt(contactCursor.getColumnIndexOrThrow(Imps.Contacts.TYPE));
+ allowBlock = (type == Imps.Contacts.TYPE_TEMPORARY);
}
- int nickNameIndex = contactCursor.getColumnIndexOrThrow(Im.Contacts.NICKNAME);
+ int nickNameIndex = contactCursor.getColumnIndexOrThrow(Imps.Contacts.NICKNAME);
menu.setHeaderTitle(contactCursor.getString(nickNameIndex));
}
@@ -402,11 +402,11 @@ public class ContactListActivity extends Activity implements View.OnCreateContex
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues(3);
- values.put(Im.AccountStatus.ACCOUNT, mAccountId);
- values.put(Im.AccountStatus.PRESENCE_STATUS, Im.Presence.OFFLINE);
- values.put(Im.AccountStatus.CONNECTION_STATUS, Im.ConnectionStatus.OFFLINE);
+ values.put(Imps.AccountStatus.ACCOUNT, mAccountId);
+ values.put(Imps.AccountStatus.PRESENCE_STATUS, Imps.Presence.OFFLINE);
+ values.put(Imps.AccountStatus.CONNECTION_STATUS, Imps.ConnectionStatus.OFFLINE);
// insert on the "account_status" uri actually replaces the existing value
- cr.insert(Im.AccountStatus.CONTENT_URI, values);
+ cr.insert(Imps.AccountStatus.CONTENT_URI, values);
}
final class ContextMenuHandler implements MenuItem.OnMenuItemClickListener {
diff --git a/src/com/android/im/app/ContactListFilterView.java b/src/com/android/im/app/ContactListFilterView.java
index 5607cde..76b410c 100644
--- a/src/com/android/im/app/ContactListFilterView.java
+++ b/src/com/android/im/app/ContactListFilterView.java
@@ -21,7 +21,6 @@ import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
-import android.provider.Im;
import android.util.AttributeSet;
import android.view.View;
import android.widget.AdapterView;
@@ -32,6 +31,7 @@ import android.widget.ResourceCursorAdapter;
import android.widget.AdapterView.OnItemClickListener;
import com.android.im.R;
+import com.android.im.provider.Imps;
public class ContactListFilterView extends LinearLayout {
@@ -95,18 +95,18 @@ public class ContactListFilterView extends LinearLayout {
StringBuilder buf = new StringBuilder();
// exclude chatting contact
- buf.append(Im.Chats.LAST_MESSAGE_DATE);
+ buf.append(Imps.Chats.LAST_MESSAGE_DATE);
buf.append(" IS NULL");
if (constraint != null) {
buf.append(" AND ");
- buf.append(Im.Contacts.NICKNAME);
+ buf.append(Imps.Contacts.NICKNAME);
buf.append(" LIKE ");
DatabaseUtils.appendValueToSql(buf, "%" + constraint + "%");
}
return mContext.getContentResolver().query(mUri, ContactView.CONTACT_PROJECTION,
- buf == null ? null : buf.toString(), null, Im.Contacts.DEFAULT_SORT_ORDER);
+ buf == null ? null : buf.toString(), null, Imps.Contacts.DEFAULT_SORT_ORDER);
}
private class ContactAdapter extends ResourceCursorAdapter {
diff --git a/src/com/android/im/app/ContactListTreeAdapter.java b/src/com/android/im/app/ContactListTreeAdapter.java
index be8b2d9..8b7abbb 100644
--- a/src/com/android/im/app/ContactListTreeAdapter.java
+++ b/src/com/android/im/app/ContactListTreeAdapter.java
@@ -29,7 +29,6 @@ import android.database.Cursor;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.RemoteException;
-import android.provider.Im;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -43,6 +42,7 @@ import android.widget.AbsListView.OnScrollListener;
import com.android.im.IImConnection;
import com.android.im.R;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
import java.util.ArrayList;
import java.util.Observable;
@@ -52,8 +52,8 @@ public class ContactListTreeAdapter extends BaseExpandableListAdapter
implements AbsListView.OnScrollListener{
private static final String[] CONTACT_LIST_PROJECTION = {
- Im.ContactList._ID,
- Im.ContactList.NAME,
+ Imps.ContactList._ID,
+ Imps.ContactList.NAME,
};
private static final int COLUMN_CONTACT_LIST_ID = 0;
@@ -80,22 +80,22 @@ public class ContactListTreeAdapter extends BaseExpandableListAdapter
private static final int TOKEN_SUBSCRITPTION = -3;
private static final String NON_CHAT_AND_BLOCKED_CONTACTS = "("
- + Im.Contacts.LAST_MESSAGE_DATE + " IS NULL) AND ("
- + Im.Contacts.TYPE + "!=" + Im.Contacts.TYPE_BLOCKED + ")";
+ + Imps.Contacts.LAST_MESSAGE_DATE + " IS NULL) AND ("
+ + Imps.Contacts.TYPE + "!=" + Imps.Contacts.TYPE_BLOCKED + ")";
- private static final String CONTACTS_SELECTION = Im.Contacts.CONTACTLIST
+ private static final String CONTACTS_SELECTION = Imps.Contacts.CONTACTLIST
+ "=? AND " + NON_CHAT_AND_BLOCKED_CONTACTS;
private static final String ONLINE_CONTACT_SELECTION = CONTACTS_SELECTION
- + " AND "+ Im.Contacts.PRESENCE_STATUS + " != " + Im.Presence.OFFLINE;
+ + " AND "+ Imps.Contacts.PRESENCE_STATUS + " != " + Imps.Presence.OFFLINE;
static final void log(String msg) {
Log.d(ImApp.LOG_TAG, "<ContactListAdapter>" + msg);
}
static final String[] CONTACT_COUNT_PROJECTION = {
- Im.Contacts.CONTACTLIST,
- Im.Contacts._COUNT,
+ Imps.Contacts.CONTACTLIST,
+ Imps.Contacts._COUNT,
};
ContentQueryMap mOnlineContactsCountMap;
@@ -211,12 +211,12 @@ public class ContactListTreeAdapter extends BaseExpandableListAdapter
log("startQueryContactLists()");
}
- Uri uri = Im.ContactList.CONTENT_URI;
+ Uri uri = Imps.ContactList.CONTENT_URI;
uri = ContentUris.withAppendedId(uri, mProviderId);
uri = ContentUris.withAppendedId(uri, mAccountId);
mQueryHandler.startQuery(TOKEN_CONTACT_LISTS, null, uri, CONTACT_LIST_PROJECTION,
- null, null, Im.ContactList.DEFAULT_SORT_ORDER);
+ null, null, Imps.ContactList.DEFAULT_SORT_ORDER);
}
void startQueryOngoingConversations() {
@@ -224,12 +224,12 @@ public class ContactListTreeAdapter extends BaseExpandableListAdapter
log("startQueryOngoingConversations()");
}
- Uri uri = Im.Contacts.CONTENT_URI_CHAT_CONTACTS_BY;
+ Uri uri = Imps.Contacts.CONTENT_URI_CHAT_CONTACTS_BY;
uri = ContentUris.withAppendedId(uri, mProviderId);
uri = ContentUris.withAppendedId(uri, mAccountId);
mQueryHandler.startQuery(TOKEN_ONGOING_CONVERSATION, null, uri,
- ContactView.CONTACT_PROJECTION, null, null, Im.Contacts.DEFAULT_SORT_ORDER);
+ ContactView.CONTACT_PROJECTION, null, null, Imps.Contacts.DEFAULT_SORT_ORDER);
}
void startQuerySubscriptions() {
@@ -237,16 +237,16 @@ public class ContactListTreeAdapter extends BaseExpandableListAdapter
log("startQuerySubscriptions()");
}
- Uri uri = Im.Contacts.CONTENT_URI_CONTACTS_BY;
+ Uri uri = Imps.Contacts.CONTENT_URI_CONTACTS_BY;
uri = ContentUris.withAppendedId(uri, mProviderId);
uri = ContentUris.withAppendedId(uri, mAccountId);
mQueryHandler.startQuery(TOKEN_SUBSCRITPTION, null, uri,
ContactView.CONTACT_PROJECTION,
String.format("%s=%d AND %s=%d",
- Im.Contacts.SUBSCRIPTION_STATUS, Im.Contacts.SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING,
- Im.Contacts.SUBSCRIPTION_TYPE, Im.Contacts.SUBSCRIPTION_TYPE_FROM),
- null,Im.Contacts.DEFAULT_SORT_ORDER);
+ Imps.Contacts.SUBSCRIPTION_STATUS, Imps.Contacts.SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING,
+ Imps.Contacts.SUBSCRIPTION_TYPE, Imps.Contacts.SUBSCRIPTION_TYPE_FROM),
+ null,Imps.Contacts.DEFAULT_SORT_ORDER);
}
void startQueryContacts(long listId) {
@@ -257,8 +257,8 @@ public class ContactListTreeAdapter extends BaseExpandableListAdapter
String selection = mHideOfflineContacts ? ONLINE_CONTACT_SELECTION : CONTACTS_SELECTION;
String[] args = { Long.toString(listId) };
int token = (int)listId;
- mQueryHandler.startQuery(token, null, Im.Contacts.CONTENT_URI,
- ContactView.CONTACT_PROJECTION, selection, args, Im.Contacts.DEFAULT_SORT_ORDER);
+ mQueryHandler.startQuery(token, null, Imps.Contacts.CONTENT_URI,
+ ContactView.CONTACT_PROJECTION, selection, args, Imps.Contacts.DEFAULT_SORT_ORDER);
}
public Object getChild(int groupPosition, int childPosition) {
@@ -640,20 +640,20 @@ public class ContactListTreeAdapter extends BaseExpandableListAdapter
private int getOnlineChildCount(Cursor groupCursor) {
long listId = groupCursor.getLong(COLUMN_CONTACT_LIST_ID);
if (mOnlineContactsCountMap == null) {
- String where = Im.Contacts.ACCOUNT + "=" + mAccountId;
+ String where = Imps.Contacts.ACCOUNT + "=" + mAccountId;
ContentResolver cr = mActivity.getContentResolver();
- Cursor c = cr.query(Im.Contacts.CONTENT_URI_ONLINE_COUNT,
+ Cursor c = cr.query(Imps.Contacts.CONTENT_URI_ONLINE_COUNT,
CONTACT_COUNT_PROJECTION, where, null, null);
mOnlineContactsCountMap = new ContentQueryMap(c,
- Im.Contacts.CONTACTLIST, true, mHandler);
+ Imps.Contacts.CONTACTLIST, true, mHandler);
mOnlineContactsCountMap.addObserver(new Observer(){
public void update(Observable observable, Object data) {
notifyDataSetChanged();
}});
}
ContentValues value = mOnlineContactsCountMap.getValues(String.valueOf(listId));
- return value == null ? 0 : value.getAsInteger(Im.Contacts._COUNT);
+ return value == null ? 0 : value.getAsInteger(Imps.Contacts._COUNT);
}
@Override
diff --git a/src/com/android/im/app/ContactListView.java b/src/com/android/im/app/ContactListView.java
index 5c31683..12ff110 100644
--- a/src/com/android/im/app/ContactListView.java
+++ b/src/com/android/im/app/ContactListView.java
@@ -27,6 +27,7 @@ import com.android.im.app.adapter.ContactListListenerAdapter;
import com.android.im.engine.Contact;
import com.android.im.engine.ContactListManager;
import com.android.im.engine.ImErrorInfo;
+import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
import android.app.Activity;
@@ -42,7 +43,6 @@ import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
-import android.provider.Im;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -176,8 +176,8 @@ public class ContactListView extends LinearLayout {
void startChat(Cursor c) {
if (c != null) {
- long id = c.getLong(c.getColumnIndexOrThrow(Im.Contacts._ID));
- String username = c.getString(c.getColumnIndexOrThrow(Im.Contacts.USERNAME));
+ long id = c.getLong(c.getColumnIndexOrThrow(Imps.Contacts._ID));
+ String username = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
try {
IChatSessionManager manager = mConn.getChatSessionManager();
IChatSession session = manager.getChatSession(username);
@@ -185,7 +185,7 @@ public class ContactListView extends LinearLayout {
manager.createChatSession(username);
}
- Uri data = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, id);
+ Uri data = ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, id);
Intent i = new Intent(Intent.ACTION_VIEW, data);
i.addCategory(ImApp.IMPS_CATEGORY);
mScreen.startActivity(i);
@@ -215,7 +215,7 @@ public class ContactListView extends LinearLayout {
void endChat(Cursor c) {
if(c != null) {
- String username = c.getString(c.getColumnIndexOrThrow(Im.Contacts.USERNAME));
+ String username = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
try {
IChatSessionManager manager = mConn.getChatSessionManager();
IChatSession session = manager.getChatSession(username);
@@ -239,8 +239,8 @@ public class ContactListView extends LinearLayout {
public void viewContactPresence(Cursor c) {
if (c != null) {
- long id = c.getLong(c.getColumnIndexOrThrow(Im.Contacts._ID));
- Uri data = ContentUris.withAppendedId(Im.Contacts.CONTENT_URI, id);
+ long id = c.getLong(c.getColumnIndexOrThrow(Imps.Contacts._ID));
+ Uri data = ContentUris.withAppendedId(Imps.Contacts.CONTENT_URI, id);
Intent i = new Intent(Intent.ACTION_VIEW, data);
mScreen.startActivity(i);
}
@@ -292,8 +292,8 @@ public class ContactListView extends LinearLayout {
if (c == null) {
mHandler.showAlert(R.string.error, R.string.select_contact);
} else {
- String nickname = c.getString(c.getColumnIndexOrThrow(Im.Contacts.NICKNAME));
- final String address = c.getString(c.getColumnIndexOrThrow(Im.Contacts.USERNAME));
+ String nickname = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.NICKNAME));
+ final String address = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
DialogInterface.OnClickListener confirmListener = new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int whichButton) {
try {
@@ -334,8 +334,8 @@ public class ContactListView extends LinearLayout {
if (c == null) {
mHandler.showAlert(R.string.error, R.string.select_contact);
} else {
- String nickname = c.getString(c.getColumnIndexOrThrow(Im.Contacts.NICKNAME));
- final String address = c.getString(c.getColumnIndexOrThrow(Im.Contacts.USERNAME));
+ String nickname = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.NICKNAME));
+ final String address = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
DialogInterface.OnClickListener confirmListener = new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int whichButton) {
try {
@@ -394,7 +394,7 @@ public class ContactListView extends LinearLayout {
if (cursor == null) {
return null;
}
- return cursor.getString(cursor.getColumnIndexOrThrow(Im.ContactList.NAME));
+ return cursor.getString(cursor.getColumnIndexOrThrow(Imps.ContactList.NAME));
}
private void registerListeners() {
@@ -432,12 +432,12 @@ public class ContactListView extends LinearLayout {
int subscriptionType = cursor.getInt(ContactView.COLUMN_SUBSCRIPTION_TYPE);
int subscriptionStatus = cursor.getInt(ContactView.COLUMN_SUBSCRIPTION_STATUS);
- if ((subscriptionType == Im.Contacts.SUBSCRIPTION_TYPE_FROM)
- && (subscriptionStatus == Im.Contacts.SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING)){
+ if ((subscriptionType == Imps.Contacts.SUBSCRIPTION_TYPE_FROM)
+ && (subscriptionStatus == Imps.Contacts.SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING)){
long providerId = cursor.getLong(ContactView.COLUMN_CONTACT_PROVIDER);
String username = cursor.getString(ContactView.COLUMN_CONTACT_USERNAME);
Intent intent = new Intent(ImServiceConstants.ACTION_MANAGE_SUBSCRIPTION,
- ContentUris.withAppendedId(Im.Contacts.CONTENT_URI, id));
+ ContentUris.withAppendedId(Imps.Contacts.CONTENT_URI, id));
intent.putExtra(ImServiceConstants.EXTRA_INTENT_PROVIDER_ID, providerId);
intent.putExtra(ImServiceConstants.EXTRA_INTENT_FROM_ADDRESS, username);
mScreen.startActivity(intent);
diff --git a/src/com/android/im/app/ContactPresenceActivity.java b/src/com/android/im/app/ContactPresenceActivity.java
index 6531503..55454d4 100644
--- a/src/com/android/im/app/ContactPresenceActivity.java
+++ b/src/com/android/im/app/ContactPresenceActivity.java
@@ -25,7 +25,6 @@ import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
-import android.provider.Im;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ImageSpan;
@@ -36,6 +35,7 @@ import android.widget.TextView;
import com.android.im.R;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
public class ContactPresenceActivity extends Activity {
@@ -70,19 +70,19 @@ public class ContactPresenceActivity extends Activity {
}
if(c.moveToFirst()) {
- long providerId = c.getLong(c.getColumnIndexOrThrow(Im.Contacts.PROVIDER));
- String username = c.getString(c.getColumnIndexOrThrow(Im.Contacts.USERNAME));
- String nickname = c.getString(c.getColumnIndexOrThrow(Im.Contacts.NICKNAME));
- int status = c.getInt(c.getColumnIndexOrThrow(Im.Contacts.PRESENCE_STATUS));
- int clientType = c.getInt(c.getColumnIndexOrThrow(Im.Contacts.CLIENT_TYPE));
- String customStatus = c.getString(c.getColumnIndexOrThrow(Im.Contacts.PRESENCE_CUSTOM_STATUS));
+ long providerId = c.getLong(c.getColumnIndexOrThrow(Imps.Contacts.PROVIDER));
+ String username = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
+ String nickname = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.NICKNAME));
+ int status = c.getInt(c.getColumnIndexOrThrow(Imps.Contacts.PRESENCE_STATUS));
+ int clientType = c.getInt(c.getColumnIndexOrThrow(Imps.Contacts.CLIENT_TYPE));
+ String customStatus = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.PRESENCE_CUSTOM_STATUS));
ImApp app = ImApp.getApplication(this);
BrandingResources brandingRes = app.getBrandingResource(providerId);
setTitle(brandingRes.getString(BrandingResourceIDs.STRING_CONTACT_INFO_TITLE));
Drawable avatar = DatabaseUtils.getAvatarFromCursor(c,
- c.getColumnIndexOrThrow(Im.Contacts.AVATAR_DATA));
+ c.getColumnIndexOrThrow(Imps.Contacts.AVATAR_DATA));
if (avatar != null) {
imgAvatar.setImageDrawable(avatar);
} else {
@@ -119,7 +119,7 @@ public class ContactPresenceActivity extends Activity {
private String getClientTypeString(int clientType) {
Resources res = getResources();
switch (clientType) {
- case Im.Contacts.CLIENT_TYPE_MOBILE:
+ case Imps.Contacts.CLIENT_TYPE_MOBILE:
return res.getString(R.string.client_type_mobile);
default:
diff --git a/src/com/android/im/app/ContactView.java b/src/com/android/im/app/ContactView.java
index 38ee6cf..08bf921 100644
--- a/src/com/android/im/app/ContactView.java
+++ b/src/com/android/im/app/ContactView.java
@@ -24,7 +24,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
-import android.provider.Im;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
@@ -40,24 +39,25 @@ import android.graphics.drawable.Drawable;
import com.android.im.R;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
import java.text.DateFormat;
import java.util.Calendar;
public class ContactView extends LinearLayout {
static final String[] CONTACT_PROJECTION = {
- Im.Contacts._ID,
- Im.Contacts.PROVIDER,
- Im.Contacts.ACCOUNT,
- Im.Contacts.USERNAME,
- Im.Contacts.NICKNAME,
- Im.Contacts.TYPE,
- Im.Contacts.SUBSCRIPTION_TYPE,
- Im.Contacts.SUBSCRIPTION_STATUS,
- Im.Presence.PRESENCE_STATUS,
- Im.Presence.PRESENCE_CUSTOM_STATUS,
- Im.Chats.LAST_MESSAGE_DATE,
- Im.Chats.LAST_UNREAD_MESSAGE,
+ Imps.Contacts._ID,
+ Imps.Contacts.PROVIDER,
+ Imps.Contacts.ACCOUNT,
+ Imps.Contacts.USERNAME,
+ Imps.Contacts.NICKNAME,
+ Imps.Contacts.TYPE,
+ Imps.Contacts.SUBSCRIPTION_TYPE,
+ Imps.Contacts.SUBSCRIPTION_STATUS,
+ Imps.Presence.PRESENCE_STATUS,
+ Imps.Presence.PRESENCE_CUSTOM_STATUS,
+ Imps.Chats.LAST_MESSAGE_DATE,
+ Imps.Chats.LAST_UNREAD_MESSAGE,
};
static final int COLUMN_CONTACT_ID = 0;
@@ -116,7 +116,7 @@ public class ContactView extends LinearLayout {
// status icon
- if (Im.Contacts.TYPE_GROUP == type) {
+ if (Imps.Contacts.TYPE_GROUP == type) {
iconId = lastMsg == null ? R.drawable.group_chat : R.drawable.group_chat_new;
} else if (hasChat) {
iconId = lastMsg == null ? BrandingResourceIDs.DRAWABLE_READ_CHAT
@@ -130,7 +130,7 @@ public class ContactView extends LinearLayout {
// line1
CharSequence line1;
- if (Im.Contacts.TYPE_GROUP == type) {
+ if (Imps.Contacts.TYPE_GROUP == type) {
ContentResolver resolver = getContext().getContentResolver();
long id = cursor.getLong(ContactView.COLUMN_CONTACT_ID);
line1 = queryGroupMembers(resolver, id);
@@ -151,7 +151,7 @@ public class ContactView extends LinearLayout {
}
}
- if (Im.Contacts.TYPE_TEMPORARY == type) {
+ if (Imps.Contacts.TYPE_TEMPORARY == type) {
// Add a mark at the front of name if it's only a temporary
// contact.
SpannableStringBuilder str = new SpannableStringBuilder(
@@ -182,7 +182,7 @@ public class ContactView extends LinearLayout {
}
if (TextUtils.isEmpty(line2)){
- if (Im.Contacts.TYPE_GROUP == type) {
+ if (Imps.Contacts.TYPE_GROUP == type) {
// Show nothing in line2 if it's a group and don't
// have any unread message.
line2 = null;
@@ -214,8 +214,8 @@ public class ContactView extends LinearLayout {
}
private String queryGroupMembers(ContentResolver resolver, long groupId) {
- String[] projection = { Im.GroupMembers.NICKNAME };
- Uri uri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, groupId);
+ String[] projection = { Imps.GroupMembers.NICKNAME };
+ Uri uri = ContentUris.withAppendedId(Imps.GroupMembers.CONTENT_URI, groupId);
Cursor c = resolver.query(uri, projection, null, null, null);
StringBuilder buf = new StringBuilder();
if(c != null) {
diff --git a/src/com/android/im/app/ContactsPickerActivity.java b/src/com/android/im/app/ContactsPickerActivity.java
index eb52aa3..0dfb287 100644
--- a/src/com/android/im/app/ContactsPickerActivity.java
+++ b/src/com/android/im/app/ContactsPickerActivity.java
@@ -18,6 +18,7 @@
package com.android.im.app;
import com.android.im.R;
+import com.android.im.provider.Imps;
import android.app.ListActivity;
import android.content.Context;
@@ -26,7 +27,6 @@ import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.Bundle;
-import android.provider.Im;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
@@ -89,7 +89,7 @@ public class ContactsPickerActivity extends ListActivity {
}
mExcludeClause = buildExcludeClause(i.getStringArrayExtra(EXTRA_EXCLUDED_CONTACTS));
Cursor cursor = managedQuery(mData, ContactView.CONTACT_PROJECTION,
- mExcludeClause, Im.Contacts.DEFAULT_SORT_ORDER);
+ mExcludeClause, Imps.Contacts.DEFAULT_SORT_ORDER);
if (cursor == null) {
return false;
}
@@ -116,7 +116,7 @@ public class ContactsPickerActivity extends ListActivity {
}
StringBuilder clause = new StringBuilder();
- clause.append(Im.Contacts.USERNAME);
+ clause.append(Imps.Contacts.USERNAME);
clause.append(" NOT IN (");
int len = excluded.length;
for (int i = 0; i < len - 1; i++) {
@@ -138,14 +138,14 @@ public class ContactsPickerActivity extends ListActivity {
buf.append(mExcludeClause).append(" AND ");
}
- buf.append(Im.Contacts.NICKNAME);
+ buf.append(Imps.Contacts.NICKNAME);
buf.append(" LIKE ");
DatabaseUtils.appendValueToSql(buf, "%" + constraint + "%");
where = buf.toString();
}
return managedQuery(mData, ContactView.CONTACT_PROJECTION, where,
- Im.Contacts.DEFAULT_SORT_ORDER);
+ Imps.Contacts.DEFAULT_SORT_ORDER);
}
private class ContactsAdapter extends ResourceCursorAdapter {
diff --git a/src/com/android/im/app/DatabaseUtils.java b/src/com/android/im/app/DatabaseUtils.java
index 503f9be..4484114 100644
--- a/src/com/android/im/app/DatabaseUtils.java
+++ b/src/com/android/im/app/DatabaseUtils.java
@@ -18,6 +18,7 @@
package com.android.im.app;
import com.android.im.plugin.ImConfigNames;
+import com.android.im.provider.Imps;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -28,7 +29,6 @@ import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.provider.Im;
import android.util.Log;
import java.util.Map;
@@ -42,9 +42,9 @@ public class DatabaseUtils {
public static Cursor queryAccountsForProvider(ContentResolver cr,
String[] projection, long providerId) {
- StringBuilder where = new StringBuilder(Im.Account.ACTIVE);
- where.append("=1 AND ").append(Im.Account.PROVIDER).append('=').append(providerId);
- Cursor c = cr.query(Im.Account.CONTENT_URI, projection, where.toString(), null, null);
+ StringBuilder where = new StringBuilder(Imps.Account.ACTIVE);
+ where.append("=1 AND ").append(Imps.Account.PROVIDER).append('=').append(providerId);
+ Cursor c = cr.query(Imps.Account.CONTENT_URI, projection, where.toString(), null, null);
if (c != null && !c.moveToFirst()) {
c.close();
return null;
@@ -116,9 +116,9 @@ public class DatabaseUtils {
private static void updateAvatarBlob(ContentResolver resolver, Uri updateUri, byte[] data,
String username) {
ContentValues values = new ContentValues(3);
- values.put(Im.Avatars.DATA, data);
+ values.put(Imps.Avatars.DATA, data);
- StringBuilder buf = new StringBuilder(Im.Avatars.CONTACT);
+ StringBuilder buf = new StringBuilder(Imps.Avatars.CONTACT);
buf.append("=?");
String[] selectionArgs = new String[] {
@@ -149,7 +149,7 @@ public class DatabaseUtils {
boolean versionChanged;
// query provider data
- long providerId = Im.Provider.getProviderIdForName(cr, providerName);
+ long providerId = Imps.Provider.getProviderIdForName(cr, providerName);
if (providerId > 0) {
// already loaded, check if version changed
String pluginVersion = config.get(ImConfigNames.PLUGIN_VERSION);
@@ -183,10 +183,10 @@ public class DatabaseUtils {
*/
private static int clearBrandingResourceMapCache(ContentResolver cr, long providerId) {
StringBuilder where = new StringBuilder();
- where.append(Im.BrandingResourceMapCache.PROVIDER_ID);
+ where.append(Imps.BrandingResourceMapCache.PROVIDER_ID);
where.append('=');
where.append(providerId);
- return cr.delete(Im.BrandingResourceMapCache.CONTENT_URI, where.toString(), null);
+ return cr.delete(Imps.BrandingResourceMapCache.CONTENT_URI, where.toString(), null);
}
/**
@@ -198,12 +198,12 @@ public class DatabaseUtils {
int index = 0;
for (Map.Entry<String, String> entry : config.entrySet()) {
ContentValues settingValue = new ContentValues();
- settingValue.put(Im.ProviderSettings.PROVIDER, providerId);
- settingValue.put(Im.ProviderSettings.NAME, entry.getKey());
- settingValue.put(Im.ProviderSettings.VALUE, entry.getValue());
+ settingValue.put(Imps.ProviderSettings.PROVIDER, providerId);
+ settingValue.put(Imps.ProviderSettings.NAME, entry.getKey());
+ settingValue.put(Imps.ProviderSettings.VALUE, entry.getValue());
settingValues[index++] = settingValue;
}
- return cr.bulkInsert(Im.ProviderSettings.CONTENT_URI, settingValues);
+ return cr.bulkInsert(Imps.ProviderSettings.CONTENT_URI, settingValues);
}
/**
@@ -212,11 +212,11 @@ public class DatabaseUtils {
private static long insertProviderRow(ContentResolver cr, String providerName,
String providerFullName, String signUpUrl) {
ContentValues values = new ContentValues(3);
- values.put(Im.Provider.NAME, providerName);
- values.put(Im.Provider.FULLNAME, providerFullName);
- values.put(Im.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
- values.put(Im.Provider.SIGNUP_URL, signUpUrl);
- Uri result = cr.insert(Im.Provider.CONTENT_URI, values);
+ values.put(Imps.Provider.NAME, providerName);
+ values.put(Imps.Provider.FULLNAME, providerFullName);
+ values.put(Imps.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
+ values.put(Imps.Provider.SIGNUP_URL, signUpUrl);
+ Uri result = cr.insert(Imps.Provider.CONTENT_URI, values);
return ContentUris.parseId(result);
}
@@ -231,10 +231,10 @@ public class DatabaseUtils {
// Note that we don't update the provider name because it's used as
// identifier at some place and the plugin should never change it.
ContentValues values = new ContentValues(3);
- values.put(Im.Provider.FULLNAME, providerFullName);
- values.put(Im.Provider.SIGNUP_URL, signUpUrl);
- values.put(Im.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
- Uri uri = ContentUris.withAppendedId(Im.Provider.CONTENT_URI, providerId);
+ values.put(Imps.Provider.FULLNAME, providerFullName);
+ values.put(Imps.Provider.SIGNUP_URL, signUpUrl);
+ values.put(Imps.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
+ Uri uri = ContentUris.withAppendedId(Imps.Provider.CONTENT_URI, providerId);
return cr.update(uri, values, null, null);
}
@@ -243,7 +243,7 @@ public class DatabaseUtils {
*/
private static boolean isPluginVersionChanged(ContentResolver cr, long providerId,
String newVersion) {
- String oldVersion = Im.ProviderSettings.getStringValue(cr, providerId,
+ String oldVersion = Imps.ProviderSettings.getStringValue(cr, providerId,
ImConfigNames.PLUGIN_VERSION);
if (oldVersion == null) {
return true;
diff --git a/src/com/android/im/app/FrontDoorPlugin.java b/src/com/android/im/app/FrontDoorPlugin.java
deleted file mode 100644
index fedd45e..0000000
--- a/src/com/android/im/app/FrontDoorPlugin.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2008 Esmertec AG.
- * 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.im.app;
-
-import com.android.im.plugin.ImConfigNames;
-import com.android.im.plugin.ImPluginConstants;
-
-import android.app.Service;
-import android.content.Intent;
-import android.content.ContentUris;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.im.IImPlugin;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.Bundle;
-import android.provider.Im;
-import android.util.Log;
-import android.text.TextUtils;
-import android.database.Cursor;
-import android.net.Uri;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.List;
-import java.util.ArrayList;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
-
-import dalvik.system.PathClassLoader;
-
-
-public class FrontDoorPlugin extends Service {
- private final static String TAG = ImApp.LOG_TAG;
- private final static boolean LOCAL_DEBUG = false;
-
- // database access constants for branding resource map cache table
- private final static String[] BRANDING_RESOURCE_MAP_CACHE_PROJECTION = {
- Im.BrandingResourceMapCache.PROVIDER_ID,
- Im.BrandingResourceMapCache.APP_RES_ID,
- Im.BrandingResourceMapCache.PLUGIN_RES_ID
- };
- private final static int BRANDING_RESOURCE_MAP_CACHE_PROVIDER_ID_COLUMN = 0;
- private final static int BRANDING_RESOURCE_MAP_CACHE_APP_RES_ID_COLUMN = 1;
- private final static int BRANDING_RESOURCE_MAP_CACHE_PLUGIN_RES_ID_COLUMN = 2;
-
- private ArrayList<String> mProviderNames;
- private HashMap<String, String> mPackageNames;
- private HashMap<String, Map<Integer, Integer>> mBrandingResources;
-
- @Override
- public IBinder onBind(Intent intent) {
- // temporary mappings
- HashMap<String, Long> providerNameToId = new HashMap<String, Long>();
- HashMap<Long, String> providerIdToName = new HashMap<Long, String>();
- HashMap<String, Class> classes = new HashMap<String, Class>();
-
- loadThirdPartyPlugins(providerNameToId, providerIdToName, classes);
- loadBrandingResources(providerNameToId, providerIdToName, classes);
-
- return mBinder;
- }
-
- private void loadThirdPartyPlugins(
- HashMap<String, Long> providerNameToId, HashMap<Long, String> providerIdToName,
- HashMap<String, Class> classes) {
- mProviderNames = new ArrayList<String>();
- mPackageNames = new HashMap<String, String>();
-
- PackageManager pm = getPackageManager();
- List<ResolveInfo> plugins = pm.queryIntentServices(
- new Intent(ImPluginConstants.PLUGIN_ACTION_NAME), PackageManager.GET_META_DATA);
- int numPlugins = plugins.size();
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- log("loadThirdPartyPlugins: # plugins found: " + numPlugins);
- }
-
- if (numPlugins == 0) {
- Log.e(TAG, "[IM.FrontDoorPlugin] no plugins found! bail...");
- return;
- }
-
- for (ResolveInfo info : plugins) {
- if (Log.isLoggable(TAG, Log.DEBUG)) log("loadThirdPartyPlugins: found plugin " + info);
-
- ServiceInfo serviceInfo = info.serviceInfo;
- if (serviceInfo == null) {
- Log.e(TAG, "[FrontDoorPlugin] loadThirdPartyPlugins: ignore bad plugin: " + info);
- continue;
- }
-
- String providerName = null;
- String providerFullName = null;
- String signUpUrl = null;
- Bundle metaData = serviceInfo.metaData;
- if (metaData != null) {
- providerName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_NAME);
- providerFullName =
- metaData.getString(ImPluginConstants.METADATA_PROVIDER_FULL_NAME);
- signUpUrl = metaData.getString(ImPluginConstants.METADATA_SIGN_UP_URL);
- }
- if (TextUtils.isEmpty(providerName) || TextUtils.isEmpty(providerFullName)) {
- Log.e(TAG, "[FrontDoorPlugin] Ignore bad IM plugin: " + info +
- ". Lack of required meta data");
- continue;
- }
-
- mProviderNames.add(providerName);
- mPackageNames.put(providerName, serviceInfo.packageName);
-
- String className = serviceInfo.name;
- String srcPath = serviceInfo.applicationInfo.sourceDir;
- Class pluginClass = loadClass(className, srcPath);
- if (pluginClass == null) {
- Log.e(TAG, "[FrontDoorPlugin] Can not load package for plugin " + providerName);
- continue;
- }
- classes.put(providerName, pluginClass);
-
- Map<String, String> config = loadProviderConfigFromPlugin(pluginClass);
- if (config == null) {
- Log.e(TAG, "[FrontDoorPlugin] Can not load config for plugin " + providerName);
- continue;
- }
- config.put(ImConfigNames.PLUGIN_PATH, srcPath);
- config.put(ImConfigNames.PLUGIN_CLASS, className);
-
- long providerId = DatabaseUtils.updateProviderDb(getContentResolver(),
- providerName, providerFullName, signUpUrl, config);
- providerNameToId.put(providerName, providerId);
- providerIdToName.put(providerId, providerName);
- }
- }
-
- private void loadBrandingResources(
- HashMap<String, Long> providerNameToId, HashMap<Long, String> providerIdToName,
- HashMap<String, Class> classes) {
- mBrandingResources = new HashMap<String, Map<Integer, Integer>>();
-
- // first try load from cache
- loadBrandingResourcesFromCache(providerIdToName);
-
- // check and load any un-cached resources
- final ArrayList<ContentValues> valuesList = new ArrayList<ContentValues>();
- for (String provider : mProviderNames) {
- long providerId = providerNameToId.get(provider);
- if (!mBrandingResources.containsKey(provider)) {
- Map<Integer, Integer> resMap = loadBrandingResource(classes.get(provider));
- if (resMap != null) {
- mBrandingResources.put(provider, resMap);
- for (int appResId : resMap.keySet()) {
- int pluginResId = resMap.get(appResId);
-
- ContentValues values = new ContentValues();
- values.put(Im.BrandingResourceMapCache.PROVIDER_ID, providerId);
- values.put(Im.BrandingResourceMapCache.APP_RES_ID, appResId);
- values.put(Im.BrandingResourceMapCache.PLUGIN_RES_ID, pluginResId);
-
- valuesList.add(values);
- }
- Log.d(TAG, "Plugin " + provider + " not in cache, loaded and saved");
- }
- }
- }
-
- // save the changes to cache
- if (valuesList.size() > 0) {
- new Thread(new Runnable() {
- public void run() {
- getContentResolver().bulkInsert(
- Im.BrandingResourceMapCache.CONTENT_URI,
- valuesList.toArray(new ContentValues[]{}));
- }
- }).start();
- }
- }
-
- /**
- * Try loading the branding resources from the database.
- * @param providerIdToName a map between provider ID and name.
- */
- private void loadBrandingResourcesFromCache(HashMap<Long, String> providerIdToName) {
- ContentResolver cr = getContentResolver();
- Cursor c = cr.query(
- Im.BrandingResourceMapCache.CONTENT_URI, /* URI */
- BRANDING_RESOURCE_MAP_CACHE_PROJECTION, /* projection */
- null, /* where */
- null, /* where args */
- null /* sort */);
-
- if (c != null) {
- try {
- while (c.moveToNext()) {
- long providerId = c.getLong(BRANDING_RESOURCE_MAP_CACHE_PROVIDER_ID_COLUMN);
- String provider = providerIdToName.get(providerId);
- if (TextUtils.isEmpty(provider)) {
- Log.e(TAG, "Empty provider name in branding resource map cache table.");
- continue;
- }
- int appResId = c.getInt(BRANDING_RESOURCE_MAP_CACHE_APP_RES_ID_COLUMN);
- int pluginResId = c.getInt(BRANDING_RESOURCE_MAP_CACHE_PLUGIN_RES_ID_COLUMN);
-
- Map<Integer, Integer> resMap = mBrandingResources.get(provider);
- if (resMap == null) {
- resMap = new HashMap<Integer, Integer>();
- mBrandingResources.put(provider, resMap);
- }
-
- resMap.put(appResId, pluginResId);
- }
- } finally {
- c.close();
- }
- } else {
- Log.e(TAG, "Query of branding resource map cache table returns empty cursor");
- }
- }
-
- /**
- * Load branding resources from one plugin.
- */
- private Map<Integer, Integer> loadBrandingResource(Class cls) {
- try {
- Method m = cls.getMethod("getResourceMap");
- // TODO: this would still cause a VM verifier exception to be thrown if.
- // the landing page Android.mk and AndroidManifest.xml don't include use-library for
- // "com.android.im.plugin". This is even with getCustomClassLoader() as the parent
- // class loader.
- return (Map)m.invoke(cls.newInstance(), new Object[]{});
-
- } catch (IllegalAccessException e) {
- Log.e(TAG, "Failed load the plugin resource map", e);
- } catch (InstantiationException e) {
- Log.e(TAG, "Failed load the plugin resource map", e);
- } catch (SecurityException e) {
- Log.e(TAG, "Failed load the plugin resource map", e);
- } catch (NoSuchMethodException e) {
- Log.e(TAG, "Failed load the plugin resource map", e);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Failed load the plugin resource map", e);
- } catch (InvocationTargetException e) {
- Log.e(TAG, "Failed load the plugin resource map", e);
- }
- return null;
- }
-
- /**
- * Load plugin config.
- */
- private Map<String, String> loadProviderConfigFromPlugin(Class cls) {
- try {
- Method m = cls.getMethod("onBind", Intent.class);
- com.android.im.plugin.IImPlugin plugin =
- (com.android.im.plugin.IImPlugin)m.invoke(cls.newInstance(), new Object[]{null});
- return plugin.getProviderConfig();
- } catch (IllegalAccessException e) {
- Log.e(TAG, "Could not create plugin instance", e);
- } catch (InstantiationException e) {
- Log.e(TAG, "Could not create plugin instance", e);
- } catch (SecurityException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- } catch (NoSuchMethodException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- } catch (InvocationTargetException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- }
- return null;
- }
-
- private Class loadClass(String className, String srcPath) {
- PathClassLoader loader = new PathClassLoader(srcPath, getClassLoader());
- try {
- return loader.loadClass(className);
- } catch (ClassNotFoundException e) {
- Log.e(TAG, "Could not find plugin class", e);
- }
- return null;
- }
-
- private void log(String msg) {
- Log.d(TAG, "[ImFrontDoor] " + msg);
- }
-
-
- /**
- * The implementation of IImFrontDoorPlugin defined through AIDL.
- */
- private final IImPlugin.Stub mBinder = new IImPlugin.Stub() {
-
- /**
- * Notify the plugin the front door activity is created. This gives the plugin a chance to
- * start its own servics, etc.
- */
- public void onStart() {
- }
-
- /**
- * Notify the plugin the front door activity is stopping.
- */
- public void onStop() {
- }
-
- /**
- * Sign in to the service for the account passed in.
- */
- public void signIn(long account) {
- if (LOCAL_DEBUG) log("signIn for account " + account);
-
- Intent intent = new Intent();
- intent.setData(ContentUris.withAppendedId(Im.Account.CONTENT_URI, account));
- intent.setClassName("com.android.im", "com.android.im.app.SigningInActivity");
-
- startActivity(intent);
- }
-
- /**
- * Sign out of the service for the account passed in.
- */
- public void signOut(long account) {
- if (LOCAL_DEBUG) log("signOut for account " + account);
- Intent intent = new Intent();
- intent.setData(ContentUris.withAppendedId(Im.Account.CONTENT_URI, account));
- intent.setClassName("com.android.im", "com.android.im.app.SignoutActivity");
-
- startActivity(intent);
- }
-
- public String getResourcePackageNameForProvider(String providerName) {
- return mPackageNames.get(providerName);
- }
-
- public Map getResourceMapForProvider(String providerName) throws RemoteException {
- return mBrandingResources.get(providerName);
- }
-
- public List getSupportedProviders() {
- return mProviderNames;
- }
- };
-
-}
diff --git a/src/com/android/im/app/ImApp.java b/src/com/android/im/app/ImApp.java
index 86acc7c..02f9cae 100644
--- a/src/com/android/im/app/ImApp.java
+++ b/src/com/android/im/app/ImApp.java
@@ -17,6 +17,12 @@
package com.android.im.app;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
import android.app.Activity;
import android.app.Application;
import android.content.ComponentName;
@@ -27,20 +33,16 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Broadcaster;
-import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
-import android.provider.Im;
-import android.text.TextUtils;
import android.util.Log;
import com.android.im.IConnectionCreationListener;
@@ -51,15 +53,11 @@ import com.android.im.app.adapter.ConnectionListenerAdapter;
import com.android.im.engine.ImConnection;
import com.android.im.engine.ImErrorInfo;
import com.android.im.plugin.BrandingResourceIDs;
-import com.android.im.plugin.ImPluginConstants;
+import com.android.im.plugin.ImPlugin;
import com.android.im.plugin.ImPluginInfo;
+import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
public class ImApp extends Application {
public static final String LOG_TAG = "ImApp";
@@ -100,18 +98,18 @@ public class ImApp extends Application {
public static final int EVENT_UPDATE_USER_PRESENCE_ERROR = 301;
private static final String[] PROVIDER_PROJECTION = {
- Im.Provider._ID,
- Im.Provider.NAME,
- Im.Provider.FULLNAME,
- Im.Provider.SIGNUP_URL,
+ Imps.Provider._ID,
+ Imps.Provider.NAME,
+ Imps.Provider.FULLNAME,
+ Imps.Provider.SIGNUP_URL,
};
private static final String[] ACCOUNT_PROJECTION = {
- Im.Account._ID,
- Im.Account.PROVIDER,
- Im.Account.NAME,
- Im.Account.USERNAME,
- Im.Account.PASSWORD,
+ Imps.Account._ID,
+ Imps.Account.PROVIDER,
+ Imps.Account.NAME,
+ Imps.Account.USERNAME,
+ Imps.Account.PASSWORD,
};
static final void log(String log) {
@@ -173,8 +171,6 @@ public class ImApp extends Application {
super.onCreate();
mBroadcaster = new Broadcaster();
loadDefaultBrandingRes();
- mBrandingResources = new HashMap<String, BrandingResources>();
- loadThirdPartyResources();
}
@Override
@@ -265,27 +261,27 @@ public class ImApp extends Application {
public static long insertOrUpdateAccount(ContentResolver cr,
long providerId, String userName, String pw) {
- String selection = Im.Account.PROVIDER + "=? AND " + Im.Account.USERNAME + "=?";
+ String selection = Imps.Account.PROVIDER + "=? AND " + Imps.Account.USERNAME + "=?";
String[] selectionArgs = {Long.toString(providerId), userName };
- Cursor c = cr.query(Im.Account.CONTENT_URI, ACCOUNT_PROJECTION,
+ Cursor c = cr.query(Imps.Account.CONTENT_URI, ACCOUNT_PROJECTION,
selection, selectionArgs, null);
if (c != null && c.moveToFirst()) {
// Update the password
- c.updateString(c.getColumnIndexOrThrow(Im.Account.PASSWORD), pw);
+ c.updateString(c.getColumnIndexOrThrow(Imps.Account.PASSWORD), pw);
c.commitUpdates();
- long id = c.getLong(c.getColumnIndexOrThrow(Im.Account._ID));
+ long id = c.getLong(c.getColumnIndexOrThrow(Imps.Account._ID));
c.close();
return id;
} else {
ContentValues values = new ContentValues(4);
- values.put(Im.Account.PROVIDER, providerId);
- values.put(Im.Account.NAME, userName);
- values.put(Im.Account.USERNAME, userName);
- values.put(Im.Account.PASSWORD, pw);
+ values.put(Imps.Account.PROVIDER, providerId);
+ values.put(Imps.Account.NAME, userName);
+ values.put(Imps.Account.USERNAME, userName);
+ values.put(Imps.Account.PASSWORD, pw);
- Uri result = cr.insert(Im.Account.CONTENT_URI, values);
+ Uri result = cr.insert(Imps.Account.CONTENT_URI, values);
return ContentUris.parseId(result);
}
}
@@ -294,15 +290,15 @@ public class ImApp extends Application {
if (mProviders != null) {
return;
}
-
+
mProviders = new HashMap<Long, ProviderDef>();
ContentResolver cr = getContentResolver();
String selectionArgs[] = new String[1];
selectionArgs[0] = ImApp.IMPS_CATEGORY;
- Cursor c = cr.query(Im.Provider.CONTENT_URI, PROVIDER_PROJECTION,
- Im.Provider.CATEGORY+"=?", selectionArgs, null);
+ Cursor c = cr.query(Imps.Provider.CONTENT_URI, PROVIDER_PROJECTION,
+ Imps.Provider.CATEGORY+"=?", selectionArgs, null);
if (c == null) {
return;
}
@@ -401,40 +397,28 @@ public class ImApp extends Application {
}
private void loadThirdPartyResources() {
+ ImPluginHelper helper = ImPluginHelper.getInstance(this);
+ helper.loadAvaiablePlugins();
+ ArrayList<ImPlugin> pluginList = helper.getPluginObjects();
+ ArrayList<ImPluginInfo> infoList = helper.getPluginsInfo();
+ int N = pluginList.size();
PackageManager pm = getPackageManager();
- List<ResolveInfo> plugins = pm.queryIntentServices(
- new Intent(ImPluginConstants.PLUGIN_ACTION_NAME), PackageManager.GET_META_DATA);
- for (ResolveInfo info : plugins) {
- Log.d(LOG_TAG, "Found plugin " + info);
-
- ServiceInfo serviceInfo = info.serviceInfo;
- if (serviceInfo == null) {
- Log.e(LOG_TAG, "Ignore bad IM plugin: " + info);
- continue;
- }
- String providerName = null;
- String providerFullName = null;
- Bundle metaData = serviceInfo.metaData;
- if (metaData != null) {
- providerName = metaData.getString(
- ImPluginConstants.METADATA_PROVIDER_NAME);
- providerFullName = metaData.getString(
- ImPluginConstants.METADATA_PROVIDER_FULL_NAME);
- }
- if (TextUtils.isEmpty(providerName)
- || TextUtils.isEmpty(providerFullName)) {
- Log.e(LOG_TAG, "Ignore bad IM plugin: " + info
- + ". Lack of required meta data");
- continue;
- }
+ for (int i = 0; i < N; i++) {
+ ImPlugin plugin = pluginList.get(i);
+ ImPluginInfo pluginInfo = infoList.get(i);
+
+ try {
+ Resources packageRes = pm.getResourcesForApplication(pluginInfo.mPackageName);
- ImPluginInfo pluginInfo = new ImPluginInfo(providerName,
- serviceInfo.packageName, serviceInfo.name,
- serviceInfo.applicationInfo.sourceDir);
+ Map<Integer, Integer> resMap = plugin.getResourceMap();
+ int[] smileyIcons = plugin.getSmileyIconIds();
- BrandingResources res = new BrandingResources(this, pluginInfo,
- mDefaultBrandingResources);
- mBrandingResources.put(providerName, res);
+ BrandingResources res = new BrandingResources(packageRes, resMap,
+ smileyIcons, mDefaultBrandingResources);
+ mBrandingResources.put(pluginInfo.mProviderName, res);
+ } catch (NameNotFoundException e) {
+ Log.e(LOG_TAG, "Failed to load third party resources.", e);
+ }
}
}
@@ -465,6 +449,10 @@ public class ImApp extends Application {
if (provider == null) {
return mDefaultBrandingResources;
}
+ if (mBrandingResources == null) {
+ mBrandingResources = new HashMap<String, BrandingResources>();
+ loadThirdPartyResources();
+ }
BrandingResources res = mBrandingResources.get(provider.mName);
return res == null ? mDefaultBrandingResources : res;
}
@@ -670,6 +658,9 @@ public class ImApp extends Application {
case ImConnection.LOGGING_OUT:
what = EVENT_CONNECTION_LOGGING_OUT;
+ synchronized (mConnections) {
+ mConnections.remove(providerId);
+ }
break;
case ImConnection.DISCONNECTED:
diff --git a/src/com/android/im/app/ImPluginHelper.java b/src/com/android/im/app/ImPluginHelper.java
new file mode 100644
index 0000000..4e9159e
--- /dev/null
+++ b/src/com/android/im/app/ImPluginHelper.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2009 Myriad Group AG.
+ * 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.im.app;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteFullException;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.im.plugin.ImConfigNames;
+import com.android.im.plugin.ImPlugin;
+import com.android.im.plugin.ImPluginConstants;
+import com.android.im.plugin.ImPluginInfo;
+import com.android.im.provider.Imps;
+
+public class ImPluginHelper {
+
+ private static final String TAG = "ImPluginUtils";
+
+ private Context mContext;
+ private ArrayList<ImPluginInfo> mPluginsInfo;
+ private ArrayList<ImPlugin> mPluginObjects;
+ private boolean mLoaded;
+
+ private static ImPluginHelper sInstance;
+ public static ImPluginHelper getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new ImPluginHelper(context);
+ }
+ return sInstance;
+ }
+
+ private ImPluginHelper(Context context) {
+ mContext = context;
+ mPluginsInfo = new ArrayList<ImPluginInfo>();
+ mPluginObjects = new ArrayList<ImPlugin>();
+ }
+
+ public ArrayList<ImPluginInfo> getPluginsInfo() {
+ if (!mLoaded) {
+ loadAvaiablePlugins();
+ }
+ return mPluginsInfo;
+ }
+
+ public ArrayList<ImPlugin> getPluginObjects() {
+ if (!mLoaded) {
+ loadAvaiablePlugins();
+ }
+ return mPluginObjects;
+ }
+
+ public void loadAvaiablePlugins() {
+ if (mLoaded) {
+ return;
+ }
+
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> plugins = pm.queryIntentServices(
+ new Intent(ImPluginConstants.PLUGIN_ACTION_NAME), PackageManager.GET_META_DATA);
+ for (ResolveInfo info : plugins) {
+ Log.d(TAG, "Found plugin " + info);
+
+ ServiceInfo serviceInfo = info.serviceInfo;
+ if (serviceInfo == null) {
+ Log.e(TAG, "Ignore bad IM plugin: " + info);
+ continue;
+ }
+ String providerName = null;
+ String providerFullName = null;
+ String signUpUrl = null;
+ Bundle metaData = serviceInfo.metaData;
+ if (metaData != null) {
+ providerName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_NAME);
+ providerFullName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_FULL_NAME);
+ signUpUrl = metaData.getString(ImPluginConstants.METADATA_SIGN_UP_URL);
+ }
+ if (TextUtils.isEmpty(providerName) || TextUtils.isEmpty(providerFullName)) {
+ Log.e(TAG, "Ignore bad IM plugin: " + info + ". Lack of required meta data");
+ continue;
+ }
+
+ if (isPluginDuplicated(providerName)) {
+ Log.e(TAG, "Ignore duplicated IM plugin: " + info);
+ continue;
+ }
+
+ if (!serviceInfo.packageName.equals(mContext.getPackageName())) {
+ Log.e(TAG, "Ignore plugin in package: " + serviceInfo.packageName);
+ continue;
+ }
+ ImPluginInfo pluginInfo = new ImPluginInfo(providerName, serviceInfo.packageName,
+ serviceInfo.name, serviceInfo.applicationInfo.sourceDir);
+
+ ImPlugin plugin = loadPlugin(pluginInfo);
+ if (plugin == null) {
+ Log.e(TAG, "Ignore bad IM plugin");
+ continue;
+ }
+
+ try {
+ updateProviderDb(plugin, pluginInfo,providerFullName, signUpUrl);
+ } catch (SQLiteFullException e) {
+ Log.e(TAG, "Storage full", e);
+ return;
+ }
+ mPluginsInfo.add(pluginInfo);
+ mPluginObjects.add(plugin);
+ }
+ mLoaded = true;
+ }
+
+ private boolean isPluginDuplicated(String providerName) {
+ for (ImPluginInfo plugin : mPluginsInfo) {
+ if (plugin.mProviderName.equals(providerName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private ImPlugin loadPlugin(ImPluginInfo pluginInfo) {
+ // XXX Load the plug-in implementation directly from the apk rather than
+ // binding to the service and call through IPC Binder API. This is much
+ // more effective since we don't need to start the service in other
+ // process. We can not run the plug-in service in the same process as a
+ // local service because that the interface is defined in a shared
+ // library in order to compile the plug-in separately. In this case, the
+ // interface will be loaded by two class loader separately and a
+ // ClassCastException will be thrown if we cast the binder to the
+ // interface.
+ ClassLoader loader = mContext.getClassLoader();
+ try {
+ Class<?> cls = loader.loadClass(pluginInfo.mClassName);
+ return (ImPlugin) cls.newInstance();
+ } catch (ClassNotFoundException e) {
+ Log.e(TAG, "Could not find plugin class", e);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Could not create plugin instance", e);
+ } catch (InstantiationException e) {
+ Log.e(TAG, "Could not create plugin instance", e);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Could not load plugin", e);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Could not load plugin", e);
+ }
+ return null;
+ }
+
+ private long updateProviderDb(ImPlugin plugin, ImPluginInfo info,
+ String providerFullName, String signUpUrl) {
+ Map<String, String> config = loadConfiguration(plugin, info);
+ if (config == null) {
+ return 0;
+ }
+
+ long providerId = 0;
+ ContentResolver cr = mContext.getContentResolver();
+ String where = Imps.Provider.NAME + "=?";
+ String[] selectionArgs = new String[]{info.mProviderName};
+ Cursor c = cr.query(Imps.Provider.CONTENT_URI,
+ null /* projection */,
+ where,
+ selectionArgs,
+ null /* sort order */);
+
+ boolean pluginChanged;
+ try {
+ if (c.moveToFirst()) {
+ providerId = c.getLong(c.getColumnIndexOrThrow(Imps.Provider._ID));
+ pluginChanged = isPluginChanged(cr, providerId, config);
+ if (pluginChanged) {
+ // Update the full name, signup url and category each time when the plugin change
+ // instead of specific version change because this is called only once.
+ // It's ok to update them even the values are not changed.
+ // Note that we don't update the provider name because it's used as
+ // identifier at some place and the plugin should never change it.
+ ContentValues values = new ContentValues(3);
+ values.put(Imps.Provider.FULLNAME, providerFullName);
+ values.put(Imps.Provider.SIGNUP_URL, signUpUrl);
+ values.put(Imps.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
+ Uri uri = ContentUris.withAppendedId(Imps.Provider.CONTENT_URI, providerId);
+ cr.update(uri, values, null, null);
+ }
+ } else {
+ ContentValues values = new ContentValues(3);
+ values.put(Imps.Provider.NAME, info.mProviderName);
+ values.put(Imps.Provider.FULLNAME, providerFullName);
+ values.put(Imps.Provider.CATEGORY, ImApp.IMPS_CATEGORY);
+ values.put(Imps.Provider.SIGNUP_URL, signUpUrl);
+
+ Uri result = cr.insert(Imps.Provider.CONTENT_URI, values);
+ providerId = ContentUris.parseId(result);
+ pluginChanged = true;
+ }
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+
+ if (pluginChanged) {
+ // Remove all the old settings
+ cr.delete(ContentUris.withAppendedId(
+ Imps.ProviderSettings.CONTENT_URI, providerId),
+ null, /*where*/
+ null /*selectionArgs*/);
+
+ ContentValues[] settingValues = new ContentValues[config.size()];
+
+ int index = 0;
+ for (Map.Entry<String, String> entry : config.entrySet()) {
+ ContentValues settingValue = new ContentValues();
+ settingValue.put(Imps.ProviderSettings.PROVIDER, providerId);
+ settingValue.put(Imps.ProviderSettings.NAME, entry.getKey());
+ settingValue.put(Imps.ProviderSettings.VALUE, entry.getValue());
+ settingValues[index++] = settingValue;
+ }
+ cr.bulkInsert(Imps.ProviderSettings.CONTENT_URI, settingValues);
+ }
+
+ return providerId;
+ }
+
+ private Map<String, String> loadConfiguration(ImPlugin plugin,
+ ImPluginInfo info) {
+ Map<String, String> config = null;
+
+ config = plugin.getProviderConfig();
+
+ if (config != null) {
+ config.put(ImConfigNames.PLUGIN_PATH, info.mSrcPath);
+ config.put(ImConfigNames.PLUGIN_CLASS, info.mClassName);
+ }
+ return config;
+ }
+
+ private boolean isPluginChanged(ContentResolver cr, long providerId,
+ Map<String, String> config) {
+ String origVersion = Imps.ProviderSettings.getStringValue(cr, providerId,
+ ImConfigNames.PLUGIN_VERSION);
+
+ if (origVersion == null) {
+ return true;
+ }
+ String newVersion = config.get(ImConfigNames.PLUGIN_VERSION);
+ return !origVersion.equals(newVersion);
+ }
+}
diff --git a/src/com/android/im/app/ImRingtonePreference.java b/src/com/android/im/app/ImRingtonePreference.java
index 9f89c61..59183e6 100644
--- a/src/com/android/im/app/ImRingtonePreference.java
+++ b/src/com/android/im/app/ImRingtonePreference.java
@@ -17,6 +17,7 @@
package com.android.im.app;
+import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
import android.app.Activity;
@@ -24,7 +25,6 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.preference.RingtonePreference;
-import android.provider.Im;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
@@ -47,7 +47,7 @@ public class ImRingtonePreference extends RingtonePreference {
@Override
protected Uri onRestoreRingtone() {
- final Im.ProviderSettings.QueryMap settings = new Im.ProviderSettings.QueryMap(
+ final Imps.ProviderSettings.QueryMap settings = new Imps.ProviderSettings.QueryMap(
getContext().getContentResolver(), mProviderId,
false /* keep updated */, null /* no handler */);
@@ -70,7 +70,7 @@ public class ImRingtonePreference extends RingtonePreference {
@Override
protected void onSaveRingtone(Uri ringtoneUri) {
- final Im.ProviderSettings.QueryMap settings = new Im.ProviderSettings.QueryMap(
+ final Imps.ProviderSettings.QueryMap settings = new Imps.ProviderSettings.QueryMap(
getContext().getContentResolver(), mProviderId,
false /* keep updated */, null /* no handler */);
diff --git a/src/com/android/im/app/ImUrlActivity.java b/src/com/android/im/app/ImUrlActivity.java
index a23a7fd..134a83f 100644
--- a/src/com/android/im/app/ImUrlActivity.java
+++ b/src/com/android/im/app/ImUrlActivity.java
@@ -20,6 +20,8 @@ import com.android.im.IChatSession;
import com.android.im.IChatSessionManager;
import com.android.im.IImConnection;
import com.android.im.engine.ImConnection;
+import com.android.im.provider.Imps;
+
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -29,7 +31,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
-import android.provider.Im;
import android.text.TextUtils;
import android.util.Log;
@@ -38,8 +39,8 @@ import java.util.Set;
public class ImUrlActivity extends Activity {
private static final String[] ACCOUNT_PROJECTION = {
- Im.Account._ID,
- Im.Account.PASSWORD,
+ Imps.Account._ID,
+ Imps.Account.PASSWORD,
};
private static final int ACCOUNT_ID_COLUMN = 0;
private static final int ACCOUNT_PW_COLUMN = 1;
@@ -78,7 +79,7 @@ public class ImUrlActivity extends Activity {
void handleIntent() {
ContentResolver cr = getContentResolver();
- long providerId = Im.Provider.getProviderIdForName(cr, mProviderName);
+ long providerId = Imps.Provider.getProviderIdForName(cr, mProviderName);
long accountId;
mConn= mApp.getConnection(providerId);
@@ -119,13 +120,13 @@ public class ImUrlActivity extends Activity {
private void addAccount(long providerId) {
Intent intent = new Intent(this, AccountActivity.class);
intent.setAction(Intent.ACTION_INSERT);
- intent.setData(ContentUris.withAppendedId(Im.Provider.CONTENT_URI, providerId));
+ intent.setData(ContentUris.withAppendedId(Imps.Provider.CONTENT_URI, providerId));
intent.putExtra(ImApp.EXTRA_INTENT_SEND_TO_USER, mToAddress);
startActivity(intent);
}
private void editAccount(long accountId) {
- Uri accountUri = ContentUris.withAppendedId(Im.Account.CONTENT_URI, accountId);
+ Uri accountUri = ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId);
Intent intent = new Intent(this, AccountActivity.class);
intent.setAction(Intent.ACTION_EDIT);
intent.setData(accountUri);
@@ -134,7 +135,7 @@ public class ImUrlActivity extends Activity {
}
private void signInAccount(long accountId) {
- Uri accountUri = ContentUris.withAppendedId(Im.Account.CONTENT_URI, accountId);
+ Uri accountUri = ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId);
Intent intent = new Intent(this, SigningInActivity.class);
intent.setData(accountUri);
intent.putExtra(ImApp.EXTRA_INTENT_SEND_TO_USER, mToAddress);
@@ -143,7 +144,7 @@ public class ImUrlActivity extends Activity {
private void showContactList(long accountId) {
Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Im.Contacts.CONTENT_URI);
+ intent.setData(Imps.Contacts.CONTENT_URI);
intent.addCategory(ImApp.IMPS_CATEGORY);
intent.putExtra("accountId", accountId);
@@ -158,7 +159,7 @@ public class ImUrlActivity extends Activity {
session = manager.createChatSession(mToAddress);
}
- Uri data = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, session.getId());
+ Uri data = ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, session.getId());
Intent i = new Intent(Intent.ACTION_VIEW, data);
i.putExtra("from", mToAddress);
i.putExtra("providerId", provider);
@@ -225,11 +226,11 @@ public class ImUrlActivity extends Activity {
private String getProviderNameForCategory(String providerCategory) {
if (providerCategory != null) {
if (providerCategory.equalsIgnoreCase("com.android.im.category.AIM")) {
- return Im.ProviderNames.AIM;
+ return Imps.ProviderNames.AIM;
} else if (providerCategory.equalsIgnoreCase("com.android.im.category.MSN")) {
- return Im.ProviderNames.MSN;
+ return Imps.ProviderNames.MSN;
} else if (providerCategory.equalsIgnoreCase("com.android.im.category.YAHOO")) {
- return Im.ProviderNames.YAHOO;
+ return Imps.ProviderNames.YAHOO;
}
}
@@ -241,16 +242,16 @@ public class ImUrlActivity extends Activity {
return null;
}
- if (Im.ProviderNames.AIM.equalsIgnoreCase(provider)) {
- return Im.ProviderNames.AIM;
+ if (Imps.ProviderNames.AIM.equalsIgnoreCase(provider)) {
+ return Imps.ProviderNames.AIM;
}
- if (Im.ProviderNames.MSN.equalsIgnoreCase(provider)) {
- return Im.ProviderNames.MSN;
+ if (Imps.ProviderNames.MSN.equalsIgnoreCase(provider)) {
+ return Imps.ProviderNames.MSN;
}
- if (Im.ProviderNames.YAHOO.equalsIgnoreCase(provider)) {
- return Im.ProviderNames.YAHOO;
+ if (Imps.ProviderNames.YAHOO.equalsIgnoreCase(provider)) {
+ return Imps.ProviderNames.YAHOO;
}
return null;
diff --git a/src/com/android/im/app/LandingPage.java b/src/com/android/im/app/LandingPage.java
new file mode 100644
index 0000000..3c9ac99
--- /dev/null
+++ b/src/com/android/im/app/LandingPage.java
@@ -0,0 +1,459 @@
+/*
+ * 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.im.app;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ListActivity;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.AdapterView;
+import android.widget.CursorAdapter;
+import android.widget.ListView;
+
+import com.android.im.IImConnection;
+import com.android.im.R;
+import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
+
+public class LandingPage extends ListActivity implements View.OnCreateContextMenuListener {
+ private static final String TAG = ImApp.LOG_TAG;
+
+ private static final int ID_SIGN_IN = Menu.FIRST + 1;
+ private static final int ID_SIGN_OUT = Menu.FIRST + 2;
+ private static final int ID_EDIT_ACCOUNT = Menu.FIRST + 3;
+ private static final int ID_REMOVE_ACCOUNT = Menu.FIRST + 4;
+ private static final int ID_SIGN_OUT_ALL = Menu.FIRST + 5;
+ private static final int ID_ADD_ACCOUNT = Menu.FIRST + 6;
+ private static final int ID_VIEW_CONTACT_LIST = Menu.FIRST + 7;
+ private static final int ID_SETTINGS = Menu.FIRST + 8;
+
+ private ProviderAdapter mAdapter;
+ private Cursor mProviderCursor;
+ private ImApp mApp;
+ private SimpleAlertHandler mHandler;
+
+ private static final String[] PROVIDER_PROJECTION = {
+ Imps.Provider._ID,
+ Imps.Provider.NAME,
+ Imps.Provider.FULLNAME,
+ Imps.Provider.CATEGORY,
+ Imps.Provider.ACTIVE_ACCOUNT_ID,
+ Imps.Provider.ACTIVE_ACCOUNT_USERNAME,
+ Imps.Provider.ACTIVE_ACCOUNT_PW,
+ Imps.Provider.ACTIVE_ACCOUNT_LOCKED,
+ Imps.Provider.ACTIVE_ACCOUNT_KEEP_SIGNED_IN,
+ Imps.Provider.ACCOUNT_PRESENCE_STATUS,
+ Imps.Provider.ACCOUNT_CONNECTION_STATUS,
+ };
+
+ static final int PROVIDER_ID_COLUMN = 0;
+ static final int PROVIDER_NAME_COLUMN = 1;
+ static final int PROVIDER_FULLNAME_COLUMN = 2;
+ static final int PROVIDER_CATEGORY_COLUMN = 3;
+ static final int ACTIVE_ACCOUNT_ID_COLUMN = 4;
+ static final int ACTIVE_ACCOUNT_USERNAME_COLUMN = 5;
+ static final int ACTIVE_ACCOUNT_PW_COLUMN = 6;
+ static final int ACTIVE_ACCOUNT_LOCKED = 7;
+ static final int ACTIVE_ACCOUNT_KEEP_SIGNED_IN = 8;
+ static final int ACCOUNT_PRESENCE_STATUS = 9;
+ static final int ACCOUNT_CONNECTION_STATUS = 10;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setTitle(R.string.landing_page_title);
+
+ mApp = ImApp.getApplication(this);
+ mHandler = new MyHandler(this);
+
+ ImPluginHelper.getInstance(this).loadAvaiablePlugins();
+
+ mProviderCursor = managedQuery(Imps.Provider.CONTENT_URI_WITH_ACCOUNT,
+ PROVIDER_PROJECTION,
+ Imps.Provider.CATEGORY + "=?" /* selection */,
+ new String[]{ ImApp.IMPS_CATEGORY } /* selection args */,
+ Imps.Provider.DEFAULT_SORT_ORDER);
+ mAdapter = new ProviderAdapter(this, mProviderCursor);
+ setListAdapter(mAdapter);
+
+ registerForContextMenu(getListView());
+ }
+
+
+ @Override
+ protected void onPause() {
+ mHandler.unregisterForBroadcastEvents();
+
+ super.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ mHandler.registerForBroadcastEvents();
+ }
+
+ private void signIn(long accountId) {
+ if (accountId == 0) {
+ Log.w(TAG, "signIn: account id is 0, bail");
+ return;
+ }
+
+ boolean isAccountEditible = mProviderCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
+ if (isAccountEditible && mProviderCursor.isNull(ACTIVE_ACCOUNT_PW_COLUMN)) {
+ // no password, edit the account
+ if (Log.isLoggable(TAG, Log.DEBUG)) log("no pw for account " + accountId);
+ Intent intent = getEditAccountIntent();
+ startActivity(intent);
+ return;
+ }
+
+ Intent intent = new Intent(this, SigningInActivity.class);
+ intent.setData(ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId));
+ startActivity(intent);
+ }
+
+ boolean isSigningIn(Cursor cursor) {
+ int connectionStatus = cursor.getInt(ACCOUNT_CONNECTION_STATUS);
+ return connectionStatus == Imps.ConnectionStatus.CONNECTING;
+ }
+
+ private boolean isSignedIn(Cursor cursor) {
+ int connectionStatus = cursor.getInt(ACCOUNT_CONNECTION_STATUS);
+ return connectionStatus == Imps.ConnectionStatus.ONLINE;
+ }
+
+ private boolean allAccountsSignedOut() {
+ if(!mProviderCursor.moveToFirst()) {
+ return false;
+ }
+ do {
+ if (isSignedIn(mProviderCursor)) {
+ return false;
+ }
+ } while (mProviderCursor.moveToNext()) ;
+
+ return true;
+ }
+
+ private void signoutAll() {
+ DialogInterface.OnClickListener confirmListener
+ = new DialogInterface.OnClickListener(){
+ public void onClick(DialogInterface dialog, int whichButton) {
+ do {
+ long accountId = mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);
+ signOut(accountId);
+ } while (mProviderCursor.moveToNext()) ;
+ }
+ };
+
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.confirm)
+ .setMessage(R.string.signout_all_confirm_message)
+ .setPositiveButton(R.string.yes, confirmListener) // default button
+ .setNegativeButton(R.string.no, null)
+ .setCancelable(true)
+ .show();
+ }
+
+ private void signOut(long accountId) {
+ if (accountId == 0) {
+ Log.w(TAG, "signOut: account id is 0, bail");
+ return;
+ }
+
+ try {
+ IImConnection conn = mApp.getConnectionByAccount(accountId);
+ if (conn != null) {
+ conn.logout();
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "signOut failed", ex);
+ }
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ menu.findItem(ID_SIGN_OUT_ALL).setVisible(!allAccountsSignedOut());
+ return true;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add(0, ID_SIGN_OUT_ALL, 0, R.string.menu_sign_out_all)
+ .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case ID_SIGN_OUT_ALL:
+ signoutAll();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+ AdapterView.AdapterContextMenuInfo info;
+ try {
+ info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ } catch (ClassCastException e) {
+ Log.e(TAG, "bad menuInfo", e);
+ return;
+ }
+
+ Cursor providerCursor = (Cursor) getListAdapter().getItem(info.position);
+ menu.setHeaderTitle(providerCursor.getString(PROVIDER_FULLNAME_COLUMN));
+
+ if (providerCursor.isNull(ACTIVE_ACCOUNT_ID_COLUMN)) {
+ menu.add(0, ID_ADD_ACCOUNT, 0, R.string.menu_add_account);
+ return;
+ }
+
+ long providerId = providerCursor.getLong(PROVIDER_ID_COLUMN);
+ boolean isLoggingIn = isSigningIn(providerCursor);
+ boolean isLoggedIn = isSignedIn(providerCursor);
+
+ BrandingResources brandingRes = mApp.getBrandingResource(providerId);
+ if (!isLoggedIn) {
+ menu.add(0, ID_SIGN_IN, 0, R.string.sign_in).setIcon(com.android.internal.R.drawable.ic_menu_login);
+ } else {
+ menu.add(0, ID_VIEW_CONTACT_LIST, 0,
+ brandingRes.getString(BrandingResourceIDs.STRING_MENU_CONTACT_LIST));
+ menu.add(0, ID_SIGN_OUT, 0, R.string.menu_sign_out)
+ .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
+ }
+
+ boolean isAccountEditible = providerCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
+ if (isAccountEditible && !isLoggingIn && !isLoggedIn) {
+ menu.add(0, ID_EDIT_ACCOUNT, 0, R.string.menu_edit_account)
+ .setIcon(android.R.drawable.ic_menu_edit);
+ menu.add(0, ID_REMOVE_ACCOUNT, 0, R.string.menu_remove_account)
+ .setIcon(android.R.drawable.ic_menu_delete);
+ }
+
+ // always add a settings menu item
+ menu.add(0, ID_SETTINGS, 0, R.string.menu_settings);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ AdapterView.AdapterContextMenuInfo info;
+ try {
+ info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
+ } catch (ClassCastException e) {
+ Log.e(TAG, "bad menuInfo", e);
+ return false;
+ }
+ long providerId = info.id;
+ Cursor providerCursor = (Cursor) getListAdapter().getItem(info.position);
+ long accountId = providerCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);
+
+ switch (item.getItemId()) {
+ case ID_EDIT_ACCOUNT:
+ {
+ startActivity(getEditAccountIntent());
+ return true;
+ }
+
+ case ID_REMOVE_ACCOUNT:
+ {
+ Uri accountUri = ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId);
+ getContentResolver().delete(accountUri, null, null);
+ // Requery the cursor to force refreshing screen
+ providerCursor.requery();
+ return true;
+ }
+
+ case ID_VIEW_CONTACT_LIST:
+ {
+ Intent intent = getViewContactsIntent();
+ startActivity(intent);
+ return true;
+ }
+ case ID_ADD_ACCOUNT:
+ {
+ startActivity(getCreateAccountIntent());
+ return true;
+ }
+
+ case ID_SIGN_IN:
+ {
+ signIn(accountId);
+ return true;
+ }
+
+ case ID_SIGN_OUT:
+ {
+ // TODO: progress bar
+ signOut(accountId);
+ return true;
+ }
+
+ case ID_SETTINGS:
+ {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Imps.ProviderSettings.CONTENT_URI);
+ intent.addCategory(getProviderCategory(providerCursor));
+ intent.putExtra("providerId", providerId);
+ startActivity(intent);
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
+ @Override
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Intent intent = null;
+ mProviderCursor.moveToPosition(position);
+
+ if (mProviderCursor.isNull(ACTIVE_ACCOUNT_ID_COLUMN)) {
+ // add account
+ intent = getCreateAccountIntent();
+ } else {
+ int state = mProviderCursor.getInt(ACCOUNT_CONNECTION_STATUS);
+ long accountId = mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);
+
+ if (state == Imps.ConnectionStatus.OFFLINE) {
+ boolean isKeepSignedIn = mProviderCursor.getInt(ACTIVE_ACCOUNT_KEEP_SIGNED_IN) != 0;
+ boolean isAccountEditible = mProviderCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
+ if (isKeepSignedIn) {
+ signIn(accountId);
+ } else if(isAccountEditible) {
+ intent = getEditAccountIntent();
+ }
+ } else if (state == Imps.ConnectionStatus.CONNECTING) {
+ signIn(accountId);
+ } else {
+ intent = getViewContactsIntent();
+ }
+ }
+
+ if (intent != null) {
+ startActivity(intent);
+ }
+ }
+
+ Intent getCreateAccountIntent() {
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_INSERT);
+
+ long providerId = mProviderCursor.getLong(PROVIDER_ID_COLUMN);
+ intent.setData(ContentUris.withAppendedId(Imps.Provider.CONTENT_URI, providerId));
+ intent.addCategory(getProviderCategory(mProviderCursor));
+ return intent;
+ }
+
+ Intent getEditAccountIntent() {
+ Intent intent = new Intent(Intent.ACTION_EDIT,
+ ContentUris.withAppendedId(Imps.Account.CONTENT_URI,
+ mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN)));
+ intent.addCategory(getProviderCategory(mProviderCursor));
+ return intent;
+ }
+
+ Intent getViewContactsIntent() {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Imps.Contacts.CONTENT_URI);
+ intent.addCategory(getProviderCategory(mProviderCursor));
+ intent.putExtra("accountId", mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN));
+ return intent;
+ }
+
+ private String getProviderCategory(Cursor cursor) {
+ return cursor.getString(PROVIDER_CATEGORY_COLUMN);
+ }
+
+ static void log(String msg) {
+ Log.d(TAG, "[LandingPage]" + msg);
+ }
+
+ private class ProviderListItemFactory implements LayoutInflater.Factory {
+ public View onCreateView(String name, Context context, AttributeSet attrs) {
+ if (name != null && name.equals(ProviderListItem.class.getName())) {
+ return new ProviderListItem(context, LandingPage.this);
+ }
+ return null;
+ }
+ }
+
+ private final class ProviderAdapter extends CursorAdapter {
+ private LayoutInflater mInflater;
+
+ public ProviderAdapter(Context context, Cursor c) {
+ super(context, c);
+ mInflater = LayoutInflater.from(context).cloneInContext(context);
+ mInflater.setFactory(new ProviderListItemFactory());
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ // create a custom view, so we can manage it ourselves. Mainly, we want to
+ // initialize the widget views (by calling getViewById()) in newView() instead of in
+ // bindView(), which can be called more often.
+ ProviderListItem view = (ProviderListItem) mInflater.inflate(
+ R.layout.account_view, parent, false);
+ view.init(cursor);
+ return view;
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ ((ProviderListItem) view).bindView(cursor);
+ }
+ }
+
+ private final static class MyHandler extends SimpleAlertHandler {
+
+ public MyHandler(Activity activity) {
+ super(activity);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == ImApp.EVENT_CONNECTION_DISCONNECTED) {
+ promptDisconnectedEvent(msg);
+ }
+ super.handleMessage(msg);
+ }
+ }
+}
diff --git a/src/com/android/im/app/MessageView.java b/src/com/android/im/app/MessageView.java
index 9a42cbb..5e2424f 100644
--- a/src/com/android/im/app/MessageView.java
+++ b/src/com/android/im/app/MessageView.java
@@ -23,7 +23,6 @@ import java.util.Date;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
-import android.provider.Im;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
@@ -36,6 +35,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.im.R;
+import com.android.im.provider.Imps;
public class MessageView extends LinearLayout {
@@ -132,20 +132,20 @@ public class MessageView extends LinearLayout {
boolean isGroupChat, boolean scrolling) {
String body;
switch (type) {
- case Im.MessageType.PRESENCE_AVAILABLE:
+ case Imps.MessageType.PRESENCE_AVAILABLE:
body = mResources.getString(isGroupChat ? R.string.contact_joined
: R.string.contact_online, contact);
break;
- case Im.MessageType.PRESENCE_AWAY:
+ case Imps.MessageType.PRESENCE_AWAY:
body = mResources.getString(R.string.contact_away, contact);
break;
- case Im.MessageType.PRESENCE_DND:
+ case Imps.MessageType.PRESENCE_DND:
body = mResources.getString(R.string.contact_busy, contact);
break;
- case Im.MessageType.PRESENCE_UNAVAILABLE:
+ case Imps.MessageType.PRESENCE_UNAVAILABLE:
body = mResources.getString(isGroupChat ? R.string.contact_left
: R.string.contact_offline, contact);
break;
diff --git a/src/com/android/im/app/NewChatActivity.java b/src/com/android/im/app/NewChatActivity.java
index 62f1790..d8c6c1d 100644
--- a/src/com/android/im/app/NewChatActivity.java
+++ b/src/com/android/im/app/NewChatActivity.java
@@ -26,6 +26,7 @@ import com.android.im.IChatSession;
import com.android.im.R;
import com.android.im.app.adapter.ChatListenerAdapter;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
import android.app.Activity;
import android.app.AlertDialog;
@@ -39,7 +40,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
-import android.provider.Im;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -134,9 +134,9 @@ public class NewChatActivity extends Activity {
} else {
Uri data = intent.getData();
String type = getContentResolver().getType(data);
- if (Im.Chats.CONTENT_ITEM_TYPE.equals(type)) {
+ if (Imps.Chats.CONTENT_ITEM_TYPE.equals(type)) {
mChatView.bindChat(ContentUris.parseId(data));
- } else if (Im.Invitation.CONTENT_ITEM_TYPE.equals(type)) {
+ } else if (Imps.Invitation.CONTENT_ITEM_TYPE.equals(type)) {
mChatView.bindInvitation(ContentUris.parseId(data));
}
}
@@ -173,8 +173,8 @@ public class NewChatActivity extends Activity {
//XXX HACK: Yahoo! doesn't allow to block a friend. We can only block a temporary contact.
ProviderDef provider = mApp.getProvider(mChatView.getProviderId());
- if ((provider != null) && Im.ProviderNames.YAHOO.equals(provider.mName)) {
- if (Im.Contacts.TYPE_TEMPORARY != mChatView.mType) {
+ if ((provider != null) && Imps.ProviderNames.YAHOO.equals(provider.mName)) {
+ if (Imps.Contacts.TYPE_TEMPORARY != mChatView.mType) {
menu.findItem(R.id.menu_block_contact).setVisible(false);
}
}
@@ -347,7 +347,7 @@ public class NewChatActivity extends Activity {
}
private void startContactPicker() {
- Uri.Builder builder = Im.Contacts.CONTENT_URI_ONLINE_CONTACTS_BY.buildUpon();
+ Uri.Builder builder = Imps.Contacts.CONTENT_URI_ONLINE_CONTACTS_BY.buildUpon();
ContentUris.appendId(builder, mChatView.getProviderId());
ContentUris.appendId(builder, mChatView.getAccountId());
Uri data = builder.build();
diff --git a/src/com/android/im/app/PreferenceActivity.java b/src/com/android/im/app/PreferenceActivity.java
index 99e3f6e..14215ec 100644
--- a/src/com/android/im/app/PreferenceActivity.java
+++ b/src/com/android/im/app/PreferenceActivity.java
@@ -24,7 +24,6 @@ import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
-import android.provider.Im;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -37,6 +36,7 @@ import com.android.im.imps.ImpsConnectionConfig.EncodingType;
import com.android.im.imps.ImpsConnectionConfig.TransportType;
import com.android.im.plugin.ImConfigNames;
import com.android.im.plugin.ImpsConfigNames;
+import com.android.im.provider.Imps;
public class PreferenceActivity extends Activity {
@@ -121,7 +121,7 @@ public class PreferenceActivity extends Activity {
finish();
} else {
Cursor c = getContentResolver().query(i.getData(),
- new String[]{Im.Provider._ID, Im.Provider.NAME}, null, null, null);
+ new String[]{Imps.Provider._ID, Imps.Provider.NAME}, null, null, null);
if (c == null || !c.moveToFirst()) {
Log.w(ImApp.LOG_TAG, "Can't query data from given URI.");
finish();
@@ -131,7 +131,7 @@ public class PreferenceActivity extends Activity {
c.close();
- mPref = Im.ProviderSettings.queryProviderSettings(getContentResolver(), mProviderId);
+ mPref = Imps.ProviderSettings.queryProviderSettings(getContentResolver(), mProviderId);
}
}
}
@@ -203,16 +203,16 @@ public class PreferenceActivity extends Activity {
valuesList[4] = getValues(ImpsConfigNames.HOST, host);
valuesList[6] = getValues(ImpsConfigNames.MSISDN, msisdn);
- getContentResolver().bulkInsert(Im.ProviderSettings.CONTENT_URI, valuesList);
+ getContentResolver().bulkInsert(Imps.ProviderSettings.CONTENT_URI, valuesList);
finish();
}
private ContentValues getValues(String name, String value) {
ContentValues values = new ContentValues();
- values.put(Im.ProviderSettings.PROVIDER, mProviderId);
- values.put(Im.ProviderSettings.NAME, name);
- values.put(Im.ProviderSettings.VALUE, value);
+ values.put(Imps.ProviderSettings.PROVIDER, mProviderId);
+ values.put(Imps.ProviderSettings.NAME, name);
+ values.put(Imps.ProviderSettings.VALUE, value);
return values;
}
diff --git a/src/com/android/im/app/PresenceUtils.java b/src/com/android/im/app/PresenceUtils.java
index dcc806c..49861e6 100644
--- a/src/com/android/im/app/PresenceUtils.java
+++ b/src/com/android/im/app/PresenceUtils.java
@@ -16,11 +16,11 @@
*/
package com.android.im.app;
-import android.provider.Im;
import android.util.Log;
import com.android.im.engine.Presence;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
public final class PresenceUtils {
private PresenceUtils() {}
@@ -28,44 +28,44 @@ public final class PresenceUtils {
public static int convertStatus(int status) {
switch (status) {
case Presence.AVAILABLE:
- return Im.Presence.AVAILABLE;
+ return Imps.Presence.AVAILABLE;
case Presence.AWAY:
- return Im.Presence.AWAY;
+ return Imps.Presence.AWAY;
case Presence.DO_NOT_DISTURB:
- return Im.Presence.DO_NOT_DISTURB;
+ return Imps.Presence.DO_NOT_DISTURB;
case Presence.IDLE:
- return Im.Presence.IDLE;
+ return Imps.Presence.IDLE;
case Presence.OFFLINE:
- return Im.Presence.OFFLINE;
+ return Imps.Presence.OFFLINE;
default:
Log.w(ImApp.LOG_TAG, "[ContactView] Unknown presence status " + status);
- return Im.Presence.AVAILABLE;
+ return Imps.Presence.AVAILABLE;
}
}
public static int getStatusStringRes(int status) {
switch (status) {
- case Im.Presence.AVAILABLE:
+ case Imps.Presence.AVAILABLE:
return BrandingResourceIDs.STRING_PRESENCE_AVAILABLE;
- case Im.Presence.AWAY:
+ case Imps.Presence.AWAY:
return BrandingResourceIDs.STRING_PRESENCE_AWAY;
- case Im.Presence.DO_NOT_DISTURB:
+ case Imps.Presence.DO_NOT_DISTURB:
return BrandingResourceIDs.STRING_PRESENCE_BUSY;
- case Im.Presence.IDLE:
+ case Imps.Presence.IDLE:
return BrandingResourceIDs.STRING_PRESENCE_IDLE;
- case Im.Presence.INVISIBLE:
+ case Imps.Presence.INVISIBLE:
return BrandingResourceIDs.STRING_PRESENCE_INVISIBLE;
- case Im.Presence.OFFLINE:
+ case Imps.Presence.OFFLINE:
return BrandingResourceIDs.STRING_PRESENCE_OFFLINE;
default:
@@ -75,19 +75,19 @@ public final class PresenceUtils {
public static int getStatusIconId(int status) {
switch (status) {
- case Im.Presence.AVAILABLE:
+ case Imps.Presence.AVAILABLE:
return BrandingResourceIDs.DRAWABLE_PRESENCE_ONLINE;
- case Im.Presence.IDLE:
+ case Imps.Presence.IDLE:
return BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY;
- case Im.Presence.AWAY:
+ case Imps.Presence.AWAY:
return BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY;
- case Im.Presence.DO_NOT_DISTURB:
+ case Imps.Presence.DO_NOT_DISTURB:
return BrandingResourceIDs.DRAWABLE_PRESENCE_BUSY;
- case Im.Presence.INVISIBLE:
+ case Imps.Presence.INVISIBLE:
return BrandingResourceIDs.DRAWABLE_PRESENCE_INVISIBLE;
default:
diff --git a/src/com/android/im/app/ProviderListItem.java b/src/com/android/im/app/ProviderListItem.java
new file mode 100644
index 0000000..00679d4
--- /dev/null
+++ b/src/com/android/im/app/ProviderListItem.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2009 Myriad Group AG
+ * 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.im.app;
+
+import com.android.im.R;
+import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
+
+import android.graphics.drawable.Drawable;
+import android.widget.LinearLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.content.Context;
+import android.content.ContentResolver;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.content.res.ColorStateList;
+import android.view.View;
+import android.util.Log;
+
+public class ProviderListItem extends LinearLayout {
+ private static final String TAG = "IM";
+ private static final boolean LOCAL_DEBUG = false;
+
+ private LandingPage mActivity;
+ private ImageView mProviderIcon;
+ private ImageView mStatusIcon;
+ private TextView mProviderName;
+ private TextView mLoginName;
+ private TextView mChatView;
+ private View mUnderBubble;
+ private Drawable mBubbleDrawable, mDefaultBackground;
+
+ private int mProviderIdColumn;
+ private int mProviderFullnameColumn;
+ private int mActiveAccountIdColumn;
+ private int mActiveAccountUserNameColumn;
+ private int mAccountPresenceStatusColumn;
+ private int mAccountConnectionStatusColumn;
+
+ private ColorStateList mProviderNameColors;
+ private ColorStateList mLoginNameColors;
+ private ColorStateList mChatViewColors;
+
+ public ProviderListItem(Context context, LandingPage activity) {
+ super(context);
+ mActivity = activity;
+ }
+
+ public void init(Cursor c) {
+ mProviderIcon = (ImageView) findViewById(R.id.providerIcon);
+ mStatusIcon = (ImageView) findViewById(R.id.statusIcon);
+ mProviderName = (TextView) findViewById(R.id.providerName);
+ mLoginName = (TextView) findViewById(R.id.loginName);
+ mChatView = (TextView) findViewById(R.id.conversations);
+ mUnderBubble = findViewById(R.id.underBubble);
+ mBubbleDrawable = getResources().getDrawable(R.drawable.bubble);
+ mDefaultBackground = getResources().getDrawable(R.drawable.default_background);
+
+ mProviderIdColumn = c.getColumnIndexOrThrow(Imps.Provider._ID);
+ mProviderFullnameColumn = c.getColumnIndexOrThrow(Imps.Provider.FULLNAME);
+ mActiveAccountIdColumn = c.getColumnIndexOrThrow(
+ Imps.Provider.ACTIVE_ACCOUNT_ID);
+ mActiveAccountUserNameColumn = c.getColumnIndexOrThrow(
+ Imps.Provider.ACTIVE_ACCOUNT_USERNAME);
+ mAccountPresenceStatusColumn = c.getColumnIndexOrThrow(
+ Imps.Provider.ACCOUNT_PRESENCE_STATUS);
+ mAccountConnectionStatusColumn = c.getColumnIndexOrThrow(
+ Imps.Provider.ACCOUNT_CONNECTION_STATUS);
+
+ mProviderNameColors = mProviderName.getTextColors();
+ mLoginNameColors = mLoginName.getTextColors();
+ mChatViewColors = mChatView.getTextColors();
+ }
+
+ public void bindView(Cursor cursor) {
+ Resources r = getResources();
+ ImageView providerIcon = mProviderIcon;
+ ImageView statusIcon = mStatusIcon;
+ TextView providerName = mProviderName;
+ TextView loginName = mLoginName;
+ TextView chatView = mChatView;
+
+ int providerId = cursor.getInt(mProviderIdColumn);
+ String providerDisplayName = cursor.getString(mProviderFullnameColumn);
+
+ ImApp app = ImApp.getApplication(mActivity);
+ BrandingResources brandingRes = app.getBrandingResource(providerId);
+ providerIcon.setImageDrawable(
+ brandingRes.getDrawable(BrandingResourceIDs.DRAWABLE_LOGO));
+
+ mUnderBubble.setBackgroundDrawable(mDefaultBackground);
+ statusIcon.setVisibility(View.GONE);
+
+ providerName.setTextColor(mProviderNameColors);
+ loginName.setTextColor(mLoginNameColors);
+ chatView.setTextColor(mChatViewColors);
+
+ if (!cursor.isNull(mActiveAccountIdColumn)) {
+ mLoginName.setVisibility(View.VISIBLE);
+ providerName.setVisibility(View.VISIBLE);
+ providerName.setText(providerDisplayName);
+
+ long accountId = cursor.getLong(mActiveAccountIdColumn);
+ int connectionStatus = cursor.getInt(mAccountConnectionStatusColumn);
+
+ String secondRowText;
+
+ chatView.setVisibility(View.GONE);
+
+ switch (connectionStatus) {
+ case Imps.ConnectionStatus.CONNECTING:
+ secondRowText = r.getString(R.string.signing_in_wait);
+ break;
+
+ case Imps.ConnectionStatus.ONLINE:
+ int presenceIconId = getPresenceIconId(cursor);
+ statusIcon.setImageDrawable(
+ brandingRes.getDrawable(presenceIconId));
+ statusIcon.setVisibility(View.VISIBLE);
+ ContentResolver cr = mActivity.getContentResolver();
+
+ int count = getConversationCount(cr, accountId);
+ if (count > 0) {
+ mUnderBubble.setBackgroundDrawable(mBubbleDrawable);
+ chatView.setVisibility(View.VISIBLE);
+ chatView.setText(r.getString(R.string.conversations, count));
+
+ providerName.setTextColor(0xff000000);
+ loginName.setTextColor(0xff000000);
+ chatView.setTextColor(0xff000000);
+ } else {
+ chatView.setVisibility(View.GONE);
+ }
+
+ secondRowText = cursor.getString(mActiveAccountUserNameColumn);
+ break;
+
+ default:
+ secondRowText = cursor.getString(mActiveAccountUserNameColumn);
+ break;
+ }
+
+ loginName.setText(secondRowText);
+
+ } else {
+ // No active account, show add account
+ mLoginName.setVisibility(View.GONE);
+ mChatView.setVisibility(View.GONE);
+ mProviderName.setText(providerDisplayName);
+ }
+ }
+
+ private int getConversationCount(ContentResolver cr, long accountId) {
+ // TODO: this is code used to get Google Talk's chat count. Not sure if this will work
+ // for IMPS chat count.
+ StringBuilder where = new StringBuilder();
+ where.append(Imps.Chats.CONTACT_ID);
+ where.append(" in (select _id from contacts where ");
+ where.append(Imps.Contacts.ACCOUNT);
+ where.append("=");
+ where.append(accountId);
+ where.append(")");
+
+ Cursor cursor = cr.query(Imps.Chats.CONTENT_URI, null, where.toString(), null, null);
+
+ try {
+ return cursor.getCount();
+ } finally {
+ cursor.close();
+ }
+ }
+
+ private int getPresenceIconId(Cursor cursor) {
+ int presenceStatus = cursor.getInt(mAccountPresenceStatusColumn);
+
+ if (LOCAL_DEBUG) log("getPresenceIconId: presenceStatus=" + presenceStatus);
+
+ switch (presenceStatus) {
+ case Imps.Presence.AVAILABLE:
+ return BrandingResourceIDs.DRAWABLE_PRESENCE_ONLINE;
+
+ case Imps.Presence.IDLE:
+ case Imps.Presence.AWAY:
+ return BrandingResourceIDs.DRAWABLE_PRESENCE_AWAY;
+
+ case Imps.Presence.DO_NOT_DISTURB:
+ return BrandingResourceIDs.DRAWABLE_PRESENCE_BUSY;
+
+ case Imps.Presence.INVISIBLE:
+ return BrandingResourceIDs.DRAWABLE_PRESENCE_INVISIBLE;
+
+ default:
+ return BrandingResourceIDs.DRAWABLE_PRESENCE_OFFLINE;
+ }
+ }
+
+ private void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/src/com/android/im/app/SettingActivity.java b/src/com/android/im/app/SettingActivity.java
index 1a5f73b..5e16c36 100644
--- a/src/com/android/im/app/SettingActivity.java
+++ b/src/com/android/im/app/SettingActivity.java
@@ -22,10 +22,10 @@ import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.preference.CheckBoxPreference;
-import android.provider.Im;
import android.util.Log;
import com.android.im.R;
+import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
public class SettingActivity extends android.preference.PreferenceActivity {
@@ -50,7 +50,7 @@ public class SettingActivity extends android.preference.PreferenceActivity {
}
private void setInitialValues() {
- Im.ProviderSettings.QueryMap settings = new Im.ProviderSettings.QueryMap(
+ Imps.ProviderSettings.QueryMap settings = new Imps.ProviderSettings.QueryMap(
getContentResolver(), mProviderId,
false /* keep updated */, null /* no handler */);
@@ -71,7 +71,7 @@ public class SettingActivity extends android.preference.PreferenceActivity {
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference instanceof CheckBoxPreference) {
- final Im.ProviderSettings.QueryMap settings = new Im.ProviderSettings.QueryMap(
+ final Imps.ProviderSettings.QueryMap settings = new Imps.ProviderSettings.QueryMap(
getContentResolver(), mProviderId,
false /* keep updated */, null /* no handler */);
String key = preference.getKey();
diff --git a/src/com/android/im/app/SigningInActivity.java b/src/com/android/im/app/SigningInActivity.java
index bcd7825..1e42645 100644
--- a/src/com/android/im/app/SigningInActivity.java
+++ b/src/com/android/im/app/SigningInActivity.java
@@ -25,6 +25,7 @@ import com.android.im.app.adapter.ConnectionListenerAdapter;
import com.android.im.engine.ImConnection;
import com.android.im.engine.ImErrorInfo;
import com.android.im.plugin.BrandingResourceIDs;
+import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
import android.app.Activity;
@@ -40,7 +41,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.Handler;
-import android.provider.Im;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -102,13 +102,13 @@ public class SigningInActivity extends Activity {
return;
}
- mProviderId = c.getLong(c.getColumnIndexOrThrow(Im.Account.PROVIDER));
- mAccountId = c.getLong(c.getColumnIndexOrThrow(Im.Account._ID));
- mUserName = c.getString(c.getColumnIndexOrThrow(Im.Account.USERNAME));
+ mProviderId = c.getLong(c.getColumnIndexOrThrow(Imps.Account.PROVIDER));
+ mAccountId = c.getLong(c.getColumnIndexOrThrow(Imps.Account._ID));
+ mUserName = c.getString(c.getColumnIndexOrThrow(Imps.Account.USERNAME));
String pwExtra = intent.getStringExtra(ImApp.EXTRA_INTENT_PASSWORD);
mPassword = pwExtra != null ? pwExtra
- : c.getString(c.getColumnIndexOrThrow(Im.Account.PASSWORD));
- final boolean isActive = c.getInt(c.getColumnIndexOrThrow(Im.Account.ACTIVE)) == 1;
+ : c.getString(c.getColumnIndexOrThrow(Imps.Account.PASSWORD));
+ final boolean isActive = c.getInt(c.getColumnIndexOrThrow(Imps.Account.ACTIVE)) == 1;
c.close();
mApp = ImApp.getApplication(this);
@@ -196,13 +196,13 @@ public class SigningInActivity extends Activity {
// this provider to inactive first and then update this
// account to active.
ContentValues values = new ContentValues(1);
- values.put(Im.Account.ACTIVE, 0);
+ values.put(Imps.Account.ACTIVE, 0);
ContentResolver cr = getContentResolver();
- cr.update(Im.Account.CONTENT_URI, values,
- Im.Account.PROVIDER + "=" + providerId, null);
+ cr.update(Imps.Account.CONTENT_URI, values,
+ Imps.Account.PROVIDER + "=" + providerId, null);
- values.put(Im.Account.ACTIVE, 1);
- cr.update(ContentUris.withAppendedId(Im.Account.CONTENT_URI, accountId),
+ values.put(Imps.Account.ACTIVE, 1);
+ cr.update(ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId),
values, null, null);
}
@@ -307,7 +307,7 @@ public class SigningInActivity extends Activity {
if(session == null) {
session = manager.createChatSession(mToAddress);
}
- Uri data = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, session.getId());
+ Uri data = ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, session.getId());
intent = new Intent(Intent.ACTION_VIEW, data);
intent.putExtra("from", mToAddress);
intent.putExtra("providerId", mProviderId);
diff --git a/src/com/android/im/app/SignoutActivity.java b/src/com/android/im/app/SignoutActivity.java
index 2cb3bcb..0b70b69 100644
--- a/src/com/android/im/app/SignoutActivity.java
+++ b/src/com/android/im/app/SignoutActivity.java
@@ -17,7 +17,6 @@
package com.android.im.app;
import android.app.Activity;
-import android.provider.Im;
import android.os.Handler;
import android.os.Bundle;
import android.os.RemoteException;
@@ -28,13 +27,14 @@ import android.net.Uri;
import android.util.Log;
import android.database.Cursor;
import com.android.im.IImConnection;
+import com.android.im.provider.Imps;
public class SignoutActivity extends Activity {
private String[] ACCOUNT_SELECTION = new String[] {
- Im.Account._ID,
- Im.Account.PROVIDER,
+ Imps.Account._ID,
+ Imps.Account.PROVIDER,
};
private ImApp mApp;
@@ -69,8 +69,8 @@ public class SignoutActivity extends Activity {
return;
}
- providerId = c.getLong(c.getColumnIndexOrThrow(Im.Account.PROVIDER));
- accountId = c.getLong(c.getColumnIndexOrThrow(Im.Account._ID));
+ providerId = c.getLong(c.getColumnIndexOrThrow(Imps.Account.PROVIDER));
+ accountId = c.getLong(c.getColumnIndexOrThrow(Imps.Account._ID));
} finally {
c.close();
}
@@ -94,12 +94,12 @@ public class SignoutActivity extends Activity {
// status will never be updated. Clear the status in this case
// to make it recoverable from the crash.
ContentValues values = new ContentValues(2);
- values.put(Im.AccountStatus.PRESENCE_STATUS,
- Im.Presence.OFFLINE);
- values.put(Im.AccountStatus.CONNECTION_STATUS,
- Im.ConnectionStatus.OFFLINE);
- String where = Im.AccountStatus.ACCOUNT + "=?";
- getContentResolver().update(Im.AccountStatus.CONTENT_URI,
+ values.put(Imps.AccountStatus.PRESENCE_STATUS,
+ Imps.Presence.OFFLINE);
+ values.put(Imps.AccountStatus.CONNECTION_STATUS,
+ Imps.ConnectionStatus.OFFLINE);
+ String where = Imps.AccountStatus.ACCOUNT + "=?";
+ getContentResolver().update(Imps.AccountStatus.CONTENT_URI,
values, where,
new String[] { Long.toString(accountId) });
}
diff --git a/src/com/android/im/app/UserPresenceView.java b/src/com/android/im/app/UserPresenceView.java
index 1250600..5e0e7ee 100644
--- a/src/com/android/im/app/UserPresenceView.java
+++ b/src/com/android/im/app/UserPresenceView.java
@@ -21,6 +21,7 @@ import com.android.im.R;
import com.android.im.engine.ImErrorInfo;
import com.android.im.engine.Presence;
import com.android.im.plugin.ImpsConfigNames;
+import com.android.im.provider.Imps;
import com.google.android.collect.Lists;
import android.app.Activity;
@@ -29,7 +30,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.os.RemoteException;
-import android.provider.Im;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
@@ -100,8 +100,8 @@ public class UserPresenceView extends LinearLayout {
int[] supportedStatus = mConn.getSupportedPresenceStatus();
for (int i = 0; i < supportedStatus.length; i++) {
int s = PresenceUtils.convertStatus(supportedStatus[i]);
- if (s == Im.Presence.OFFLINE) {
- s = Im.Presence.INVISIBLE;
+ if (s == Imps.Presence.OFFLINE) {
+ s = Imps.Presence.INVISIBLE;
}
ImApp app = ImApp.getApplication((Activity)mContext);
BrandingResources brandingRes = app.getBrandingResource(mProviderId);
@@ -162,14 +162,14 @@ public class UserPresenceView extends LinearLayout {
// the AIM and MSN server don't support it now.
ProviderDef provider = app.getProvider(mProviderId);
String providerName = provider == null ? null : provider.mName;
- if (Im.ProviderNames.AIM.equals(providerName)
- || Im.ProviderNames.MSN.equals(providerName)) {
+ if (Imps.ProviderNames.AIM.equals(providerName)
+ || Imps.ProviderNames.MSN.equals(providerName)) {
mStatusBar.setFocusable(false);
}
}
private TextView initStatusBar(long providerId) {
- String value = Im.ProviderSettings.getStringValue(
+ String value = Imps.ProviderSettings.getStringValue(
mContext.getContentResolver(), providerId,
ImpsConfigNames.SUPPORT_USER_DEFINED_PRESENCE);
diff --git a/src/com/android/im/engine/SmsService.java b/src/com/android/im/engine/SmsService.java
index 5ba170b..a5b0a46 100644
--- a/src/com/android/im/engine/SmsService.java
+++ b/src/com/android/im/engine/SmsService.java
@@ -20,6 +20,8 @@ package com.android.im.engine;
* An abstract interface to access system SMS service.
*/
public interface SmsService {
+ public static final String ANY_ADDRESS = "*";
+
/**
* The listener which will be notified when an incoming SMS is received.
*
diff --git a/src/com/android/im/imps/CirChannel.java b/src/com/android/im/imps/CirChannel.java
index f147d00..48228c8 100644
--- a/src/com/android/im/imps/CirChannel.java
+++ b/src/com/android/im/imps/CirChannel.java
@@ -41,10 +41,18 @@ abstract class CirChannel {
*/
public abstract void connect() throws ImException;
+ /**
+ * Re-establish the connection and drop the old one.
+ */
public void reconnect(){
}
/**
+ * Tells if the CIR has been shutdown or not.
+ */
+ public abstract boolean isShutdown();
+
+ /**
* Shutdown the CIR channel, stops to listen to CIR requests from the server.
*
*/
diff --git a/src/com/android/im/imps/CustomPasswordDigest.java b/src/com/android/im/imps/CustomPasswordDigest.java
index 5ce1f5a..c2c758d 100644
--- a/src/com/android/im/imps/CustomPasswordDigest.java
+++ b/src/com/android/im/imps/CustomPasswordDigest.java
@@ -17,21 +17,19 @@
package com.android.im.imps;
import com.android.im.engine.ImException;
-import com.android.im.plugin.IPasswordDigest;
-
-import android.os.RemoteException;
+import com.android.im.plugin.PasswordDigest;
import dalvik.system.PathClassLoader;
public class CustomPasswordDigest implements PasswordDigest {
- private IPasswordDigest mPasswordDigest;
+ private PasswordDigest mPasswordDigest;
public CustomPasswordDigest(String pluginPath, String implClass) throws ImException {
PathClassLoader classLoader = new PathClassLoader(pluginPath,
getClass().getClassLoader());
try {
- Class cls = classLoader.loadClass(implClass);
- mPasswordDigest = (IPasswordDigest)cls.newInstance();
+ Class<?> cls = classLoader.loadClass(implClass);
+ mPasswordDigest = (PasswordDigest)cls.newInstance();
} catch (ClassNotFoundException e) {
throw new ImException(e);
} catch (IllegalAccessException e) {
@@ -41,19 +39,11 @@ public class CustomPasswordDigest implements PasswordDigest {
}
}
public String digest(String schema, String nonce, String password) throws ImException {
- try {
- return mPasswordDigest.digest(schema, nonce, password);
- } catch (RemoteException e) {
- throw new ImException(e);
- }
+ return mPasswordDigest.digest(schema, nonce, password);
}
public String[] getSupportedDigestSchema() {
- try {
- return mPasswordDigest.getSupportedDigestSchema();
- } catch (RemoteException e) {
- return new String[0];
- }
+ return mPasswordDigest.getSupportedDigestSchema();
}
}
diff --git a/src/com/android/im/imps/CustomPresenceMapping.java b/src/com/android/im/imps/CustomPresenceMapping.java
index 9f7270e..e9f0176 100644
--- a/src/com/android/im/imps/CustomPresenceMapping.java
+++ b/src/com/android/im/imps/CustomPresenceMapping.java
@@ -16,25 +16,25 @@
*/
package com.android.im.imps;
+import java.util.Map;
+
+import android.os.RemoteException;
+
import com.android.im.engine.ImException;
-import com.android.im.plugin.IPresenceMapping;
import com.android.im.plugin.ImPluginConstants;
+import com.android.im.plugin.PresenceMapping;
import dalvik.system.PathClassLoader;
-import android.os.RemoteException;
-
-import java.util.Map;
-
public class CustomPresenceMapping implements PresenceMapping {
- private IPresenceMapping mPresenceMapping;
+ private PresenceMapping mPresenceMapping;
public CustomPresenceMapping(String pluginPath, String implClass) throws ImException {
PathClassLoader classLoader = new PathClassLoader(pluginPath,
getClass().getClassLoader());
try {
- Class cls = classLoader.loadClass(implClass);
- mPresenceMapping = (IPresenceMapping)cls.newInstance();
+ Class<?> cls = classLoader.loadClass(implClass);
+ mPresenceMapping = (PresenceMapping)cls.newInstance();
} catch (ClassNotFoundException e) {
throw new ImException(e);
} catch (IllegalAccessException e) {
@@ -45,52 +45,28 @@ public class CustomPresenceMapping implements PresenceMapping {
}
public Map<String, Object> getExtra(int status) {
- try {
- return mPresenceMapping.getExtra(status);
- } catch (RemoteException e) {
- return null;
- }
+ return mPresenceMapping.getExtra(status);
}
public boolean getOnlineStatus(int status) {
- try {
- return mPresenceMapping.getOnlineStatus(status);
- } catch (RemoteException e) {
- return false;
- }
+ return mPresenceMapping.getOnlineStatus(status);
}
public int getPresenceStatus(boolean onlineStatus, String userAvailability,
Map<String, Object> allValues) {
- try {
- return mPresenceMapping.getPresenceStatus(onlineStatus, userAvailability, allValues);
- } catch (RemoteException e) {
- return ImPluginConstants.PRESENCE_OFFLINE;
- }
+ return mPresenceMapping.getPresenceStatus(onlineStatus, userAvailability, allValues);
}
public int[] getSupportedPresenceStatus() {
- try {
- return mPresenceMapping.getSupportedPresenceStatus();
- } catch (RemoteException e) {
- return new int[0];
- }
+ return mPresenceMapping.getSupportedPresenceStatus();
}
public String getUserAvaibility(int status) {
- try {
- return mPresenceMapping.getUserAvaibility(status);
- } catch (RemoteException e) {
- return ImPluginConstants.PA_NOT_AVAILABLE;
- }
+ return mPresenceMapping.getUserAvaibility(status);
}
public boolean requireAllPresenceValues() {
- try {
- return mPresenceMapping.requireAllPresenceValues();
- } catch (RemoteException e) {
- return false;
- }
+ return mPresenceMapping.requireAllPresenceValues();
}
}
diff --git a/src/com/android/im/imps/DefaultPresenceMapping.java b/src/com/android/im/imps/DefaultPresenceMapping.java
index fa5f954..bf4e4fa 100644
--- a/src/com/android/im/imps/DefaultPresenceMapping.java
+++ b/src/com/android/im/imps/DefaultPresenceMapping.java
@@ -17,6 +17,7 @@
package com.android.im.imps;
import com.android.im.plugin.ImPluginConstants;
+import com.android.im.plugin.PresenceMapping;
import java.util.Map;
diff --git a/src/com/android/im/imps/HttpCirChannel.java b/src/com/android/im/imps/HttpCirChannel.java
index 1cca355..77d6bf5 100644
--- a/src/com/android/im/imps/HttpCirChannel.java
+++ b/src/com/android/im/imps/HttpCirChannel.java
@@ -45,7 +45,7 @@ class HttpCirChannel extends CirChannel implements Runnable {
}
@Override
- public void connect() {
+ public synchronized void connect() {
ImpsSession session = mConnection.getSession();
try {
if (session.getCirHttpAddress() != null) {
@@ -56,13 +56,18 @@ class HttpCirChannel extends CirChannel implements Runnable {
}
mServerPollMin = session.getServerPollMin() * 1000;
+ mStopped = false;
mPollingTask = new Thread(this, "HTTPCIRChannel");
mPollingTask.setDaemon(true);
mPollingTask.start();
}
+ public synchronized boolean isShutdown() {
+ return mStopped;
+ }
+
@Override
- public void shutdown() {
+ public synchronized void shutdown() {
mStopped = true;
}
diff --git a/src/com/android/im/imps/ImpsConnectionConfig.java b/src/com/android/im/imps/ImpsConnectionConfig.java
index 0986dbc..0d49a60 100644
--- a/src/com/android/im/imps/ImpsConnectionConfig.java
+++ b/src/com/android/im/imps/ImpsConnectionConfig.java
@@ -23,6 +23,8 @@ import com.android.im.engine.ConnectionConfig;
import com.android.im.engine.ImException;
import com.android.im.imps.ImpsConstants.ImpsVersion;
import com.android.im.plugin.ImpsConfigNames;
+import com.android.im.plugin.PasswordDigest;
+import com.android.im.plugin.PresenceMapping;
/**
* The configuration for IMPS connection.
diff --git a/src/com/android/im/imps/ImpsContactListManager.java b/src/com/android/im/imps/ImpsContactListManager.java
index 480671d..31ddce2 100644
--- a/src/com/android/im/imps/ImpsContactListManager.java
+++ b/src/com/android/im/imps/ImpsContactListManager.java
@@ -32,6 +32,7 @@ import com.android.im.engine.ImException;
import com.android.im.engine.Presence;
import com.android.im.engine.SubscriptionRequestListener;
import com.android.im.imps.ImpsConstants.ImpsVersion;
+import com.android.im.plugin.PresenceMapping;
/**
* An implementation of ContactListManager of Wireless Village IMPS protocol.
diff --git a/src/com/android/im/imps/ImpsPresenceUtils.java b/src/com/android/im/imps/ImpsPresenceUtils.java
index ec1403f..e9b0b5f 100644
--- a/src/com/android/im/imps/ImpsPresenceUtils.java
+++ b/src/com/android/im/imps/ImpsPresenceUtils.java
@@ -18,6 +18,8 @@
package com.android.im.imps;
import com.android.im.engine.Presence;
+import com.android.im.plugin.PresenceMapping;
+
import org.apache.commons.codec.binary.Base64;
import android.os.Base64Utils;
@@ -151,7 +153,7 @@ public class ImpsPresenceUtils {
if (value instanceof String) {
elem.setContents((String)value);
} else if (value instanceof Map) {
- mapToPrimitives((Map)value, elem.getChildren());
+ mapToPrimitives((Map<String, Object>)value, elem.getChildren());
}
elems.add(elem);
}
diff --git a/src/com/android/im/imps/PasswordDigest.java b/src/com/android/im/imps/PasswordDigest.java
deleted file mode 100644
index d911fc5..0000000
--- a/src/com/android/im/imps/PasswordDigest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008 Esmertec AG.
- * 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.im.imps;
-
-import com.android.im.engine.ImException;
-
-public interface PasswordDigest {
- /**
- * Gets an array of supported digest schema.
- *
- * @return an array of digest schema
- */
- String[] getSupportedDigestSchema();
-
- /**
- * Generates digest bytes.
- *
- */
- String digest(String schema, String nonce, String password) throws ImException;
-}
diff --git a/src/com/android/im/imps/PresenceMapping.java b/src/com/android/im/imps/PresenceMapping.java
deleted file mode 100644
index 04602a9..0000000
--- a/src/com/android/im/imps/PresenceMapping.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2008 Esmertec AG.
- * 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.im.imps;
-
-import java.util.Map;
-
-public interface PresenceMapping {
- /**
- * Tells if the mapping needs all presence values sent in protocol. If this
- * method returns true, the framework will pass all the presence values
- * received from the server when map to the predefined status.
- *
- * @return true if needs; false otherwise.
- */
- boolean requireAllPresenceValues();
-
- /**
- * Map the presence values sent in protocol to the predefined presence
- * status.
- *
- * @param onlineStatus The value of presence &lt;OnlineStatus&gt; received
- * from the server.
- * @param userAvailability The value of presence &lt;UserAvailibility&gt;
- * received from the server.
- * @param allValues The whole presence values received from the server.
- * @return a predefined status.
- * @see #requireAllPresenceValues()
- */
- int getPresenceStatus(boolean onlineStatus, String userAvailability,
- Map<String, Object> allValues);
-
- /**
- * Gets the value of &lt;OnlineStatus&gt; will be sent to the server when
- * update presence to the predefined status.
- *
- * @param status the predefined status.
- * @return The value of &lt;OnlineStatus&gt; will be sent to the server
- */
- boolean getOnlineStatus(int status);
-
- /**
- * Gets the value of &lt;UserAvaibility&gt; will be sent to the server when
- * update presence to the predefined status.
- *
- * @param status the predefined status.
- * @return The value of &lt;UserAvaibility&gt; will be sent to the server
- */
- String getUserAvaibility(int status);
-
- /**
- * Gets the extra presence values other than &lt;OnlineStatus&gt; and
- * &lt;UserAvaibility&gt; will be sent to the server when update presence to
- * the predefined status.
- *
- * @param status the predefined status.
- * @return The extra values that will be sent to the server.
- */
- Map<String, Object> getExtra(int status);
-
- /**
- * Gets an array of the supported presence status. The client can only update
- * presence to the values in the array.
- *
- * @return an array of the supported presence status.
- */
- int[] getSupportedPresenceStatus();
-}
diff --git a/src/com/android/im/imps/PresencePollingManager.java b/src/com/android/im/imps/PresencePollingManager.java
index e7d917c..b3601db 100644
--- a/src/com/android/im/imps/PresencePollingManager.java
+++ b/src/com/android/im/imps/PresencePollingManager.java
@@ -86,7 +86,9 @@ public class PresencePollingManager implements Runnable {
// poll. Fetch the presence of all contacts in list.
pollingAddress = getContactLists();
}
- mManager.fetchPresence(pollingAddress);
+ if (pollingAddress != null) {
+ mManager.fetchPresence(pollingAddress);
+ }
}
try {
diff --git a/src/com/android/im/imps/SmsCirChannel.java b/src/com/android/im/imps/SmsCirChannel.java
index 24ece3b..12f9f1d 100644
--- a/src/com/android/im/imps/SmsCirChannel.java
+++ b/src/com/android/im/imps/SmsCirChannel.java
@@ -16,6 +16,8 @@
*/
package com.android.im.imps;
+import android.util.Log;
+
import com.android.im.engine.ImErrorInfo;
import com.android.im.engine.ImException;
import com.android.im.engine.SmsService;
@@ -41,13 +43,17 @@ public class SmsCirChannel extends CirChannel
@Override
public void connect() throws ImException {
- if (mAddr == null || mAddr.length() == 0) {
- throw new ImException(ImpsErrorInfo.UNKNOWN_SERVER,
- "Invalid sms addr");
- }
mSmsService = SystemService.getDefault().getSmsService();
- mSmsService.addSmsListener(mAddr, mPort, this);
- sendHelo();
+ if (mAddr != null) {
+ mSmsService.addSmsListener(mAddr, mPort, this);
+ sendHelo();
+ } else {
+ mSmsService.addSmsListener(SmsService.ANY_ADDRESS, mPort, this);
+ }
+ }
+
+ public boolean isShutdown() {
+ return false;
}
@Override
@@ -59,23 +65,23 @@ public class SmsCirChannel extends CirChannel
// It's safe to assume that each character is encoded into 7-bit since
// all characters in CIR are in gsm 7-bit alphabet.
int lengthSeptets = data.length * 8 / 7;
- int numPaddingBits = data.length * 8 % 7;
String s = GsmAlphabet.gsm7BitPackedToString(data, 0,
- lengthSeptets, numPaddingBits);
+ lengthSeptets, 0);
// CIR format: WVCI <version> <session cookie>
if (!s.startsWith("WVCI")) {
// not a valid CIR, ignore.
+ Log.w("SmsCir", "Received a non-CIR SMS, ignore!");
return;
}
+
+ String sessionCookie = mConnection.getSession().getCookie();
String[] fields = s.split(" ");
- if (fields.length != 3) {
+ if (fields.length != 3 || !sessionCookie.equalsIgnoreCase(fields[2])) {
// Not a valid CIR, ignore
- return;
- }
- String sessionCookie = mConnection.getSession().getCookie();
- if (sessionCookie.equalsIgnoreCase(fields[2])) {
- mConnection.sendPollingRequest();
+ Log.w("SmsCir", "The CIR format is not correct or session cookie" +
+ " does not match");
}
+ mConnection.sendPollingRequest();
}
public void onFailure(int errorCode) {
diff --git a/src/com/android/im/imps/StandardPasswordDigest.java b/src/com/android/im/imps/StandardPasswordDigest.java
index dd7bbaf..e88f377 100644
--- a/src/com/android/im/imps/StandardPasswordDigest.java
+++ b/src/com/android/im/imps/StandardPasswordDigest.java
@@ -18,6 +18,7 @@
package com.android.im.imps;
import com.android.im.engine.ImException;
+import com.android.im.plugin.PasswordDigest;
import org.apache.commons.codec.binary.Base64;
diff --git a/src/com/android/im/imps/TcpCirChannel.java b/src/com/android/im/imps/TcpCirChannel.java
index 6679a0a..45dfdcd 100644
--- a/src/com/android/im/imps/TcpCirChannel.java
+++ b/src/com/android/im/imps/TcpCirChannel.java
@@ -62,6 +62,7 @@ class TcpCirChannel extends CirChannel implements Runnable, HeartbeatService.Cal
@Override
public synchronized void connect() throws ImException {
try {
+ mDone = false;
connectServer();
mCirThread = new Thread(this, "TcpCirChannel");
mCirThread.setDaemon(true);
@@ -86,8 +87,8 @@ class TcpCirChannel extends CirChannel implements Runnable, HeartbeatService.Cal
ImpsLog.log(mUser + " Shutting down CIR channel");
}
mDone = true;
- synchronized (mReconnectLock) {
- if (mReconnecting) {
+ if (mReconnecting) {
+ synchronized (mReconnectLock) {
mReconnecting = false;
mReconnectLock.notify();
}
@@ -106,6 +107,10 @@ class TcpCirChannel extends CirChannel implements Runnable, HeartbeatService.Cal
}
}
+ public boolean isShutdown() {
+ return mDone;
+ }
+
public void run() {
while (!mDone) {
try {
diff --git a/src/com/android/im/provider/Imps.java b/src/com/android/im/provider/Imps.java
new file mode 100644
index 0000000..091e993
--- /dev/null
+++ b/src/com/android/im/provider/Imps.java
@@ -0,0 +1,2333 @@
+/*
+ * 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.im.provider;
+
+import android.content.ContentQueryMap;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.BaseColumns;
+
+import java.util.HashMap;
+
+/**
+ * The IM provider stores all information about roster contacts, chat messages, presence, etc.
+ *
+ * @hide
+ */
+public class Imps {
+ /**
+ * no public constructor since this is a utility class
+ */
+ private Imps() {}
+
+ /**
+ * The Columns for IM providers (i.e. AIM, Y!, GTalk)
+ */
+ public interface ProviderColumns {
+ /**
+ * The name of the IM provider
+ * <P>Type: TEXT</P>
+ */
+ String NAME = "name";
+
+ /**
+ * The full name of the provider
+ * <P>Type: TEXT</P>
+ */
+ String FULLNAME = "fullname";
+
+ /**
+ * The category for the provider, used to form intent.
+ * <P>Type: TEXT</P>
+ */
+ String CATEGORY = "category";
+
+ /**
+ * The url users should visit to create a new account for this provider
+ * <P>Type: TEXT</P>
+ */
+ String SIGNUP_URL = "signup_url";
+ }
+
+ /**
+ * Known names corresponding to the {@link ProviderColumns#NAME} column
+ */
+ public interface ProviderNames {
+ //
+ //NOTE: update Contacts.java with new providers when they're added.
+ //
+ String YAHOO = "Yahoo";
+ String GTALK = "GTalk";
+ String MSN = "MSN";
+ String ICQ = "ICQ";
+ String AIM = "AIM";
+ String XMPP = "XMPP";
+ String JABBER = "JABBER";
+ String SKYPE = "SKYPE";
+ String QQ = "QQ";
+ }
+
+ /**
+ * This table contains the IM providers
+ */
+ public static final class Provider implements BaseColumns, ProviderColumns {
+ private Provider() {}
+
+ public static final long getProviderIdForName(ContentResolver cr, String providerName) {
+ String[] selectionArgs = new String[1];
+ selectionArgs[0] = providerName;
+
+ Cursor cursor = cr.query(CONTENT_URI,
+ PROVIDER_PROJECTION,
+ NAME+"=?",
+ selectionArgs, null);
+
+ long retVal = 0;
+ try {
+ if (cursor.moveToFirst()) {
+ retVal = cursor.getLong(cursor.getColumnIndexOrThrow(_ID));
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return retVal;
+ }
+
+ public static final String getProviderNameForId(ContentResolver cr, long providerId) {
+ Cursor cursor = cr.query(CONTENT_URI,
+ PROVIDER_PROJECTION,
+ _ID + "=" + providerId,
+ null, null);
+
+ String retVal = null;
+ try {
+ if (cursor.moveToFirst()) {
+ retVal = cursor.getString(cursor.getColumnIndexOrThrow(NAME));
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return retVal;
+ }
+
+ private static final String[] PROVIDER_PROJECTION = new String[] {
+ _ID,
+ NAME
+ };
+
+ public static final String ACTIVE_ACCOUNT_ID = "account_id";
+ public static final String ACTIVE_ACCOUNT_USERNAME = "account_username";
+ public static final String ACTIVE_ACCOUNT_PW = "account_pw";
+ public static final String ACTIVE_ACCOUNT_LOCKED = "account_locked";
+ public static final String ACTIVE_ACCOUNT_KEEP_SIGNED_IN = "account_keepSignedIn";
+ public static final String ACCOUNT_PRESENCE_STATUS = "account_presenceStatus";
+ public static final String ACCOUNT_CONNECTION_STATUS = "account_connStatus";
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/providers");
+
+ public static final Uri CONTENT_URI_WITH_ACCOUNT =
+ Uri.parse("content://imps/providers/account");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * people.
+ */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/imps-providers";
+
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-providers";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "name ASC";
+ }
+
+ /**
+ * The columns for IM accounts. There can be more than one account for each IM provider.
+ */
+ public interface AccountColumns {
+ /**
+ * The name of the account
+ * <P>Type: TEXT</P>
+ */
+ String NAME = "name";
+
+ /**
+ * The IM provider for this account
+ * <P>Type: INTEGER</P>
+ */
+ String PROVIDER = "provider";
+
+ /**
+ * The username for this account
+ * <P>Type: TEXT</P>
+ */
+ String USERNAME = "username";
+
+ /**
+ * The password for this account
+ * <P>Type: TEXT</P>
+ */
+ String PASSWORD = "pw";
+
+ /**
+ * A boolean value indicates if the account is active.
+ * <P>Type: INTEGER</P>
+ */
+ String ACTIVE = "active";
+
+ /**
+ * A boolean value indicates if the account is locked (not editable)
+ * <P>Type: INTEGER</P>
+ */
+ String LOCKED = "locked";
+
+ /**
+ * A boolean value to indicate whether this account is kept signed in.
+ * <P>Type: INTEGER</P>
+ */
+ String KEEP_SIGNED_IN = "keep_signed_in";
+
+ /**
+ * A boolean value indiciating the last login state for this account
+ * <P>Type: INTEGER</P>
+ */
+ String LAST_LOGIN_STATE = "last_login_state";
+ }
+
+ /**
+ * This table contains the IM accounts.
+ */
+ public static final class Account implements BaseColumns, AccountColumns {
+ private Account() {}
+
+ public static final long getProviderIdForAccount(ContentResolver cr, long accountId) {
+ Cursor cursor = cr.query(CONTENT_URI,
+ PROVIDER_PROJECTION,
+ _ID + "=" + accountId,
+ null /* selection args */,
+ null /* sort order */);
+
+ long providerId = 0;
+
+ try {
+ if (cursor.moveToFirst()) {
+ providerId = cursor.getLong(PROVIDER_COLUMN);
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return providerId;
+ }
+
+ private static final String[] PROVIDER_PROJECTION = new String[] { PROVIDER };
+ private static final int PROVIDER_COLUMN = 0;
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/accounts");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * account.
+ */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/imps-accounts";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
+ * account.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-accounts";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "name ASC";
+
+ }
+
+ /**
+ * Connection status
+ */
+ public interface ConnectionStatus {
+ /**
+ * The connection is offline, not logged in.
+ */
+ int OFFLINE = 0;
+
+ /**
+ * The connection is attempting to connect.
+ */
+ int CONNECTING = 1;
+
+ /**
+ * The connection is suspended due to network not available.
+ */
+ int SUSPENDED = 2;
+
+ /**
+ * The connection is logged in and online.
+ */
+ int ONLINE = 3;
+ }
+
+ public interface AccountStatusColumns {
+ /**
+ * account id
+ * <P>Type: INTEGER</P>
+ */
+ String ACCOUNT = "account";
+
+ /**
+ * User's presence status, see definitions in {#link CommonPresenceColumn}
+ * <P>Type: INTEGER</P>
+ */
+ String PRESENCE_STATUS = "presenceStatus";
+
+ /**
+ * The connection status of this account, see {#link ConnectionStatus}
+ * <P>Type: INTEGER</P>
+ */
+ String CONNECTION_STATUS = "connStatus";
+ }
+
+ public static final class AccountStatus implements BaseColumns, AccountStatusColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/accountStatus");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of account status.
+ */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/imps-account-status";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single account status.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-account-status";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "name ASC";
+ }
+
+ /**
+ * Columns from the Contacts table.
+ */
+ public interface ContactsColumns {
+ /**
+ * The username
+ * <P>Type: TEXT</P>
+ */
+ String USERNAME = "username";
+
+ /**
+ * The nickname or display name
+ * <P>Type: TEXT</P>
+ */
+ String NICKNAME = "nickname";
+
+ /**
+ * The IM provider for this contact
+ * <P>Type: INTEGER</P>
+ */
+ String PROVIDER = "provider";
+
+ /**
+ * The account (within a IM provider) for this contact
+ * <P>Type: INTEGER</P>
+ */
+ String ACCOUNT = "account";
+
+ /**
+ * The contactList this contact belongs to
+ * <P>Type: INTEGER</P>
+ */
+ String CONTACTLIST = "contactList";
+
+ /**
+ * Contact type
+ * <P>Type: INTEGER</P>
+ */
+ String TYPE = "type";
+
+ /**
+ * normal IM contact
+ */
+ int TYPE_NORMAL = 0;
+ /**
+ * temporary contact, someone not in the list of contacts that we
+ * subscribe presence for. Usually created because of the user is
+ * having a chat session with this contact.
+ */
+ int TYPE_TEMPORARY = 1;
+ /**
+ * temporary contact created for group chat.
+ */
+ int TYPE_GROUP = 2;
+ /**
+ * blocked contact.
+ */
+ int TYPE_BLOCKED = 3;
+ /**
+ * the contact is hidden. The client should always display this contact to the user.
+ */
+ int TYPE_HIDDEN = 4;
+ /**
+ * the contact is pinned. The client should always display this contact to the user.
+ */
+ int TYPE_PINNED = 5;
+
+ /**
+ * Contact subscription status
+ * <P>Type: INTEGER</P>
+ */
+ String SUBSCRIPTION_STATUS = "subscriptionStatus";
+
+ /**
+ * no pending subscription
+ */
+ int SUBSCRIPTION_STATUS_NONE = 0;
+ /**
+ * requested to subscribe
+ */
+ int SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING = 1;
+ /**
+ * requested to unsubscribe
+ */
+ int SUBSCRIPTION_STATUS_UNSUBSCRIBE_PENDING = 2;
+
+ /**
+ * Contact subscription type
+ * <P>Type: INTEGER </P>
+ */
+ String SUBSCRIPTION_TYPE = "subscriptionType";
+
+ /**
+ * The user and contact have no interest in each other's presence.
+ */
+ int SUBSCRIPTION_TYPE_NONE = 0;
+ /**
+ * The user wishes to stop receiving presence updates from the contact.
+ */
+ int SUBSCRIPTION_TYPE_REMOVE = 1;
+ /**
+ * The user is interested in receiving presence updates from the contact.
+ */
+ int SUBSCRIPTION_TYPE_TO = 2;
+ /**
+ * The contact is interested in receiving presence updates from the user.
+ */
+ int SUBSCRIPTION_TYPE_FROM = 3;
+ /**
+ * The user and contact have a mutual interest in each other's presence.
+ */
+ int SUBSCRIPTION_TYPE_BOTH = 4;
+ /**
+ * This is a special type reserved for pending subscription requests
+ */
+ int SUBSCRIPTION_TYPE_INVITATIONS = 5;
+
+ /**
+ * Quick Contact: derived from Google Contact Extension's "message_count" attribute.
+ * <P>Type: INTEGER</P>
+ */
+ String QUICK_CONTACT = "qc";
+
+ /**
+ * Google Contact Extension attribute
+ *
+ * Rejected: a boolean value indicating whether a subscription request from
+ * this client was ever rejected by the user. "true" indicates that it has.
+ * This is provided so that a client can block repeated subscription requests.
+ * <P>Type: INTEGER</P>
+ */
+ String REJECTED = "rejected";
+
+ /**
+ * Off The Record status: 0 for disabled, 1 for enabled
+ * <P>Type: INTEGER </P>
+ */
+ String OTR = "otr";
+ }
+
+ /**
+ * This defines the different type of values of {@link ContactsColumns#OTR}
+ */
+ public interface OffTheRecordType {
+ /*
+ * Off the record not turned on
+ */
+ int DISABLED = 0;
+ /**
+ * Off the record turned on, but we don't know who turned it on
+ */
+ int ENABLED = 1;
+ /**
+ * Off the record turned on by the user
+ */
+ int ENABLED_BY_USER = 2;
+ /**
+ * Off the record turned on by the buddy
+ */
+ int ENABLED_BY_BUDDY = 3;
+ };
+
+ /**
+ * This table contains contacts.
+ */
+ public static final class Contacts implements BaseColumns,
+ ContactsColumns, PresenceColumns, ChatsColumns {
+ /**
+ * no public constructor since this is a utility class
+ */
+ private Contacts() {}
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/contacts");
+
+ /**
+ * The content:// style URL for contacts joined with presence
+ */
+ public static final Uri CONTENT_URI_WITH_PRESENCE =
+ Uri.parse("content://imps/contactsWithPresence");
+
+ /**
+ * The content:// style URL for barebone contacts, not joined with any other table
+ */
+ public static final Uri CONTENT_URI_CONTACTS_BAREBONE =
+ Uri.parse("content://imps/contactsBarebone");
+
+ /**
+ * The content:// style URL for contacts who have an open chat session
+ */
+ public static final Uri CONTENT_URI_CHAT_CONTACTS =
+ Uri.parse("content://imps/contacts/chatting");
+
+ /**
+ * The content:// style URL for contacts who have been blocked
+ */
+ public static final Uri CONTENT_URI_BLOCKED_CONTACTS =
+ Uri.parse("content://imps/contacts/blocked");
+
+ /**
+ * The content:// style URL for contacts by provider and account
+ */
+ public static final Uri CONTENT_URI_CONTACTS_BY =
+ Uri.parse("content://imps/contacts");
+
+ /**
+ * The content:// style URL for contacts by provider and account,
+ * and who have an open chat session
+ */
+ public static final Uri CONTENT_URI_CHAT_CONTACTS_BY =
+ Uri.parse("content://imps/contacts/chatting");
+
+ /**
+ * The content:// style URL for contacts by provider and account,
+ * and who are online
+ */
+ public static final Uri CONTENT_URI_ONLINE_CONTACTS_BY =
+ Uri.parse("content://imps/contacts/online");
+
+ /**
+ * The content:// style URL for contacts by provider and account,
+ * and who are offline
+ */
+ public static final Uri CONTENT_URI_OFFLINE_CONTACTS_BY =
+ Uri.parse("content://imps/contacts/offline");
+
+ /**
+ * The content:// style URL for operations on bulk contacts
+ */
+ public static final Uri BULK_CONTENT_URI =
+ Uri.parse("content://imps/bulk_contacts");
+
+ /**
+ * The content:// style URL for the count of online contacts in each
+ * contact list by provider and account.
+ */
+ public static final Uri CONTENT_URI_ONLINE_COUNT =
+ Uri.parse("content://imps/contacts/onlineCount");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * people.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-contacts";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
+ * person.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/imps-contacts";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER =
+ "subscriptionType DESC, last_message_date DESC," +
+ " mode DESC, nickname COLLATE UNICODE ASC";
+
+ public static final String CHATS_CONTACT = "chats_contact";
+
+ public static final String AVATAR_HASH = "avatars_hash";
+
+ public static final String AVATAR_DATA = "avatars_data";
+ }
+
+ /**
+ * Columns from the ContactList table.
+ */
+ public interface ContactListColumns {
+ String NAME = "name";
+ String PROVIDER = "provider";
+ String ACCOUNT = "account";
+ }
+
+ /**
+ * This table contains the contact lists.
+ */
+ public static final class ContactList implements BaseColumns,
+ ContactListColumns {
+ private ContactList() {}
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/contactLists");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * people.
+ */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/imps-contactLists";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
+ * person.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-contactLists";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "name COLLATE UNICODE ASC";
+
+ public static final String PROVIDER_NAME = "provider_name";
+
+ public static final String ACCOUNT_NAME = "account_name";
+ }
+
+ /**
+ * Columns from the BlockedList table.
+ */
+ public interface BlockedListColumns {
+ /**
+ * The username of the blocked contact.
+ * <P>Type: TEXT</P>
+ */
+ String USERNAME = "username";
+
+ /**
+ * The nickname of the blocked contact.
+ * <P>Type: TEXT</P>
+ */
+ String NICKNAME = "nickname";
+
+ /**
+ * The provider id of the blocked contact.
+ * <P>Type: INT</P>
+ */
+ String PROVIDER = "provider";
+
+ /**
+ * The account id of the blocked contact.
+ * <P>Type: INT</P>
+ */
+ String ACCOUNT = "account";
+ }
+
+ /**
+ * This table contains blocked lists
+ */
+ public static final class BlockedList implements BaseColumns, BlockedListColumns {
+ private BlockedList() {}
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/blockedList");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * people.
+ */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/imps-blockedList";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
+ * person.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-blockedList";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "nickname ASC";
+
+ public static final String PROVIDER_NAME = "provider_name";
+
+ public static final String ACCOUNT_NAME = "account_name";
+
+ public static final String AVATAR_DATA = "avatars_data";
+ }
+
+ /**
+ * Columns from the contactsEtag table
+ */
+ public interface ContactsEtagColumns {
+ /**
+ * The roster etag, computed by the server, stored on the client. There is one etag
+ * per account roster.
+ * <P>Type: TEXT</P>
+ */
+ String ETAG = "etag";
+
+ /**
+ * The OTR etag, computed by the server, stored on the client. There is one OTR etag
+ * per account roster.
+ * <P>Type: TEXT</P>
+ */
+ String OTR_ETAG = "otr_etag";
+
+ /**
+ * The account id for the etag.
+ * <P> Type: INTEGER </P>
+ */
+ String ACCOUNT = "account";
+ }
+
+ public static final class ContactsEtag implements BaseColumns, ContactsEtagColumns {
+ private ContactsEtag() {}
+
+ public static final Cursor query(ContentResolver cr,
+ String[] projection) {
+ return cr.query(CONTENT_URI, projection, null, null, null);
+ }
+
+ public static final Cursor query(ContentResolver cr,
+ String[] projection, String where, String orderBy) {
+ return cr.query(CONTENT_URI, projection, where,
+ null, orderBy == null ? null : orderBy);
+ }
+
+ public static final String getRosterEtag(ContentResolver resolver, long accountId) {
+ String retVal = null;
+
+ Cursor c = resolver.query(CONTENT_URI,
+ CONTACT_ETAG_PROJECTION,
+ ACCOUNT + "=" + accountId,
+ null /* selection args */,
+ null /* sort order */);
+
+ try {
+ if (c.moveToFirst()) {
+ retVal = c.getString(COLUMN_ETAG);
+ }
+ } finally {
+ c.close();
+ }
+
+ return retVal;
+ }
+
+ public static final String getOtrEtag(ContentResolver resolver, long accountId) {
+ String retVal = null;
+
+ Cursor c = resolver.query(CONTENT_URI,
+ CONTACT_OTR_ETAG_PROJECTION,
+ ACCOUNT + "=" + accountId,
+ null /* selection args */,
+ null /* sort order */);
+
+ try {
+ if (c.moveToFirst()) {
+ retVal = c.getString(COLUMN_OTR_ETAG);
+ }
+ } finally {
+ c.close();
+ }
+
+ return retVal;
+ }
+
+ private static final String[] CONTACT_ETAG_PROJECTION = new String[] {
+ Imps.ContactsEtag.ETAG // 0
+ };
+
+ private static int COLUMN_ETAG = 0;
+
+ private static final String[] CONTACT_OTR_ETAG_PROJECTION = new String[] {
+ Imps.ContactsEtag.OTR_ETAG // 0
+ };
+
+ private static int COLUMN_OTR_ETAG = 0;
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/contactsEtag");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * people.
+ */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/imps-contactsEtag";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
+ * person.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-contactsEtag";
+ }
+
+ /**
+ * Message type definition
+ */
+ public interface MessageType {
+ /* sent message */
+ int OUTGOING = 0;
+ /* received message */
+ int INCOMING = 1;
+ /* presence became available */
+ int PRESENCE_AVAILABLE = 2;
+ /* presence became away */
+ int PRESENCE_AWAY = 3;
+ /* presence became DND (busy) */
+ int PRESENCE_DND = 4;
+ /* presence became unavailable */
+ int PRESENCE_UNAVAILABLE = 5;
+ /* the message is converted to a group chat */
+ int CONVERT_TO_GROUPCHAT = 6;
+ /* generic status */
+ int STATUS = 7;
+ /* the message cannot be sent now, but will be sent later */
+ int POSTPONED = 8;
+ /* off The Record status is turned off */
+ int OTR_IS_TURNED_OFF = 9;
+ /* off the record status is turned on */
+ int OTR_IS_TURNED_ON = 10;
+ /* off the record status turned on by user */
+ int OTR_TURNED_ON_BY_USER = 11;
+ /* off the record status turned on by buddy */
+ int OTR_TURNED_ON_BY_BUDDY = 12;
+ }
+
+ /**
+ * The common columns for messages table
+ */
+ public interface MessageColumns {
+ /**
+ * The thread_id column stores the contact id of the contact the message belongs to.
+ * For groupchat messages, the thread_id stores the group id, which is the contact id
+ * of the temporary group contact created for the groupchat. So there should be no
+ * collision between groupchat message thread id and regular message thread id.
+ */
+ String THREAD_ID = "thread_id";
+
+ /**
+ * The nickname. This is used for groupchat messages to indicate the participant's
+ * nickname. For non groupchat messages, this field should be left empty.
+ */
+ String NICKNAME = "nickname";
+
+ /**
+ * The body
+ * <P>Type: TEXT</P>
+ */
+ String BODY = "body";
+
+ /**
+ * The date this message is sent or received
+ * <P>Type: INTEGER</P>
+ */
+ String DATE = "date";
+
+ /**
+ * Message Type, see {@link MessageType}
+ * <P>Type: INTEGER</P>
+ */
+ String TYPE = "type";
+
+ /**
+ * Error Code: 0 means no error.
+ * <P>Type: INTEGER </P>
+ */
+ String ERROR_CODE = "err_code";
+
+ /**
+ * Error Message
+ * <P>Type: TEXT</P>
+ */
+ String ERROR_MESSAGE = "err_msg";
+
+ /**
+ * Packet ID, auto assigned by the GTalkService for outgoing messages or the
+ * GTalk server for incoming messages. The packet id field is optional for messages,
+ * so it could be null.
+ * <P>Type: STRING</P>
+ */
+ String PACKET_ID = "packet_id";
+
+ /**
+ * Is groupchat message or not
+ * <P>Type: INTEGER</P>
+ */
+ String IS_GROUP_CHAT = "is_muc";
+
+ /**
+ * A hint that the UI should show the sent time of this message
+ * <P>Type: INTEGER</P>
+ */
+ String DISPLAY_SENT_TIME = "show_ts";
+ }
+
+ /**
+ * This table contains messages.
+ */
+ public static final class Messages implements BaseColumns, MessageColumns {
+ /**
+ * no public constructor since this is a utility class
+ */
+ private Messages() {}
+
+ /**
+ * Gets the Uri to query messages by thread id.
+ *
+ * @param threadId the thread id of the message.
+ * @return the Uri
+ */
+ public static final Uri getContentUriByThreadId(long threadId) {
+ Uri.Builder builder = CONTENT_URI_MESSAGES_BY_THREAD_ID.buildUpon();
+ ContentUris.appendId(builder, threadId);
+ return builder.build();
+ }
+
+ /**
+ * @deprecated
+ *
+ * Gets the Uri to query messages by account and contact.
+ *
+ * @param accountId the account id of the contact.
+ * @param username the user name of the contact.
+ * @return the Uri
+ */
+ public static final Uri getContentUriByContact(long accountId, String username) {
+ Uri.Builder builder = CONTENT_URI_MESSAGES_BY_ACCOUNT_AND_CONTACT.buildUpon();
+ ContentUris.appendId(builder, accountId);
+ builder.appendPath(username);
+ return builder.build();
+ }
+
+ /**
+ * Gets the Uri to query messages by provider.
+ *
+ * @param providerId the service provider id.
+ * @return the Uri
+ */
+ public static final Uri getContentUriByProvider(long providerId) {
+ Uri.Builder builder = CONTENT_URI_MESSAGES_BY_PROVIDER.buildUpon();
+ ContentUris.appendId(builder, providerId);
+ return builder.build();
+ }
+
+ /**
+ * Gets the Uri to query off the record messages by account.
+ *
+ * @param accountId the account id.
+ * @return the Uri
+ */
+ public static final Uri getContentUriByAccount(long accountId) {
+ Uri.Builder builder = CONTENT_URI_BY_ACCOUNT.buildUpon();
+ ContentUris.appendId(builder, accountId);
+ return builder.build();
+ }
+
+ /**
+ * Gets the Uri to query off the record messages by thread id.
+ *
+ * @param threadId the thread id of the message.
+ * @return the Uri
+ */
+ public static final Uri getOtrMessagesContentUriByThreadId(long threadId) {
+ Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID.buildUpon();
+ ContentUris.appendId(builder, threadId);
+ return builder.build();
+ }
+
+ /**
+ * @deprecated
+ *
+ * Gets the Uri to query off the record messages by account and contact.
+ *
+ * @param accountId the account id of the contact.
+ * @param username the user name of the contact.
+ * @return the Uri
+ */
+ public static final Uri getOtrMessagesContentUriByContact(long accountId, String username) {
+ Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT.buildUpon();
+ ContentUris.appendId(builder, accountId);
+ builder.appendPath(username);
+ return builder.build();
+ }
+
+ /**
+ * Gets the Uri to query off the record messages by provider.
+ *
+ * @param providerId the service provider id.
+ * @return the Uri
+ */
+ public static final Uri getOtrMessagesContentUriByProvider(long providerId) {
+ Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_PROVIDER.buildUpon();
+ ContentUris.appendId(builder, providerId);
+ return builder.build();
+ }
+
+ /**
+ * Gets the Uri to query off the record messages by account.
+ *
+ * @param accountId the account id.
+ * @return the Uri
+ */
+ public static final Uri getOtrMessagesContentUriByAccount(long accountId) {
+ Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT.buildUpon();
+ ContentUris.appendId(builder, accountId);
+ return builder.build();
+ }
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/messages");
+
+ /**
+ * The content:// style URL for messages by thread id
+ */
+ public static final Uri CONTENT_URI_MESSAGES_BY_THREAD_ID =
+ Uri.parse("content://imps/messagesByThreadId");
+
+ /**
+ * The content:// style URL for messages by account and contact
+ */
+ public static final Uri CONTENT_URI_MESSAGES_BY_ACCOUNT_AND_CONTACT =
+ Uri.parse("content://imps/messagesByAcctAndContact");
+
+ /**
+ * The content:// style URL for messages by provider
+ */
+ public static final Uri CONTENT_URI_MESSAGES_BY_PROVIDER =
+ Uri.parse("content://imps/messagesByProvider");
+
+ /**
+ * The content:// style URL for messages by account
+ */
+ public static final Uri CONTENT_URI_BY_ACCOUNT =
+ Uri.parse("content://imps/messagesByAccount");
+
+ /**
+ * The content:// style url for off the record messages
+ */
+ public static final Uri OTR_MESSAGES_CONTENT_URI =
+ Uri.parse("content://imps/otrMessages");
+
+ /**
+ * The content:// style url for off the record messages by thread id
+ */
+ public static final Uri OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID =
+ Uri.parse("content://imps/otrMessagesByThreadId");
+
+ /**
+ * The content:// style url for off the record messages by account and contact
+ */
+ public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT =
+ Uri.parse("content://imps/otrMessagesByAcctAndContact");
+
+ /**
+ * The content:// style URL for off the record messages by provider
+ */
+ public static final Uri OTR_MESSAGES_CONTENT_URI_BY_PROVIDER =
+ Uri.parse("content://imps/otrMessagesByProvider");
+
+ /**
+ * The content:// style URL for off the record messages by account
+ */
+ public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT =
+ Uri.parse("content://imps/otrMessagesByAccount");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * people.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-messages";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
+ * person.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-messages";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "date ASC";
+
+ /**
+ * The "contact" column. This is not a real column in the messages table, but a
+ * temoprary column created when querying for messages (joined with the contacts table)
+ */
+ public static final String CONTACT = "contact";
+ }
+
+ /**
+ * Columns for the GroupMember table.
+ */
+ public interface GroupMemberColumns {
+ /**
+ * The id of the group this member belongs to.
+ * <p>Type: INTEGER</p>
+ */
+ String GROUP = "groupId";
+
+ /**
+ * The full name of this member.
+ * <p>Type: TEXT</p>
+ */
+ String USERNAME = "username";
+
+ /**
+ * The nick name of this member.
+ * <p>Type: TEXT</p>
+ */
+ String NICKNAME = "nickname";
+ }
+
+ public final static class GroupMembers implements GroupMemberColumns {
+ private GroupMembers(){}
+
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/groupMembers");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * group members.
+ */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/imps-groupMembers";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
+ * group member.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-groupMembers";
+ }
+
+ /**
+ * Columns from the Invitation table.
+ */
+ public interface InvitationColumns {
+ /**
+ * The provider id.
+ * <p>Type: INTEGER</p>
+ */
+ String PROVIDER = "providerId";
+
+ /**
+ * The account id.
+ * <p>Type: INTEGER</p>
+ */
+ String ACCOUNT = "accountId";
+
+ /**
+ * The invitation id.
+ * <p>Type: TEXT</p>
+ */
+ String INVITE_ID = "inviteId";
+
+ /**
+ * The name of the sender of the invitation.
+ * <p>Type: TEXT</p>
+ */
+ String SENDER = "sender";
+
+ /**
+ * The name of the group which the sender invite you to join.
+ * <p>Type: TEXT</p>
+ */
+ String GROUP_NAME = "groupName";
+
+ /**
+ * A note
+ * <p>Type: TEXT</p>
+ */
+ String NOTE = "note";
+
+ /**
+ * The current status of the invitation.
+ * <p>Type: TEXT</p>
+ */
+ String STATUS = "status";
+
+ int STATUS_PENDING = 0;
+ int STATUS_ACCEPTED = 1;
+ int STATUS_REJECTED = 2;
+ }
+
+ /**
+ * This table contains the invitations received from others.
+ */
+ public final static class Invitation implements InvitationColumns,
+ BaseColumns {
+ private Invitation() {
+ }
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/invitations");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * invitations.
+ */
+ public static final String CONTENT_TYPE =
+ "vnd.android.cursor.dir/imps-invitations";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
+ * invitation.
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-invitations";
+ }
+
+ /**
+ * Columns from the Avatars table
+ */
+ public interface AvatarsColumns {
+ /**
+ * The contact this avatar belongs to
+ * <P>Type: TEXT</P>
+ */
+ String CONTACT = "contact";
+
+ String PROVIDER = "provider_id";
+
+ String ACCOUNT = "account_id";
+
+ /**
+ * The hash of the image data
+ * <P>Type: TEXT</P>
+ */
+ String HASH = "hash";
+
+ /**
+ * raw image data
+ * <P>Type: BLOB</P>
+ */
+ String DATA = "data";
+ }
+
+ /**
+ * This table contains avatars.
+ */
+ public static final class Avatars implements BaseColumns, AvatarsColumns {
+ /**
+ * no public constructor since this is a utility class
+ */
+ private Avatars() {}
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://imps/avatars");
+
+ /**
+ * The content:// style URL for avatars by provider, account and contact
+ */
+ public static final Uri CONTENT_URI_AVATARS_BY =
+ Uri.parse("content://imps/avatarsBy");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing the avatars
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-avatars";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI}
+ */
+ public static final String CONTENT_ITEM_TYPE =
+ "vnd.android.cursor.item/imps-avatars";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "contact ASC";
+
+ }
+
+ /**
+ * Common presence columns shared between the IM and contacts presence tables
+ */
+ public interface CommonPresenceColumns {
+ /**
+ * The priority, an integer, used by XMPP presence
+ * <P>Type: INTEGER</P>
+ */
+ String PRIORITY = "priority";
+
+ /**
+ * The server defined status.
+ * <P>Type: INTEGER (one of the values below)</P>
+ */
+ String PRESENCE_STATUS = "mode";
+
+ /**
+ * Presence Status definition
+ */
+ int OFFLINE = 0;
+ int INVISIBLE = 1;
+ int AWAY = 2;
+ int IDLE = 3;
+ int DO_NOT_DISTURB = 4;
+ int AVAILABLE = 5;
+
+ /**
+ * The user defined status line.
+ * <P>Type: TEXT</P>
+ */
+ String PRESENCE_CUSTOM_STATUS = "status";
+ }
+
+ /**
+ * Columns from the Presence table.
+ */
+ public interface PresenceColumns extends CommonPresenceColumns {
+ /**
+ * The contact id
+ * <P>Type: INTEGER</P>
+ */
+ String CONTACT_ID = "contact_id";
+
+ /**
+ * The contact's JID resource, only relevant for XMPP contact
+ * <P>Type: TEXT</P>
+ */
+ String JID_RESOURCE = "jid_resource";
+
+ /**
+ * The contact's client type
+ */
+ String CLIENT_TYPE = "client_type";
+
+ /**
+ * client type definitions
+ */
+ int CLIENT_TYPE_DEFAULT = 0;
+ int CLIENT_TYPE_MOBILE = 1;
+ int CLIENT_TYPE_ANDROID = 2;
+ }
+
+ /**
+ * Contains presence infomation for contacts.
+ */
+ public static final class Presence implements BaseColumns, PresenceColumns {
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://imps/presence");
+
+ /**
+ * The content URL for IM presences for an account
+ */
+ public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://imps/presence/account");
+
+ /**
+ * The content:// style URL for operations on bulk contacts
+ */
+ public static final Uri BULK_CONTENT_URI = Uri.parse("content://imps/bulk_presence");
+
+ /**
+ * The content:// style URL for seeding presences for a given account id.
+ */
+ public static final Uri SEED_PRESENCE_BY_ACCOUNT_CONTENT_URI =
+ Uri.parse("content://imps/seed_presence/account");
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} providing a directory of presence
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-presence";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "mode DESC";
+ }
+
+ /**
+ * Columns from the Chats table.
+ */
+ public interface ChatsColumns {
+ /**
+ * The contact ID this chat belongs to. The value is a long.
+ * <P>Type: INT</P>
+ */
+ String CONTACT_ID = "contact_id";
+
+ /**
+ * The GTalk JID resource. The value is a string.
+ * <P>Type: TEXT</P>
+ */
+ String JID_RESOURCE = "jid_resource";
+
+ /**
+ * Whether this is a groupchat or not.
+ * <P>Type: INT</P>
+ */
+ String GROUP_CHAT = "groupchat";
+
+ /**
+ * The last unread message. This both indicates that there is an
+ * unread message, and what the message is.
+ * <P>Type: TEXT</P>
+ */
+ String LAST_UNREAD_MESSAGE = "last_unread_message";
+
+ /**
+ * The last message timestamp
+ * <P>Type: INT</P>
+ */
+ String LAST_MESSAGE_DATE = "last_message_date";
+
+ /**
+ * A message that is being composed. This indicates that there was a
+ * message being composed when the chat screen was shutdown, and what the
+ * message is.
+ * <P>Type: TEXT</P>
+ */
+ String UNSENT_COMPOSED_MESSAGE = "unsent_composed_message";
+
+ /**
+ * A value from 0-9 indicating which quick-switch chat screen slot this
+ * chat is occupying. If none (for instance, this is the 12th active chat)
+ * then the value is -1.
+ * <P>Type: INT</P>
+ */
+ String SHORTCUT = "shortcut";
+ }
+
+ /**
+ * Contains ongoing chat sessions.
+ */
+ public static final class Chats implements BaseColumns, ChatsColumns {
+ /**
+ * no public constructor since this is a utility class
+ */
+ private Chats() {}
+
+ /**
+ * The content:// style URL for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/chats");
+
+ /**
+ * The content URL for all chats that belong to the account
+ */
+ public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://imps/chats/account");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of chats.
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-chats";
+
+ /**
+ * The MIME type of a {@link #CONTENT_URI} subdirectory of a single chat.
+ */
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/imps-chats";
+
+ /**
+ * The default sort order for this table
+ */
+ public static final String DEFAULT_SORT_ORDER = "last_message_date ASC";
+ }
+
+ /**
+ * Columns from session cookies table. Used for IMPS.
+ */
+ public static interface SessionCookiesColumns {
+ String NAME = "name";
+ String VALUE = "value";
+ String PROVIDER = "provider";
+ String ACCOUNT = "account";
+ }
+
+ /**
+ * Contains IMPS session cookies.
+ */
+ public static class SessionCookies implements SessionCookiesColumns, BaseColumns {
+ private SessionCookies() {
+ }
+
+ /**
+ * The content:// style URI for this table
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://imps/sessionCookies");
+
+ /**
+ * The content:// style URL for session cookies by provider and account
+ */
+ public static final Uri CONTENT_URI_SESSION_COOKIES_BY =
+ Uri.parse("content://imps/sessionCookiesBy");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing a directory of
+ * people.
+ */
+ public static final String CONTENT_TYPE = "vnd.android-dir/imps-sessionCookies";
+ }
+
+ /**
+ * Columns from ProviderSettings table
+ */
+ public static interface ProviderSettingsColumns {
+ /**
+ * The id in database of the related provider
+ *
+ * <P>Type: INT</P>
+ */
+ String PROVIDER = "provider";
+
+ /**
+ * The name of the setting
+ * <P>Type: TEXT</P>
+ */
+ String NAME = "name";
+
+ /**
+ * The value of the setting
+ * <P>Type: TEXT</P>
+ */
+ String VALUE = "value";
+ }
+
+ public static class ProviderSettings implements ProviderSettingsColumns {
+ private ProviderSettings() {
+ }
+
+ /**
+ * The content:// style URI for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.parse("content://imps/providerSettings");
+
+ /**
+ * The MIME type of {@link #CONTENT_URI} providing provider settings
+ */
+ public static final String CONTENT_TYPE = "vnd.android-dir/imps-providerSettings";
+
+ /**
+ * A boolean value to indicate whether this provider should show the offline contacts
+ */
+ public static final String SHOW_OFFLINE_CONTACTS = "show_offline_contacts";
+
+ /** controls whether or not the GTalk service automatically connect to server. */
+ public static final String SETTING_AUTOMATICALLY_CONNECT_GTALK = "gtalk_auto_connect";
+
+ /** controls whether or not the IM service will be automatically started after boot */
+ public static final String SETTING_AUTOMATICALLY_START_SERVICE = "auto_start_service";
+
+ /** controls whether or not the offline contacts will be hided */
+ public static final String SETTING_HIDE_OFFLINE_CONTACTS = "hide_offline_contacts";
+
+ /** controls whether or not enable the IM notification */
+ public static final String SETTING_ENABLE_NOTIFICATION = "enable_notification";
+
+ /** specifies whether or not to vibrate */
+ public static final String SETTING_VIBRATE = "vibrate";
+
+ /** specifies the Uri string of the ringtone */
+ public static final String SETTING_RINGTONE = "ringtone";
+
+ /** specifies the Uri of the default ringtone */
+ public static final String SETTING_RINGTONE_DEFAULT =
+ "content://settings/system/notification_sound";
+
+ /** specifies whether or not to show mobile indicator to friends */
+ public static final String SETTING_SHOW_MOBILE_INDICATOR = "mobile_indicator";
+
+ /** specifies whether or not to show as away when device is idle */
+ public static final String SETTING_SHOW_AWAY_ON_IDLE = "show_away_on_idle";
+
+ /** specifies whether or not to upload heartbeat stat upon login */
+ public static final String SETTING_UPLOAD_HEARTBEAT_STAT = "upload_heartbeat_stat";
+
+ /** specifies the last heartbeat interval received from the server */
+ public static final String SETTING_HEARTBEAT_INTERVAL = "heartbeat_interval";
+
+ /** specifiy the JID resource used for Google Talk connection */
+ public static final String SETTING_JID_RESOURCE = "jid_resource";
+
+ /**
+ * Used for reliable message queue (RMQ). This is for storing the last rmq id received
+ * from the GTalk server
+ */
+ public static final String LAST_RMQ_RECEIVED = "last_rmq_rec";
+
+ /**
+ * Query the settings of the provider specified by id
+ *
+ * @param cr
+ * the relative content resolver
+ * @param providerId
+ * the specified id of provider
+ * @return a HashMap which contains all the settings for the specified
+ * provider
+ */
+ public static HashMap<String, String> queryProviderSettings(ContentResolver cr,
+ long providerId) {
+ HashMap<String, String> settings = new HashMap<String, String>();
+
+ String[] projection = { NAME, VALUE };
+ Cursor c = cr.query(ContentUris.withAppendedId(CONTENT_URI, providerId), projection, null, null, null);
+ if (c == null) {
+ return null;
+ }
+
+ while(c.moveToNext()) {
+ settings.put(c.getString(0), c.getString(1));
+ }
+
+ c.close();
+
+ return settings;
+ }
+
+ /**
+ * Get the string value of setting which is specified by provider id and the setting name.
+ *
+ * @param cr The ContentResolver to use to access the settings table.
+ * @param providerId The id of the provider.
+ * @param settingName The name of the setting.
+ * @return The value of the setting if the setting exist, otherwise return null.
+ */
+ public static String getStringValue(ContentResolver cr, long providerId, String settingName) {
+ String ret = null;
+ Cursor c = getSettingValue(cr, providerId, settingName);
+ if (c != null) {
+ ret = c.getString(0);
+ c.close();
+ }
+
+ return ret;
+ }
+
+ /**
+ * Get the boolean value of setting which is specified by provider id and the setting name.
+ *
+ * @param cr The ContentResolver to use to access the settings table.
+ * @param providerId The id of the provider.
+ * @param settingName The name of the setting.
+ * @return The value of the setting if the setting exist, otherwise return false.
+ */
+ public static boolean getBooleanValue(ContentResolver cr, long providerId, String settingName) {
+ boolean ret = false;
+ Cursor c = getSettingValue(cr, providerId, settingName);
+ if (c != null) {
+ ret = c.getInt(0) != 0;
+ c.close();
+ }
+ return ret;
+ }
+
+ private static Cursor getSettingValue(ContentResolver cr, long providerId, String settingName) {
+ Cursor c = cr.query(ContentUris.withAppendedId(CONTENT_URI, providerId), new String[]{VALUE}, NAME + "=?",
+ new String[]{settingName}, null);
+ if (c != null) {
+ if (!c.moveToFirst()) {
+ c.close();
+ return null;
+ }
+ }
+ return c;
+ }
+
+ /**
+ * Save a long value of setting in the table providerSetting.
+ *
+ * @param cr The ContentProvider used to access the providerSetting table.
+ * @param providerId The id of the provider.
+ * @param name The name of the setting.
+ * @param value The value of the setting.
+ */
+ public static void putLongValue(ContentResolver cr, long providerId, String name,
+ long value) {
+ ContentValues v = new ContentValues(3);
+ v.put(PROVIDER, providerId);
+ v.put(NAME, name);
+ v.put(VALUE, value);
+
+ cr.insert(CONTENT_URI, v);
+ }
+
+ /**
+ * Save a boolean value of setting in the table providerSetting.
+ *
+ * @param cr The ContentProvider used to access the providerSetting table.
+ * @param providerId The id of the provider.
+ * @param name The name of the setting.
+ * @param value The value of the setting.
+ */
+ public static void putBooleanValue(ContentResolver cr, long providerId, String name,
+ boolean value) {
+ ContentValues v = new ContentValues(3);
+ v.put(PROVIDER, providerId);
+ v.put(NAME, name);
+ v.put(VALUE, Boolean.toString(value));
+
+ cr.insert(CONTENT_URI, v);
+ }
+
+ /**
+ * Save a string value of setting in the table providerSetting.
+ *
+ * @param cr The ContentProvider used to access the providerSetting table.
+ * @param providerId The id of the provider.
+ * @param name The name of the setting.
+ * @param value The value of the setting.
+ */
+ public static void putStringValue(ContentResolver cr, long providerId, String name,
+ String value) {
+ ContentValues v = new ContentValues(3);
+ v.put(PROVIDER, providerId);
+ v.put(NAME, name);
+ v.put(VALUE, value);
+
+ cr.insert(CONTENT_URI, v);
+ }
+
+ /**
+ * A convenience method to set whether or not the GTalk service should be started
+ * automatically.
+ *
+ * @param contentResolver The ContentResolver to use to access the settings table
+ * @param autoConnect Whether the GTalk service should be started automatically.
+ */
+ public static void setAutomaticallyConnectGTalk(ContentResolver contentResolver,
+ long providerId, boolean autoConnect) {
+ putBooleanValue(contentResolver, providerId, SETTING_AUTOMATICALLY_CONNECT_GTALK,
+ autoConnect);
+ }
+
+ /**
+ * A convenience method to set whether or not the offline contacts should be hided
+ *
+ * @param contentResolver The ContentResolver to use to access the setting table
+ * @param hideOfflineContacts Whether the offline contacts should be hided
+ */
+ public static void setHideOfflineContacts(ContentResolver contentResolver,
+ long providerId, boolean hideOfflineContacts) {
+ putBooleanValue(contentResolver, providerId, SETTING_HIDE_OFFLINE_CONTACTS,
+ hideOfflineContacts);
+ }
+
+ /**
+ * A convenience method to set whether or not enable the IM notification.
+ *
+ * @param contentResolver The ContentResolver to use to access the setting table.
+ * @param enable Whether enable the IM notification
+ */
+ public static void setEnableNotification(ContentResolver contentResolver, long providerId,
+ boolean enable) {
+ putBooleanValue(contentResolver, providerId, SETTING_ENABLE_NOTIFICATION, enable);
+ }
+
+ /**
+ * A convenience method to set whether or not to vibrate.
+ *
+ * @param contentResolver The ContentResolver to use to access the setting table.
+ * @param vibrate Whether or not to vibrate
+ */
+ public static void setVibrate(ContentResolver contentResolver, long providerId,
+ boolean vibrate) {
+ putBooleanValue(contentResolver, providerId, SETTING_VIBRATE, vibrate);
+ }
+
+ /**
+ * A convenience method to set the Uri String of the ringtone.
+ *
+ * @param contentResolver The ContentResolver to use to access the setting table.
+ * @param ringtoneUri The Uri String of the ringtone to be set.
+ */
+ public static void setRingtoneURI(ContentResolver contentResolver, long providerId,
+ String ringtoneUri) {
+ putStringValue(contentResolver, providerId, SETTING_RINGTONE, ringtoneUri);
+ }
+
+ /**
+ * A convenience method to set whether or not to show mobile indicator.
+ *
+ * @param contentResolver The ContentResolver to use to access the setting table.
+ * @param showMobileIndicator Whether or not to show mobile indicator.
+ */
+ public static void setShowMobileIndicator(ContentResolver contentResolver, long providerId,
+ boolean showMobileIndicator) {
+ putBooleanValue(contentResolver, providerId, SETTING_SHOW_MOBILE_INDICATOR,
+ showMobileIndicator);
+ }
+
+ /**
+ * A convenience method to set whether or not to show as away when device is idle.
+ *
+ * @param contentResolver The ContentResolver to use to access the setting table.
+ * @param showAway Whether or not to show as away when device is idle.
+ */
+ public static void setShowAwayOnIdle(ContentResolver contentResolver,
+ long providerId, boolean showAway) {
+ putBooleanValue(contentResolver, providerId, SETTING_SHOW_AWAY_ON_IDLE, showAway);
+ }
+
+ /**
+ * A convenience method to set whether or not to upload heartbeat stat.
+ *
+ * @param contentResolver The ContentResolver to use to access the setting table.
+ * @param uploadStat Whether or not to upload heartbeat stat.
+ */
+ public static void setUploadHeartbeatStat(ContentResolver contentResolver,
+ long providerId, boolean uploadStat) {
+ putBooleanValue(contentResolver, providerId, SETTING_UPLOAD_HEARTBEAT_STAT, uploadStat);
+ }
+
+ /**
+ * A convenience method to set the heartbeat interval last received from the server.
+ *
+ * @param contentResolver The ContentResolver to use to access the setting table.
+ * @param interval The heartbeat interval last received from the server.
+ */
+ public static void setHeartbeatInterval(ContentResolver contentResolver,
+ long providerId, long interval) {
+ putLongValue(contentResolver, providerId, SETTING_HEARTBEAT_INTERVAL, interval);
+ }
+
+ /**
+ * A convenience method to set the jid resource.
+ */
+ public static void setJidResource(ContentResolver contentResolver,
+ long providerId, String jidResource) {
+ putStringValue(contentResolver, providerId, SETTING_JID_RESOURCE, jidResource);
+ }
+
+ public static class QueryMap extends ContentQueryMap {
+ private ContentResolver mContentResolver;
+ private long mProviderId;
+
+ public QueryMap(ContentResolver contentResolver, long providerId, boolean keepUpdated,
+ Handler handlerForUpdateNotifications) {
+ super(contentResolver.query(CONTENT_URI,
+ new String[] {NAME,VALUE},
+ PROVIDER + "=" + providerId,
+ null, // no selection args
+ null), // no sort order
+ NAME, keepUpdated, handlerForUpdateNotifications);
+ mContentResolver = contentResolver;
+ mProviderId = providerId;
+ }
+
+ /**
+ * Set if the GTalk service should automatically connect to server.
+ *
+ * @param autoConnect if the GTalk service should auto connect to server.
+ */
+ public void setAutomaticallyConnectToGTalkServer(boolean autoConnect) {
+ ProviderSettings.setAutomaticallyConnectGTalk(mContentResolver, mProviderId,
+ autoConnect);
+ }
+
+ /**
+ * Check if the GTalk service should automatically connect to server.
+ * @return if the GTalk service should automatically connect to server.
+ */
+ public boolean getAutomaticallyConnectToGTalkServer() {
+ return getBoolean(SETTING_AUTOMATICALLY_CONNECT_GTALK,
+ true /* default to automatically sign in */);
+ }
+
+ /**
+ * Set whether or not the offline contacts should be hided.
+ *
+ * @param hideOfflineContacts Whether or not the offline contacts should be hided.
+ */
+ public void setHideOfflineContacts(boolean hideOfflineContacts) {
+ ProviderSettings.setHideOfflineContacts(mContentResolver, mProviderId,
+ hideOfflineContacts);
+ }
+
+ /**
+ * Check if the offline contacts should be hided.
+ *
+ * @return Whether or not the offline contacts should be hided.
+ */
+ public boolean getHideOfflineContacts() {
+ return getBoolean(SETTING_HIDE_OFFLINE_CONTACTS,
+ false/* by default not hide the offline contacts*/);
+ }
+
+ /**
+ * Set whether or not enable the IM notification.
+ *
+ * @param enable Whether or not enable the IM notification.
+ */
+ public void setEnableNotification(boolean enable) {
+ ProviderSettings.setEnableNotification(mContentResolver, mProviderId, enable);
+ }
+
+ /**
+ * Check if the IM notification is enabled.
+ *
+ * @return Whether or not enable the IM notification.
+ */
+ public boolean getEnableNotification() {
+ return getBoolean(SETTING_ENABLE_NOTIFICATION,
+ true/* by default enable the notification */);
+ }
+
+ /**
+ * Set whether or not to vibrate on IM notification.
+ *
+ * @param vibrate Whether or not to vibrate.
+ */
+ public void setVibrate(boolean vibrate) {
+ ProviderSettings.setVibrate(mContentResolver, mProviderId, vibrate);
+ }
+
+ /**
+ * Gets whether or not to vibrate on IM notification.
+ *
+ * @return Whether or not to vibrate.
+ */
+ public boolean getVibrate() {
+ return getBoolean(SETTING_VIBRATE, false /* by default disable vibrate */);
+ }
+
+ /**
+ * Set the Uri for the ringtone.
+ *
+ * @param ringtoneUri The Uri of the ringtone to be set.
+ */
+ public void setRingtoneURI(String ringtoneUri) {
+ ProviderSettings.setRingtoneURI(mContentResolver, mProviderId, ringtoneUri);
+ }
+
+ /**
+ * Get the Uri String of the current ringtone.
+ *
+ * @return The Uri String of the current ringtone.
+ */
+ public String getRingtoneURI() {
+ return getString(SETTING_RINGTONE, SETTING_RINGTONE_DEFAULT);
+ }
+
+ /**
+ * Set whether or not to show mobile indicator to friends.
+ *
+ * @param showMobile whether or not to show mobile indicator.
+ */
+ public void setShowMobileIndicator(boolean showMobile) {
+ ProviderSettings.setShowMobileIndicator(mContentResolver, mProviderId, showMobile);
+ }
+
+ /**
+ * Gets whether or not to show mobile indicator.
+ *
+ * @return Whether or not to show mobile indicator.
+ */
+ public boolean getShowMobileIndicator() {
+ return getBoolean(SETTING_SHOW_MOBILE_INDICATOR,
+ true /* by default show mobile indicator */);
+ }
+
+ /**
+ * Set whether or not to show as away when device is idle.
+ *
+ * @param showAway whether or not to show as away when device is idle.
+ */
+ public void setShowAwayOnIdle(boolean showAway) {
+ ProviderSettings.setShowAwayOnIdle(mContentResolver, mProviderId, showAway);
+ }
+
+ /**
+ * Get whether or not to show as away when device is idle.
+ *
+ * @return Whether or not to show as away when device is idle.
+ */
+ public boolean getShowAwayOnIdle() {
+ return getBoolean(SETTING_SHOW_AWAY_ON_IDLE,
+ true /* by default show as away on idle*/);
+ }
+
+ /**
+ * Set whether or not to upload heartbeat stat.
+ *
+ * @param uploadStat whether or not to upload heartbeat stat.
+ */
+ public void setUploadHeartbeatStat(boolean uploadStat) {
+ ProviderSettings.setUploadHeartbeatStat(mContentResolver, mProviderId, uploadStat);
+ }
+
+ /**
+ * Get whether or not to upload heartbeat stat.
+ *
+ * @return Whether or not to upload heartbeat stat.
+ */
+ public boolean getUploadHeartbeatStat() {
+ return getBoolean(SETTING_UPLOAD_HEARTBEAT_STAT,
+ false /* by default do not upload */);
+ }
+
+ /**
+ * Set the last received heartbeat interval from the server.
+ *
+ * @param interval the last received heartbeat interval from the server.
+ */
+ public void setHeartbeatInterval(long interval) {
+ ProviderSettings.setHeartbeatInterval(mContentResolver, mProviderId, interval);
+ }
+
+ /**
+ * Get the last received heartbeat interval from the server.
+ *
+ * @return the last received heartbeat interval from the server.
+ */
+ public long getHeartbeatInterval() {
+ return getLong(SETTING_HEARTBEAT_INTERVAL, 0L /* an invalid default interval */);
+ }
+
+ /**
+ * Set the JID resource.
+ *
+ * @param jidResource the jid resource to be stored.
+ */
+ public void setJidResource(String jidResource) {
+ ProviderSettings.setJidResource(mContentResolver, mProviderId, jidResource);
+ }
+ /**
+ * Get the JID resource used for the Google Talk connection
+ *
+ * @return the JID resource stored.
+ */
+ public String getJidResource() {
+ return getString(SETTING_JID_RESOURCE, null);
+ }
+
+ /**
+ * Convenience function for retrieving a single settings value
+ * as a boolean.
+ *
+ * @param name The name of the setting to retrieve.
+ * @param def Value to return if the setting is not defined.
+ * @return The setting's current value, or 'def' if it is not defined.
+ */
+ private boolean getBoolean(String name, boolean def) {
+ ContentValues values = getValues(name);
+ return values != null ? values.getAsBoolean(VALUE) : def;
+ }
+
+ /**
+ * Convenience function for retrieving a single settings value
+ * as a String.
+ *
+ * @param name The name of the setting to retrieve.
+ * @param def The value to return if the setting is not defined.
+ * @return The setting's current value or 'def' if it is not defined.
+ */
+ private String getString(String name, String def) {
+ ContentValues values = getValues(name);
+ return values != null ? values.getAsString(VALUE) : def;
+ }
+
+ /**
+ * Convenience function for retrieving a single settings value
+ * as an Integer.
+ *
+ * @param name The name of the setting to retrieve.
+ * @param def The value to return if the setting is not defined.
+ * @return The setting's current value or 'def' if it is not defined.
+ */
+ private int getInteger(String name, int def) {
+ ContentValues values = getValues(name);
+ return values != null ? values.getAsInteger(VALUE) : def;
+ }
+
+ /**
+ * Convenience function for retrieving a single settings value
+ * as a Long.
+ *
+ * @param name The name of the setting to retrieve.
+ * @param def The value to return if the setting is not defined.
+ * @return The setting's current value or 'def' if it is not defined.
+ */
+ private long getLong(String name, long def) {
+ ContentValues values = getValues(name);
+ return values != null ? values.getAsLong(VALUE) : def;
+ }
+ }
+
+ }
+
+
+ /**
+ * Columns for IM branding resource map cache table. This table caches the result of
+ * loading the branding resources to speed up IM landing page start.
+ */
+ public interface BrandingResourceMapCacheColumns {
+ /**
+ * The provider ID
+ * <P>Type: INTEGER</P>
+ */
+ String PROVIDER_ID = "provider_id";
+ /**
+ * The application resource ID
+ * <P>Type: INTEGER</P>
+ */
+ String APP_RES_ID = "app_res_id";
+ /**
+ * The plugin resource ID
+ * <P>Type: INTEGER</P>
+ */
+ String PLUGIN_RES_ID = "plugin_res_id";
+ }
+
+ /**
+ * The table for caching the result of loading IM branding resources.
+ */
+ public static final class BrandingResourceMapCache
+ implements BaseColumns, BrandingResourceMapCacheColumns {
+ /**
+ * The content:// style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://imps/brandingResMapCache");
+ }
+
+
+
+ /**
+ * //TODO: move these to MCS specific provider.
+ * The following are MCS stuff, and should really live in a separate provider specific to
+ * MCS code.
+ */
+
+ /**
+ * Columns from OutgoingRmq table
+ */
+ public interface OutgoingRmqColumns {
+ String RMQ_ID = "rmq_id";
+ String TIMESTAMP = "ts";
+ String DATA = "data";
+ String PROTOBUF_TAG = "type";
+ }
+
+ /**
+ * //TODO: we should really move these to their own provider and database.
+ * The table for storing outgoing rmq packets.
+ */
+ public static final class OutgoingRmq implements BaseColumns, OutgoingRmqColumns {
+ private static String[] RMQ_ID_PROJECTION = new String[] {
+ RMQ_ID,
+ };
+
+ /**
+ * queryHighestRmqId
+ *
+ * @param resolver the content resolver
+ * @return the highest rmq id assigned to the rmq packet, or 0 if there are no rmq packets
+ * in the OutgoingRmq table.
+ */
+ public static final long queryHighestRmqId(ContentResolver resolver) {
+ Cursor cursor = resolver.query(Imps.OutgoingRmq.CONTENT_URI_FOR_HIGHEST_RMQ_ID,
+ RMQ_ID_PROJECTION,
+ null, // selection
+ null, // selection args
+ null // sort
+ );
+
+ long retVal = 0;
+ try {
+ //if (DBG) log("initializeRmqid: cursor.count= " + cursor.count());
+
+ if (cursor.moveToFirst()) {
+ retVal = cursor.getLong(cursor.getColumnIndexOrThrow(RMQ_ID));
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return retVal;
+ }
+
+ /**
+ * The content:// style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://imps/outgoingRmqMessages");
+
+ /**
+ * The content:// style URL for the highest rmq id for the outgoing rmq messages
+ */
+ public static final Uri CONTENT_URI_FOR_HIGHEST_RMQ_ID =
+ Uri.parse("content://imps/outgoingHighestRmqId");
+
+ /**
+ * The default sort order for this table.
+ */
+ public static final String DEFAULT_SORT_ORDER = "rmq_id ASC";
+ }
+
+ /**
+ * Columns for the LastRmqId table, which stores a single row for the last client rmq id
+ * sent to the server.
+ */
+ public interface LastRmqIdColumns {
+ String RMQ_ID = "rmq_id";
+ }
+
+ /**
+ * //TODO: move these out into their own provider and database
+ * The table for storing the last client rmq id sent to the server.
+ */
+ public static final class LastRmqId implements BaseColumns, LastRmqIdColumns {
+ private static String[] PROJECTION = new String[] {
+ RMQ_ID,
+ };
+
+ /**
+ * queryLastRmqId
+ *
+ * queries the last rmq id saved in the LastRmqId table.
+ *
+ * @param resolver the content resolver.
+ * @return the last rmq id stored in the LastRmqId table, or 0 if not found.
+ */
+ public static final long queryLastRmqId(ContentResolver resolver) {
+ Cursor cursor = resolver.query(Imps.LastRmqId.CONTENT_URI,
+ PROJECTION,
+ null, // selection
+ null, // selection args
+ null // sort
+ );
+
+ long retVal = 0;
+ try {
+ if (cursor.moveToFirst()) {
+ retVal = cursor.getLong(cursor.getColumnIndexOrThrow(RMQ_ID));
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return retVal;
+ }
+
+ /**
+ * saveLastRmqId
+ *
+ * saves the rmqId to the lastRmqId table. This will override the existing row if any,
+ * as we only keep one row of data in this table.
+ *
+ * @param resolver the content resolver.
+ * @param rmqId the rmq id to be saved.
+ */
+ public static final void saveLastRmqId(ContentResolver resolver, long rmqId) {
+ ContentValues values = new ContentValues();
+
+ // always replace the first row.
+ values.put(_ID, 1);
+ values.put(RMQ_ID, rmqId);
+ resolver.insert(CONTENT_URI, values);
+ }
+
+ /**
+ * The content:// style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://imps/lastRmqId");
+ }
+
+ /**
+ * Columns for the s2dRmqIds table, which stores the server-to-device message
+ * persistent ids. These are used in the RMQ2 protocol, where in the login request, the
+ * client selective acks these s2d ids to the server.
+ */
+ public interface ServerToDeviceRmqIdsColumn {
+ String RMQ_ID = "rmq_id";
+ }
+
+ public static final class ServerToDeviceRmqIds implements BaseColumns,
+ ServerToDeviceRmqIdsColumn {
+
+ /**
+ * The content:// style URL for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.parse("content://imps/s2dids");
+ }
+
+}
diff --git a/src/com/android/im/provider/ImpsProvider.java b/src/com/android/im/provider/ImpsProvider.java
new file mode 100644
index 0000000..0a32d50
--- /dev/null
+++ b/src/com/android/im/provider/ImpsProvider.java
@@ -0,0 +1,3332 @@
+/*
+ * 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.im.provider;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.UriMatcher;
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteConstraintException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.text.TextUtils;
+import android.util.Log;
+
+
+import java.io.FileNotFoundException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * A content provider for IM
+ */
+public class ImpsProvider extends ContentProvider {
+ private static final String LOG_TAG = "imProvider";
+ private static final boolean DBG = false;
+
+ private static final String AUTHORITY = "imps";
+
+ private static final String TABLE_ACCOUNTS = "accounts";
+ private static final String TABLE_PROVIDERS = "providers";
+ private static final String TABLE_PROVIDER_SETTINGS = "providerSettings";
+
+ private static final String TABLE_CONTACTS = "contacts";
+ private static final String TABLE_CONTACTS_ETAG = "contactsEtag";
+ private static final String TABLE_BLOCKED_LIST = "blockedList";
+ private static final String TABLE_CONTACT_LIST = "contactList";
+ private static final String TABLE_INVITATIONS = "invitations";
+ private static final String TABLE_GROUP_MEMBERS = "groupMembers";
+ private static final String TABLE_PRESENCE = "presence";
+ private static final String USERNAME = "username";
+ private static final String TABLE_CHATS = "chats";
+ private static final String TABLE_AVATARS = "avatars";
+ private static final String TABLE_SESSION_COOKIES = "sessionCookies";
+ private static final String TABLE_MESSAGES = "messages";
+ private static final String TABLE_IN_MEMORY_MESSAGES = "inMemoryMessages";
+ private static final String TABLE_ACCOUNT_STATUS = "accountStatus";
+ private static final String TABLE_BRANDING_RESOURCE_MAP_CACHE = "brandingResMapCache";
+
+ // tables for mcs and rmq
+ private static final String TABLE_OUTGOING_RMQ_MESSAGES = "outgoingRmqMessages";
+ private static final String TABLE_LAST_RMQ_ID = "lastrmqid";
+ private static final String TABLE_S2D_RMQ_IDS = "s2dRmqIds";
+
+
+ private static final String DATABASE_NAME = "imps.db";
+ private static final int DATABASE_VERSION = 1;
+
+ protected static final int MATCH_PROVIDERS = 1;
+ protected static final int MATCH_PROVIDERS_BY_ID = 2;
+ protected static final int MATCH_PROVIDERS_WITH_ACCOUNT = 3;
+ protected static final int MATCH_ACCOUNTS = 10;
+ protected static final int MATCH_ACCOUNTS_BY_ID = 11;
+ protected static final int MATCH_CONTACTS = 18;
+ protected static final int MATCH_CONTACTS_JOIN_PRESENCE = 19;
+ protected static final int MATCH_CONTACTS_BAREBONE = 20;
+ protected static final int MATCH_CHATTING_CONTACTS = 21;
+ protected static final int MATCH_CONTACTS_BY_PROVIDER = 22;
+ protected static final int MATCH_CHATTING_CONTACTS_BY_PROVIDER = 23;
+ protected static final int MATCH_NO_CHATTING_CONTACTS_BY_PROVIDER = 24;
+ protected static final int MATCH_ONLINE_CONTACTS_BY_PROVIDER = 25;
+ protected static final int MATCH_OFFLINE_CONTACTS_BY_PROVIDER = 26;
+ protected static final int MATCH_CONTACT = 27;
+ protected static final int MATCH_CONTACTS_BULK = 28;
+ protected static final int MATCH_ONLINE_CONTACT_COUNT = 30;
+ protected static final int MATCH_BLOCKED_CONTACTS = 31;
+ protected static final int MATCH_CONTACTLISTS = 32;
+ protected static final int MATCH_CONTACTLISTS_BY_PROVIDER = 33;
+ protected static final int MATCH_CONTACTLIST = 34;
+ protected static final int MATCH_BLOCKEDLIST = 35;
+ protected static final int MATCH_BLOCKEDLIST_BY_PROVIDER = 36;
+ protected static final int MATCH_CONTACTS_ETAGS = 37;
+ protected static final int MATCH_CONTACTS_ETAG = 38;
+ protected static final int MATCH_PRESENCE = 40;
+ protected static final int MATCH_PRESENCE_ID = 41;
+ protected static final int MATCH_PRESENCE_BY_ACCOUNT = 42;
+ protected static final int MATCH_PRESENCE_SEED_BY_ACCOUNT = 43;
+ protected static final int MATCH_PRESENCE_BULK = 44;
+
+ protected static final int MATCH_MESSAGES = 50;
+ protected static final int MATCH_MESSAGES_BY_CONTACT = 51;
+ protected static final int MATCH_MESSAGES_BY_THREAD_ID = 52;
+ protected static final int MATCH_MESSAGES_BY_PROVIDER = 53;
+ protected static final int MATCH_MESSAGES_BY_ACCOUNT = 54;
+ protected static final int MATCH_MESSAGE = 55;
+ protected static final int MATCH_OTR_MESSAGES = 56;
+ protected static final int MATCH_OTR_MESSAGES_BY_CONTACT = 57;
+ protected static final int MATCH_OTR_MESSAGES_BY_THREAD_ID = 58;
+ protected static final int MATCH_OTR_MESSAGES_BY_PROVIDER = 59;
+ protected static final int MATCH_OTR_MESSAGES_BY_ACCOUNT = 60;
+ protected static final int MATCH_OTR_MESSAGE = 61;
+
+ protected static final int MATCH_GROUP_MEMBERS = 65;
+ protected static final int MATCH_GROUP_MEMBERS_BY_GROUP = 66;
+ protected static final int MATCH_AVATARS = 70;
+ protected static final int MATCH_AVATAR = 71;
+ protected static final int MATCH_AVATAR_BY_PROVIDER = 72;
+ protected static final int MATCH_CHATS = 80;
+ protected static final int MATCH_CHATS_BY_ACCOUNT = 81;
+ protected static final int MATCH_CHATS_ID = 82;
+ protected static final int MATCH_SESSIONS = 83;
+ protected static final int MATCH_SESSIONS_BY_PROVIDER = 84;
+ protected static final int MATCH_PROVIDER_SETTINGS = 90;
+ protected static final int MATCH_PROVIDER_SETTINGS_BY_ID = 91;
+ protected static final int MATCH_PROVIDER_SETTINGS_BY_ID_AND_NAME = 92;
+ protected static final int MATCH_INVITATIONS = 100;
+ protected static final int MATCH_INVITATION = 101;
+ protected static final int MATCH_ACCOUNTS_STATUS = 104;
+ protected static final int MATCH_ACCOUNT_STATUS = 105;
+ protected static final int MATCH_BRANDING_RESOURCE_MAP_CACHE = 106;
+
+ // mcs url matcher
+ protected static final int MATCH_OUTGOING_RMQ_MESSAGES = 200;
+ protected static final int MATCH_OUTGOING_RMQ_MESSAGE = 201;
+ protected static final int MATCH_OUTGOING_HIGHEST_RMQ_ID = 202;
+ protected static final int MATCH_LAST_RMQ_ID = 203;
+ protected static final int MATCH_S2D_RMQ_IDS = 204;
+
+
+ protected final UriMatcher mUrlMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ private final String mTransientDbName;
+
+ private static final HashMap<String, String> sProviderAccountsProjectionMap;
+ private static final HashMap<String, String> sContactsProjectionMap;
+ private static final HashMap<String, String> sContactListProjectionMap;
+ private static final HashMap<String, String> sBlockedListProjectionMap;
+ private static final HashMap<String, String> sMessagesProjectionMap;
+ private static final HashMap<String, String> sInMemoryMessagesProjectionMap;
+
+
+ private static final String PROVIDER_JOIN_ACCOUNT_TABLE =
+ "providers LEFT OUTER JOIN accounts ON " +
+ "(providers._id = accounts.provider AND accounts.active = 1) " +
+ "LEFT OUTER JOIN accountStatus ON (accounts._id = accountStatus.account)";
+
+
+ private static final String CONTACT_JOIN_PRESENCE_TABLE =
+ "contacts LEFT OUTER JOIN presence ON (contacts._id = presence.contact_id)";
+
+ private static final String CONTACT_JOIN_PRESENCE_CHAT_TABLE =
+ CONTACT_JOIN_PRESENCE_TABLE +
+ " LEFT OUTER JOIN chats ON (contacts._id = chats.contact_id)";
+
+ private static final String CONTACT_JOIN_PRESENCE_CHAT_AVATAR_TABLE =
+ CONTACT_JOIN_PRESENCE_CHAT_TABLE +
+ " LEFT OUTER JOIN avatars ON (contacts.username = avatars.contact" +
+ " AND contacts.account = avatars.account_id)";
+
+ private static final String BLOCKEDLIST_JOIN_AVATAR_TABLE =
+ "blockedList LEFT OUTER JOIN avatars ON (blockedList.username = avatars.contact" +
+ " AND blockedList.account = avatars.account_id)";
+
+ private static final String MESSAGE_JOIN_CONTACT_TABLE =
+ "messages LEFT OUTER JOIN contacts ON (contacts._id = messages.thread_id)";
+
+ private static final String IN_MEMORY_MESSAGES_JOIN_CONTACT_TABLE =
+ "inMemoryMessages LEFT OUTER JOIN contacts ON " +
+ "(contacts._id = inMemoryMessages.thread_id)";
+
+ /**
+ * The where clause for filtering out blocked contacts
+ */
+ private static final String NON_BLOCKED_CONTACTS_WHERE_CLAUSE = "("
+ + Imps.Contacts.TYPE + " IS NULL OR "
+ + Imps.Contacts.TYPE + "!="
+ + String.valueOf(Imps.Contacts.TYPE_BLOCKED)
+ + ")";
+
+ private static final String BLOCKED_CONTACTS_WHERE_CLAUSE =
+ "(contacts." + Imps.Contacts.TYPE + "=" + Imps.Contacts.TYPE_BLOCKED + ")";
+
+ private static final String CONTACT_ID = TABLE_CONTACTS + '.' + Imps.Contacts._ID;
+ private static final String PRESENCE_CONTACT_ID = TABLE_PRESENCE + '.' + Imps.Presence.CONTACT_ID;
+
+ protected SQLiteOpenHelper mOpenHelper;
+ private final String mDatabaseName;
+ private final int mDatabaseVersion;
+
+ private final String[] BACKFILL_PROJECTION = {
+ Imps.Chats._ID, Imps.Chats.SHORTCUT, Imps.Chats.LAST_MESSAGE_DATE
+ };
+
+ private final String[] FIND_SHORTCUT_PROJECTION = {
+ Imps.Chats._ID, Imps.Chats.SHORTCUT
+ };
+
+ // contact id query projection
+ private static final String[] CONTACT_ID_PROJECTION = new String[] {
+ Imps.Contacts._ID, // 0
+ };
+ private static final int CONTACT_ID_COLUMN = 0;
+
+ // contact id query selection for "seed presence" operation
+ private static final String CONTACTS_WITH_NO_PRESENCE_SELECTION =
+ Imps.Contacts.ACCOUNT + "=?" + " AND " + Imps.Contacts._ID +
+ " in (select " + CONTACT_ID + " from " + TABLE_CONTACTS +
+ " left outer join " + TABLE_PRESENCE + " on " + CONTACT_ID + '=' +
+ PRESENCE_CONTACT_ID + " where " + PRESENCE_CONTACT_ID + " IS NULL)";
+
+ // contact id query selection args 1
+ private String[] mQueryContactIdSelectionArgs1 = new String[1];
+
+ // contact id query selection for getContactId()
+ private static final String CONTACT_ID_QUERY_SELECTION =
+ Imps.Contacts.ACCOUNT + "=? AND " + Imps.Contacts.USERNAME + "=?";
+
+ // contact id query selection args 2
+ private String[] mQueryContactIdSelectionArgs2 = new String[2];
+
+
+
+ private class DatabaseHelper extends SQLiteOpenHelper {
+
+ DatabaseHelper(Context context) {
+ super(context, mDatabaseName, null, mDatabaseVersion);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+
+ if (DBG) log("DatabaseHelper.onCreate");
+
+ db.execSQL("CREATE TABLE " + TABLE_PROVIDERS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "name TEXT," + // eg AIM
+ "fullname TEXT," + // eg AOL Instance Messenger
+ "category TEXT," + // a category used for forming intent
+ "signup_url TEXT" + // web url to visit to create a new account
+ ");");
+
+ db.execSQL("CREATE TABLE " + TABLE_ACCOUNTS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "name TEXT," +
+ "provider INTEGER," +
+ "username TEXT," +
+ "pw TEXT," +
+ "active INTEGER NOT NULL DEFAULT 0," +
+ "locked INTEGER NOT NULL DEFAULT 0," +
+ "keep_signed_in INTEGER NOT NULL DEFAULT 0," +
+ "last_login_state INTEGER NOT NULL DEFAULT 0," +
+ "UNIQUE (provider, username)" +
+ ");");
+
+ createContactsTables(db);
+ createMessageChatTables(db, true /* create show_ts column */);
+
+ db.execSQL("CREATE TABLE " + TABLE_AVATARS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "contact TEXT," +
+ "provider_id INTEGER," +
+ "account_id INTEGER," +
+ "hash TEXT," +
+ "data BLOB," + // raw image data
+ "UNIQUE (account_id, contact)" +
+ ");");
+
+ db.execSQL("CREATE TABLE " + TABLE_PROVIDER_SETTINGS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "provider INTEGER," +
+ "name TEXT," +
+ "value TEXT," +
+ "UNIQUE (provider, name)" +
+ ");");
+
+ db.execSQL("create TABLE " + TABLE_BRANDING_RESOURCE_MAP_CACHE + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "provider_id INTEGER," +
+ "app_res_id INTEGER," +
+ "plugin_res_id INTEGER" +
+ ");");
+
+ // clean up account specific data when an account is deleted.
+ db.execSQL("CREATE TRIGGER account_cleanup " +
+ "DELETE ON " + TABLE_ACCOUNTS +
+ " BEGIN " +
+ "DELETE FROM " + TABLE_AVATARS + " WHERE account_id= OLD._id;" +
+ "END");
+
+ // add a database trigger to clean up associated provider settings
+ // while deleting a provider
+ db.execSQL("CREATE TRIGGER provider_cleanup " +
+ "DELETE ON " + TABLE_PROVIDERS +
+ " BEGIN " +
+ "DELETE FROM " + TABLE_PROVIDER_SETTINGS + " WHERE provider= OLD._id;" +
+ "END");
+
+ // the following are tables for mcs
+ db.execSQL("create TABLE " + TABLE_OUTGOING_RMQ_MESSAGES + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "rmq_id INTEGER," +
+ "type INTEGER," +
+ "ts INTEGER," +
+ "data TEXT" +
+ ");");
+
+ db.execSQL("create TABLE " + TABLE_LAST_RMQ_ID + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "rmq_id INTEGER" +
+ ");");
+
+ db.execSQL("create TABLE " + TABLE_S2D_RMQ_IDS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "rmq_id INTEGER" +
+ ");");
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.d(LOG_TAG, "Upgrading database from version " + oldVersion + " to " + newVersion);
+
+ switch (oldVersion) {
+ case 43: // this is the db version shipped in Dream 1.0
+ // no-op: no schema changed from 43 to 44. The db version was changed to flush
+ // old provider settings, so new provider setting (including new name/value
+ // pairs) could be inserted by the plugins.
+
+ // follow thru.
+ case 44:
+ if (newVersion <= 44) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ // add category column to the providers table
+ db.execSQL("ALTER TABLE " + TABLE_PROVIDERS + " ADD COLUMN category TEXT;");
+ // add otr column to the contacts table
+ db.execSQL("ALTER TABLE " + TABLE_CONTACTS + " ADD COLUMN otr INTEGER;");
+
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(LOG_TAG, ex.getMessage(), ex);
+ break; // force to destroy all old data;
+ } finally {
+ db.endTransaction();
+ }
+
+ case 45:
+ if (newVersion <= 45) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ // add an otr_etag column to contact etag table
+ db.execSQL(
+ "ALTER TABLE " + TABLE_CONTACTS_ETAG + " ADD COLUMN otr_etag TEXT;");
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(LOG_TAG, ex.getMessage(), ex);
+ break; // force to destroy all old data;
+ } finally {
+ db.endTransaction();
+ }
+
+ case 46:
+ if (newVersion <= 46) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ // add branding resource map cache table
+ db.execSQL("create TABLE " + TABLE_BRANDING_RESOURCE_MAP_CACHE + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "provider_id INTEGER," +
+ "app_res_id INTEGER," +
+ "plugin_res_id INTEGER" +
+ ");");
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(LOG_TAG, ex.getMessage(), ex);
+ break; // force to destroy all old data;
+ } finally {
+ db.endTransaction();
+ }
+
+ case 47:
+ if (newVersion <= 47) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ // when upgrading from version 47, don't create the show_ts column
+ // here. The upgrade step in 51 will add the show_ts column to the
+ // messages table. If we created the messages table with show_ts here,
+ // we'll get a duplicate column error later.
+ createMessageChatTables(db, false /* don't create show_ts column */);
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(LOG_TAG, ex.getMessage(), ex);
+ break; // force to destroy all old data;
+ } finally {
+ db.endTransaction();
+ }
+
+ // fall thru.
+
+ case 48:
+ case 49:
+ case 50:
+ if (newVersion <= 50) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ // add rmq2 s2d ids table
+ db.execSQL("create TABLE " + TABLE_S2D_RMQ_IDS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "rmq_id INTEGER" +
+ ");");
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(LOG_TAG, ex.getMessage(), ex);
+ break; // force to destroy all old data;
+ } finally {
+ db.endTransaction();
+ }
+
+ case 51:
+ if (newVersion <= 51) {
+ return;
+ }
+
+ db.beginTransaction();
+ try {
+ db.execSQL(
+ "ALTER TABLE " + TABLE_MESSAGES + " ADD COLUMN show_ts INTEGER;");
+ db.setTransactionSuccessful();
+ } catch (Throwable ex) {
+ Log.e(LOG_TAG, ex.getMessage(), ex);
+ break; // force to destroy all old data;
+ } finally {
+ db.endTransaction();
+ }
+
+ return;
+ }
+
+ Log.w(LOG_TAG, "Couldn't upgrade db to " + newVersion + ". Destroying old data.");
+ destroyOldTables(db);
+ onCreate(db);
+ }
+
+ private void destroyOldTables(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_PROVIDERS);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_ACCOUNTS);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACT_LIST);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_BLOCKED_LIST);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS_ETAG);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_AVATARS);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_PROVIDER_SETTINGS);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_BRANDING_RESOURCE_MAP_CACHE);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_MESSAGES);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_CHATS);
+
+ // mcs/rmq stuff
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_OUTGOING_RMQ_MESSAGES);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_LAST_RMQ_ID);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_S2D_RMQ_IDS);
+ }
+
+ private void createContactsTables(SQLiteDatabase db) {
+ if (DBG) log("createContactsTables");
+
+ StringBuilder buf = new StringBuilder();
+ String contactsTableName = TABLE_CONTACTS;
+
+ // creating the "contacts" table
+ buf.append("CREATE TABLE IF NOT EXISTS ");
+ buf.append(contactsTableName);
+ buf.append(" (");
+ buf.append("_id INTEGER PRIMARY KEY,");
+ buf.append("username TEXT,");
+ buf.append("nickname TEXT,");
+
+ buf.append("provider INTEGER,");
+ buf.append("account INTEGER,");
+ buf.append("contactList INTEGER,");
+ buf.append("type INTEGER,");
+ buf.append("subscriptionStatus INTEGER,");
+ buf.append("subscriptionType INTEGER,");
+
+ // the following are derived from Google Contact Extension, we don't include all
+ // the attributes, just the ones we can use.
+ // (see http://code.google.com/apis/talk/jep_extensions/roster_attributes.html)
+ //
+ // qc: quick contact (derived from message count)
+ // rejected: if the contact has ever been rejected by the user
+ buf.append("qc INTEGER,");
+ buf.append("rejected INTEGER,");
+
+ // Off the record status
+ buf.append("otr INTEGER");
+
+ buf.append(");");
+
+ db.execSQL(buf.toString());
+
+ buf.delete(0, buf.length());
+
+ // creating contact etag table
+ buf.append("CREATE TABLE IF NOT EXISTS ");
+ buf.append(TABLE_CONTACTS_ETAG);
+ buf.append(" (");
+ buf.append("_id INTEGER PRIMARY KEY,");
+ buf.append("etag TEXT,");
+ buf.append("otr_etag TEXT,");
+ buf.append("account INTEGER UNIQUE");
+ buf.append(");");
+
+ db.execSQL(buf.toString());
+
+ buf.delete(0, buf.length());
+
+ // creating the "contactList" table
+ buf.append("CREATE TABLE IF NOT EXISTS ");
+ buf.append(TABLE_CONTACT_LIST);
+ buf.append(" (");
+ buf.append("_id INTEGER PRIMARY KEY,");
+ buf.append("name TEXT,");
+ buf.append("provider INTEGER,");
+ buf.append("account INTEGER");
+ buf.append(");");
+
+ db.execSQL(buf.toString());
+
+ buf.delete(0, buf.length());
+
+ // creating the "blockedList" table
+ buf.append("CREATE TABLE IF NOT EXISTS ");
+ buf.append(TABLE_BLOCKED_LIST);
+ buf.append(" (");
+ buf.append("_id INTEGER PRIMARY KEY,");
+ buf.append("username TEXT,");
+ buf.append("nickname TEXT,");
+ buf.append("provider INTEGER,");
+ buf.append("account INTEGER");
+ buf.append(");");
+
+ db.execSQL(buf.toString());
+ }
+
+ private void createMessageChatTables(SQLiteDatabase db,
+ boolean addShowTsColumnForMessagesTable) {
+ if (DBG) log("createMessageChatTables");
+
+ // message table
+ StringBuilder buf = new StringBuilder();
+ buf.append("CREATE TABLE IF NOT EXISTS ");
+ buf.append(TABLE_MESSAGES);
+ buf.append(" (_id INTEGER PRIMARY KEY,");
+ buf.append("thread_id INTEGER,");
+ buf.append("nickname TEXT,");
+ buf.append("body TEXT,");
+ buf.append("date INTEGER,");
+ buf.append("type INTEGER,");
+ buf.append("packet_id TEXT UNIQUE,");
+ buf.append("err_code INTEGER NOT NULL DEFAULT 0,");
+ buf.append("err_msg TEXT,");
+ buf.append("is_muc INTEGER");
+
+ if (addShowTsColumnForMessagesTable) {
+ buf.append(",show_ts INTEGER");
+ }
+
+ buf.append(");");
+
+ String sqlStatement = buf.toString();
+
+ if (DBG) log("create message table: " + sqlStatement);
+ db.execSQL(sqlStatement);
+
+ buf.delete(0, buf.length());
+ buf.append("CREATE TABLE IF NOT EXISTS ");
+ buf.append(TABLE_CHATS);
+ buf.append(" (_id INTEGER PRIMARY KEY,");
+ buf.append("contact_id INTEGER UNIQUE,");
+ buf.append("jid_resource TEXT,"); // the JID resource for the user, for non-group chats
+ buf.append("groupchat INTEGER,"); // 1 if group chat, 0 if not TODO: remove this column
+ buf.append("last_unread_message TEXT,"); // the last unread message
+ buf.append("last_message_date INTEGER,"); // in seconds
+ buf.append("unsent_composed_message TEXT,"); // a composed, but not sent message
+ buf.append("shortcut INTEGER);"); // which of 10 slots (if any) this chat occupies
+
+ // chat sessions, including single person chats and group chats
+ sqlStatement = buf.toString();
+
+ if (DBG) log("create chat table: " + sqlStatement);
+ db.execSQL(sqlStatement);
+
+ buf.delete(0, buf.length());
+ buf.append("CREATE TRIGGER IF NOT EXISTS contact_cleanup ");
+ buf.append("DELETE ON contacts ");
+ buf.append("BEGIN ");
+ buf.append("DELETE FROM ").append(TABLE_CHATS).append(" WHERE contact_id = OLD._id;");
+ buf.append("DELETE FROM ").append(TABLE_MESSAGES).append(" WHERE thread_id = OLD._id;");
+ buf.append("END");
+
+ sqlStatement = buf.toString();
+
+ if (DBG) log("create trigger: " + sqlStatement);
+ db.execSQL(sqlStatement);
+ }
+
+ private void createInMemoryMessageTables(SQLiteDatabase db, String tablePrefix) {
+ String tableName = (tablePrefix != null) ?
+ tablePrefix+TABLE_IN_MEMORY_MESSAGES : TABLE_IN_MEMORY_MESSAGES;
+
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + tableName + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "thread_id INTEGER," +
+ "nickname TEXT," +
+ "body TEXT," +
+ "date INTEGER," + // in millisec
+ "type INTEGER," +
+ "packet_id TEXT UNIQUE," +
+ "err_code INTEGER NOT NULL DEFAULT 0," +
+ "err_msg TEXT," +
+ "is_muc INTEGER," +
+ "show_ts INTEGER" +
+ ");");
+
+ }
+
+ @Override
+ public void onOpen(SQLiteDatabase db) {
+ if (db.isReadOnly()) {
+ Log.w(LOG_TAG, "ImProvider database opened in read only mode.");
+ Log.w(LOG_TAG, "Transient tables not created.");
+ return;
+ }
+
+ if (DBG) log("##### createTransientTables");
+
+ // Create transient tables
+ String cpDbName;
+ db.execSQL("ATTACH DATABASE ':memory:' AS " + mTransientDbName + ";");
+ cpDbName = mTransientDbName + ".";
+
+ // in-memory message table
+ createInMemoryMessageTables(db, cpDbName);
+
+ // presence
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + cpDbName + TABLE_PRESENCE + " ("+
+ "_id INTEGER PRIMARY KEY," +
+ "contact_id INTEGER UNIQUE," +
+ "jid_resource TEXT," + // jid resource for the presence
+ "client_type INTEGER," + // client type
+ "priority INTEGER," + // presence priority (XMPP)
+ "mode INTEGER," + // presence mode
+ "status TEXT" + // custom status
+ ");");
+
+ // group chat invitations
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + cpDbName + TABLE_INVITATIONS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "providerId INTEGER," +
+ "accountId INTEGER," +
+ "inviteId TEXT," +
+ "sender TEXT," +
+ "groupName TEXT," +
+ "note TEXT," +
+ "status INTEGER" +
+ ");");
+
+ // group chat members
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + cpDbName + TABLE_GROUP_MEMBERS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "groupId INTEGER," +
+ "username TEXT," +
+ "nickname TEXT" +
+ ");");
+
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + cpDbName + TABLE_ACCOUNT_STATUS + " (" +
+ "_id INTEGER PRIMARY KEY," +
+ "account INTEGER UNIQUE," +
+ "presenceStatus INTEGER," +
+ "connStatus INTEGER" +
+ ");"
+ );
+
+ /* when we moved the contact table out of transient_db and into the main db, the
+ presence and groupchat cleanup triggers don't work anymore. It seems we can't
+ create triggers that reference objects in a different database!
+
+ // Insert a default presence for newly inserted contact
+ db.execSQL("CREATE TRIGGER IF NOT EXISTS contact_create_presence " +
+ "AFTER INSERT ON " + contactsTableName +
+ " WHEN NEW.type != " + Im.Contacts.TYPE_GROUP +
+ " BEGIN " +
+ "INSERT INTO presence (contact_id) VALUES (NEW._id);" +
+ " END");
+
+ // Remove the presence when the contact is removed.
+ db.execSQL("CREATE TRIGGER IF NOT EXISTS contact_presence_cleanup " +
+ "DELETE ON " + contactsTableName +
+ " BEGIN " +
+ "DELETE FROM presence WHERE contact_id = OLD._id;" +
+ "END");
+
+ // Cleans up group members and group messages when a group chat is deleted
+ db.execSQL("CREATE TRIGGER IF NOT EXISTS " + cpDbName + "group_cleanup " +
+ "DELETE ON " + cpDbName + contactsTableName +
+ " FOR EACH ROW WHEN OLD.type = " + Im.Contacts.TYPE_GROUP +
+ " BEGIN " +
+ "DELETE FROM groupMembers WHERE groupId = OLD._id;" +
+ "DELETE FROM groupMessages WHERE groupId = OLD._id;" +
+ " END");
+ */
+
+ // only store the session cookies in memory right now. This means
+ // that we don't persist them across device reboot
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + cpDbName + TABLE_SESSION_COOKIES + " ("+
+ "_id INTEGER PRIMARY KEY," +
+ "provider INTEGER," +
+ "account INTEGER," +
+ "name TEXT," +
+ "value TEXT" +
+ ");");
+
+ }
+ }
+
+ static {
+ sProviderAccountsProjectionMap = new HashMap<String, String>();
+ sProviderAccountsProjectionMap.put(Imps.Provider._ID,
+ "providers._id AS _id");
+ sProviderAccountsProjectionMap.put(Imps.Provider._COUNT,
+ "COUNT(*) AS _account");
+ sProviderAccountsProjectionMap.put(Imps.Provider.NAME,
+ "providers.name AS name");
+ sProviderAccountsProjectionMap.put(Imps.Provider.FULLNAME,
+ "providers.fullname AS fullname");
+ sProviderAccountsProjectionMap.put(Imps.Provider.CATEGORY,
+ "providers.category AS category");
+ sProviderAccountsProjectionMap.put(Imps.Provider.ACTIVE_ACCOUNT_ID,
+ "accounts._id AS account_id");
+ sProviderAccountsProjectionMap.put(Imps.Provider.ACTIVE_ACCOUNT_USERNAME,
+ "accounts.username AS account_username");
+ sProviderAccountsProjectionMap.put(Imps.Provider.ACTIVE_ACCOUNT_PW,
+ "accounts.pw AS account_pw");
+ sProviderAccountsProjectionMap.put(Imps.Provider.ACTIVE_ACCOUNT_LOCKED,
+ "accounts.locked AS account_locked");
+ sProviderAccountsProjectionMap.put(Imps.Provider.ACTIVE_ACCOUNT_KEEP_SIGNED_IN,
+ "accounts.keep_signed_in AS account_keepSignedIn");
+ sProviderAccountsProjectionMap.put(Imps.Provider.ACCOUNT_PRESENCE_STATUS,
+ "accountStatus.presenceStatus AS account_presenceStatus");
+ sProviderAccountsProjectionMap.put(Imps.Provider.ACCOUNT_CONNECTION_STATUS,
+ "accountStatus.connStatus AS account_connStatus");
+
+ // contacts projection map
+ sContactsProjectionMap = new HashMap<String, String>();
+
+ // Base column
+ sContactsProjectionMap.put(Imps.Contacts._ID, "contacts._id AS _id");
+ sContactsProjectionMap.put(Imps.Contacts._COUNT, "COUNT(*) AS _count");
+
+ // contacts column
+ sContactsProjectionMap.put(Imps.Contacts._ID, "contacts._id as _id");
+ sContactsProjectionMap.put(Imps.Contacts.USERNAME, "contacts.username as username");
+ sContactsProjectionMap.put(Imps.Contacts.NICKNAME, "contacts.nickname as nickname");
+ sContactsProjectionMap.put(Imps.Contacts.PROVIDER, "contacts.provider as provider");
+ sContactsProjectionMap.put(Imps.Contacts.ACCOUNT, "contacts.account as account");
+ sContactsProjectionMap.put(Imps.Contacts.CONTACTLIST, "contacts.contactList as contactList");
+ sContactsProjectionMap.put(Imps.Contacts.TYPE, "contacts.type as type");
+ sContactsProjectionMap.put(Imps.Contacts.SUBSCRIPTION_STATUS,
+ "contacts.subscriptionStatus as subscriptionStatus");
+ sContactsProjectionMap.put(Imps.Contacts.SUBSCRIPTION_TYPE,
+ "contacts.subscriptionType as subscriptionType");
+ sContactsProjectionMap.put(Imps.Contacts.QUICK_CONTACT, "contacts.qc as qc");
+ sContactsProjectionMap.put(Imps.Contacts.REJECTED, "contacts.rejected as rejected");
+
+ // Presence columns
+ sContactsProjectionMap.put(Imps.Presence.CONTACT_ID,
+ "presence.contact_id AS contact_id");
+ sContactsProjectionMap.put(Imps.Contacts.PRESENCE_STATUS,
+ "presence.mode AS mode");
+ sContactsProjectionMap.put(Imps.Contacts.PRESENCE_CUSTOM_STATUS,
+ "presence.status AS status");
+ sContactsProjectionMap.put(Imps.Contacts.CLIENT_TYPE,
+ "presence.client_type AS client_type");
+
+ // Chats columns
+ sContactsProjectionMap.put(Imps.Contacts.CHATS_CONTACT,
+ "chats.contact_id AS chats_contact_id");
+ sContactsProjectionMap.put(Imps.Chats.JID_RESOURCE,
+ "chats.jid_resource AS jid_resource");
+ sContactsProjectionMap.put(Imps.Chats.GROUP_CHAT,
+ "chats.groupchat AS groupchat");
+ sContactsProjectionMap.put(Imps.Contacts.LAST_UNREAD_MESSAGE,
+ "chats.last_unread_message AS last_unread_message");
+ sContactsProjectionMap.put(Imps.Contacts.LAST_MESSAGE_DATE,
+ "chats.last_message_date AS last_message_date");
+ sContactsProjectionMap.put(Imps.Contacts.UNSENT_COMPOSED_MESSAGE,
+ "chats.unsent_composed_message AS unsent_composed_message");
+ sContactsProjectionMap.put(Imps.Contacts.SHORTCUT, "chats.SHORTCUT AS shortcut");
+
+ // Avatars columns
+ sContactsProjectionMap.put(Imps.Contacts.AVATAR_HASH, "avatars.hash AS avatars_hash");
+ sContactsProjectionMap.put(Imps.Contacts.AVATAR_DATA, "avatars.data AS avatars_data");
+
+ // contactList projection map
+ sContactListProjectionMap = new HashMap<String, String>();
+ sContactListProjectionMap.put(Imps.ContactList._ID, "contactList._id AS _id");
+ sContactListProjectionMap.put(Imps.ContactList._COUNT, "COUNT(*) AS _count");
+ sContactListProjectionMap.put(Imps.ContactList.NAME, "name");
+ sContactListProjectionMap.put(Imps.ContactList.PROVIDER, "provider");
+ sContactListProjectionMap.put(Imps.ContactList.ACCOUNT, "account");
+
+ // blockedList projection map
+ sBlockedListProjectionMap = new HashMap<String, String>();
+ sBlockedListProjectionMap.put(Imps.BlockedList._ID, "blockedList._id AS _id");
+ sBlockedListProjectionMap.put(Imps.BlockedList._COUNT, "COUNT(*) AS _count");
+ sBlockedListProjectionMap.put(Imps.BlockedList.USERNAME, "username");
+ sBlockedListProjectionMap.put(Imps.BlockedList.NICKNAME, "nickname");
+ sBlockedListProjectionMap.put(Imps.BlockedList.PROVIDER, "provider");
+ sBlockedListProjectionMap.put(Imps.BlockedList.ACCOUNT, "account");
+ sBlockedListProjectionMap.put(Imps.BlockedList.AVATAR_DATA,
+ "avatars.data AS avatars_data");
+
+ // messages projection map
+ sMessagesProjectionMap = new HashMap<String, String>();
+ sMessagesProjectionMap.put(Imps.Messages._ID, "messages._id AS _id");
+ sMessagesProjectionMap.put(Imps.Messages._COUNT, "COUNT(*) AS _count");
+ sMessagesProjectionMap.put(Imps.Messages.THREAD_ID, "messages.thread_id AS thread_id");
+ sMessagesProjectionMap.put(Imps.Messages.PACKET_ID, "messages.packet_id AS packet_id");
+ sMessagesProjectionMap.put(Imps.Messages.NICKNAME, "messages.nickname AS nickname");
+ sMessagesProjectionMap.put(Imps.Messages.BODY, "messages.body AS body");
+ sMessagesProjectionMap.put(Imps.Messages.DATE, "messages.date AS date");
+ sMessagesProjectionMap.put(Imps.Messages.TYPE, "messages.type AS type");
+ sMessagesProjectionMap.put(Imps.Messages.ERROR_CODE, "messages.err_code AS err_code");
+ sMessagesProjectionMap.put(Imps.Messages.ERROR_MESSAGE, "messages.err_msg AS err_msg");
+ sMessagesProjectionMap.put(Imps.Messages.IS_GROUP_CHAT, "messages.is_muc AS is_muc");
+ sMessagesProjectionMap.put(Imps.Messages.DISPLAY_SENT_TIME, "messages.show_ts AS show_ts");
+ // contacts columns
+ sMessagesProjectionMap.put(Imps.Messages.CONTACT, "contacts.username AS contact");
+ sMessagesProjectionMap.put(Imps.Contacts.PROVIDER, "contacts.provider AS provider");
+ sMessagesProjectionMap.put(Imps.Contacts.ACCOUNT, "contacts.account AS account");
+ sMessagesProjectionMap.put("contact_type", "contacts.type AS contact_type");
+
+ sInMemoryMessagesProjectionMap = new HashMap<String, String>();
+ sInMemoryMessagesProjectionMap.put(Imps.Messages._ID,
+ "inMemoryMessages._id AS _id");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages._COUNT,
+ "COUNT(*) AS _count");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.THREAD_ID,
+ "inMemoryMessages.thread_id AS thread_id");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.PACKET_ID,
+ "inMemoryMessages.packet_id AS packet_id");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.NICKNAME,
+ "inMemoryMessages.nickname AS nickname");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.BODY,
+ "inMemoryMessages.body AS body");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.DATE,
+ "inMemoryMessages.date AS date");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.TYPE,
+ "inMemoryMessages.type AS type");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.ERROR_CODE,
+ "inMemoryMessages.err_code AS err_code");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.ERROR_MESSAGE,
+ "inMemoryMessages.err_msg AS err_msg");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.IS_GROUP_CHAT,
+ "inMemoryMessages.is_muc AS is_muc");
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.DISPLAY_SENT_TIME,
+ "inMemoryMessages.show_ts AS show_ts");
+ // contacts columns
+ sInMemoryMessagesProjectionMap.put(Imps.Messages.CONTACT, "contacts.username AS contact");
+ sInMemoryMessagesProjectionMap.put(Imps.Contacts.PROVIDER, "contacts.provider AS provider");
+ sInMemoryMessagesProjectionMap.put(Imps.Contacts.ACCOUNT, "contacts.account AS account");
+ sInMemoryMessagesProjectionMap.put("contact_type", "contacts.type AS contact_type");
+ }
+
+ public ImpsProvider() {
+ this(DATABASE_NAME, DATABASE_VERSION);
+
+ setupImUrlMatchers(AUTHORITY);
+ setupMcsUrlMatchers(AUTHORITY);
+ }
+
+ protected ImpsProvider(String dbName, int dbVersion) {
+ mDatabaseName = dbName;
+ mDatabaseVersion = dbVersion;
+ mTransientDbName = "transient_" + dbName.replace(".", "_");
+ }
+
+ private void setupImUrlMatchers(String authority) {
+ mUrlMatcher.addURI(authority, "providers", MATCH_PROVIDERS);
+ mUrlMatcher.addURI(authority, "providers/#", MATCH_PROVIDERS_BY_ID);
+ mUrlMatcher.addURI(authority, "providers/account", MATCH_PROVIDERS_WITH_ACCOUNT);
+
+ mUrlMatcher.addURI(authority, "accounts", MATCH_ACCOUNTS);
+ mUrlMatcher.addURI(authority, "accounts/#", MATCH_ACCOUNTS_BY_ID);
+
+ mUrlMatcher.addURI(authority, "contacts", MATCH_CONTACTS);
+ mUrlMatcher.addURI(authority, "contactsWithPresence", MATCH_CONTACTS_JOIN_PRESENCE);
+ mUrlMatcher.addURI(authority, "contactsBarebone", MATCH_CONTACTS_BAREBONE);
+ mUrlMatcher.addURI(authority, "contacts/#/#", MATCH_CONTACTS_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "contacts/chatting", MATCH_CHATTING_CONTACTS);
+ mUrlMatcher.addURI(authority, "contacts/chatting/#/#", MATCH_CHATTING_CONTACTS_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "contacts/online/#/#", MATCH_ONLINE_CONTACTS_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "contacts/offline/#/#", MATCH_OFFLINE_CONTACTS_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "contacts/#", MATCH_CONTACT);
+ mUrlMatcher.addURI(authority, "contacts/blocked", MATCH_BLOCKED_CONTACTS);
+ mUrlMatcher.addURI(authority, "bulk_contacts", MATCH_CONTACTS_BULK);
+ mUrlMatcher.addURI(authority, "contacts/onlineCount", MATCH_ONLINE_CONTACT_COUNT);
+
+ mUrlMatcher.addURI(authority, "contactLists", MATCH_CONTACTLISTS);
+ mUrlMatcher.addURI(authority, "contactLists/#/#", MATCH_CONTACTLISTS_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "contactLists/#", MATCH_CONTACTLIST);
+ mUrlMatcher.addURI(authority, "blockedList", MATCH_BLOCKEDLIST);
+ mUrlMatcher.addURI(authority, "blockedList/#/#", MATCH_BLOCKEDLIST_BY_PROVIDER);
+
+ mUrlMatcher.addURI(authority, "contactsEtag", MATCH_CONTACTS_ETAGS);
+ mUrlMatcher.addURI(authority, "contactsEtag/#", MATCH_CONTACTS_ETAG);
+
+ mUrlMatcher.addURI(authority, "presence", MATCH_PRESENCE);
+ mUrlMatcher.addURI(authority, "presence/#", MATCH_PRESENCE_ID);
+ mUrlMatcher.addURI(authority, "presence/account/#", MATCH_PRESENCE_BY_ACCOUNT);
+ mUrlMatcher.addURI(authority, "seed_presence/account/#", MATCH_PRESENCE_SEED_BY_ACCOUNT);
+ mUrlMatcher.addURI(authority, "bulk_presence", MATCH_PRESENCE_BULK);
+
+ mUrlMatcher.addURI(authority, "messages", MATCH_MESSAGES);
+ mUrlMatcher.addURI(authority, "messagesByAcctAndContact/#/*", MATCH_MESSAGES_BY_CONTACT);
+ mUrlMatcher.addURI(authority, "messagesByThreadId/#", MATCH_MESSAGES_BY_THREAD_ID);
+ mUrlMatcher.addURI(authority, "messagesByProvider/#", MATCH_MESSAGES_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "messagesByAccount/#", MATCH_MESSAGES_BY_ACCOUNT);
+ mUrlMatcher.addURI(authority, "messages/#", MATCH_MESSAGE);
+
+ mUrlMatcher.addURI(authority, "otrMessages", MATCH_OTR_MESSAGES);
+ mUrlMatcher.addURI(authority, "otrMessagesByAcctAndContact/#/*",
+ MATCH_OTR_MESSAGES_BY_CONTACT);
+ mUrlMatcher.addURI(authority, "otrMessagesByThreadId/#", MATCH_OTR_MESSAGES_BY_THREAD_ID);
+ mUrlMatcher.addURI(authority, "otrMessagesByProvider/#", MATCH_OTR_MESSAGES_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "otrMessagesByAccount/#", MATCH_OTR_MESSAGES_BY_ACCOUNT);
+ mUrlMatcher.addURI(authority, "otrMessages/#", MATCH_OTR_MESSAGE);
+
+ mUrlMatcher.addURI(authority, "groupMembers", MATCH_GROUP_MEMBERS);
+ mUrlMatcher.addURI(authority, "groupMembers/#", MATCH_GROUP_MEMBERS_BY_GROUP);
+
+ mUrlMatcher.addURI(authority, "avatars", MATCH_AVATARS);
+ mUrlMatcher.addURI(authority, "avatars/#", MATCH_AVATAR);
+ mUrlMatcher.addURI(authority, "avatarsBy/#/#", MATCH_AVATAR_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "chats", MATCH_CHATS);
+ mUrlMatcher.addURI(authority, "chats/account/#", MATCH_CHATS_BY_ACCOUNT);
+ mUrlMatcher.addURI(authority, "chats/#", MATCH_CHATS_ID);
+
+ mUrlMatcher.addURI(authority, "sessionCookies", MATCH_SESSIONS);
+ mUrlMatcher.addURI(authority, "sessionCookiesBy/#/#", MATCH_SESSIONS_BY_PROVIDER);
+ mUrlMatcher.addURI(authority, "providerSettings", MATCH_PROVIDER_SETTINGS);
+ mUrlMatcher.addURI(authority, "providerSettings/#", MATCH_PROVIDER_SETTINGS_BY_ID);
+ mUrlMatcher.addURI(authority, "providerSettings/#/*",
+ MATCH_PROVIDER_SETTINGS_BY_ID_AND_NAME);
+
+ mUrlMatcher.addURI(authority, "invitations", MATCH_INVITATIONS);
+ mUrlMatcher.addURI(authority, "invitations/#", MATCH_INVITATION);
+
+ mUrlMatcher.addURI(authority, "accountStatus", MATCH_ACCOUNTS_STATUS);
+ mUrlMatcher.addURI(authority, "accountStatus/#", MATCH_ACCOUNT_STATUS);
+
+ mUrlMatcher.addURI(authority, "brandingResMapCache", MATCH_BRANDING_RESOURCE_MAP_CACHE);
+ }
+
+ private void setupMcsUrlMatchers(String authority) {
+ mUrlMatcher.addURI(authority, "outgoingRmqMessages", MATCH_OUTGOING_RMQ_MESSAGES);
+ mUrlMatcher.addURI(authority, "outgoingRmqMessages/#", MATCH_OUTGOING_RMQ_MESSAGE);
+ mUrlMatcher.addURI(authority, "outgoingHighestRmqId", MATCH_OUTGOING_HIGHEST_RMQ_ID);
+ mUrlMatcher.addURI(authority, "lastRmqId", MATCH_LAST_RMQ_ID);
+ mUrlMatcher.addURI(authority, "s2dids", MATCH_S2D_RMQ_IDS);
+ }
+
+ @Override
+ public boolean onCreate() {
+ mOpenHelper = new DatabaseHelper(getContext());
+ return true;
+ }
+
+ @Override
+ public final int update(final Uri url, final ContentValues values,
+ final String selection, final String[] selectionArgs) {
+
+ int result = 0;
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ result = updateInternal(url, values, selection, selectionArgs);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ if (result > 0) {
+ getContext().getContentResolver()
+ .notifyChange(url, null /* observer */, false /* sync */);
+ }
+ return result;
+ }
+
+ @Override
+ public final int delete(final Uri url, final String selection,
+ final String[] selectionArgs) {
+ int result;
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ result = deleteInternal(url, selection, selectionArgs);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ if (result > 0) {
+ getContext().getContentResolver()
+ .notifyChange(url, null /* observer */, false /* sync */);
+ }
+ return result;
+ }
+
+ @Override
+ public final Uri insert(final Uri url, final ContentValues values) {
+ Uri result;
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ result = insertInternal(url, values);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ if (result != null) {
+ getContext().getContentResolver()
+ .notifyChange(url, null /* observer */, false /* sync */);
+ }
+ return result;
+ }
+
+ @Override
+ public final Cursor query(final Uri url, final String[] projection,
+ final String selection, final String[] selectionArgs,
+ final String sortOrder) {
+ return queryInternal(url, projection, selection, selectionArgs, sortOrder);
+ }
+
+ public Cursor queryInternal(Uri url, String[] projectionIn,
+ String selection, String[] selectionArgs, String sort) {
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ StringBuilder whereClause = new StringBuilder();
+ if(selection != null) {
+ whereClause.append(selection);
+ }
+ String groupBy = null;
+ String limit = null;
+
+ // Generate the body of the query
+ int match = mUrlMatcher.match(url);
+
+ if (DBG) {
+ log("query " + url + ", match " + match + ", where " + selection);
+ if (selectionArgs != null) {
+ for (String selectionArg : selectionArgs) {
+ log(" selectionArg: " + selectionArg);
+ }
+ }
+ }
+
+ switch (match) {
+ case MATCH_PROVIDERS_BY_ID:
+ appendWhere(whereClause, Imps.Provider._ID, "=", url.getPathSegments().get(1));
+ // fall thru.
+
+ case MATCH_PROVIDERS:
+ qb.setTables(TABLE_PROVIDERS);
+ break;
+
+ case MATCH_PROVIDERS_WITH_ACCOUNT:
+ qb.setTables(PROVIDER_JOIN_ACCOUNT_TABLE);
+ qb.setProjectionMap(sProviderAccountsProjectionMap);
+ break;
+
+ case MATCH_ACCOUNTS_BY_ID:
+ appendWhere(whereClause, Imps.Account._ID, "=", url.getPathSegments().get(1));
+ // falls down
+ case MATCH_ACCOUNTS:
+ qb.setTables(TABLE_ACCOUNTS);
+ break;
+
+ case MATCH_CONTACTS:
+ qb.setTables(CONTACT_JOIN_PRESENCE_CHAT_AVATAR_TABLE);
+ qb.setProjectionMap(sContactsProjectionMap);
+ break;
+
+ case MATCH_CONTACTS_JOIN_PRESENCE:
+ qb.setTables(CONTACT_JOIN_PRESENCE_TABLE);
+ qb.setProjectionMap(sContactsProjectionMap);
+ break;
+
+ case MATCH_CONTACTS_BAREBONE:
+ qb.setTables(TABLE_CONTACTS);
+ break;
+
+ case MATCH_CHATTING_CONTACTS:
+ qb.setTables(CONTACT_JOIN_PRESENCE_CHAT_AVATAR_TABLE);
+ qb.setProjectionMap(sContactsProjectionMap);
+ appendWhere(whereClause, "chats.last_message_date IS NOT NULL");
+ // no need to add the non blocked contacts clause because
+ // blocked contacts can't have conversations.
+ break;
+
+ case MATCH_CONTACTS_BY_PROVIDER:
+ buildQueryContactsByProvider(qb, whereClause, url);
+ appendWhere(whereClause, NON_BLOCKED_CONTACTS_WHERE_CLAUSE);
+ break;
+
+ case MATCH_CHATTING_CONTACTS_BY_PROVIDER:
+ buildQueryContactsByProvider(qb, whereClause, url);
+ appendWhere(whereClause, "chats.last_message_date IS NOT NULL");
+ // no need to add the non blocked contacts clause because
+ // blocked contacts can't have conversations.
+ break;
+
+ case MATCH_NO_CHATTING_CONTACTS_BY_PROVIDER:
+ buildQueryContactsByProvider(qb, whereClause, url);
+ appendWhere(whereClause, "chats.last_message_date IS NULL");
+ appendWhere(whereClause, NON_BLOCKED_CONTACTS_WHERE_CLAUSE);
+ break;
+
+ case MATCH_ONLINE_CONTACTS_BY_PROVIDER:
+ buildQueryContactsByProvider(qb, whereClause, url);
+ appendWhere(whereClause, Imps.Contacts.PRESENCE_STATUS, "!=", Imps.Presence.OFFLINE);
+ appendWhere(whereClause, NON_BLOCKED_CONTACTS_WHERE_CLAUSE);
+ break;
+
+ case MATCH_OFFLINE_CONTACTS_BY_PROVIDER:
+ buildQueryContactsByProvider(qb, whereClause, url);
+ appendWhere(whereClause, Imps.Contacts.PRESENCE_STATUS, "=", Imps.Presence.OFFLINE);
+ appendWhere(whereClause, NON_BLOCKED_CONTACTS_WHERE_CLAUSE);
+ break;
+
+ case MATCH_BLOCKED_CONTACTS:
+ qb.setTables(CONTACT_JOIN_PRESENCE_CHAT_AVATAR_TABLE);
+ qb.setProjectionMap(sContactsProjectionMap);
+ appendWhere(whereClause, BLOCKED_CONTACTS_WHERE_CLAUSE);
+ break;
+
+ case MATCH_CONTACT:
+ qb.setTables(CONTACT_JOIN_PRESENCE_CHAT_AVATAR_TABLE);
+ qb.setProjectionMap(sContactsProjectionMap);
+ appendWhere(whereClause, "contacts._id", "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_ONLINE_CONTACT_COUNT:
+ qb.setTables(CONTACT_JOIN_PRESENCE_CHAT_TABLE);
+ qb.setProjectionMap(sContactsProjectionMap);
+ appendWhere(whereClause, Imps.Contacts.PRESENCE_STATUS, "!=", Imps.Presence.OFFLINE);
+ appendWhere(whereClause, "chats.last_message_date IS NULL");
+ appendWhere(whereClause, NON_BLOCKED_CONTACTS_WHERE_CLAUSE);
+ groupBy = Imps.Contacts.CONTACTLIST;
+ break;
+
+ case MATCH_CONTACTLISTS_BY_PROVIDER:
+ appendWhere(whereClause, Imps.ContactList.ACCOUNT, "=",
+ url.getPathSegments().get(2));
+ // fall through
+ case MATCH_CONTACTLISTS:
+ qb.setTables(TABLE_CONTACT_LIST);
+ qb.setProjectionMap(sContactListProjectionMap);
+ break;
+
+ case MATCH_CONTACTLIST:
+ qb.setTables(TABLE_CONTACT_LIST);
+ appendWhere(whereClause, Imps.ContactList._ID, "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_BLOCKEDLIST:
+ qb.setTables(BLOCKEDLIST_JOIN_AVATAR_TABLE);
+ qb.setProjectionMap(sBlockedListProjectionMap);
+ break;
+
+ case MATCH_BLOCKEDLIST_BY_PROVIDER:
+ qb.setTables(BLOCKEDLIST_JOIN_AVATAR_TABLE);
+ qb.setProjectionMap(sBlockedListProjectionMap);
+ appendWhere(whereClause, Imps.BlockedList.ACCOUNT, "=",
+ url.getPathSegments().get(2));
+ break;
+
+ case MATCH_CONTACTS_ETAGS:
+ qb.setTables(TABLE_CONTACTS_ETAG);
+ break;
+
+ case MATCH_CONTACTS_ETAG:
+ qb.setTables(TABLE_CONTACTS_ETAG);
+ appendWhere(whereClause, "_id", "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_MESSAGES_BY_THREAD_ID:
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=", url.getPathSegments().get(1));
+ // fall thru.
+
+ case MATCH_MESSAGES:
+ qb.setTables(TABLE_MESSAGES);
+
+ final String selectionClause = whereClause.toString();
+ final String query1 = qb.buildQuery(projectionIn, selectionClause,
+ null, null, null, null, null /* limit */);
+
+ // Build the second query for frequent
+ qb = new SQLiteQueryBuilder();
+ qb.setTables(TABLE_IN_MEMORY_MESSAGES);
+ final String query2 = qb.buildQuery(projectionIn,
+ selectionClause, null, null, null, null, null /* limit */);
+
+ // Put them together
+ final String query = qb.buildUnionQuery(new String[] {query1, query2}, sort, null);
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ Cursor c = db.rawQueryWithFactory(null, query, null, TABLE_MESSAGES);
+ if ((c != null) && !isTemporary()) {
+ c.setNotificationUri(getContext().getContentResolver(), url);
+ }
+ return c;
+
+ case MATCH_MESSAGE:
+ qb.setTables(TABLE_MESSAGES);
+ appendWhere(whereClause, Imps.Messages._ID, "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_MESSAGES_BY_CONTACT:
+ qb.setTables(MESSAGE_JOIN_CONTACT_TABLE);
+ qb.setProjectionMap(sMessagesProjectionMap);
+
+ appendWhere(whereClause, Imps.Contacts.ACCOUNT, "=", url.getPathSegments().get(1));
+ appendWhere(whereClause, "contacts.username", "=",
+ decodeURLSegment(url.getPathSegments().get(2)));
+
+ final String sel = whereClause.toString();
+ final String q1 = qb.buildQuery(projectionIn, sel, null, null, null, null, null);
+
+ // Build the second query for frequent
+ qb = new SQLiteQueryBuilder();
+ qb.setTables(IN_MEMORY_MESSAGES_JOIN_CONTACT_TABLE);
+ qb.setProjectionMap(sInMemoryMessagesProjectionMap);
+ final String q2 = qb.buildQuery(projectionIn, sel, null, null, null, null, null);
+
+ // Put them together
+ final String q3 = qb.buildUnionQuery(new String[] {q1, q2}, sort, null);
+ final SQLiteDatabase db2 = mOpenHelper.getWritableDatabase();
+ Cursor c2 = db2.rawQueryWithFactory(null, q3, null, MESSAGE_JOIN_CONTACT_TABLE);
+ if ((c2 != null) && !isTemporary()) {
+ c2.setNotificationUri(getContext().getContentResolver(), url);
+ }
+ return c2;
+
+ case MATCH_INVITATIONS:
+ qb.setTables(TABLE_INVITATIONS);
+ break;
+
+ case MATCH_INVITATION:
+ qb.setTables(TABLE_INVITATIONS);
+ appendWhere(whereClause, Imps.Invitation._ID, "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_GROUP_MEMBERS:
+ qb.setTables(TABLE_GROUP_MEMBERS);
+ break;
+
+ case MATCH_GROUP_MEMBERS_BY_GROUP:
+ qb.setTables(TABLE_GROUP_MEMBERS);
+ appendWhere(whereClause, Imps.GroupMembers.GROUP, "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_AVATARS:
+ qb.setTables(TABLE_AVATARS);
+ break;
+
+ case MATCH_AVATAR_BY_PROVIDER:
+ qb.setTables(TABLE_AVATARS);
+ appendWhere(whereClause, Imps.Avatars.ACCOUNT, "=", url.getPathSegments().get(2));
+ break;
+
+ case MATCH_CHATS:
+ qb.setTables(TABLE_CHATS);
+ break;
+
+ case MATCH_CHATS_ID:
+ qb.setTables(TABLE_CHATS);
+ appendWhere(whereClause, Imps.Chats.CONTACT_ID, "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_CHATS_BY_ACCOUNT:
+ qb.setTables(TABLE_CHATS);
+ String accountStr = decodeURLSegment(url.getLastPathSegment());
+ appendWhere(whereClause, buildContactIdSelection(Imps.Chats.CONTACT_ID,
+ Imps.Contacts.ACCOUNT + "='" + accountStr + "'"));
+ break;
+
+ case MATCH_PRESENCE:
+ qb.setTables(TABLE_PRESENCE);
+ break;
+
+ case MATCH_PRESENCE_ID:
+ qb.setTables(TABLE_PRESENCE);
+ appendWhere(whereClause, Imps.Presence.CONTACT_ID, "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_SESSIONS:
+ qb.setTables(TABLE_SESSION_COOKIES);
+ break;
+
+ case MATCH_SESSIONS_BY_PROVIDER:
+ qb.setTables(TABLE_SESSION_COOKIES);
+ appendWhere(whereClause, Imps.SessionCookies.ACCOUNT, "=", url.getPathSegments().get(2));
+ break;
+
+ case MATCH_PROVIDER_SETTINGS_BY_ID_AND_NAME:
+ appendWhere(whereClause, Imps.ProviderSettings.NAME, "=", url.getPathSegments().get(2));
+ // fall through
+ case MATCH_PROVIDER_SETTINGS_BY_ID:
+ appendWhere(whereClause, Imps.ProviderSettings.PROVIDER, "=", url.getPathSegments().get(1));
+ // fall through
+ case MATCH_PROVIDER_SETTINGS:
+ qb.setTables(TABLE_PROVIDER_SETTINGS);
+ break;
+
+ case MATCH_ACCOUNTS_STATUS:
+ qb.setTables(TABLE_ACCOUNT_STATUS);
+ break;
+
+ case MATCH_ACCOUNT_STATUS:
+ qb.setTables(TABLE_ACCOUNT_STATUS);
+ appendWhere(whereClause, Imps.AccountStatus.ACCOUNT, "=",
+ url.getPathSegments().get(1));
+ break;
+
+ case MATCH_BRANDING_RESOURCE_MAP_CACHE:
+ qb.setTables(TABLE_BRANDING_RESOURCE_MAP_CACHE);
+ break;
+
+ // mcs and rmq queries
+ case MATCH_OUTGOING_RMQ_MESSAGES:
+ qb.setTables(TABLE_OUTGOING_RMQ_MESSAGES);
+ break;
+
+ case MATCH_OUTGOING_HIGHEST_RMQ_ID:
+ qb.setTables(TABLE_OUTGOING_RMQ_MESSAGES);
+ sort = "rmq_id DESC";
+ limit = "1";
+ break;
+
+ case MATCH_LAST_RMQ_ID:
+ qb.setTables(TABLE_LAST_RMQ_ID);
+ limit = "1";
+ break;
+
+ case MATCH_S2D_RMQ_IDS:
+ qb.setTables(TABLE_S2D_RMQ_IDS);
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URL " + url);
+ }
+
+ // run the query
+ final SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor c = null;
+
+ try {
+ c = qb.query(db, projectionIn, whereClause.toString(), selectionArgs,
+ groupBy, null, sort, limit);
+ if (c != null) {
+ switch(match) {
+ case MATCH_CHATTING_CONTACTS:
+ case MATCH_CONTACTS_BY_PROVIDER:
+ case MATCH_CHATTING_CONTACTS_BY_PROVIDER:
+ case MATCH_ONLINE_CONTACTS_BY_PROVIDER:
+ case MATCH_OFFLINE_CONTACTS_BY_PROVIDER:
+ case MATCH_CONTACTS_BAREBONE:
+ case MATCH_CONTACTS_JOIN_PRESENCE:
+ case MATCH_ONLINE_CONTACT_COUNT:
+ url = Imps.Contacts.CONTENT_URI;
+ break;
+ }
+ if (DBG) log("set notify url " + url);
+ c.setNotificationUri(getContext().getContentResolver(), url);
+ }
+ } catch (Exception ex) {
+ Log.e(LOG_TAG, "query db caught ", ex);
+ }
+
+ return c;
+ }
+
+ private void buildQueryContactsByProvider(SQLiteQueryBuilder qb,
+ StringBuilder whereClause, Uri url) {
+ qb.setTables(CONTACT_JOIN_PRESENCE_CHAT_AVATAR_TABLE);
+ qb.setProjectionMap(sContactsProjectionMap);
+ // we don't really need the provider id in query. account id is enough.
+ appendWhere(whereClause, Imps.Contacts.ACCOUNT, "=", url.getLastPathSegment());
+ }
+
+ @Override
+ public String getType(Uri url) {
+ int match = mUrlMatcher.match(url);
+ switch (match) {
+ case MATCH_PROVIDERS:
+ return Imps.Provider.CONTENT_TYPE;
+
+ case MATCH_PROVIDERS_BY_ID:
+ return Imps.Provider.CONTENT_ITEM_TYPE;
+
+ case MATCH_ACCOUNTS:
+ return Imps.Account.CONTENT_TYPE;
+
+ case MATCH_ACCOUNTS_BY_ID:
+ return Imps.Account.CONTENT_ITEM_TYPE;
+
+ case MATCH_CONTACTS:
+ case MATCH_CONTACTS_BY_PROVIDER:
+ case MATCH_ONLINE_CONTACTS_BY_PROVIDER:
+ case MATCH_OFFLINE_CONTACTS_BY_PROVIDER:
+ case MATCH_CONTACTS_BULK:
+ case MATCH_CONTACTS_BAREBONE:
+ case MATCH_CONTACTS_JOIN_PRESENCE:
+ return Imps.Contacts.CONTENT_TYPE;
+
+ case MATCH_CONTACT:
+ return Imps.Contacts.CONTENT_ITEM_TYPE;
+
+ case MATCH_CONTACTLISTS:
+ case MATCH_CONTACTLISTS_BY_PROVIDER:
+ return Imps.ContactList.CONTENT_TYPE;
+
+ case MATCH_CONTACTLIST:
+ return Imps.ContactList.CONTENT_ITEM_TYPE;
+
+ case MATCH_BLOCKEDLIST:
+ case MATCH_BLOCKEDLIST_BY_PROVIDER:
+ return Imps.BlockedList.CONTENT_TYPE;
+
+ case MATCH_CONTACTS_ETAGS:
+ case MATCH_CONTACTS_ETAG:
+ return Imps.ContactsEtag.CONTENT_TYPE;
+
+ case MATCH_MESSAGES:
+ case MATCH_MESSAGES_BY_CONTACT:
+ case MATCH_MESSAGES_BY_THREAD_ID:
+ case MATCH_MESSAGES_BY_PROVIDER:
+ case MATCH_MESSAGES_BY_ACCOUNT:
+ case MATCH_OTR_MESSAGES:
+ case MATCH_OTR_MESSAGES_BY_CONTACT:
+ case MATCH_OTR_MESSAGES_BY_THREAD_ID:
+ case MATCH_OTR_MESSAGES_BY_PROVIDER:
+ case MATCH_OTR_MESSAGES_BY_ACCOUNT:
+ return Imps.Messages.CONTENT_TYPE;
+
+ case MATCH_MESSAGE:
+ case MATCH_OTR_MESSAGE:
+ return Imps.Messages.CONTENT_ITEM_TYPE;
+
+ case MATCH_PRESENCE:
+ case MATCH_PRESENCE_BULK:
+ return Imps.Presence.CONTENT_TYPE;
+
+ case MATCH_AVATARS:
+ return Imps.Avatars.CONTENT_TYPE;
+
+ case MATCH_AVATAR:
+ return Imps.Avatars.CONTENT_ITEM_TYPE;
+
+ case MATCH_CHATS:
+ return Imps.Chats.CONTENT_TYPE;
+
+ case MATCH_CHATS_ID:
+ return Imps.Chats.CONTENT_ITEM_TYPE;
+
+ case MATCH_INVITATIONS:
+ return Imps.Invitation.CONTENT_TYPE;
+
+ case MATCH_INVITATION:
+ return Imps.Invitation.CONTENT_ITEM_TYPE;
+
+ case MATCH_GROUP_MEMBERS:
+ case MATCH_GROUP_MEMBERS_BY_GROUP:
+ return Imps.GroupMembers.CONTENT_TYPE;
+
+ case MATCH_SESSIONS:
+ case MATCH_SESSIONS_BY_PROVIDER:
+ return Imps.SessionCookies.CONTENT_TYPE;
+
+ case MATCH_PROVIDER_SETTINGS:
+ return Imps.ProviderSettings.CONTENT_TYPE;
+
+ case MATCH_ACCOUNTS_STATUS:
+ return Imps.AccountStatus.CONTENT_TYPE;
+
+ case MATCH_ACCOUNT_STATUS:
+ return Imps.AccountStatus.CONTENT_ITEM_TYPE;
+
+ default:
+ throw new IllegalArgumentException("Unknown URL");
+ }
+ }
+
+ // package scope for testing.
+ boolean insertBulkContacts(ContentValues values) {
+ //if (DBG) log("insertBulkContacts: begin");
+
+ ArrayList<String> usernames = values.getStringArrayList(Imps.Contacts.USERNAME);
+ ArrayList<String> nicknames = values.getStringArrayList(Imps.Contacts.NICKNAME);
+ int usernameCount = usernames.size();
+ int nicknameCount = nicknames.size();
+
+ if (usernameCount != nicknameCount) {
+ Log.e(LOG_TAG, "[ImProvider] insertBulkContacts: input bundle " +
+ "username & nickname lists have diff. length!");
+ return false;
+ }
+
+ ArrayList<String> contactTypeArray = values.getStringArrayList(Imps.Contacts.TYPE);
+ ArrayList<String> subscriptionStatusArray =
+ values.getStringArrayList(Imps.Contacts.SUBSCRIPTION_STATUS);
+ ArrayList<String> subscriptionTypeArray =
+ values.getStringArrayList(Imps.Contacts.SUBSCRIPTION_TYPE);
+ ArrayList<String> quickContactArray = values.getStringArrayList(Imps.Contacts.QUICK_CONTACT);
+ ArrayList<String> rejectedArray = values.getStringArrayList(Imps.Contacts.REJECTED);
+ int sum = 0;
+
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+
+ db.beginTransaction();
+ try {
+ Long provider = values.getAsLong(Imps.Contacts.PROVIDER);
+ Long account = values.getAsLong(Imps.Contacts.ACCOUNT);
+ Long listId = values.getAsLong(Imps.Contacts.CONTACTLIST);
+
+ ContentValues contactValues = new ContentValues();
+ contactValues.put(Imps.Contacts.PROVIDER, provider);
+ contactValues.put(Imps.Contacts.ACCOUNT, account);
+ contactValues.put(Imps.Contacts.CONTACTLIST, listId);
+ ContentValues presenceValues = new ContentValues();
+ presenceValues.put(Imps.Presence.PRESENCE_STATUS,
+ Imps.Presence.OFFLINE);
+
+ for (int i=0; i<usernameCount; i++) {
+ String username = usernames.get(i);
+ String nickname = nicknames.get(i);
+ int type = 0;
+ int subscriptionStatus = 0;
+ int subscriptionType = 0;
+ int quickContact = 0;
+ int rejected = 0;
+
+ try {
+ type = Integer.parseInt(contactTypeArray.get(i));
+ if (subscriptionStatusArray != null) {
+ subscriptionStatus = Integer.parseInt(subscriptionStatusArray.get(i));
+ }
+ if (subscriptionTypeArray != null) {
+ subscriptionType = Integer.parseInt(subscriptionTypeArray.get(i));
+ }
+ if (quickContactArray != null) {
+ quickContact = Integer.parseInt(quickContactArray.get(i));
+ }
+ if (rejectedArray != null) {
+ rejected = Integer.parseInt(rejectedArray.get(i));
+ }
+ } catch (NumberFormatException ex) {
+ Log.e(LOG_TAG, "insertBulkContacts: caught " + ex);
+ }
+
+ /*
+ if (DBG) log("insertBulkContacts[" + i + "] username=" +
+ username + ", nickname=" + nickname + ", type=" + type +
+ ", subscriptionStatus=" + subscriptionStatus + ", subscriptionType=" +
+ subscriptionType + ", qc=" + quickContact);
+ */
+
+ contactValues.put(Imps.Contacts.USERNAME, username);
+ contactValues.put(Imps.Contacts.NICKNAME, nickname);
+ contactValues.put(Imps.Contacts.TYPE, type);
+ if (subscriptionStatusArray != null) {
+ contactValues.put(Imps.Contacts.SUBSCRIPTION_STATUS, subscriptionStatus);
+ }
+ if (subscriptionTypeArray != null) {
+ contactValues.put(Imps.Contacts.SUBSCRIPTION_TYPE, subscriptionType);
+ }
+ if (quickContactArray != null) {
+ contactValues.put(Imps.Contacts.QUICK_CONTACT, quickContact);
+ }
+ if (rejectedArray != null) {
+ contactValues.put(Imps.Contacts.REJECTED, rejected);
+ }
+
+ long rowId;
+
+ /* save this code for when we add constraint (account, username) to the contacts
+ table
+ try {
+ rowId = db.insertOrThrow(TABLE_CONTACTS, USERNAME, contactValues);
+ } catch (android.database.sqlite.SQLiteConstraintException ex) {
+ if (DBG) log("insertBulkContacts: insert " + username + " caught " + ex);
+
+ // append username to the selection clause
+ updateSelection.delete(0, updateSelection.length());
+ updateSelection.append(Im.Contacts.USERNAME);
+ updateSelection.append("=?");
+ updateSelectionArgs[0] = username;
+
+ int updated = db.update(TABLE_CONTACTS, contactValues,
+ updateSelection.toString(), updateSelectionArgs);
+
+ if (DBG && updated != 1) {
+ log("insertBulkContacts: update " + username + " failed!");
+ }
+ }
+ */
+
+ rowId = db.insert(TABLE_CONTACTS, USERNAME, contactValues);
+ if (rowId > 0) {
+ sum++;
+
+ // seed the presence for the new contact
+ if (DBG) log("### seedPresence for contact id " + rowId);
+ presenceValues.put(Imps.Presence.CONTACT_ID, rowId);
+
+ try {
+ db.insert(TABLE_PRESENCE, null, presenceValues);
+ } catch (android.database.sqlite.SQLiteConstraintException ex) {
+ Log.w(LOG_TAG, "insertBulkContacts: seeding presence caught " + ex);
+ }
+ }
+
+ // yield the lock if anyone else is trying to
+ // perform a db operation here.
+ db.yieldIfContended();
+ }
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ // We know that we succeeded becuase endTransaction throws if the transaction failed.
+ if (DBG) log("insertBulkContacts: added " + sum + " contacts!");
+ return true;
+ }
+
+ // package scope for testing.
+ int updateBulkContacts(ContentValues values, String userWhere) {
+ ArrayList<String> usernames = values.getStringArrayList(Imps.Contacts.USERNAME);
+ ArrayList<String> nicknames = values.getStringArrayList(Imps.Contacts.NICKNAME);
+
+ int usernameCount = usernames.size();
+ int nicknameCount = nicknames.size();
+
+ if (usernameCount != nicknameCount) {
+ Log.e(LOG_TAG, "[ImProvider] updateBulkContacts: input bundle " +
+ "username & nickname lists have diff. length!");
+ return 0;
+ }
+
+ ArrayList<String> contactTypeArray = values.getStringArrayList(Imps.Contacts.TYPE);
+ ArrayList<String> subscriptionStatusArray =
+ values.getStringArrayList(Imps.Contacts.SUBSCRIPTION_STATUS);
+ ArrayList<String> subscriptionTypeArray =
+ values.getStringArrayList(Imps.Contacts.SUBSCRIPTION_TYPE);
+ ArrayList<String> quickContactArray = values.getStringArrayList(Imps.Contacts.QUICK_CONTACT);
+ ArrayList<String> rejectedArray = values.getStringArrayList(Imps.Contacts.REJECTED);
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+
+ db.beginTransaction();
+ int sum = 0;
+
+ try {
+ Long provider = values.getAsLong(Imps.Contacts.PROVIDER);
+ Long account = values.getAsLong(Imps.Contacts.ACCOUNT);
+
+ ContentValues contactValues = new ContentValues();
+ contactValues.put(Imps.Contacts.PROVIDER, provider);
+ contactValues.put(Imps.Contacts.ACCOUNT, account);
+
+ StringBuilder updateSelection = new StringBuilder();
+ String[] updateSelectionArgs = new String[1];
+
+ for (int i=0; i<usernameCount; i++) {
+ String username = usernames.get(i);
+ String nickname = nicknames.get(i);
+ int type = 0;
+ int subscriptionStatus = 0;
+ int subscriptionType = 0;
+ int quickContact = 0;
+ int rejected = 0;
+
+ try {
+ type = Integer.parseInt(contactTypeArray.get(i));
+ subscriptionStatus = Integer.parseInt(subscriptionStatusArray.get(i));
+ subscriptionType = Integer.parseInt(subscriptionTypeArray.get(i));
+ quickContact = Integer.parseInt(quickContactArray.get(i));
+ rejected = Integer.parseInt(rejectedArray.get(i));
+ } catch (NumberFormatException ex) {
+ Log.e(LOG_TAG, "insertBulkContacts: caught " + ex);
+ }
+
+ if (DBG) log("updateBulkContacts[" + i + "] username=" +
+ username + ", nickname=" + nickname + ", type=" + type +
+ ", subscriptionStatus=" + subscriptionStatus + ", subscriptionType=" +
+ subscriptionType + ", qc=" + quickContact);
+
+ contactValues.put(Imps.Contacts.USERNAME, username);
+ contactValues.put(Imps.Contacts.NICKNAME, nickname);
+ contactValues.put(Imps.Contacts.TYPE, type);
+ contactValues.put(Imps.Contacts.SUBSCRIPTION_STATUS, subscriptionStatus);
+ contactValues.put(Imps.Contacts.SUBSCRIPTION_TYPE, subscriptionType);
+ contactValues.put(Imps.Contacts.QUICK_CONTACT, quickContact);
+ contactValues.put(Imps.Contacts.REJECTED, rejected);
+
+ // append username to the selection clause
+ updateSelection.delete(0, updateSelection.length());
+ updateSelection.append(userWhere);
+ updateSelection.append(" AND ");
+ updateSelection.append(Imps.Contacts.USERNAME);
+ updateSelection.append("=?");
+
+ updateSelectionArgs[0] = username;
+
+ int numUpdated = db.update(TABLE_CONTACTS, contactValues,
+ updateSelection.toString(), updateSelectionArgs);
+ if (numUpdated == 0) {
+ Log.e(LOG_TAG, "[ImProvider] updateBulkContacts: " +
+ " update failed for selection = " + updateSelection);
+ } else {
+ sum += numUpdated;
+ }
+
+ // yield the lock if anyone else is trying to
+ // perform a db operation here.
+ db.yieldIfContended();
+ }
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ if (DBG) log("updateBulkContacts: " + sum + " entries updated");
+ return sum;
+ }
+
+ /**
+ * make sure the presence for all contacts of a given account is set to offline, and
+ * each contact has a presence row associated with it. However, this method does not remove
+ * presences for which the corresponding contacts no longer exist. That's probably ok since
+ * presence is kept in memory, so it won't stay around for too long. Here is the algorithm.
+ *
+ * 1. for all presence that have a corresponding contact, make it OFFLINE. This is one sqlite
+ * call.
+ * 2. query for all the contacts that don't have a presence, and add a presence row for them.
+ *
+ * TODO simplify the presence management! The desire is to have a presence row for each
+ * TODO contact in the database, so later we can just call update() on the presence rows
+ * TODO instead of checking for the existence of presence first. The assumption is we get
+ * TODO presence updates much more frequently. However, the logic to maintain that goal is
+ * TODO overly complicated. One possible solution is to use insert_or_replace the presence rows
+ * TODO when updating the presence. That way we don't always need to maintain an empty presence
+ * TODO row for each contact.
+ *
+ * @param account the account of the contacts for which we want to create seed presence rows.
+ */
+ private void seedInitialPresenceByAccount(long account) {
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ qb.setTables(TABLE_CONTACTS);
+ qb.setProjectionMap(sContactsProjectionMap);
+
+ mQueryContactIdSelectionArgs1[0] = String.valueOf(account);
+
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+
+ Cursor c = null;
+
+ try {
+ ContentValues presenceValues = new ContentValues();
+ presenceValues.put(Imps.Presence.PRESENCE_STATUS, Imps.Presence.OFFLINE);
+ presenceValues.put(Imps.Presence.PRESENCE_CUSTOM_STATUS, "");
+
+ // update all the presence for the account so they are offline
+ StringBuilder buf = new StringBuilder();
+ buf.append(Imps.Presence.CONTACT_ID);
+ buf.append(" in (select ");
+ buf.append(Imps.Contacts._ID);
+ buf.append(" from ");
+ buf.append(TABLE_CONTACTS);
+ buf.append(" where ");
+ buf.append(Imps.Contacts.ACCOUNT);
+ buf.append("=?) ");
+
+ String selection = buf.toString();
+ if (DBG) log("seedInitialPresence: reset presence selection=" + selection);
+
+ int count = db.update(TABLE_PRESENCE, presenceValues, selection,
+ mQueryContactIdSelectionArgs1);
+ if (DBG) log("seedInitialPresence: reset " + count + " presence rows to OFFLINE");
+
+ // for in-memory presence table, add a presence row for each contact that
+ // doesn't have a presence. in-memory presence table isn't reliable, and goes away
+ // when device reboot or IMProvider process dies, so we can't rely on each contact
+ // have a corresponding presence.
+ if (DBG) {
+ log("seedInitialPresence: contacts_with_no_presence_selection => " +
+ CONTACTS_WITH_NO_PRESENCE_SELECTION);
+ }
+
+ c = qb.query(db,
+ CONTACT_ID_PROJECTION,
+ CONTACTS_WITH_NO_PRESENCE_SELECTION,
+ mQueryContactIdSelectionArgs1,
+ null, null, null, null);
+
+ if (DBG) log("seedInitialPresence: found " + c.getCount() + " contacts w/o presence");
+
+ count = 0;
+
+ while (c.moveToNext()) {
+ long id = c.getLong(CONTACT_ID_COLUMN);
+ presenceValues.put(Imps.Presence.CONTACT_ID, id);
+
+ try {
+ if (db.insert(TABLE_PRESENCE, null, presenceValues) > 0) {
+ count++;
+ }
+ } catch (SQLiteConstraintException ex) {
+ // we could possibly catch this exception, since there could be a presence
+ // row with the same contact_id. That's fine, just ignore the error
+ if (DBG) log("seedInitialPresence: insert presence for contact_id " + id +
+ " failed, caught " + ex);
+ }
+ }
+
+ if (DBG) log("seedInitialPresence: added " + count + " new presence rows");
+
+ db.setTransactionSuccessful();
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ db.endTransaction();
+ }
+ }
+
+ private int updateBulkPresence(ContentValues values, String userWhere, String[] whereArgs) {
+ ArrayList<String> usernames = values.getStringArrayList(Imps.Contacts.USERNAME);
+ int count = usernames.size();
+ Long account = values.getAsLong(Imps.Contacts.ACCOUNT);
+
+ ArrayList<String> priorityArray = values.getStringArrayList(Imps.Presence.PRIORITY);
+ ArrayList<String> modeArray = values.getStringArrayList(Imps.Presence.PRESENCE_STATUS);
+ ArrayList<String> statusArray = values.getStringArrayList(
+ Imps.Presence.PRESENCE_CUSTOM_STATUS);
+ ArrayList<String> clientTypeArray = values.getStringArrayList(Imps.Presence.CLIENT_TYPE);
+ ArrayList<String> resourceArray = values.getStringArrayList(Imps.Presence.JID_RESOURCE);
+
+ // append username to the selection clause
+ StringBuilder buf = new StringBuilder();
+
+ if (!TextUtils.isEmpty(userWhere)) {
+ buf.append(userWhere);
+ buf.append(" AND ");
+ }
+
+ buf.append(Imps.Presence.CONTACT_ID);
+ buf.append(" in (select ");
+ buf.append(Imps.Contacts._ID);
+ buf.append(" from ");
+ buf.append(TABLE_CONTACTS);
+ buf.append(" where ");
+ buf.append(Imps.Contacts.ACCOUNT);
+ buf.append("=? AND ");
+
+ // use username LIKE ? for case insensitive comparison
+ buf.append(Imps.Contacts.USERNAME);
+ buf.append(" LIKE ?) AND (");
+
+ buf.append(Imps.Presence.PRIORITY);
+ buf.append("<=? OR ");
+ buf.append(Imps.Presence.PRIORITY);
+ buf.append(" IS NULL OR ");
+ buf.append(Imps.Presence.JID_RESOURCE);
+ buf.append("=?)");
+
+ String selection = buf.toString();
+
+ if (DBG) log("updateBulkPresence: selection => " + selection);
+
+ int numArgs = (whereArgs != null ? whereArgs.length + 4 : 4);
+ String[] selectionArgs = new String[numArgs];
+ int selArgsIndex = 0;
+
+ if (whereArgs != null) {
+ for (selArgsIndex=0; selArgsIndex<numArgs-1; selArgsIndex++) {
+ selectionArgs[selArgsIndex] = whereArgs[selArgsIndex];
+ }
+ }
+
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+
+ db.beginTransaction();
+ int sum = 0;
+
+ try {
+ ContentValues presenceValues = new ContentValues();
+
+ for (int i=0; i<count; i++) {
+ String username = usernames.get(i);
+ int priority = 0;
+ int mode = 0;
+ String status = statusArray.get(i);
+ String jidResource = resourceArray == null ? "" : resourceArray.get(i);
+ int clientType = Imps.Presence.CLIENT_TYPE_DEFAULT;
+
+ try {
+ if (priorityArray != null) {
+ priority = Integer.parseInt(priorityArray.get(i));
+ }
+ if (modeArray != null) {
+ mode = Integer.parseInt(modeArray.get(i));
+ }
+ if (clientTypeArray != null) {
+ clientType = Integer.parseInt(clientTypeArray.get(i));
+ }
+ } catch (NumberFormatException ex) {
+ Log.e(LOG_TAG, "[ImProvider] updateBulkPresence: caught " + ex);
+ }
+
+ /*
+ if (DBG) {
+ log("updateBulkPresence[" + i + "] username=" + username + ", priority=" +
+ priority + ", mode=" + mode + ", status=" + status + ", resource=" +
+ jidResource + ", clientType=" + clientType);
+ }
+ */
+
+ if (modeArray != null) {
+ presenceValues.put(Imps.Presence.PRESENCE_STATUS, mode);
+ }
+ if (priorityArray != null) {
+ presenceValues.put(Imps.Presence.PRIORITY, priority);
+ }
+ presenceValues.put(Imps.Presence.PRESENCE_CUSTOM_STATUS, status);
+ if (clientTypeArray != null) {
+ presenceValues.put(Imps.Presence.CLIENT_TYPE, clientType);
+ }
+
+ if (!TextUtils.isEmpty(jidResource)) {
+ presenceValues.put(Imps.Presence.JID_RESOURCE, jidResource);
+ }
+
+ // fill in the selection args
+ int idx = selArgsIndex;
+ selectionArgs[idx++] = String.valueOf(account);
+ selectionArgs[idx++] = username;
+ selectionArgs[idx++] = String.valueOf(priority);
+ selectionArgs[idx] = jidResource;
+
+ int numUpdated = db.update(TABLE_PRESENCE,
+ presenceValues, selection, selectionArgs);
+ if (numUpdated == 0) {
+ Log.e(LOG_TAG, "[ImProvider] updateBulkPresence: failed for " + username);
+ } else {
+ sum += numUpdated;
+ }
+
+ // yield the lock if anyone else is trying to
+ // perform a db operation here.
+ db.yieldIfContended();
+ }
+
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+
+ if (DBG) log("updateBulkPresence: " + sum + " entries updated");
+ return sum;
+ }
+
+ private Uri insertInternal(Uri url, ContentValues initialValues) {
+ Uri resultUri = null;
+ long rowID = 0;
+ long account = 0;
+ String contact = null;
+ long threadId = 0;
+
+ boolean notifyContactListContentUri = false;
+ boolean notifyContactContentUri = false;
+ boolean notifyMessagesContentUri = false;
+ boolean notifyMessagesByContactContentUri = false;
+ boolean notifyMessagesByThreadIdContentUri = false;
+ boolean notifyProviderAccountContentUri = false;
+
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ int match = mUrlMatcher.match(url);
+
+ if (DBG) log("insert to " + url + ", match " + match);
+ switch (match) {
+ case MATCH_PROVIDERS:
+ // Insert into the providers table
+ rowID = db.insert(TABLE_PROVIDERS, "name", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Provider.CONTENT_URI + "/" + rowID);
+ }
+ notifyProviderAccountContentUri = true;
+ break;
+
+ case MATCH_ACCOUNTS:
+ // Insert into the accounts table
+ rowID = db.insert(TABLE_ACCOUNTS, "name", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Account.CONTENT_URI + "/" + rowID);
+ }
+ notifyProviderAccountContentUri = true;
+ break;
+
+ case MATCH_CONTACTS_BY_PROVIDER:
+ appendValuesFromUrl(initialValues, url, Imps.Contacts.PROVIDER,
+ Imps.Contacts.ACCOUNT);
+ // fall through
+ case MATCH_CONTACTS:
+ case MATCH_CONTACTS_BAREBONE:
+ // Insert into the contacts table
+ rowID = db.insert(TABLE_CONTACTS, "username", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Contacts.CONTENT_URI + "/" + rowID);
+ }
+
+ notifyContactContentUri = true;
+ break;
+
+ case MATCH_CONTACTS_BULK:
+ if (insertBulkContacts(initialValues)) {
+ // notify change using the "content://im/contacts" url,
+ // so the change will be observed by listeners interested
+ // in contacts changes.
+ resultUri = Imps.Contacts.CONTENT_URI;
+ }
+ notifyContactContentUri = true;
+ break;
+
+ case MATCH_CONTACTLISTS_BY_PROVIDER:
+ appendValuesFromUrl(initialValues, url, Imps.ContactList.PROVIDER,
+ Imps.ContactList.ACCOUNT);
+ // fall through
+ case MATCH_CONTACTLISTS:
+ // Insert into the contactList table
+ rowID = db.insert(TABLE_CONTACT_LIST, "name", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.ContactList.CONTENT_URI + "/" + rowID);
+ }
+ notifyContactListContentUri = true;
+ break;
+
+ case MATCH_BLOCKEDLIST_BY_PROVIDER:
+ appendValuesFromUrl(initialValues, url, Imps.BlockedList.PROVIDER,
+ Imps.BlockedList.ACCOUNT);
+ // fall through
+ case MATCH_BLOCKEDLIST:
+ // Insert into the blockedList table
+ rowID = db.insert(TABLE_BLOCKED_LIST, "username", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.BlockedList.CONTENT_URI + "/" + rowID);
+ }
+
+ break;
+
+ case MATCH_CONTACTS_ETAGS:
+ rowID = db.replace(TABLE_CONTACTS_ETAG, Imps.ContactsEtag.ETAG, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.ContactsEtag.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_MESSAGES_BY_CONTACT:
+ String accountStr = decodeURLSegment(url.getPathSegments().get(1));
+ try {
+ account = Long.parseLong(accountStr);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ contact = decodeURLSegment(url.getPathSegments().get(2));
+ initialValues.put(Imps.Messages.THREAD_ID, getContactId(db, accountStr, contact));
+
+ notifyMessagesContentUri = true;
+
+ // Insert into the messages table.
+ rowID = db.insert(TABLE_MESSAGES, "thread_id", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Messages.CONTENT_URI + "/" + rowID);
+ }
+
+ break;
+
+ case MATCH_MESSAGES_BY_THREAD_ID:
+ appendValuesFromUrl(initialValues, url, Imps.Messages.THREAD_ID);
+ // fall through
+
+ case MATCH_MESSAGES:
+ // Insert into the messages table.
+ notifyMessagesContentUri = true;
+ rowID = db.insert(TABLE_MESSAGES, "thread_id", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Messages.CONTENT_URI + "/" + rowID);
+ }
+
+ break;
+
+ case MATCH_OTR_MESSAGES_BY_CONTACT:
+ String accountStr2 = decodeURLSegment(url.getPathSegments().get(1));
+
+ try {
+ account = Long.parseLong(accountStr2);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ contact = decodeURLSegment(url.getPathSegments().get(2));
+ initialValues.put(Imps.Messages.THREAD_ID, getContactId(db, accountStr2, contact));
+
+ notifyMessagesByContactContentUri = true;
+
+ // Insert into the in-memory messages table.
+ rowID = db.insert(TABLE_IN_MEMORY_MESSAGES, "thread_id", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Messages.OTR_MESSAGES_CONTENT_URI + "/" + rowID);
+ }
+
+ break;
+
+ case MATCH_OTR_MESSAGES_BY_THREAD_ID:
+ try {
+ threadId = Long.parseLong(decodeURLSegment(url.getPathSegments().get(1)));
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ initialValues.put(Imps.Messages.THREAD_ID, threadId);
+
+ notifyMessagesByThreadIdContentUri = true;
+ // fall through
+
+ case MATCH_OTR_MESSAGES:
+ // Insert into the messages table.
+ rowID = db.insert(TABLE_IN_MEMORY_MESSAGES, "thread_id", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Messages.OTR_MESSAGES_CONTENT_URI + "/" + rowID);
+ }
+
+ break;
+
+ case MATCH_INVITATIONS:
+ rowID = db.insert(TABLE_INVITATIONS, null, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Invitation.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_GROUP_MEMBERS:
+ rowID = db.insert(TABLE_GROUP_MEMBERS, "nickname", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.GroupMembers.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_GROUP_MEMBERS_BY_GROUP:
+ appendValuesFromUrl(initialValues, url, Imps.GroupMembers.GROUP);
+ rowID = db.insert(TABLE_GROUP_MEMBERS, "nickname", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.GroupMembers.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_AVATAR_BY_PROVIDER:
+ appendValuesFromUrl(initialValues, url, Imps.Avatars.PROVIDER, Imps.Avatars.ACCOUNT);
+ // fall through
+ case MATCH_AVATARS:
+ // Insert into the avatars table
+ rowID = db.replace(TABLE_AVATARS, "contact", initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Avatars.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_CHATS_ID:
+ appendValuesFromUrl(initialValues, url, Imps.Chats.CONTACT_ID);
+ // fall through
+ case MATCH_CHATS:
+ // Insert into the chats table
+ initialValues.put(Imps.Chats.SHORTCUT, -1);
+ rowID = db.replace(TABLE_CHATS, Imps.Chats.CONTACT_ID, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Chats.CONTENT_URI + "/" + rowID);
+ addToQuickSwitch(rowID);
+ }
+ notifyContactContentUri = true;
+ break;
+
+ case MATCH_PRESENCE:
+ rowID = db.replace(TABLE_PRESENCE, null, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.Presence.CONTENT_URI + "/" + rowID);
+ }
+ notifyContactContentUri = true;
+ break;
+
+ case MATCH_PRESENCE_SEED_BY_ACCOUNT:
+ try {
+ seedInitialPresenceByAccount(Long.parseLong(url.getLastPathSegment()));
+ resultUri = Imps.Presence.CONTENT_URI;
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+ break;
+
+ case MATCH_SESSIONS_BY_PROVIDER:
+ appendValuesFromUrl(initialValues, url, Imps.SessionCookies.PROVIDER,
+ Imps.SessionCookies.ACCOUNT);
+ // fall through
+ case MATCH_SESSIONS:
+ rowID = db.insert(TABLE_SESSION_COOKIES, null, initialValues);
+ if(rowID > 0) {
+ resultUri = Uri.parse(Imps.SessionCookies.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_PROVIDER_SETTINGS:
+ rowID = db.replace(TABLE_PROVIDER_SETTINGS, null, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.ProviderSettings.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_ACCOUNTS_STATUS:
+ rowID = db.replace(TABLE_ACCOUNT_STATUS, null, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.AccountStatus.CONTENT_URI + "/" + rowID);
+ }
+ notifyProviderAccountContentUri = true;
+ break;
+
+ case MATCH_BRANDING_RESOURCE_MAP_CACHE:
+ rowID = db.insert(TABLE_BRANDING_RESOURCE_MAP_CACHE, null, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.BrandingResourceMapCache.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ // mcs/rmq stuff
+ case MATCH_OUTGOING_RMQ_MESSAGES:
+ rowID = db.insert(TABLE_OUTGOING_RMQ_MESSAGES, null, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.OutgoingRmq.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_LAST_RMQ_ID:
+ rowID = db.replace(TABLE_LAST_RMQ_ID, null, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.LastRmqId.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ case MATCH_S2D_RMQ_IDS:
+ rowID = db.insert(TABLE_S2D_RMQ_IDS, null, initialValues);
+ if (rowID > 0) {
+ resultUri = Uri.parse(Imps.ServerToDeviceRmqIds.CONTENT_URI + "/" + rowID);
+ }
+ break;
+
+ default:
+ throw new UnsupportedOperationException("Cannot insert into URL: " + url);
+ }
+ // TODO: notify the data change observer?
+
+ if (resultUri != null) {
+ ContentResolver resolver = getContext().getContentResolver();
+
+ // In most case, we query contacts with presence and chats joined, thus
+ // we should also notify that contacts changes when presence or chats changed.
+ if (notifyContactContentUri) {
+ resolver.notifyChange(Imps.Contacts.CONTENT_URI, null);
+ }
+
+ if (notifyContactListContentUri) {
+ resolver.notifyChange(Imps.ContactList.CONTENT_URI, null);
+ }
+
+ if (notifyMessagesContentUri) {
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ }
+
+ if (notifyMessagesByContactContentUri) {
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ resolver.notifyChange(Imps.Messages.getContentUriByContact(account, contact), null);
+ }
+
+ if (notifyMessagesByThreadIdContentUri) {
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ resolver.notifyChange(Imps.Messages.getContentUriByThreadId(threadId), null);
+ }
+
+ if (notifyProviderAccountContentUri) {
+ if (DBG) log("notify insert for " + Imps.Provider.CONTENT_URI_WITH_ACCOUNT);
+ resolver.notifyChange(Imps.Provider.CONTENT_URI_WITH_ACCOUNT, null);
+ }
+ }
+ return resultUri;
+ }
+
+ private void appendValuesFromUrl(ContentValues values, Uri url, String...columns){
+ if(url.getPathSegments().size() <= columns.length) {
+ throw new IllegalArgumentException("Not enough values in url");
+ }
+ for(int i = 0; i < columns.length; i++){
+ if(values.containsKey(columns[i])){
+ throw new UnsupportedOperationException("Cannot override the value for " + columns[i]);
+ }
+ values.put(columns[i], decodeURLSegment(url.getPathSegments().get(i + 1)));
+ }
+ }
+
+ private long getContactId(final SQLiteDatabase db,
+ final String accountId, final String contact) {
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+ qb.setTables(TABLE_CONTACTS);
+ qb.setProjectionMap(sContactsProjectionMap);
+
+ mQueryContactIdSelectionArgs2[0] = accountId;
+ mQueryContactIdSelectionArgs2[1] = contact;
+
+ Cursor c = qb.query(db,
+ CONTACT_ID_PROJECTION,
+ CONTACT_ID_QUERY_SELECTION,
+ mQueryContactIdSelectionArgs2,
+ null, null, null, null);
+
+ long contactId = 0;
+
+ try {
+ if (c.moveToFirst()) {
+ contactId = c.getLong(CONTACT_ID_COLUMN);
+ }
+ } finally {
+ c.close();
+ }
+
+ return contactId;
+ }
+
+ // Quick-switch management
+ // The chat UI provides slots (0, 9, .., 1) for the first 10 chats. This allows you to
+ // quickly switch between these chats by chording menu+#. We number from the right end of
+ // the number row and move leftward to make an easier two-hand chord with the menu button
+ // on the left side of the keyboard.
+ private void addToQuickSwitch(long newRow) {
+ // Since there are fewer than 10, there must be an empty slot. Let's find it.
+ int slot = findEmptyQuickSwitchSlot();
+
+ if (slot == -1) {
+ return;
+ }
+
+ updateSlotForChat(newRow, slot);
+ }
+
+ // If there are more than 10 chats and one with a quick switch slot ends then pick a chat
+ // that doesn't have a slot and have it inhabit the newly emptied slot.
+ private void backfillQuickSwitchSlots() {
+ // Find all the chats without a quick switch slot, and order
+ Cursor c = query(Imps.Chats.CONTENT_URI,
+ BACKFILL_PROJECTION,
+ Imps.Chats.SHORTCUT + "=-1", null, Imps.Chats.LAST_MESSAGE_DATE + " DESC");
+
+ try {
+ if (c.getCount() < 1) {
+ return;
+ }
+
+ int slot = findEmptyQuickSwitchSlot();
+
+ if (slot != -1) {
+ c.moveToFirst();
+
+ long id = c.getLong(c.getColumnIndex(Imps.Chats._ID));
+
+ updateSlotForChat(id, slot);
+ }
+ } finally {
+ c.close();
+ }
+ }
+
+ private int updateSlotForChat(long chatId, int slot) {
+ ContentValues values = new ContentValues();
+
+ values.put(Imps.Chats.SHORTCUT, slot);
+
+ return update(Imps.Chats.CONTENT_URI, values, Imps.Chats._ID + "=?",
+ new String[] { Long.toString(chatId) });
+ }
+
+ private int findEmptyQuickSwitchSlot() {
+ Cursor c = queryInternal(Imps.Chats.CONTENT_URI, FIND_SHORTCUT_PROJECTION, null, null, null);
+ final int N = c.getCount();
+
+ try {
+ // If there are 10 or more chats then all the quick switch slots are already filled
+ if (N >= 10) {
+ return -1;
+ }
+
+ int slots = 0;
+ int column = c.getColumnIndex(Imps.Chats.SHORTCUT);
+
+ // The map is here because numbers go from 0-9, but we want to assign slots in
+ // 0, 9, 8, ..., 1 order to match the right-to-left reading of the number row
+ // on the keyboard.
+ int[] map = new int[] { 0, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
+
+ // Mark all the slots that are in use
+ // The shortcuts represent actual keyboard number row keys, and not ordinals.
+ // So 7 would mean the shortcut is the 7 key on the keyboard and NOT the 7th
+ // shortcut. The passing of slot through map[] below maps these keyboard key
+ // shortcuts into an ordinal bit position in the 'slots' bitfield.
+ for (c.moveToFirst(); ! c.isAfterLast(); c.moveToNext()) {
+ int slot = c.getInt(column);
+
+ if (slot != -1) {
+ slots |= (1 << map[slot]);
+ }
+ }
+
+ // Try to find an empty one
+ // As we exit this, the push of i through map[] maps the ordinal bit position
+ // in the 'slots' bitfield onto a key on the number row of the device keyboard.
+ // The keyboard key is what is used to designate the shortcut.
+ for (int i = 0; i < 10; i++) {
+ if ((slots & (1 << i)) == 0) {
+ return map[i];
+ }
+ }
+
+ return -1;
+ } finally {
+ c.close();
+ }
+ }
+
+ /**
+ * manual trigger for deleting contacts
+ */
+ private static final String DELETE_PRESENCE_SELECTION =
+ Imps.Presence.CONTACT_ID + " in (select " +
+ PRESENCE_CONTACT_ID + " from " + TABLE_PRESENCE + " left outer join " + TABLE_CONTACTS +
+ " on " + PRESENCE_CONTACT_ID + '=' + CONTACT_ID + " where " + CONTACT_ID + " IS NULL)";
+
+ private static final String CHATS_CONTACT_ID = TABLE_CHATS + '.' + Imps.Chats.CONTACT_ID;
+ private static final String DELETE_CHATS_SELECTION = Imps.Chats.CONTACT_ID + " in (select "+
+ CHATS_CONTACT_ID + " from " + TABLE_CHATS + " left outer join " + TABLE_CONTACTS +
+ " on " + CHATS_CONTACT_ID + '=' + CONTACT_ID + " where " + CONTACT_ID + " IS NULL)";
+
+ private static final String GROUP_MEMBER_ID = TABLE_GROUP_MEMBERS + '.' + Imps.GroupMembers.GROUP;
+ private static final String DELETE_GROUP_MEMBER_SELECTION =
+ Imps.GroupMembers.GROUP + " in (select "+
+ GROUP_MEMBER_ID + " from " + TABLE_GROUP_MEMBERS + " left outer join " + TABLE_CONTACTS +
+ " on " + GROUP_MEMBER_ID + '=' + CONTACT_ID + " where " + CONTACT_ID + " IS NULL)";
+
+ private static final String GROUP_MESSAGES_ID = TABLE_MESSAGES + '.' + Imps.Messages.THREAD_ID;
+ private static final String DELETE_GROUP_MESSAGES_SELECTION =
+ Imps.Messages.THREAD_ID + " in (select "+ GROUP_MESSAGES_ID + " from " +
+ TABLE_MESSAGES + " left outer join " + TABLE_CONTACTS + " on " +
+ GROUP_MESSAGES_ID + '=' + CONTACT_ID + " where " + CONTACT_ID + " IS NULL)";
+
+ private void performContactRemovalCleanup(long contactId) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+
+ if (contactId > 0) {
+ StringBuilder buf = new StringBuilder();
+
+ // delete presence
+ buf.append(Imps.Presence.CONTACT_ID).append('=').append(contactId);
+ deleteWithSelection(db, TABLE_PRESENCE, buf.toString(), null);
+
+ // delete group memebers
+ buf.delete(0, buf.length());
+ buf.append(Imps.GroupMembers.GROUP).append('=').append(contactId);
+ deleteWithSelection(db, TABLE_GROUP_MEMBERS, buf.toString(), null);
+ } else {
+ // delete presence
+ deleteWithSelection(db, TABLE_PRESENCE, DELETE_PRESENCE_SELECTION, null);
+
+ // delete group members
+ deleteWithSelection(db, TABLE_GROUP_MEMBERS, DELETE_GROUP_MEMBER_SELECTION, null);
+ }
+ }
+
+ private void deleteWithSelection(SQLiteDatabase db, String tableName,
+ String selection, String[] selectionArgs) {
+ if (DBG) log("deleteWithSelection: table " + tableName + ", selection => " + selection);
+ int count = db.delete(tableName, selection, selectionArgs);
+ if (DBG) log("deleteWithSelection: deleted " + count + " rows");
+ }
+
+ private String buildContactIdSelection(String columnName, String contactSelection) {
+ StringBuilder buf = new StringBuilder();
+
+ buf.append(columnName);
+ buf.append(" in (select ");
+ buf.append(Imps.Contacts._ID);
+ buf.append(" from ");
+ buf.append(TABLE_CONTACTS);
+ buf.append(" where ");
+ buf.append(contactSelection);
+ buf.append(")");
+
+ return buf.toString();
+ }
+
+ private int deleteInternal(Uri url, String userWhere, String[] whereArgs) {
+ String tableToChange;
+
+ // In some cases a given url requires that we delete rows from more than one
+ // table. The motivating example is deleting messages from both the on disk
+ // and in memory messages tables.
+ String tableToChange2 = null;
+ String idColumnName = null;
+ String changedItemId = null;
+ String provider = null;
+ String accountStr = null;
+ long account = 0;
+ String contact = null;
+ long threadId = 0;
+
+ StringBuilder whereClause = new StringBuilder();
+ if(userWhere != null) {
+ whereClause.append(userWhere);
+ }
+
+ boolean notifyMessagesContentUri = false;
+ boolean notifyMessagesByContactContentUri = false;
+ boolean notifyMessagesByThreadIdContentUri = false;
+ boolean notifyContactListContentUri = false;
+ boolean notifyProviderAccountContentUri = false;
+ int match = mUrlMatcher.match(url);
+
+ boolean contactDeleted = false;
+ long deletedContactId = 0;
+
+ boolean backfillQuickSwitchSlots = false;
+
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+
+ switch (match) {
+ case MATCH_PROVIDERS:
+ tableToChange = TABLE_PROVIDERS;
+ notifyProviderAccountContentUri = true;
+ break;
+
+ case MATCH_ACCOUNTS_BY_ID:
+ changedItemId = url.getPathSegments().get(1);
+ // fall through
+ case MATCH_ACCOUNTS:
+ tableToChange = TABLE_ACCOUNTS;
+ notifyProviderAccountContentUri = true;
+ break;
+
+ case MATCH_ACCOUNT_STATUS:
+ changedItemId = url.getPathSegments().get(1);
+ // fall through
+ case MATCH_ACCOUNTS_STATUS:
+ tableToChange = TABLE_ACCOUNT_STATUS;
+ notifyProviderAccountContentUri = true;
+ break;
+
+ case MATCH_CONTACTS:
+ case MATCH_CONTACTS_BAREBONE:
+ tableToChange = TABLE_CONTACTS;
+ contactDeleted = true;
+ break;
+
+ case MATCH_CONTACT:
+ tableToChange = TABLE_CONTACTS;
+ changedItemId = url.getPathSegments().get(1);
+
+ try {
+ deletedContactId = Long.parseLong(changedItemId);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ contactDeleted = true;
+ break;
+
+ case MATCH_CONTACTS_BY_PROVIDER:
+ tableToChange = TABLE_CONTACTS;
+ appendWhere(whereClause, Imps.Contacts.ACCOUNT, "=", url.getPathSegments().get(2));
+ contactDeleted = true;
+ break;
+
+ case MATCH_CONTACTLISTS_BY_PROVIDER:
+ appendWhere(whereClause, Imps.ContactList.ACCOUNT, "=",
+ url.getPathSegments().get(2));
+ // fall through
+ case MATCH_CONTACTLISTS:
+ tableToChange = TABLE_CONTACT_LIST;
+ notifyContactListContentUri = true;
+ break;
+
+ case MATCH_CONTACTLIST:
+ tableToChange = TABLE_CONTACT_LIST;
+ changedItemId = url.getPathSegments().get(1);
+ break;
+
+ case MATCH_BLOCKEDLIST:
+ tableToChange = TABLE_BLOCKED_LIST;
+ break;
+
+ case MATCH_BLOCKEDLIST_BY_PROVIDER:
+ tableToChange = TABLE_BLOCKED_LIST;
+ appendWhere(whereClause, Imps.BlockedList.ACCOUNT, "=", url.getPathSegments().get(2));
+ break;
+
+ case MATCH_CONTACTS_ETAGS:
+ tableToChange = TABLE_CONTACTS_ETAG;
+ break;
+
+ case MATCH_CONTACTS_ETAG:
+ tableToChange = TABLE_CONTACTS_ETAG;
+ changedItemId = url.getPathSegments().get(1);
+ break;
+
+ case MATCH_MESSAGES:
+ tableToChange = TABLE_MESSAGES;
+ break;
+
+ case MATCH_MESSAGES_BY_CONTACT:
+ tableToChange = TABLE_MESSAGES;
+ tableToChange2 = TABLE_IN_MEMORY_MESSAGES;
+
+ accountStr = decodeURLSegment(url.getPathSegments().get(1));
+ try {
+ account = Long.parseLong(accountStr);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ contact = decodeURLSegment(url.getPathSegments().get(2));
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=",
+ getContactId(db, accountStr, contact));
+
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_MESSAGES_BY_THREAD_ID:
+ tableToChange = TABLE_MESSAGES;
+ tableToChange2 = TABLE_IN_MEMORY_MESSAGES;
+
+ try {
+ threadId = Long.parseLong(decodeURLSegment(url.getPathSegments().get(1)));
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=", threadId);
+
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_MESSAGES_BY_PROVIDER:
+ tableToChange = TABLE_MESSAGES;
+
+ provider = decodeURLSegment(url.getPathSegments().get(1));
+ appendWhere(whereClause, buildContactIdSelection(Imps.Messages.THREAD_ID,
+ Imps.Contacts.PROVIDER + "='" + provider + "'"));
+
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_MESSAGES_BY_ACCOUNT:
+ tableToChange = TABLE_MESSAGES;
+
+ accountStr = decodeURLSegment(url.getPathSegments().get(1));
+ appendWhere(whereClause, buildContactIdSelection(Imps.Messages.THREAD_ID,
+ Imps.Contacts.ACCOUNT + "='" + accountStr + "'"));
+
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_MESSAGE:
+ tableToChange = TABLE_MESSAGES;
+ changedItemId = url.getPathSegments().get(1);
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_OTR_MESSAGES:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+ break;
+
+ case MATCH_OTR_MESSAGES_BY_CONTACT:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+
+ accountStr = decodeURLSegment(url.getPathSegments().get(1));
+ try {
+ account = Long.parseLong(accountStr);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ contact = decodeURLSegment(url.getPathSegments().get(2));
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=",
+ getContactId(db, accountStr, contact));
+
+ notifyMessagesByContactContentUri = true;
+ break;
+
+ case MATCH_OTR_MESSAGES_BY_THREAD_ID:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+
+ try {
+ threadId = Long.parseLong(decodeURLSegment(url.getPathSegments().get(1)));
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=", threadId);
+
+ notifyMessagesByThreadIdContentUri = true;
+ break;
+
+ case MATCH_OTR_MESSAGES_BY_PROVIDER:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+
+ provider = decodeURLSegment(url.getPathSegments().get(1));
+ appendWhere(whereClause, buildContactIdSelection(Imps.Messages.THREAD_ID,
+ Imps.Contacts.PROVIDER + "='" + provider + "'"));
+
+ if (DBG) log("delete (MATCH_OTR_MESSAGES_BY_PROVIDER) sel => " + whereClause);
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_OTR_MESSAGES_BY_ACCOUNT:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+
+ accountStr = decodeURLSegment(url.getPathSegments().get(1));
+ appendWhere(whereClause, buildContactIdSelection(Imps.Messages.THREAD_ID,
+ Imps.Contacts.ACCOUNT + "='" + accountStr + "'"));
+
+ if (DBG) log("delete (MATCH_OTR_MESSAGES_BY_ACCOUNT) sel => " + whereClause);
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_OTR_MESSAGE:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+ changedItemId = url.getPathSegments().get(1);
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_GROUP_MEMBERS:
+ tableToChange = TABLE_GROUP_MEMBERS;
+ break;
+
+ case MATCH_GROUP_MEMBERS_BY_GROUP:
+ tableToChange = TABLE_GROUP_MEMBERS;
+ appendWhere(whereClause, Imps.GroupMembers.GROUP, "=", url.getPathSegments().get(1));
+ break;
+
+ case MATCH_INVITATIONS:
+ tableToChange = TABLE_INVITATIONS;
+ break;
+
+ case MATCH_INVITATION:
+ tableToChange = TABLE_INVITATIONS;
+ changedItemId = url.getPathSegments().get(1);
+ break;
+
+ case MATCH_AVATARS:
+ tableToChange = TABLE_AVATARS;
+ break;
+
+ case MATCH_AVATAR:
+ tableToChange = TABLE_AVATARS;
+ changedItemId = url.getPathSegments().get(1);
+ break;
+
+ case MATCH_AVATAR_BY_PROVIDER:
+ tableToChange = TABLE_AVATARS;
+ changedItemId = url.getPathSegments().get(2);
+ idColumnName = Imps.Avatars.ACCOUNT;
+ break;
+
+ case MATCH_CHATS:
+ tableToChange = TABLE_CHATS;
+ backfillQuickSwitchSlots = true;
+ break;
+
+ case MATCH_CHATS_BY_ACCOUNT:
+ tableToChange = TABLE_CHATS;
+
+ accountStr = decodeURLSegment(url.getLastPathSegment());
+ appendWhere(whereClause, buildContactIdSelection(Imps.Chats.CONTACT_ID,
+ Imps.Contacts.ACCOUNT + "='" + accountStr + "'"));
+
+ if (DBG) log("delete (MATCH_CHATS_BY_ACCOUNT) sel => " + whereClause);
+
+ changedItemId = null;
+ break;
+
+ case MATCH_CHATS_ID:
+ tableToChange = TABLE_CHATS;
+ changedItemId = url.getPathSegments().get(1);
+ idColumnName = Imps.Chats.CONTACT_ID;
+ break;
+
+ case MATCH_PRESENCE:
+ tableToChange = TABLE_PRESENCE;
+ break;
+
+ case MATCH_PRESENCE_ID:
+ tableToChange = TABLE_PRESENCE;
+ changedItemId = url.getPathSegments().get(1);
+ idColumnName = Imps.Presence.CONTACT_ID;
+ break;
+
+ case MATCH_PRESENCE_BY_ACCOUNT:
+ tableToChange = TABLE_PRESENCE;
+
+ accountStr = decodeURLSegment(url.getLastPathSegment());
+ appendWhere(whereClause, buildContactIdSelection(Imps.Presence.CONTACT_ID,
+ Imps.Contacts.ACCOUNT + "='" + accountStr + "'"));
+
+ if (DBG) log("delete (MATCH_PRESENCE_BY_ACCOUNT): sel => " + whereClause);
+ changedItemId = null;
+ break;
+
+ case MATCH_SESSIONS:
+ tableToChange = TABLE_SESSION_COOKIES;
+ break;
+
+ case MATCH_SESSIONS_BY_PROVIDER:
+ tableToChange = TABLE_SESSION_COOKIES;
+ changedItemId = url.getPathSegments().get(2);
+ idColumnName = Imps.SessionCookies.ACCOUNT;
+ break;
+
+ case MATCH_PROVIDER_SETTINGS_BY_ID:
+ tableToChange = TABLE_PROVIDER_SETTINGS;
+ changedItemId = url.getPathSegments().get(1);
+ idColumnName = Imps.ProviderSettings.PROVIDER;
+ break;
+
+ case MATCH_PROVIDER_SETTINGS_BY_ID_AND_NAME:
+ tableToChange = TABLE_PROVIDER_SETTINGS;
+
+ String providerId = url.getPathSegments().get(1);
+ String name = url.getPathSegments().get(2);
+
+ appendWhere(whereClause, Imps.ProviderSettings.PROVIDER, "=", providerId);
+ appendWhere(whereClause, Imps.ProviderSettings.NAME, "=", name);
+ break;
+
+ case MATCH_BRANDING_RESOURCE_MAP_CACHE:
+ tableToChange = TABLE_BRANDING_RESOURCE_MAP_CACHE;
+ break;
+
+ // mcs/rmq stuff
+ case MATCH_OUTGOING_RMQ_MESSAGES:
+ tableToChange = TABLE_OUTGOING_RMQ_MESSAGES;
+ break;
+
+ case MATCH_LAST_RMQ_ID:
+ tableToChange = TABLE_LAST_RMQ_ID;
+ break;
+
+ case MATCH_S2D_RMQ_IDS:
+ tableToChange = TABLE_S2D_RMQ_IDS;
+ break;
+
+ default:
+ throw new UnsupportedOperationException("Cannot delete that URL: " + url);
+ }
+
+ if (idColumnName == null) {
+ idColumnName = "_id";
+ }
+
+ if (changedItemId != null) {
+ appendWhere(whereClause, idColumnName, "=", changedItemId);
+ }
+
+ if (DBG) log("delete from " + url + " WHERE " + whereClause);
+
+ int count = db.delete(tableToChange, whereClause.toString(), whereArgs);
+
+ // see the comment at the declaration of tableToChange2 for an explanation
+ if (tableToChange2 != null){
+ count += db.delete(tableToChange2, whereClause.toString(), whereArgs);
+ }
+
+ if (contactDeleted && count > 0) {
+ // since the contact cleanup triggers no longer work for cross database tables,
+ // we have to do it by hand here.
+ performContactRemovalCleanup(deletedContactId);
+ }
+
+ if (count > 0) {
+ ContentResolver resolver = getContext().getContentResolver();
+
+ // In most case, we query contacts with presence and chats joined, thus
+ // we should also notify that contacts changes when presence or chats changed.
+ if (match == MATCH_CHATS || match == MATCH_CHATS_ID
+ || match == MATCH_PRESENCE || match == MATCH_PRESENCE_ID
+ || match == MATCH_CONTACTS_BAREBONE) {
+ resolver.notifyChange(Imps.Contacts.CONTENT_URI, null);
+ }
+
+ if (notifyMessagesContentUri) {
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ }
+
+ if (notifyMessagesByContactContentUri) {
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ resolver.notifyChange(Imps.Messages.getContentUriByContact(account, contact), null);
+ }
+
+ if (notifyMessagesByThreadIdContentUri) {
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ resolver.notifyChange(Imps.Messages.getContentUriByThreadId(threadId), null);
+ }
+
+ if (notifyContactListContentUri) {
+ resolver.notifyChange(Imps.ContactList.CONTENT_URI, null);
+ }
+
+ if (notifyProviderAccountContentUri) {
+ if (DBG) log("notify delete for " + Imps.Provider.CONTENT_URI_WITH_ACCOUNT);
+ resolver.notifyChange(Imps.Provider.CONTENT_URI_WITH_ACCOUNT, null);
+ }
+
+ if (backfillQuickSwitchSlots) {
+ backfillQuickSwitchSlots();
+ }
+ }
+
+ return count;
+ }
+
+ private int updateInternal(Uri url, ContentValues values, String userWhere,
+ String[] whereArgs) {
+ String tableToChange;
+ String idColumnName = null;
+ String changedItemId = null;
+ String accountStr = null;
+ long account = 0;
+ String contact = null;
+ long threadId = 0;
+ int count;
+
+ StringBuilder whereClause = new StringBuilder();
+ if(userWhere != null) {
+ whereClause.append(userWhere);
+ }
+
+ boolean notifyMessagesContentUri = false;
+ boolean notifyMessagesByContactContentUri = false;
+ boolean notifyMessagesByThreadIdContentUri = false;
+ boolean notifyContactListContentUri = false;
+ boolean notifyProviderAccountContentUri = false;
+
+ int match = mUrlMatcher.match(url);
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+
+ switch (match) {
+ case MATCH_PROVIDERS_BY_ID:
+ changedItemId = url.getPathSegments().get(1);
+ // fall through
+ case MATCH_PROVIDERS:
+ tableToChange = TABLE_PROVIDERS;
+ break;
+
+ case MATCH_ACCOUNTS_BY_ID:
+ changedItemId = url.getPathSegments().get(1);
+ // fall through
+ case MATCH_ACCOUNTS:
+ tableToChange = TABLE_ACCOUNTS;
+ notifyProviderAccountContentUri = true;
+ break;
+
+ case MATCH_ACCOUNT_STATUS:
+ changedItemId = url.getPathSegments().get(1);
+ // fall through
+ case MATCH_ACCOUNTS_STATUS:
+ tableToChange = TABLE_ACCOUNT_STATUS;
+ notifyProviderAccountContentUri = true;
+ break;
+
+ case MATCH_CONTACTS:
+ case MATCH_CONTACTS_BAREBONE:
+ tableToChange = TABLE_CONTACTS;
+ break;
+
+ case MATCH_CONTACTS_BY_PROVIDER:
+ tableToChange = TABLE_CONTACTS;
+ changedItemId = url.getPathSegments().get(2);
+ idColumnName = Imps.Contacts.ACCOUNT;
+ break;
+
+ case MATCH_CONTACT:
+ tableToChange = TABLE_CONTACTS;
+ changedItemId = url.getPathSegments().get(1);
+ break;
+
+ case MATCH_CONTACTS_BULK:
+ count = updateBulkContacts(values, userWhere);
+ // notify change using the "content://im/contacts" url,
+ // so the change will be observed by listeners interested
+ // in contacts changes.
+ if (count > 0) {
+ getContext().getContentResolver().notifyChange(
+ Imps.Contacts.CONTENT_URI, null);
+ }
+ return count;
+
+ case MATCH_CONTACTLIST:
+ tableToChange = TABLE_CONTACT_LIST;
+ changedItemId = url.getPathSegments().get(1);
+ notifyContactListContentUri = true;
+ break;
+
+ case MATCH_CONTACTS_ETAGS:
+ tableToChange = TABLE_CONTACTS_ETAG;
+ break;
+
+ case MATCH_CONTACTS_ETAG:
+ tableToChange = TABLE_CONTACTS_ETAG;
+ changedItemId = url.getPathSegments().get(1);
+ break;
+
+ case MATCH_MESSAGES:
+ tableToChange = TABLE_MESSAGES;
+ break;
+
+ case MATCH_MESSAGES_BY_CONTACT:
+ tableToChange = TABLE_MESSAGES;
+
+ accountStr = decodeURLSegment(url.getPathSegments().get(1));
+ try {
+ account = Long.parseLong(accountStr);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ contact = decodeURLSegment(url.getPathSegments().get(2));
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=",
+ getContactId(db, accountStr, contact));
+
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_MESSAGES_BY_THREAD_ID:
+ tableToChange = TABLE_MESSAGES;
+
+ try {
+ threadId = Long.parseLong(decodeURLSegment(url.getPathSegments().get(1)));
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=", threadId);
+
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_MESSAGE:
+ tableToChange = TABLE_MESSAGES;
+ changedItemId = url.getPathSegments().get(1);
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_OTR_MESSAGES:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+ break;
+
+ case MATCH_OTR_MESSAGES_BY_CONTACT:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+
+ accountStr = decodeURLSegment(url.getPathSegments().get(1));
+ try {
+ account = Long.parseLong(accountStr);
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ contact = decodeURLSegment(url.getPathSegments().get(2));
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=",
+ getContactId(db, accountStr, contact));
+
+ notifyMessagesByContactContentUri = true;
+ break;
+
+ case MATCH_OTR_MESSAGES_BY_THREAD_ID:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+
+ try {
+ threadId = Long.parseLong(decodeURLSegment(url.getPathSegments().get(1)));
+ } catch (NumberFormatException ex) {
+ throw new IllegalArgumentException();
+ }
+
+ appendWhere(whereClause, Imps.Messages.THREAD_ID, "=", threadId);
+
+ notifyMessagesByThreadIdContentUri = true;
+ break;
+
+ case MATCH_OTR_MESSAGE:
+ tableToChange = TABLE_IN_MEMORY_MESSAGES;
+ changedItemId = url.getPathSegments().get(1);
+ notifyMessagesContentUri = true;
+ break;
+
+ case MATCH_AVATARS:
+ tableToChange = TABLE_AVATARS;
+ break;
+
+ case MATCH_AVATAR:
+ tableToChange = TABLE_AVATARS;
+ changedItemId = url.getPathSegments().get(1);
+ break;
+
+ case MATCH_AVATAR_BY_PROVIDER:
+ tableToChange = TABLE_AVATARS;
+ changedItemId = url.getPathSegments().get(2);
+ idColumnName = Imps.Avatars.ACCOUNT;
+ break;
+
+ case MATCH_CHATS:
+ tableToChange = TABLE_CHATS;
+ break;
+
+ case MATCH_CHATS_ID:
+ tableToChange = TABLE_CHATS;
+ changedItemId = url.getPathSegments().get(1);
+ idColumnName = Imps.Chats.CONTACT_ID;
+ break;
+
+ case MATCH_PRESENCE:
+ //if (DBG) log("update presence: where='" + userWhere + "'");
+ tableToChange = TABLE_PRESENCE;
+ break;
+
+ case MATCH_PRESENCE_ID:
+ tableToChange = TABLE_PRESENCE;
+ changedItemId = url.getPathSegments().get(1);
+ idColumnName = Imps.Presence.CONTACT_ID;
+ break;
+
+ case MATCH_PRESENCE_BULK:
+ count = updateBulkPresence(values, userWhere, whereArgs);
+ // notify change using the "content://im/contacts" url,
+ // so the change will be observed by listeners interested
+ // in contacts changes.
+ if (count > 0) {
+ getContext().getContentResolver().notifyChange(Imps.Contacts.CONTENT_URI, null);
+ }
+
+ return count;
+
+ case MATCH_INVITATION:
+ tableToChange = TABLE_INVITATIONS;
+ changedItemId = url.getPathSegments().get(1);
+ break;
+
+ case MATCH_SESSIONS:
+ tableToChange = TABLE_SESSION_COOKIES;
+ break;
+
+ case MATCH_PROVIDER_SETTINGS_BY_ID_AND_NAME:
+ tableToChange = TABLE_PROVIDER_SETTINGS;
+
+ String providerId = url.getPathSegments().get(1);
+ String name = url.getPathSegments().get(2);
+
+ if (values.containsKey(Imps.ProviderSettings.PROVIDER) ||
+ values.containsKey(Imps.ProviderSettings.NAME)) {
+ throw new SecurityException("Cannot override the value for provider|name");
+ }
+
+ appendWhere(whereClause, Imps.ProviderSettings.PROVIDER, "=", providerId);
+ appendWhere(whereClause, Imps.ProviderSettings.NAME, "=", name);
+
+ break;
+
+ case MATCH_OUTGOING_RMQ_MESSAGES:
+ tableToChange = TABLE_OUTGOING_RMQ_MESSAGES;
+ break;
+
+ case MATCH_LAST_RMQ_ID:
+ tableToChange = TABLE_LAST_RMQ_ID;
+ break;
+
+ case MATCH_S2D_RMQ_IDS:
+ tableToChange = TABLE_S2D_RMQ_IDS;
+ break;
+
+ default:
+ throw new UnsupportedOperationException("Cannot update URL: " + url);
+ }
+
+ if (idColumnName == null) {
+ idColumnName = "_id";
+ }
+ if(changedItemId != null) {
+ appendWhere(whereClause, idColumnName, "=", changedItemId);
+ }
+
+ if (DBG) log("update " + url + " WHERE " + whereClause);
+
+ count = db.update(tableToChange, values, whereClause.toString(), whereArgs);
+
+ if (count > 0) {
+ ContentResolver resolver = getContext().getContentResolver();
+
+ // In most case, we query contacts with presence and chats joined, thus
+ // we should also notify that contacts changes when presence or chats changed.
+ if (match == MATCH_CHATS || match == MATCH_CHATS_ID
+ || match == MATCH_PRESENCE || match == MATCH_PRESENCE_ID
+ || match == MATCH_CONTACTS_BAREBONE) {
+ resolver.notifyChange(Imps.Contacts.CONTENT_URI, null);
+ }
+
+ if (notifyMessagesContentUri) {
+ if (DBG) log("notify change for " + Imps.Messages.CONTENT_URI);
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ }
+
+ if (notifyMessagesByContactContentUri) {
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ resolver.notifyChange(Imps.Messages.getContentUriByContact(account, contact), null);
+ }
+
+ if (notifyMessagesByThreadIdContentUri) {
+ resolver.notifyChange(Imps.Messages.CONTENT_URI, null);
+ resolver.notifyChange(Imps.Messages.getContentUriByThreadId(threadId), null);
+ }
+
+ if (notifyContactListContentUri) {
+ resolver.notifyChange(Imps.ContactList.CONTENT_URI, null);
+ }
+
+ if (notifyProviderAccountContentUri) {
+ if (DBG) log("notify change for " + Imps.Provider.CONTENT_URI_WITH_ACCOUNT);
+ resolver.notifyChange(Imps.Provider.CONTENT_URI_WITH_ACCOUNT, null);
+ }
+ }
+
+ return count;
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode)
+ throws FileNotFoundException {
+ return openFileHelper(uri, mode);
+ }
+
+ private static void appendWhere(StringBuilder where, String columnName,
+ String condition, Object value) {
+ if (where.length() > 0) {
+ where.append(" AND ");
+ }
+ where.append(columnName).append(condition);
+ if(value != null) {
+ DatabaseUtils.appendValueToSql(where, value);
+ }
+ }
+
+ private static void appendWhere(StringBuilder where, String clause) {
+ if (where.length() > 0) {
+ where.append(" AND ");
+ }
+ where.append(clause);
+ }
+
+ private static String decodeURLSegment(String segment) {
+ try {
+ return URLDecoder.decode(segment, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // impossible
+ return segment;
+ }
+ }
+
+ static void log(String message) {
+ Log.d(LOG_TAG, message);
+ }
+}
diff --git a/src/com/android/im/receiver/ImServiceAutoStarter.java b/src/com/android/im/receiver/ImServiceAutoStarter.java
index 7f1992f..519e0f3 100644
--- a/src/com/android/im/receiver/ImServiceAutoStarter.java
+++ b/src/com/android/im/receiver/ImServiceAutoStarter.java
@@ -17,13 +17,13 @@
package com.android.im.receiver;
+import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
import android.content.Context;
import android.content.Intent;
import android.content.BroadcastReceiver;
import android.database.Cursor;
-import android.provider.Im;
import android.util.Log;
public class ImServiceAutoStarter extends BroadcastReceiver {
@@ -34,10 +34,10 @@ public class ImServiceAutoStarter extends BroadcastReceiver {
// Received intent only when the system boot is completed
Log.d(TAG, "onReceiveIntent");
- String selection = Im.Account.KEEP_SIGNED_IN + "=1 AND "
- + Im.Account.ACTIVE + "=1";
- Cursor cursor = context.getContentResolver().query(Im.Account.CONTENT_URI,
- new String[]{Im.Account._ID}, selection, null, null);
+ String selection = Imps.Account.KEEP_SIGNED_IN + "=1 AND "
+ + Imps.Account.ACTIVE + "=1";
+ Cursor cursor = context.getContentResolver().query(Imps.Account.CONTENT_URI,
+ new String[]{Imps.Account._ID}, selection, null, null);
if (cursor != null) {
if (cursor.getCount() > 0) {
Log.d(TAG, "start service");
diff --git a/src/com/android/im/service/AndroidHeartBeatService.java b/src/com/android/im/service/AndroidHeartBeatService.java
index fe7aa29..659451f 100644
--- a/src/com/android/im/service/AndroidHeartBeatService.java
+++ b/src/com/android/im/service/AndroidHeartBeatService.java
@@ -17,7 +17,8 @@
package com.android.im.service;
-import com.android.im.engine.HeartbeatService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -31,6 +32,8 @@ import android.os.PowerManager;
import android.os.SystemClock;
import android.util.SparseArray;
+import com.android.im.engine.HeartbeatService;
+
public class AndroidHeartBeatService extends BroadcastReceiver
implements HeartbeatService {
@@ -43,16 +46,18 @@ public class AndroidHeartBeatService extends BroadcastReceiver
private static final String HEARTBEAT_CONTENT_TYPE
= "vnd.android.im/heartbeat";
- private Context mContext;
- private AlarmManager mAlarmManager;
- private PowerManager.WakeLock mWakeLock;
+ private static final ExecutorService sExecutor = Executors.newSingleThreadExecutor();
+
+ private final Context mContext;
+ private final AlarmManager mAlarmManager;
+ /*package*/ PowerManager.WakeLock mWakeLock;
static class Alarm {
public PendingIntent mAlaramSender;
public Callback mCallback;
}
- private SparseArray<Alarm> mAlarms;
+ private final SparseArray<Alarm> mAlarms;
public AndroidHeartBeatService(Context context) {
mContext = context;
@@ -72,7 +77,8 @@ public class AndroidHeartBeatService extends BroadcastReceiver
int id = nextId();
alarm.mCallback = callback;
Uri data = ContentUris.withAppendedId(HEARTBEAT_CONTENT_URI, id);
- Intent i = new Intent().setDataAndType(data, HEARTBEAT_CONTENT_TYPE);
+ Intent i = new Intent(HEARTBEAT_INTENT_ACTION)
+ .setDataAndType(data, HEARTBEAT_CONTENT_TYPE);
alarm.mAlaramSender = PendingIntent.getBroadcast(mContext, 0, i, 0);
if (mAlarms.size() == 0) {
mContext.registerReceiver(this, IntentFilter.create(
@@ -99,22 +105,34 @@ public class AndroidHeartBeatService extends BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) {
- mWakeLock.acquire();
- try {
- int id = (int)ContentUris.parseId(intent.getData());
- Alarm alarm = mAlarms.get(id);
- if (alarm == null) {
- return;
- }
- Callback callback = alarm.mCallback;
- long nextSchedule = callback.sendHeartbeat();
- if (nextSchedule <= 0) {
- cancelAlarm(alarm);
- } else {
- setAlarm(alarm, nextSchedule);
+ int id = (int)ContentUris.parseId(intent.getData());
+ Alarm alarm = mAlarms.get(id);
+ if (alarm == null) {
+ return;
+ }
+ sExecutor.execute(new Worker(alarm));
+ }
+
+ private class Worker implements Runnable {
+ private final Alarm mAlarm;
+
+ public Worker(Alarm alarm) {
+ mAlarm = alarm;
+ }
+
+ public void run() {
+ mWakeLock.acquire();
+ try {
+ Callback callback = mAlarm.mCallback;
+ long nextSchedule = callback.sendHeartbeat();
+ if (nextSchedule <= 0) {
+ cancelAlarm(mAlarm);
+ } else {
+ setAlarm(mAlarm, nextSchedule);
+ }
+ } finally {
+ mWakeLock.release();
}
- } finally {
- mWakeLock.release();
}
}
@@ -128,13 +146,13 @@ public class AndroidHeartBeatService extends BroadcastReceiver
return null;
}
- private void setAlarm(Alarm alarm, long offset) {
+ /*package*/ synchronized void setAlarm(Alarm alarm, long offset) {
long triggerAtTime = SystemClock.elapsedRealtime() + offset;
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime,
alarm.mAlaramSender);
}
- private void cancelAlarm(Alarm alarm) {
+ /*package*/ synchronized void cancelAlarm(Alarm alarm) {
mAlarmManager.cancel(alarm.mAlaramSender);
int index = mAlarms.indexOfValue(alarm);
if (index >= 0) {
diff --git a/src/com/android/im/service/AndroidSmsService.java b/src/com/android/im/service/AndroidSmsService.java
index ddcb24e..9a32e1c 100644
--- a/src/com/android/im/service/AndroidSmsService.java
+++ b/src/com/android/im/service/AndroidSmsService.java
@@ -49,6 +49,7 @@ public class AndroidSmsService implements SmsService {
private Context mContext;
private SmsReceiver mSmsReceiver;
private IntentFilter mIntentFilter;
+ private boolean mStarted;
/*package*/HashMap<Integer, ListenerList> mListeners;
/*package*/HashMap<Long, SmsSendFailureCallback> mFailureCallbacks;
@@ -110,11 +111,17 @@ public class AndroidSmsService implements SmsService {
if (l == null) {
l = new ListenerList(port);
mListeners.put(port, l);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ log("Register SMS receiver on port " + port);
+ }
// We didn't listen on the port yet, register the receiver with the
// additional port.
mIntentFilter.addDataAuthority("*", String.valueOf(port));
mContext.registerReceiver(mSmsReceiver, mIntentFilter);
+ synchronized (this) {
+ mStarted = true;
+ }
}
l.addListener(from, listener);
}
@@ -130,8 +137,11 @@ public class AndroidSmsService implements SmsService {
}
}
- public void stop() {
- mContext.unregisterReceiver(mSmsReceiver);
+ public synchronized void stop() {
+ if (mStarted) {
+ mContext.unregisterReceiver(mSmsReceiver);
+ mStarted = false;
+ }
}
private static long sNextMsgId = 0;
@@ -166,6 +176,11 @@ public class AndroidSmsService implements SmsService {
} else if (DATA_SMS_RECEIVED_ACTION.equals(intent.getAction())){
Uri uri = intent.getData();
int port = uri.getPort();
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ log("Received sms on port:" + port);
+ }
+
ListenerList listeners = mListeners.get(port);
if (listeners == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -219,7 +234,10 @@ public class AndroidSmsService implements SmsService {
public void notifySms(String addr, byte[] data) {
int N = mListenerList.size();
for (int i = 0; i < N; i++) {
- if (PhoneNumberUtils.compare(addr, mAddrList.get(i))) {
+ String listenAddr = mAddrList.get(i);
+ if (ANY_ADDRESS.equals(listenAddr)
+ || addr.equals(listenAddr)
+ || PhoneNumberUtils.compare(addr, listenAddr)) {
mListenerList.get(i).onIncomingSms(data);
}
}
diff --git a/src/com/android/im/service/ChatSessionAdapter.java b/src/com/android/im/service/ChatSessionAdapter.java
index 35c3825..3ac6c60 100644
--- a/src/com/android/im/service/ChatSessionAdapter.java
+++ b/src/com/android/im/service/ChatSessionAdapter.java
@@ -31,6 +31,7 @@ import com.android.im.engine.ImErrorInfo;
import com.android.im.engine.Message;
import com.android.im.engine.MessageListener;
import com.android.im.engine.Presence;
+import com.android.im.provider.Imps;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -40,7 +41,6 @@ import android.net.Uri;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.BaseColumns;
-import android.provider.Im;
import android.util.Log;
import java.util.ArrayList;
@@ -49,9 +49,9 @@ import java.util.List;
public class ChatSessionAdapter extends IChatSession.Stub {
- private static final String NON_CHAT_MESSAGE_SELECTION = Im.BaseMessageColumns.TYPE
- + "!=" + Im.MessageType.INCOMING + " AND " + Im.BaseMessageColumns.TYPE
- + "!=" + Im.MessageType.OUTGOING;
+ private static final String NON_CHAT_MESSAGE_SELECTION = Imps.Messages.TYPE
+ + "!=" + Imps.MessageType.INCOMING + " AND " + Imps.Messages.TYPE
+ + "!=" + Imps.MessageType.OUTGOING;
static final String TAG = RemoteImService.TAG;
@@ -106,9 +106,8 @@ public class ChatSessionAdapter extends IChatSession.Stub {
mIsGroupChat = true;
long groupId = insertGroupContactInDb(group);
group.addMemberListener(mListenerAdapter);
- mMessageURI = ContentUris.withAppendedId(
- Im.GroupMessages.CONTENT_URI_GROUP_MESSAGES_BY, groupId);
- mChatURI = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, groupId);
+ mMessageURI = Imps.Messages.getContentUriByThreadId(groupId);
+ mChatURI = ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, groupId);
insertOrUpdateChat(null);
for (Contact c : group.getMembers()) {
@@ -122,11 +121,8 @@ public class ChatSessionAdapter extends IChatSession.Stub {
(ContactListManagerAdapter) mConnection.getContactListManager();
long contactId = listManager.queryOrInsertContact(contact);
- long provider = mConnection.getProviderId();
- long account = mConnection.getAccountId();
- String address = contact.getAddress().getFullName();
- mMessageURI = Im.Messages.getContentUriByContact(provider, account, address);
- mChatURI = ContentUris.withAppendedId(Im.Chats.CONTENT_URI, contactId);
+ mMessageURI = Imps.Messages.getContentUriByThreadId(contactId);
+ mChatURI = ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, contactId);
insertOrUpdateChat(null);
mContactStatusMap.put(contact.getName(), contact.getPresence().getStatus());
@@ -215,10 +211,9 @@ public class ChatSessionAdapter extends IChatSession.Stub {
public void leave() {
if (mIsGroupChat) {
getGroupManager().leaveChatGroupAsync((ChatGroup)mAdaptee.getParticipant());
- mContentResolver.delete(mMessageURI, null, null);
- } else {
- mContentResolver.delete(mMessageURI, null, null);
}
+
+ mContentResolver.delete(mMessageURI, null, null);
mContentResolver.delete(mChatURI, null, null);
mStatusBarNotifier.dismissChatNotification(
mConnection.getProviderId(), getAddress());
@@ -234,27 +229,27 @@ public class ChatSessionAdapter extends IChatSession.Stub {
public void sendMessage(String text) {
if (mConnection.getState() == ImConnection.SUSPENDED) {
// connection has been suspended, save the message without send it
- insertMessageInDb(null, text, -1, Im.MessageType.POSTPONED);
+ insertMessageInDb(null, text, -1, Imps.MessageType.POSTPONED);
return;
}
Message msg = new Message(text);
mAdaptee.sendMessageAsync(msg);
long now = System.currentTimeMillis();
- insertMessageInDb(null, text, now, Im.MessageType.OUTGOING);
+ insertMessageInDb(null, text, now, Imps.MessageType.OUTGOING);
}
void sendPostponedMessages() {
String[] projection = new String[] {
BaseColumns._ID,
- Im.BaseMessageColumns.BODY,
- Im.BaseMessageColumns.DATE,
- Im.BaseMessageColumns.TYPE,
+ Imps.Messages.BODY,
+ Imps.Messages.DATE,
+ Imps.Messages.TYPE,
};
- String selection = Im.BaseMessageColumns.TYPE + "=?";
+ String selection = "messages.type=?";
Cursor c = mContentResolver.query(mMessageURI, projection, selection,
- new String[]{Integer.toString(Im.MessageType.POSTPONED)}, null);
+ new String[]{Integer.toString(Imps.MessageType.POSTPONED)}, null);
if (c == null) {
Log.e(TAG, "Query error while querying postponed messages");
return;
@@ -265,7 +260,7 @@ public class ChatSessionAdapter extends IChatSession.Stub {
mAdaptee.sendMessageAsync(new Message(body));
c.updateLong(2, System.currentTimeMillis());
- c.updateInt(3, Im.MessageType.OUTGOING);
+ c.updateInt(3, Imps.MessageType.OUTGOING);
}
c.commitUpdates();
c.close();
@@ -286,7 +281,7 @@ public class ChatSessionAdapter extends IChatSession.Stub {
public void markAsRead() {
if (mHasUnreadMessages) {
ContentValues values = new ContentValues(1);
- values.put(Im.Chats.LAST_UNREAD_MESSAGE, (String) null);
+ values.put(Imps.Chats.LAST_UNREAD_MESSAGE, (String) null);
mConnection.getContext().getContentResolver().update(mChatURI, values, null, null);
mStatusBarNotifier.dismissChatNotification(mConnection.getProviderId(), getAddress());
@@ -340,15 +335,15 @@ public class ChatSessionAdapter extends IChatSession.Stub {
String contact = incoming ? oldParticipant.getName() : null;
long time = msg.getDateTime().getTime();
insertMessageInDb(contact, msg.getBody(), time,
- incoming ? Im.MessageType.INCOMING : Im.MessageType.OUTGOING);
+ incoming ? Imps.MessageType.INCOMING : Imps.MessageType.OUTGOING);
}
}
void insertOrUpdateChat(String message) {
ContentValues values = new ContentValues(2);
- values.put(Im.Chats.LAST_MESSAGE_DATE, System.currentTimeMillis());
- values.put(Im.Chats.LAST_UNREAD_MESSAGE, message);
+ values.put(Imps.Chats.LAST_MESSAGE_DATE, System.currentTimeMillis());
+ values.put(Imps.Chats.LAST_UNREAD_MESSAGE, message);
// ImProvider.insert() will replace the chat if it already exist.
mContentResolver.insert(mChatURI, values);
}
@@ -356,13 +351,13 @@ public class ChatSessionAdapter extends IChatSession.Stub {
private long insertGroupContactInDb(ChatGroup group) {
// Insert a record in contacts table
ContentValues values = new ContentValues(4);
- values.put(Im.Contacts.USERNAME, group.getAddress().getFullName());
- values.put(Im.Contacts.NICKNAME, group.getName());
- values.put(Im.Contacts.CONTACTLIST, ContactListManagerAdapter.FAKE_TEMPORARY_LIST_ID);
- values.put(Im.Contacts.TYPE, Im.Contacts.TYPE_GROUP);
+ values.put(Imps.Contacts.USERNAME, group.getAddress().getFullName());
+ values.put(Imps.Contacts.NICKNAME, group.getName());
+ values.put(Imps.Contacts.CONTACTLIST, ContactListManagerAdapter.FAKE_TEMPORARY_LIST_ID);
+ values.put(Imps.Contacts.TYPE, Imps.Contacts.TYPE_GROUP);
Uri contactUri = ContentUris.withAppendedId(ContentUris.withAppendedId(
- Im.Contacts.CONTENT_URI, mConnection.mProviderId), mConnection.mAccountId);
+ Imps.Contacts.CONTENT_URI, mConnection.mProviderId), mConnection.mAccountId);
long id = ContentUris.parseId(mContentResolver.insert(contactUri, values));
ArrayList<ContentValues> memberValues = new ArrayList<ContentValues>();
@@ -370,9 +365,9 @@ public class ChatSessionAdapter extends IChatSession.Stub {
for (Contact member : group.getMembers()) {
if (!member.equals(self)) { // avoid to insert the user himself
ContentValues memberValue = new ContentValues(2);
- memberValue.put(Im.GroupMembers.USERNAME,
+ memberValue.put(Imps.GroupMembers.USERNAME,
member.getAddress().getFullName());
- memberValue.put(Im.GroupMembers.NICKNAME,
+ memberValue.put(Imps.GroupMembers.NICKNAME,
member.getName());
memberValues.add(memberValue);
}
@@ -380,7 +375,7 @@ public class ChatSessionAdapter extends IChatSession.Stub {
if (!memberValues.isEmpty()) {
ContentValues[] result = new ContentValues[memberValues.size()];
memberValues.toArray(result);
- Uri memberUri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, id);
+ Uri memberUri = ContentUris.withAppendedId(Imps.GroupMembers.CONTENT_URI, id);
mContentResolver.bulkInsert(memberUri, result);
}
return id;
@@ -388,27 +383,27 @@ public class ChatSessionAdapter extends IChatSession.Stub {
void insertGroupMemberInDb(Contact member) {
ContentValues values1 = new ContentValues(2);
- values1.put(Im.GroupMembers.USERNAME, member.getAddress().getFullName());
- values1.put(Im.GroupMembers.NICKNAME, member.getName());
+ values1.put(Imps.GroupMembers.USERNAME, member.getAddress().getFullName());
+ values1.put(Imps.GroupMembers.NICKNAME, member.getName());
ContentValues values = values1;
long groupId = ContentUris.parseId(mChatURI);
- Uri uri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, groupId);
+ Uri uri = ContentUris.withAppendedId(Imps.GroupMembers.CONTENT_URI, groupId);
mContentResolver.insert(uri, values);
insertMessageInDb(member.getName(), null, System.currentTimeMillis(),
- Im.MessageType.PRESENCE_AVAILABLE);
+ Imps.MessageType.PRESENCE_AVAILABLE);
}
void deleteGroupMemberInDb(Contact member) {
- String where = Im.GroupMembers.USERNAME + "=?";
+ String where = Imps.GroupMembers.USERNAME + "=?";
String[] selectionArgs = { member.getAddress().getFullName() };
long groupId = ContentUris.parseId(mChatURI);
- Uri uri = ContentUris.withAppendedId(Im.GroupMembers.CONTENT_URI, groupId);
+ Uri uri = ContentUris.withAppendedId(Imps.GroupMembers.CONTENT_URI, groupId);
mContentResolver.delete(uri, where, selectionArgs);
insertMessageInDb(member.getName(), null, System.currentTimeMillis(),
- Im.MessageType.PRESENCE_UNAVAILABLE);
+ Imps.MessageType.PRESENCE_UNAVAILABLE);
}
void insertPresenceUpdatesMsg(String contact, Presence presence) {
@@ -425,20 +420,20 @@ public class ChatSessionAdapter extends IChatSession.Stub {
int messageType;
switch (status) {
case Presence.AVAILABLE:
- messageType = Im.MessageType.PRESENCE_AVAILABLE;
+ messageType = Imps.MessageType.PRESENCE_AVAILABLE;
break;
case Presence.AWAY:
case Presence.IDLE:
- messageType = Im.MessageType.PRESENCE_AWAY;
+ messageType = Imps.MessageType.PRESENCE_AWAY;
break;
case Presence.DO_NOT_DISTURB:
- messageType = Im.MessageType.PRESENCE_DND;
+ messageType = Imps.MessageType.PRESENCE_DND;
break;
default:
- messageType = Im.MessageType.PRESENCE_UNAVAILABLE;
+ messageType = Imps.MessageType.PRESENCE_UNAVAILABLE;
break;
}
@@ -450,7 +445,7 @@ public class ChatSessionAdapter extends IChatSession.Stub {
}
void removeMessageInDb(int type) {
- mContentResolver.delete(mMessageURI, Im.BaseMessageColumns.TYPE + "=?",
+ mContentResolver.delete(mMessageURI, Imps.Messages.TYPE + "=?",
new String[]{Integer.toString(type)});
}
@@ -460,12 +455,13 @@ public class ChatSessionAdapter extends IChatSession.Stub {
Uri insertMessageInDb(String contact, String body, long time, int type, int errCode) {
ContentValues values = new ContentValues(mIsGroupChat ? 4 : 3);
- values.put(Im.BaseMessageColumns.BODY, body);
- values.put(Im.BaseMessageColumns.DATE, time);
- values.put(Im.BaseMessageColumns.TYPE, type);
- values.put(Im.BaseMessageColumns.ERROR_CODE, errCode);
+ values.put(Imps.Messages.BODY, body);
+ values.put(Imps.Messages.DATE, time);
+ values.put(Imps.Messages.TYPE, type);
+ values.put(Imps.Messages.ERROR_CODE, errCode);
if (mIsGroupChat) {
- values.put(Im.BaseMessageColumns.CONTACT, contact);
+ values.put(Imps.Messages.NICKNAME, contact);
+ values.put(Imps.Messages.IS_GROUP_CHAT, 1);
}
return mContentResolver.insert(mMessageURI, values);
@@ -483,7 +479,7 @@ public class ChatSessionAdapter extends IChatSession.Stub {
} else {
insertOrUpdateChat(body);
}
- insertMessageInDb(nickname, body, time, Im.MessageType.INCOMING);
+ insertMessageInDb(nickname, body, time, Imps.MessageType.INCOMING);
int N = mRemoteListeners.beginBroadcast();
for (int i = 0; i < N; i++) {
@@ -506,7 +502,7 @@ public class ChatSessionAdapter extends IChatSession.Stub {
public void onSendMessageError(ChatSession ses, final Message msg,
final ImErrorInfo error) {
insertMessageInDb(null, null, System.currentTimeMillis(),
- Im.MessageType.OUTGOING, error.getCode());
+ Imps.MessageType.OUTGOING, error.getCode());
final int N = mRemoteListeners.beginBroadcast();
for (int i = 0; i < N; i++) {
diff --git a/src/com/android/im/service/ContactListManagerAdapter.java b/src/com/android/im/service/ContactListManagerAdapter.java
index eaa0a48..47c1615 100644
--- a/src/com/android/im/service/ContactListManagerAdapter.java
+++ b/src/com/android/im/service/ContactListManagerAdapter.java
@@ -33,7 +33,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.provider.Im;
import android.util.Log;
import android.widget.Toast;
@@ -52,6 +51,7 @@ import com.android.im.engine.ImErrorInfo;
import com.android.im.engine.ImException;
import com.android.im.engine.Presence;
import com.android.im.engine.SubscriptionRequestListener;
+import com.android.im.provider.Imps;
public class ContactListManagerAdapter extends IContactListManager.Stub {
static final String TAG = RemoteImService.TAG;
@@ -82,7 +82,7 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
private Uri mContactUrl;
static final long FAKE_TEMPORARY_LIST_ID = -1;
- static final String[] CONTACT_LIST_ID_PROJECTION = { Im.ContactList._ID };
+ static final String[] CONTACT_LIST_ID_PROJECTION = { Imps.ContactList._ID };
RemoteImService mContext;
@@ -106,13 +106,13 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
mAccountId = mConn.getAccountId();
mProviderId = mConn.getProviderId();
- Uri.Builder builder = Im.Avatars.CONTENT_URI_AVATARS_BY.buildUpon();
+ Uri.Builder builder = Imps.Avatars.CONTENT_URI_AVATARS_BY.buildUpon();
ContentUris.appendId(builder, mProviderId);
ContentUris.appendId(builder, mAccountId);
mAvatarUrl = builder.build();
- builder = Im.Contacts.CONTENT_URI_CONTACTS_BY.buildUpon();
+ builder = Imps.Contacts.CONTENT_URI_CONTACTS_BY.buildUpon();
ContentUris.appendId(builder, mProviderId);
ContentUris.appendId(builder, mAccountId);
@@ -151,7 +151,7 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
// database.
closeChatSession(address);
- String selection = Im.Contacts.USERNAME + "=?";
+ String selection = Imps.Contacts.USERNAME + "=?";
String[] selectionArgs = { address };
mResolver.delete(mContactUrl, selection, selectionArgs);
synchronized (mTemporaryContacts) {
@@ -274,9 +274,9 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
long result;
String username = c.getAddress().getFullName();
- String selection = Im.Contacts.USERNAME + "=?";
+ String selection = Imps.Contacts.USERNAME + "=?";
String[] selectionArgs = { username };
- String[] projection = {Im.Contacts._ID};
+ String[] projection = {Imps.Contacts._ID};
Cursor cursor = mResolver.query(mContactUrl, projection, selection,
selectionArgs, null);
@@ -370,13 +370,13 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
private void removeObsoleteContactsAndLists() {
// remove all contacts for this provider & account which have not been
// added since login, yet still exist in db from a prior login
- Exclusion exclusion = new Exclusion(Im.Contacts.USERNAME, mValidatedContacts);
+ Exclusion exclusion = new Exclusion(Imps.Contacts.USERNAME, mValidatedContacts);
mResolver.delete(mContactUrl, exclusion.getSelection(), exclusion.getSelectionArgs());
// remove all blocked contacts for this provider & account which have not been
// added since login, yet still exist in db from a prior login
- exclusion = new Exclusion(Im.BlockedList.USERNAME, mValidatedBlockedContacts);
- Uri.Builder builder = Im.BlockedList.CONTENT_URI.buildUpon();
+ exclusion = new Exclusion(Imps.BlockedList.USERNAME, mValidatedBlockedContacts);
+ Uri.Builder builder = Imps.BlockedList.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, mProviderId);
ContentUris.appendId(builder, mAccountId);
Uri uri = builder.build();
@@ -384,8 +384,8 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
// remove all contact lists for this provider & account which have not been
// added since login, yet still exist in db from a prior login
- exclusion = new Exclusion(Im.ContactList.NAME, mValidatedContactLists);
- builder = Im.ContactList.CONTENT_URI.buildUpon();
+ exclusion = new Exclusion(Imps.ContactList.NAME, mValidatedContactLists);
+ builder = Imps.ContactList.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, mProviderId);
ContentUris.appendId(builder, mAccountId);
uri = builder.build();
@@ -514,7 +514,7 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
case CONTACT_BLOCKED:
insertBlockedContactToDataBase(contact);
address = contact.getAddress().getFullName();
- updateContactType(address, Im.Contacts.TYPE_BLOCKED);
+ updateContactType(address, Imps.Contacts.TYPE_BLOCKED);
closeChatSession(address);
notificationText = mContext.getResources().getString(
R.string.block_contact_success, contact.getName());
@@ -613,8 +613,8 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
String username = from.getAddress().getFullName();
String nickname = from.getName();
Uri uri = insertOrUpdateSubscription(username, nickname,
- Im.Contacts.SUBSCRIPTION_TYPE_FROM,
- Im.Contacts.SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING);
+ Imps.Contacts.SUBSCRIPTION_TYPE_FROM,
+ Imps.Contacts.SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING);
mContext.getStatusBarNotifier().notifySubscriptionRequest(mProviderId, mAccountId,
ContentUris.parseId(uri), username, nickname);
final int N = mRemoteSubscriptionListeners.beginBroadcast();
@@ -633,8 +633,8 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
public void onSubscriptionApproved(final String contact) {
insertOrUpdateSubscription(contact, null,
- Im.Contacts.SUBSCRIPTION_TYPE_NONE,
- Im.Contacts.SUBSCRIPTION_STATUS_NONE);
+ Imps.Contacts.SUBSCRIPTION_TYPE_NONE,
+ Imps.Contacts.SUBSCRIPTION_STATUS_NONE);
final int N = mRemoteSubscriptionListeners.beginBroadcast();
for (int i = 0; i < N; i++) {
@@ -652,8 +652,8 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
public void onSubscriptionDeclined(final String contact) {
insertOrUpdateSubscription(contact, null,
- Im.Contacts.SUBSCRIPTION_TYPE_NONE,
- Im.Contacts.SUBSCRIPTION_STATUS_NONE);
+ Imps.Contacts.SUBSCRIPTION_TYPE_NONE,
+ Imps.Contacts.SUBSCRIPTION_STATUS_NONE);
final int N = mRemoteSubscriptionListeners.beginBroadcast();
for (int i = 0; i < N; i++) {
@@ -694,15 +694,15 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
// handle the odd case where a blocked contact's nickname has changed
removeBlockedContactFromDataBase(contact);
- Uri.Builder builder = Im.BlockedList.CONTENT_URI.buildUpon();
+ Uri.Builder builder = Imps.BlockedList.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, mProviderId);
ContentUris.appendId(builder, mAccountId);
Uri uri = builder.build();
String username = contact.getAddress().getFullName();
ContentValues values = new ContentValues(2);
- values.put(Im.BlockedList.USERNAME, username);
- values.put(Im.BlockedList.NICKNAME, contact.getName());
+ values.put(Imps.BlockedList.USERNAME, username);
+ values.put(Imps.BlockedList.NICKNAME, contact.getName());
mResolver.insert(uri, values);
@@ -712,15 +712,15 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
void removeBlockedContactFromDataBase(Contact contact) {
String address = contact.getAddress().getFullName();
- Uri.Builder builder = Im.BlockedList.CONTENT_URI.buildUpon();
+ Uri.Builder builder = Imps.BlockedList.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, mProviderId);
ContentUris.appendId(builder, mAccountId);
Uri uri = builder.build();
- mResolver.delete(uri, Im.BlockedList.USERNAME + "=?", new String[]{ address });
+ mResolver.delete(uri, Imps.BlockedList.USERNAME + "=?", new String[]{ address });
- int type = isTemporary(address) ? Im.Contacts.TYPE_TEMPORARY
- : Im.Contacts.TYPE_NORMAL;
+ int type = isTemporary(address) ? Imps.Contacts.TYPE_TEMPORARY
+ : Imps.Contacts.TYPE_NORMAL;
updateContactType(address, type);
}
@@ -729,11 +729,11 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
mTemporaryContacts.remove(address);
}
ContentValues values = new ContentValues(2);
- values.put(Im.Contacts.TYPE, Im.Contacts.TYPE_NORMAL);
- values.put(Im.Contacts.CONTACTLIST, listId);
+ values.put(Imps.Contacts.TYPE, Imps.Contacts.TYPE_NORMAL);
+ values.put(Imps.Contacts.CONTACTLIST, listId);
- String selection = Im.Contacts.USERNAME + "=? AND " + Im.Contacts.TYPE + "="
- + Im.Contacts.TYPE_TEMPORARY;
+ String selection = Imps.Contacts.USERNAME + "=? AND " + Imps.Contacts.TYPE + "="
+ + Imps.Contacts.TYPE_TEMPORARY;
String[] selectionArgs = { address };
mResolver.update(mContactUrl, values, selection, selectionArgs);
@@ -741,7 +741,7 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
void updateContactType(String address, int type) {
ContentValues values = new ContentValues(1);
- values.put(Im.Contacts.TYPE, type);
+ values.put(Imps.Contacts.TYPE, type);
updateContact(address, values);
}
@@ -755,8 +755,8 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
*/
Uri insertOrUpdateSubscription(String username, String nickname, int subscriptionType,
int subscriptionStatus) {
- Cursor cursor = mResolver.query(mContactUrl, new String[]{ Im.Contacts._ID },
- Im.Contacts.USERNAME + "=?", new String[]{username}, null);
+ Cursor cursor = mResolver.query(mContactUrl, new String[]{ Imps.Contacts._ID },
+ Imps.Contacts.USERNAME + "=?", new String[]{username}, null);
if (cursor == null) {
Log.w(TAG, "query contact " + username + " failed");
return null;
@@ -765,20 +765,20 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
Uri uri;
if (cursor.moveToFirst()) {
ContentValues values = new ContentValues(2);
- values.put(Im.Contacts.SUBSCRIPTION_TYPE, subscriptionType);
- values.put(Im.Contacts.SUBSCRIPTION_STATUS, subscriptionStatus);
+ values.put(Imps.Contacts.SUBSCRIPTION_TYPE, subscriptionType);
+ values.put(Imps.Contacts.SUBSCRIPTION_STATUS, subscriptionStatus);
long contactId = cursor.getLong(0);
- uri = ContentUris.withAppendedId(Im.Contacts.CONTENT_URI, contactId);
+ uri = ContentUris.withAppendedId(Imps.Contacts.CONTENT_URI, contactId);
mResolver.update(uri, values, null, null);
} else {
ContentValues values = new ContentValues(6);
- values.put(Im.Contacts.USERNAME, username);
- values.put(Im.Contacts.NICKNAME, nickname);
- values.put(Im.Contacts.TYPE, Im.Contacts.TYPE_NORMAL);
- values.put(Im.Contacts.CONTACTLIST, FAKE_TEMPORARY_LIST_ID);
- values.put(Im.Contacts.SUBSCRIPTION_TYPE, subscriptionType);
- values.put(Im.Contacts.SUBSCRIPTION_STATUS, subscriptionStatus);
+ values.put(Imps.Contacts.USERNAME, username);
+ values.put(Imps.Contacts.NICKNAME, nickname);
+ values.put(Imps.Contacts.TYPE, Imps.Contacts.TYPE_NORMAL);
+ values.put(Imps.Contacts.CONTACTLIST, FAKE_TEMPORARY_LIST_ID);
+ values.put(Imps.Contacts.SUBSCRIPTION_TYPE, subscriptionType);
+ values.put(Imps.Contacts.SUBSCRIPTION_STATUS, subscriptionStatus);
uri = mResolver.insert(mContactUrl, values);
}
@@ -787,7 +787,7 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
}
void updateContact(String username, ContentValues values) {
- String selection = Im.Contacts.USERNAME + "=?";
+ String selection = Imps.Contacts.USERNAME + "=?";
String[] selectionArgs = { username };
mResolver.update(mContactUrl, values, selection, selectionArgs);
}
@@ -812,13 +812,13 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
}
ContentValues values = new ContentValues();
- values.put(Im.Contacts.ACCOUNT, mAccountId);
- values.putStringArrayList(Im.Contacts.USERNAME, usernames);
- values.putStringArrayList(Im.Presence.PRESENCE_STATUS, statusArray);
- values.putStringArrayList(Im.Presence.PRESENCE_CUSTOM_STATUS, customStatusArray);
- values.putStringArrayList(Im.Presence.CONTENT_TYPE, clientTypeArray);
+ values.put(Imps.Contacts.ACCOUNT, mAccountId);
+ values.putStringArrayList(Imps.Contacts.USERNAME, usernames);
+ values.putStringArrayList(Imps.Presence.PRESENCE_STATUS, statusArray);
+ values.putStringArrayList(Imps.Presence.PRESENCE_CUSTOM_STATUS, customStatusArray);
+ values.putStringArrayList(Imps.Presence.CONTENT_TYPE, clientTypeArray);
- mResolver.update(Im.Presence.BULK_CONTENT_URI, values, null, null);
+ mResolver.update(Imps.Presence.BULK_CONTENT_URI, values, null, null);
}
void updateAvatarsContent(Contact[] contacts) {
@@ -834,8 +834,8 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
String username = contact.getAddress().getFullName();
ContentValues values = new ContentValues(2);
- values.put(Im.Avatars.CONTACT, username);
- values.put(Im.Avatars.DATA, avatarData);
+ values.put(Imps.Avatars.CONTACT, username);
+ values.put(Imps.Avatars.DATA, avatarData);
avatars.add(values);
usernames.add(username);
}
@@ -862,22 +862,22 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
// delete contacts of this list first
mResolver.delete(mContactUrl,
- Im.Contacts.CONTACTLIST + "=?", new String[]{Long.toString(id)});
+ Imps.Contacts.CONTACTLIST + "=?", new String[]{Long.toString(id)});
- mResolver.delete(ContentUris.withAppendedId(Im.ContactList.CONTENT_URI, id), null, null);
+ mResolver.delete(ContentUris.withAppendedId(Imps.ContactList.CONTENT_URI, id), null, null);
synchronized (mContactLists) {
return mContactLists.remove(listAdapter.getAddress());
}
}
void addContactListContent(ContactList list) {
- String selection = Im.ContactList.NAME + "=? AND "
- + Im.ContactList.PROVIDER + "=? AND "
- + Im.ContactList.ACCOUNT + "=?";
+ String selection = Imps.ContactList.NAME + "=? AND "
+ + Imps.ContactList.PROVIDER + "=? AND "
+ + Imps.ContactList.ACCOUNT + "=?";
String[] selectionArgs = { list.getName(),
Long.toString(mProviderId),
Long.toString(mAccountId) };
- Cursor cursor = mResolver.query(Im.ContactList.CONTENT_URI,
+ Cursor cursor = mResolver.query(Imps.ContactList.CONTENT_URI,
CONTACT_LIST_ID_PROJECTION,
selection,
selectionArgs,
@@ -887,7 +887,7 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
try {
if (cursor.moveToFirst()) {
listId = cursor.getLong(0);
- uri = ContentUris.withAppendedId(Im.ContactList.CONTENT_URI, listId);
+ uri = ContentUris.withAppendedId(Imps.ContactList.CONTENT_URI, listId);
//Log.d(TAG,"Found and removing ContactList with name "+list.getName());
}
} finally {
@@ -896,19 +896,19 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
if (uri != null) {
// remove existing ContactList and Contacts of that list for replacement by the newly
// downloaded list
- mResolver.delete(mContactUrl, Im.Contacts.CONTACTLIST + "=?",
+ mResolver.delete(mContactUrl, Imps.Contacts.CONTACTLIST + "=?",
new String[]{Long.toString(listId)});
mResolver.delete(uri, selection, selectionArgs);
}
ContentValues contactListValues = new ContentValues(3);
- contactListValues.put(Im.ContactList.NAME, list.getName());
- contactListValues.put(Im.ContactList.PROVIDER, mProviderId);
- contactListValues.put(Im.ContactList.ACCOUNT, mAccountId);
+ contactListValues.put(Imps.ContactList.NAME, list.getName());
+ contactListValues.put(Imps.ContactList.PROVIDER, mProviderId);
+ contactListValues.put(Imps.ContactList.ACCOUNT, mAccountId);
//Log.d(TAG, "Adding ContactList name="+list.getName());
mValidatedContactLists.add(list.getName());
- uri = mResolver.insert(Im.ContactList.CONTENT_URI, contactListValues);
+ uri = mResolver.insert(Imps.ContactList.CONTENT_URI, contactListValues);
listId = ContentUris.parseId(uri);
synchronized (mContactLists) {
@@ -938,12 +938,12 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
for (Contact c : contacts) {
String username = c.getAddress().getFullName();
String nickname = c.getName();
- int type = Im.Contacts.TYPE_NORMAL;
+ int type = Imps.Contacts.TYPE_NORMAL;
if(isTemporary(username)) {
- type = Im.Contacts.TYPE_TEMPORARY;
+ type = Imps.Contacts.TYPE_TEMPORARY;
}
if (isBlocked(username)) {
- type = Im.Contacts.TYPE_BLOCKED;
+ type = Imps.Contacts.TYPE_BLOCKED;
}
usernames.add(username);
@@ -952,29 +952,29 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
}
ContentValues values = new ContentValues(6);
- values.put(Im.Contacts.PROVIDER, mProviderId);
- values.put(Im.Contacts.ACCOUNT, mAccountId);
- values.put(Im.Contacts.CONTACTLIST, listId);
- values.putStringArrayList(Im.Contacts.USERNAME, usernames);
- values.putStringArrayList(Im.Contacts.NICKNAME, nicknames);
- values.putStringArrayList(Im.Contacts.TYPE, contactTypeArray);
+ values.put(Imps.Contacts.PROVIDER, mProviderId);
+ values.put(Imps.Contacts.ACCOUNT, mAccountId);
+ values.put(Imps.Contacts.CONTACTLIST, listId);
+ values.putStringArrayList(Imps.Contacts.USERNAME, usernames);
+ values.putStringArrayList(Imps.Contacts.NICKNAME, nicknames);
+ values.putStringArrayList(Imps.Contacts.TYPE, contactTypeArray);
- mResolver.insert(Im.Contacts.BULK_CONTENT_URI, values);
+ mResolver.insert(Imps.Contacts.BULK_CONTENT_URI, values);
}
void updateListNameInDataBase(ContactList list) {
ContactListAdapter listAdapter = getContactListAdapter(list.getAddress());
- Uri uri = ContentUris.withAppendedId(Im.ContactList.CONTENT_URI, listAdapter.getDataBaseId());
+ Uri uri = ContentUris.withAppendedId(Imps.ContactList.CONTENT_URI, listAdapter.getDataBaseId());
ContentValues values = new ContentValues(1);
- values.put(Im.ContactList.NAME, list.getName());
+ values.put(Imps.ContactList.NAME, list.getName());
mResolver.update(uri, values, null, null);
}
void deleteContactFromDataBase(Contact contact, ContactList list) {
- String selection = Im.Contacts.USERNAME
- + "=? AND " + Im.Contacts.CONTACTLIST + "=?";
+ String selection = Imps.Contacts.USERNAME
+ + "=? AND " + Imps.Contacts.CONTACTLIST + "=?";
long listId = getContactListAdapter(list.getAddress()).getDataBaseId();
String username = contact.getAddress().getFullName();
String[] selectionArgs = {username, Long.toString(listId)};
@@ -996,7 +996,7 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
ContentValues presenceValues = getPresenceValues(ContentUris.parseId(uri),
contact.getPresence());
- mResolver.insert(Im.Presence.CONTENT_URI, presenceValues);
+ mResolver.insert(Imps.Presence.CONTENT_URI, presenceValues);
return uri;
}
@@ -1004,34 +1004,33 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
private ContentValues getContactContentValues(Contact contact, long listId) {
final String username = contact.getAddress().getFullName();
final String nickname = contact.getName();
- int type = Im.Contacts.TYPE_NORMAL;
+ int type = Imps.Contacts.TYPE_NORMAL;
if(isTemporary(username)) {
- type = Im.Contacts.TYPE_TEMPORARY;
+ type = Imps.Contacts.TYPE_TEMPORARY;
}
if (isBlocked(username)) {
- type = Im.Contacts.TYPE_BLOCKED;
+ type = Imps.Contacts.TYPE_BLOCKED;
}
ContentValues values = new ContentValues(4);
- values.put(Im.Contacts.USERNAME, username);
- values.put(Im.Contacts.NICKNAME, nickname);
- values.put(Im.Contacts.CONTACTLIST, listId);
- values.put(Im.Contacts.TYPE, type);
+ values.put(Imps.Contacts.USERNAME, username);
+ values.put(Imps.Contacts.NICKNAME, nickname);
+ values.put(Imps.Contacts.CONTACTLIST, listId);
+ values.put(Imps.Contacts.TYPE, type);
return values;
}
void clearHistoryMessages(String contact) {
- Uri uri = Im.Messages.getContentUriByContact(mProviderId,
- mAccountId, contact);
+ Uri uri = Imps.Messages.getContentUriByContact(mAccountId, contact);
mResolver.delete(uri, null, null);
}
private ContentValues getPresenceValues(long contactId, Presence p) {
ContentValues values = new ContentValues(3);
- values.put(Im.Presence.CONTACT_ID, contactId);
- values.put(Im.Contacts.PRESENCE_STATUS, convertPresenceStatus(p));
- values.put(Im.Contacts.PRESENCE_CUSTOM_STATUS, p.getStatusText());
- values.put(Im.Presence.CLIENT_TYPE, translateClientType(p));
+ values.put(Imps.Presence.CONTACT_ID, contactId);
+ values.put(Imps.Contacts.PRESENCE_STATUS, convertPresenceStatus(p));
+ values.put(Imps.Contacts.PRESENCE_CUSTOM_STATUS, p.getStatusText());
+ values.put(Imps.Presence.CLIENT_TYPE, translateClientType(p));
return values;
}
@@ -1039,9 +1038,9 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
int clientType = presence.getClientType();
switch (clientType) {
case Presence.CLIENT_TYPE_MOBILE:
- return Im.Presence.CLIENT_TYPE_MOBILE;
+ return Imps.Presence.CLIENT_TYPE_MOBILE;
default:
- return Im.Presence.CLIENT_TYPE_DEFAULT;
+ return Imps.Presence.CLIENT_TYPE_DEFAULT;
}
}
@@ -1054,24 +1053,24 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
public static int convertPresenceStatus(Presence presence) {
switch (presence.getStatus()) {
case Presence.AVAILABLE:
- return Im.Presence.AVAILABLE;
+ return Imps.Presence.AVAILABLE;
case Presence.IDLE:
- return Im.Presence.IDLE;
+ return Imps.Presence.IDLE;
case Presence.AWAY:
- return Im.Presence.AWAY;
+ return Imps.Presence.AWAY;
case Presence.DO_NOT_DISTURB:
- return Im.Presence.DO_NOT_DISTURB;
+ return Imps.Presence.DO_NOT_DISTURB;
case Presence.OFFLINE:
- return Im.Presence.OFFLINE;
+ return Imps.Presence.OFFLINE;
}
// impossible...
Log.e(TAG, "Illegal presence status value " + presence.getStatus());
- return Im.Presence.AVAILABLE;
+ return Imps.Presence.AVAILABLE;
}
public void clearOnLogout() {
@@ -1099,7 +1098,7 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
* IM sessions, the temporary contacts need to be cleared after logout.
*/
private void clearTemporaryContacts() {
- String selection = Im.Contacts.CONTACTLIST + "=" + FAKE_TEMPORARY_LIST_ID;
+ String selection = Imps.Contacts.CONTACTLIST + "=" + FAKE_TEMPORARY_LIST_ID;
mResolver.delete(mContactUrl, selection, null);
}
@@ -1109,13 +1108,13 @@ public class ContactListManagerAdapter extends IContactListManager.Stub {
*/
void clearPresence() {
StringBuilder where = new StringBuilder();
- where.append(Im.Presence.CONTACT_ID);
+ where.append(Imps.Presence.CONTACT_ID);
where.append(" in (select _id from contacts where ");
- where.append(Im.Contacts.ACCOUNT);
+ where.append(Imps.Contacts.ACCOUNT);
where.append("=");
where.append(mAccountId);
where.append(")");
- mResolver.delete(Im.Presence.CONTENT_URI, where.toString(), null);
+ mResolver.delete(Imps.Presence.CONTENT_URI, where.toString(), null);
}
void closeChatSession(String address) {
diff --git a/src/com/android/im/service/ImConnectionAdapter.java b/src/com/android/im/service/ImConnectionAdapter.java
index 7b97ac6..e8bbc31 100644
--- a/src/com/android/im/service/ImConnectionAdapter.java
+++ b/src/com/android/im/service/ImConnectionAdapter.java
@@ -27,7 +27,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.provider.Im;
import android.util.Log;
import com.android.im.IChatSessionManager;
@@ -46,13 +45,14 @@ import com.android.im.engine.Invitation;
import com.android.im.engine.InvitationListener;
import com.android.im.engine.LoginInfo;
import com.android.im.engine.Presence;
+import com.android.im.provider.Imps;
public class ImConnectionAdapter extends IImConnection.Stub {
private static final String TAG = RemoteImService.TAG;
private static final String[] SESSION_COOKIE_PROJECTION = {
- Im.SessionCookies.NAME,
- Im.SessionCookies.VALUE,
+ Imps.SessionCookies.NAME,
+ Imps.SessionCookies.VALUE,
};
private static final int COLUMN_SESSION_COOKIE_NAME = 0;
@@ -133,7 +133,7 @@ public class ImConnectionAdapter extends IImConnection.Stub {
}
private Uri getSessionCookiesUri() {
- Uri.Builder builder = Im.SessionCookies.CONTENT_URI_SESSION_COOKIES_BY.buildUpon();
+ Uri.Builder builder = Imps.SessionCookies.CONTENT_URI_SESSION_COOKIES_BY.buildUpon();
ContentUris.appendId(builder, mProviderId);
ContentUris.appendId(builder, mAccountId);
@@ -258,21 +258,21 @@ public class ImConnectionAdapter extends IImConnection.Stub {
return;
}
ContentResolver cr = mService.getContentResolver();
- Cursor c = cr.query(ContentUris.withAppendedId(Im.Invitation.CONTENT_URI, id), null, null, null, null);
+ Cursor c = cr.query(ContentUris.withAppendedId(Imps.Invitation.CONTENT_URI, id), null, null, null, null);
if(c == null) {
return;
}
if(c.moveToFirst()) {
- String inviteId = c.getString(c.getColumnIndexOrThrow(Im.Invitation.INVITE_ID));
+ String inviteId = c.getString(c.getColumnIndexOrThrow(Imps.Invitation.INVITE_ID));
int status;
if(accept) {
mGroupManager.acceptInvitationAsync(inviteId);
- status = Im.Invitation.STATUS_ACCEPTED;
+ status = Imps.Invitation.STATUS_ACCEPTED;
} else {
mGroupManager.rejectInvitationAsync(inviteId);
- status = Im.Invitation.STATUS_REJECTED;
+ status = Imps.Invitation.STATUS_REJECTED;
}
- c.updateInt(c.getColumnIndexOrThrow(Im.Invitation.STATUS), status);
+ c.updateInt(c.getColumnIndexOrThrow(Imps.Invitation.STATUS), status);
c.commitUpdates();
}
c.close();
@@ -287,8 +287,8 @@ public class ImConnectionAdapter extends IImConnection.Stub {
for(Map.Entry<String,String> entry : cookies.entrySet()){
ContentValues values = new ContentValues(2);
- values.put(Im.SessionCookies.NAME, entry.getKey());
- values.put(Im.SessionCookies.VALUE, entry.getValue());
+ values.put(Imps.SessionCookies.NAME, entry.getKey());
+ values.put(Imps.SessionCookies.VALUE, entry.getValue());
valuesList[i++] = values;
}
@@ -302,7 +302,7 @@ public class ImConnectionAdapter extends IImConnection.Stub {
void updateAccountStatusInDb() {
Presence p = getUserPresence();
- int presenceStatus = Im.Presence.OFFLINE;
+ int presenceStatus = Imps.Presence.OFFLINE;
int connectionStatus = convertConnStateForDb(mConnectionState);
if (p != null) {
@@ -310,12 +310,12 @@ public class ImConnectionAdapter extends IImConnection.Stub {
}
ContentResolver cr = mService.getContentResolver();
- Uri uri = Im.AccountStatus.CONTENT_URI;
+ Uri uri = Imps.AccountStatus.CONTENT_URI;
ContentValues values = new ContentValues();
- values.put(Im.AccountStatus.ACCOUNT, mAccountId);
- values.put(Im.AccountStatus.PRESENCE_STATUS, presenceStatus);
- values.put(Im.AccountStatus.CONNECTION_STATUS, connectionStatus);
+ values.put(Imps.AccountStatus.ACCOUNT, mAccountId);
+ values.put(Imps.AccountStatus.PRESENCE_STATUS, presenceStatus);
+ values.put(Imps.AccountStatus.CONNECTION_STATUS, connectionStatus);
cr.insert(uri, values);
}
@@ -324,20 +324,20 @@ public class ImConnectionAdapter extends IImConnection.Stub {
switch (state) {
case ImConnection.DISCONNECTED:
case ImConnection.LOGGING_OUT:
- return Im.ConnectionStatus.OFFLINE;
+ return Imps.ConnectionStatus.OFFLINE;
case ImConnection.LOGGING_IN:
- return Im.ConnectionStatus.CONNECTING;
+ return Imps.ConnectionStatus.CONNECTING;
case ImConnection.LOGGED_IN:
- return Im.ConnectionStatus.ONLINE;
+ return Imps.ConnectionStatus.ONLINE;
case ImConnection.SUSPENDED:
case ImConnection.SUSPENDING:
- return Im.ConnectionStatus.SUSPENDED;
+ return Imps.ConnectionStatus.SUSPENDED;
default:
- return Im.ConnectionStatus.OFFLINE;
+ return Imps.ConnectionStatus.OFFLINE;
}
}
@@ -449,15 +449,15 @@ public class ImConnectionAdapter extends IImConnection.Stub {
public void onGroupInvitation(Invitation invitation) {
String sender = invitation.getSender().getScreenName();
ContentValues values = new ContentValues(7);
- values.put(Im.Invitation.PROVIDER, mProviderId);
- values.put(Im.Invitation.ACCOUNT, mAccountId);
- values.put(Im.Invitation.INVITE_ID, invitation.getInviteID());
- values.put(Im.Invitation.SENDER, sender);
- values.put(Im.Invitation.GROUP_NAME, invitation.getGroupAddress().getScreenName());
- values.put(Im.Invitation.NOTE, invitation.getReason());
- values.put(Im.Invitation.STATUS, Im.Invitation.STATUS_PENDING);
+ values.put(Imps.Invitation.PROVIDER, mProviderId);
+ values.put(Imps.Invitation.ACCOUNT, mAccountId);
+ values.put(Imps.Invitation.INVITE_ID, invitation.getInviteID());
+ values.put(Imps.Invitation.SENDER, sender);
+ values.put(Imps.Invitation.GROUP_NAME, invitation.getGroupAddress().getScreenName());
+ values.put(Imps.Invitation.NOTE, invitation.getReason());
+ values.put(Imps.Invitation.STATUS, Imps.Invitation.STATUS_PENDING);
ContentResolver resolver = mService.getContentResolver();
- Uri uri = resolver.insert(Im.Invitation.CONTENT_URI, values);
+ Uri uri = resolver.insert(Imps.Invitation.CONTENT_URI, values);
long id = ContentUris.parseId(uri);
try {
if (mRemoteListener != null) {
diff --git a/src/com/android/im/service/RemoteImService.java b/src/com/android/im/service/RemoteImService.java
index cb350bd..5764f1e 100644
--- a/src/com/android/im/service/RemoteImService.java
+++ b/src/com/android/im/service/RemoteImService.java
@@ -28,14 +28,9 @@ import java.util.Vector;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkConnectivityListener;
@@ -49,34 +44,32 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemProperties;
-import android.provider.Im;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
-import com.android.im.app.DatabaseUtils;
import com.android.im.IConnectionCreationListener;
import com.android.im.IImConnection;
import com.android.im.IRemoteImService;
+import com.android.im.app.ImPluginHelper;
import com.android.im.engine.ConnectionFactory;
import com.android.im.engine.ImConnection;
import com.android.im.engine.ImException;
import com.android.im.imps.ImpsConnectionConfig;
-import com.android.im.plugin.IImPlugin;
import com.android.im.plugin.ImConfigNames;
-import com.android.im.plugin.ImPluginConstants;
import com.android.im.plugin.ImPluginInfo;
import com.android.im.plugin.ImpsConfigNames;
-import dalvik.system.PathClassLoader;
+import com.android.im.provider.Imps;
+
public class RemoteImService extends Service {
private static final String[] ACCOUNT_PROJECTION = {
- Im.Account._ID,
- Im.Account.PROVIDER,
- Im.Account.USERNAME,
- Im.Account.PASSWORD,
+ Imps.Account._ID,
+ Imps.Account.PROVIDER,
+ Imps.Account.USERNAME,
+ Imps.Account.PASSWORD,
};
private static final int ACCOUNT_ID_COLUMN = 0;
private static final int ACCOUNT_PROVIDER_COLUMN = 1;
@@ -98,15 +91,14 @@ public class RemoteImService extends Service {
private SettingsMonitor mSettingsMonitor;
+ private ImPluginHelper mPluginHelper;
Vector<ImConnectionAdapter> mConnections;
final RemoteCallbackList<IConnectionCreationListener> mRemoteListeners
= new RemoteCallbackList<IConnectionCreationListener>();
- private HashMap<Long, ImPluginInfo> mPlugins;
public RemoteImService() {
mConnections = new Vector<ImConnectionAdapter>();
- mPlugins = new HashMap<Long, ImPluginInfo>();
}
@Override
@@ -128,89 +120,11 @@ public class RemoteImService extends Service {
= (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
setBackgroundData(manager.getBackgroundDataSetting());
- findAvaiablePlugins();
+ mPluginHelper = ImPluginHelper.getInstance(this);
+ mPluginHelper.loadAvaiablePlugins();
AndroidSystemService.getInstance().initialize(this);
}
- private void findAvaiablePlugins() {
- PackageManager pm = getPackageManager();
- List<ResolveInfo> plugins = pm.queryIntentServices(
- new Intent(ImPluginConstants.PLUGIN_ACTION_NAME), PackageManager.GET_META_DATA);
- for (ResolveInfo info : plugins) {
- Log.d(TAG, "Found plugin " + info);
-
- ServiceInfo serviceInfo = info.serviceInfo;
- if (serviceInfo == null) {
- Log.e(TAG, "Ignore bad IM plugin: " + info);
- continue;
- }
- String providerName = null;
- String providerFullName = null;
- String signUpUrl = null;
- Bundle metaData = serviceInfo.metaData;
- if (metaData != null) {
- providerName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_NAME);
- providerFullName = metaData.getString(ImPluginConstants.METADATA_PROVIDER_FULL_NAME);
- signUpUrl = metaData.getString(ImPluginConstants.METADATA_SIGN_UP_URL);
- }
- if (TextUtils.isEmpty(providerName) || TextUtils.isEmpty(providerFullName)) {
- Log.e(TAG, "Ignore bad IM plugin: " + info + ". Lack of required meta data");
- continue;
- }
-
- ImPluginInfo pluginInfo = new ImPluginInfo(providerName, serviceInfo.packageName,
- serviceInfo.name, serviceInfo.applicationInfo.sourceDir);
-
- Map<String, String> config = loadProviderConfigFromPlugin(pluginInfo);
- if (config == null) {
- Log.e(TAG, "Ignore bad IM plugin");
- break;
- }
-
- config.put(ImConfigNames.PLUGIN_PATH, pluginInfo.mSrcPath);
- config.put(ImConfigNames.PLUGIN_CLASS, pluginInfo.mClassName);
- long providerId = DatabaseUtils.updateProviderDb(getContentResolver(),
- providerName, providerFullName, signUpUrl, config);
- mPlugins.put(providerId, pluginInfo);
- }
- }
-
- private Map<String, String> loadProviderConfigFromPlugin(ImPluginInfo pluginInfo) {
- // XXX Load the plug-in implementation directly from the apk rather than
- // binding to the service and call through IPC Binder API. This is much
- // more effective since we don't need to start the service in other
- // process. We can not run the plug-in service in the same process as a
- // local service because that the interface is defined in a shared
- // library in order to compile the plug-in separately. In this case, the
- // interface will be loaded by two class loader separately and a
- // ClassCastException will be thrown if we cast the binder to the
- // interface.
- PathClassLoader loader = new PathClassLoader(pluginInfo.mSrcPath, getClassLoader());
- try {
- Class cls = loader.loadClass(pluginInfo.mClassName);
- Method m = cls.getMethod("onBind", Intent.class);
- IImPlugin plugin = (IImPlugin)m.invoke(cls.newInstance(), new Object[]{null});
- return plugin.getProviderConfig();
- } catch (ClassNotFoundException e) {
- Log.e(TAG, "Could not find plugin class", e);
- } catch (IllegalAccessException e) {
- Log.e(TAG, "Could not create plugin instance", e);
- } catch (InstantiationException e) {
- Log.e(TAG, "Could not create plugin instance", e);
- } catch (SecurityException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- } catch (NoSuchMethodException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- } catch (InvocationTargetException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not load config from the plugin", e);
- }
- return null;
- }
-
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
@@ -232,8 +146,8 @@ public class RemoteImService extends Service {
ContentResolver resolver = getContentResolver();
- String where = Im.Account.KEEP_SIGNED_IN + "=1 AND " + Im.Account.ACTIVE + "=1";
- Cursor cursor = resolver.query(Im.Account.CONTENT_URI,
+ String where = Imps.Account.KEEP_SIGNED_IN + "=1 AND " + Imps.Account.ACTIVE + "=1";
+ Cursor cursor = resolver.query(Imps.Account.CONTENT_URI,
ACCOUNT_PROJECTION, where, null, null);
if (cursor == null) {
Log.w(TAG, "Can't query account!");
@@ -258,7 +172,7 @@ public class RemoteImService extends Service {
private Map<String, String> loadProviderSettings(long providerId) {
ContentResolver cr = getContentResolver();
- Map<String, String> settings = Im.ProviderSettings.queryProviderSettings(cr, providerId);
+ Map<String, String> settings = Imps.ProviderSettings.queryProviderSettings(cr, providerId);
NetworkInfo networkInfo = mNetworkConnectivityListener.getNetworkInfo();
// Insert a fake msisdn on emulator. We don't need this on device
@@ -454,8 +368,8 @@ public class RemoteImService extends Service {
private final IRemoteImService.Stub mBinder = new IRemoteImService.Stub() {
- public List getAllPlugins() {
- return new ArrayList(mPlugins.values());
+ public List<ImPluginInfo> getAllPlugins() {
+ return new ArrayList<ImPluginInfo>(mPluginHelper.getPluginsInfo());
}
public void addConnectionCreatedListener(IConnectionCreationListener listener) {
diff --git a/src/com/android/im/service/StatusBarNotifier.java b/src/com/android/im/service/StatusBarNotifier.java
index fb3d1ba..071969e 100644
--- a/src/com/android/im/service/StatusBarNotifier.java
+++ b/src/com/android/im/service/StatusBarNotifier.java
@@ -28,13 +28,13 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemClock;
-import android.provider.Im;
import android.text.TextUtils;
import android.util.Log;
import com.android.im.R;
import com.android.im.app.ContactListActivity;
import com.android.im.app.NewChatActivity;
+import com.android.im.provider.Imps;
public class StatusBarNotifier {
private static final boolean DBG = false;
@@ -46,7 +46,7 @@ public class StatusBarNotifier {
private Context mContext;
private NotificationManager mNotificationManager;
- private HashMap<Long, Im.ProviderSettings.QueryMap> mSettings;
+ private HashMap<Long, Imps.ProviderSettings.QueryMap> mSettings;
private Handler mHandler;
private HashMap<Long, NotificationInfo> mNotificationInfos;
private long mLastSoundPlayedMs;
@@ -55,13 +55,13 @@ public class StatusBarNotifier {
mContext = context;
mNotificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
- mSettings = new HashMap<Long, Im.ProviderSettings.QueryMap>();
+ mSettings = new HashMap<Long, Imps.ProviderSettings.QueryMap>();
mHandler = new Handler();
mNotificationInfos = new HashMap<Long, NotificationInfo>();
}
public void onServiceStop() {
- for(Im.ProviderSettings.QueryMap queryMap : mSettings.values()) {
+ for(Imps.ProviderSettings.QueryMap queryMap : mSettings.values()) {
queryMap.close();
}
}
@@ -76,7 +76,7 @@ public class StatusBarNotifier {
String title = nickname;
String snippet = nickname + ": " + msg;
Intent intent = new Intent(Intent.ACTION_VIEW,
- ContentUris.withAppendedId(Im.Chats.CONTENT_URI, chatId));
+ ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, chatId));
intent.addCategory(com.android.im.app.ImApp.IMPS_CATEGORY);
notify(username, title, snippet, msg, providerId, accountId, intent, lightWeightNotify);
}
@@ -90,7 +90,7 @@ public class StatusBarNotifier {
String title = nickname;
String message = mContext.getString(R.string.subscription_notify_text, nickname);
Intent intent = new Intent(ImServiceConstants.ACTION_MANAGE_SUBSCRIPTION,
- ContentUris.withAppendedId(Im.Contacts.CONTENT_URI, contactId));
+ ContentUris.withAppendedId(Imps.Contacts.CONTENT_URI, contactId));
intent.putExtra(ImServiceConstants.EXTRA_INTENT_PROVIDER_ID, providerId);
intent.putExtra(ImServiceConstants.EXTRA_INTENT_FROM_ADDRESS, username);
notify(username, title, message, message, providerId, accountId, intent, false);
@@ -100,7 +100,7 @@ public class StatusBarNotifier {
long invitationId, String username) {
Intent intent = new Intent(Intent.ACTION_VIEW,
- ContentUris.withAppendedId(Im.Invitation.CONTENT_URI, invitationId));
+ ContentUris.withAppendedId(Imps.Invitation.CONTENT_URI, invitationId));
String title = mContext.getString(R.string.notify_groupchat_label);
String message = mContext.getString(
@@ -146,10 +146,10 @@ public class StatusBarNotifier {
}
}
- private Im.ProviderSettings.QueryMap getProviderSettings(long providerId) {
- Im.ProviderSettings.QueryMap res = mSettings.get(providerId);
+ private Imps.ProviderSettings.QueryMap getProviderSettings(long providerId) {
+ Imps.ProviderSettings.QueryMap res = mSettings.get(providerId);
if (res == null) {
- res = new Im.ProviderSettings.QueryMap(mContext.getContentResolver(),
+ res = new Imps.ProviderSettings.QueryMap(mContext.getContentResolver(),
providerId, true, mHandler);
mSettings.put(providerId, res);
}
@@ -157,7 +157,7 @@ public class StatusBarNotifier {
}
private boolean isNotificationEnabled(long providerId) {
- Im.ProviderSettings.QueryMap settings = getProviderSettings(providerId);
+ Imps.ProviderSettings.QueryMap settings = getProviderSettings(providerId);
return settings.getEnableNotification();
}
@@ -178,7 +178,7 @@ public class StatusBarNotifier {
}
private void setRinger(long providerId, Notification notification) {
- Im.ProviderSettings.QueryMap settings = getProviderSettings(providerId);
+ Imps.ProviderSettings.QueryMap settings = getProviderSettings(providerId);
String ringtoneUri = settings.getRingtoneURI();
boolean vibrate = settings.getVibrate();
@@ -262,7 +262,7 @@ public class StatusBarNotifier {
private Intent getDefaultIntent() {
Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setType(Im.Contacts.CONTENT_TYPE);
+ intent.setType(Imps.Contacts.CONTENT_TYPE);
intent.setClass(mContext, ContactListActivity.class);
intent.putExtra(ImServiceConstants.EXTRA_INTENT_ACCOUNT_ID, mAccountId);
@@ -287,7 +287,7 @@ public class StatusBarNotifier {
return item.mTitle;
} else {
return mContext.getString(R.string.newMessages_label,
- Im.Provider.getProviderNameForId(mContext.getContentResolver(), mProviderId));
+ Imps.Provider.getProviderNameForId(mContext.getContentResolver(), mProviderId));
}
}