eclair snapshot
This commit is contained in:
@@ -31,6 +31,9 @@
|
||||
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.ALL_SERVICES" />
|
||||
<uses-permission android:name="com.google.android.googleapps.permission.GOOGLE_AUTH.YouTubeUser" />
|
||||
<uses-permission android:name="com.google.android.googleapps.permission.ACCESS_GOOGLE_PASSWORD" />
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
||||
|
||||
<application android:label="Dev Tools"
|
||||
android:icon="@drawable/ic_launcher_devtools">
|
||||
@@ -73,6 +76,22 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="AccountsTester" android:label="AccountsTester"
|
||||
android:theme="@android:style/Theme.Light">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.TEST" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="SyncAdapterDriver" android:label="Sync Tester"
|
||||
android:theme="@android:style/Theme.Light">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.TEST" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name="DataList">
|
||||
</activity>
|
||||
<activity android:name="Details">
|
||||
|
||||
BIN
apps/Development/res/drawable-hdpi/ic_launcher_devtools.png
Executable file
BIN
apps/Development/res/drawable-hdpi/ic_launcher_devtools.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
BIN
apps/Development/res/drawable-hdpi/stat_sample.png
Executable file
BIN
apps/Development/res/drawable-hdpi/stat_sample.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 388 B |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
34
apps/Development/res/layout/account_list_context_menu.xml
Normal file
34
apps/Development/res/layout/account_list_context_menu.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:id="@+id/accounts_tester_remove_account"
|
||||
android:title="@string/accounts_tester_remove_account" />
|
||||
|
||||
<item android:id="@+id/accounts_tester_get_auth_token"
|
||||
android:title="@string/accounts_tester_get_auth_token" />
|
||||
|
||||
<item android:id="@+id/accounts_tester_invalidate_auth_token"
|
||||
android:title="@string/accounts_tester_invalidate_auth_token" />
|
||||
|
||||
<item android:id="@+id/accounts_tester_update_credentials"
|
||||
android:title="@string/accounts_tester_update_credentials" />
|
||||
|
||||
<item android:id="@+id/accounts_tester_confirm_credentials"
|
||||
android:title="@string/accounts_tester_confirm_credentials" />
|
||||
|
||||
</menu>
|
||||
20
apps/Development/res/layout/account_list_view.xml
Normal file
20
apps/Development/res/layout/account_list_view.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<ListView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"/>
|
||||
117
apps/Development/res/layout/accounts_tester.xml
Normal file
117
apps/Development/res/layout/accounts_tester.xml
Normal file
@@ -0,0 +1,117 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ListView android:id="@+id/accounts_tester_authenticators_list"
|
||||
android:layout_width="fill_parent" android:layout_height="fill_parent"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:id="@+id/accounts_tester_account_types_spinner_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accounts_tester_select_account_type"/>
|
||||
|
||||
<Spinner android:id="@+id/accounts_tester_account_types_spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<Button
|
||||
android:id="@+id/accounts_tester_get_accounts_by_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accounts_tester_get_accounts_by_type"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/accounts_tester_get_all_accounts"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accounts_tester_get_all_accounts"/>
|
||||
<Button android:id="@+id/accounts_tester_add_account"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accounts_tester_add_account"/>
|
||||
|
||||
<Button android:id="@+id/accounts_tester_edit_properties"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accounts_tester_edit_properties"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView android:id="@+id/accounts_tester_desiredFeatures"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accounts_tester_desired_features_label"/>
|
||||
|
||||
<EditText android:id="@+id/accounts_tester_desired_features"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minEms="15"/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView android:id="@+id/accounts_tester_desiredFeatures"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accounts_tester_desired_authtokentype_label"/>
|
||||
|
||||
<EditText android:id="@+id/accounts_tester_desired_authtokentype"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minEms="15"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ListView android:id="@+id/accounts_tester_accounts_list"
|
||||
android:layout_width="fill_parent" android:layout_height="fill_parent"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
43
apps/Development/res/layout/authenticators_list_item.xml
Normal file
43
apps/Development/res/layout/authenticators_list_item.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingTop="1dip"
|
||||
android:paddingBottom="1dip"
|
||||
android:paddingLeft="9dip"
|
||||
android:paddingRight="9dip">
|
||||
|
||||
<ImageView android:id="@+id/accounts_tester_authenticator_icon"
|
||||
android:paddingRight="9dip"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<TextView android:id="@+id/accounts_tester_authenticator_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="fill_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_gravity="center_horizontal|center_vertical" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -68,10 +68,17 @@
|
||||
android:layout_alignParentLeft="true"
|
||||
android:text="@string/development_settings_show_updates_text" />
|
||||
|
||||
<CheckBox android:id="@+id/compatibility_mode"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/show_updates"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:text="@string/development_settings_compatibility_mode_text" />
|
||||
|
||||
<Spinner android:id="@+id/max_procs"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/show_updates"
|
||||
android:layout_below="@id/compatibility_mode"
|
||||
android:layout_alignParentLeft="true" />
|
||||
|
||||
<View android:id="@+id/separator2"
|
||||
|
||||
36
apps/Development/res/layout/get_auth_token_view.xml
Normal file
36
apps/Development/res/layout/get_auth_token_view.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<TextView android:id="@+id/accounts_tester_get_auth_token_dialog_message"
|
||||
android:layout_width="fill_parent" android:layout_height="wrap_content"
|
||||
android:text="@string/accounts_tester_enter_auth_token_type" />
|
||||
|
||||
<EditText android:id="@+id/accounts_tester_auth_token_type"
|
||||
android:singleLine="true"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="250dip"
|
||||
android:scrollHorizontally="true"
|
||||
android:capitalize="none"
|
||||
android:autoText="false"/>
|
||||
|
||||
</LinearLayout>
|
||||
68
apps/Development/res/layout/package_list_item.xml
Normal file
68
apps/Development/res/layout/package_list_item.xml
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright 2009, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:orientation="vertical"
|
||||
android:gravity="fill" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:paddingRight="6dip"
|
||||
android:paddingLeft="6dip"
|
||||
android:gravity="center_vertical" >
|
||||
|
||||
<ImageView android:id="@+id/icon"
|
||||
android:layout_width="@android:dimen/app_icon_size"
|
||||
android:layout_height="@android:dimen/app_icon_size"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginRight="11dip"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:scaleType="fitCenter"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
<TextView android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textStyle="bold"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:layout_marginBottom="2dip" />
|
||||
<TextView android:id="@+id/description"
|
||||
android:layout_marginTop="-4dip"
|
||||
android:layout_gravity="center_vertical|left"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="4dip"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
86
apps/Development/res/layout/sync_adapter_driver.xml
Normal file
86
apps/Development/res/layout/sync_adapter_driver.xml
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView android:id="@+id/sync_adapters_spinner_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="22dip"
|
||||
android:text="@string/sync_adapters_spinner_label"/>
|
||||
|
||||
<Spinner android:id="@+id/sync_adapters_spinner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="52dip">
|
||||
<Button
|
||||
android:id="@+id/bind_button"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/bind_button"
|
||||
android:onClick="initiateBind"
|
||||
android:layout_weight="2"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/unbind_button"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/unbind_button"
|
||||
android:onClick="initiateUnbind"
|
||||
android:layout_weight="2"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:id="@+id/bound_adapter_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:textSize="20dip"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="52dip">
|
||||
<Button
|
||||
android:id="@+id/start_sync_button"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/start_sync_button"
|
||||
android:onClick="startSyncSelected"
|
||||
android:layout_weight="2"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/cancel_sync_button"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel_sync_button"
|
||||
android:onClick="cancelSync"
|
||||
android:layout_weight="2"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:id="@+id/status_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
26
apps/Development/res/layout/sync_adapter_item.xml
Normal file
26
apps/Development/res/layout/sync_adapter_item.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2009, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/text1"
|
||||
style="?android:attr/spinnerItemStyle"
|
||||
android:singleLine="true"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="52dip"
|
||||
android:ellipsize="marquee" />
|
||||
@@ -77,6 +77,9 @@
|
||||
<string name="development_settings_always_finish_text">Immediately destroy activities</string>
|
||||
<string name="development_settings_show_load_text">Show running processes</string>
|
||||
<string name="development_settings_show_updates_text">Show screen updates</string>
|
||||
<string name="development_settings_compatibility_mode_text">Disable compatibility mode</string>
|
||||
<string name="development_settings_compatibility_mode_toast">Reboot required for
|
||||
change to take effect.</string>
|
||||
<string name="development_settings_enable_gl_text">Enable OpenGL ES (reboot needed)</string>
|
||||
<string name="development_settings_allow_mock_location_text">Allow mock locations for testing</string>
|
||||
<string name="development_settings_wait_for_debugger_text">Wait for debugger</string>
|
||||
@@ -133,4 +136,44 @@
|
||||
<string name="perm_list_header_text">Apps using permission </string>
|
||||
<string name="source_uid_text">Source uid : </string>
|
||||
<string name="shared_pkgs_text">Packages accessing via shared uid : </string>
|
||||
|
||||
<!-- AccountsTester -->
|
||||
<string name="accounts_tester_app_name">Accounts Tester</string>
|
||||
<string name="accounts_tester_get_accounts_by_type">Get By Type</string>
|
||||
<string name="accounts_tester_get_all_accounts">Get All</string>
|
||||
<string name="accounts_tester_add_account">Add</string>
|
||||
<string name="accounts_tester_select_account_type">Select Account Type</string>
|
||||
<string name="accounts_tester_process_name_header">Process Name:</string>
|
||||
<string name="accounts_tester_remove_account">remove</string>
|
||||
<string name="accounts_tester_get_auth_token">authenticate</string>
|
||||
<string name="accounts_tester_invalidate_auth_token">invalidate token</string>
|
||||
<string name="accounts_tester_account_context_menu_title">account operations</string>
|
||||
<string name="accounts_tester_do_get_auth_token">Ok</string>
|
||||
<string name="accounts_tester_enter_auth_token_type">Enter the authtoken type:</string>
|
||||
<string name="accounts_tester_update_credentials">Update Credentials</string>
|
||||
<string name="accounts_tester_confirm_credentials">Confirm Credentials</string>
|
||||
<string name="accounts_tester_edit_properties">Properties</string>
|
||||
<string name="accounts_tester_desired_authtokentype_label">authtoken type:</string>
|
||||
<string name="accounts_tester_desired_features_label">features:</string>
|
||||
|
||||
<!-- SyncAdapterDriver -->
|
||||
<string name="bind_button">bind</string>
|
||||
<string name="unbind_button">unbind</string>
|
||||
<string name="start_sync_button">start sync</string>
|
||||
<string name="cancel_sync_button">cancel sync</string>
|
||||
<string name="sync_adapters_spinner_label">Registered Sync Adapters:</string>
|
||||
<string name="status_starting_sync_format">Starting a sync of account %s...</string>
|
||||
<string name="status_remote_exception_while_starting_sync">Got a RemoteException while starting the sync</string>
|
||||
<string name="status_canceled_sync">Canceled the sync</string>
|
||||
<string name="status_remote_exception_while_canceling_sync">Got a RemoteException while canceling the sync</string>
|
||||
<string name="status_received_heartbeat">Received heartbeat</string>
|
||||
<string name="status_sync_failed_format">Sync failed: %s</string>
|
||||
<string name="status_sync_succeeded_format">Sync succeeded: %s</string>
|
||||
<string name="status_already_bound">Already bound to sync adapter</string>
|
||||
<string name="status_sync_adapter_not_selected">No selected sync adapter</string>
|
||||
<string name="binding_connected_format">Connected to Sync Adapter\n\tauthority: %s\n\taccount type: %s</string>
|
||||
<string name="binding_not_connected">Not connected to a sync adapter</string>
|
||||
<string name="binding_bind_failed">Bind failed</string>
|
||||
<string name="binding_waiting_for_connection">Waiting for service to be connected...</string>
|
||||
<string name="select_account_to_sync">Select account to sync</string>
|
||||
</resources>
|
||||
|
||||
431
apps/Development/src/com/android/development/AccountsTester.java
Normal file
431
apps/Development/src/com/android/development/AccountsTester.java
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.development;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.*;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.accounts.*;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Handler;
|
||||
import android.view.*;
|
||||
import android.widget.*;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.util.Log;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class AccountsTester extends Activity implements OnAccountsUpdateListener {
|
||||
private static final String TAG = "AccountsTester";
|
||||
private Spinner mAccountTypesSpinner;
|
||||
private ListView mAccountsListView;
|
||||
private ListView mAuthenticatorsListView;
|
||||
private AccountManager mAccountManager;
|
||||
private String mLongPressedAccount = null;
|
||||
private static final String COM_GOOGLE = "com.google";
|
||||
private AuthenticatorDescription[] mAuthenticatorDescs;
|
||||
|
||||
private static final int GET_AUTH_TOKEN_DIALOG_ID = 1;
|
||||
private static final int UPDATE_CREDENTIALS_DIALOG_ID = 2;
|
||||
private static final int INVALIDATE_AUTH_TOKEN_DIALOG_ID = 3;
|
||||
private EditText mDesiredAuthTokenTypeEditText;
|
||||
private EditText mDesiredFeaturesEditText;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mAccountManager = AccountManager.get(this);
|
||||
setContentView(R.layout.accounts_tester);
|
||||
ButtonClickListener buttonClickListener = new ButtonClickListener();
|
||||
|
||||
mAccountTypesSpinner = (Spinner) findViewById(R.id.accounts_tester_account_types_spinner);
|
||||
mAccountsListView = (ListView) findViewById(R.id.accounts_tester_accounts_list);
|
||||
mAuthenticatorsListView = (ListView) findViewById(R.id.accounts_tester_authenticators_list);
|
||||
registerForContextMenu(mAccountsListView);
|
||||
getAuthenticatorTypes();
|
||||
findViewById(R.id.accounts_tester_get_all_accounts).setOnClickListener(buttonClickListener);
|
||||
findViewById(R.id.accounts_tester_get_accounts_by_type).setOnClickListener(
|
||||
buttonClickListener);
|
||||
findViewById(R.id.accounts_tester_add_account).setOnClickListener(buttonClickListener);
|
||||
findViewById(R.id.accounts_tester_edit_properties).setOnClickListener(buttonClickListener);
|
||||
mDesiredAuthTokenTypeEditText =
|
||||
(EditText) findViewById(R.id.accounts_tester_desired_authtokentype);
|
||||
mDesiredFeaturesEditText = (EditText) findViewById(R.id.accounts_tester_desired_features);
|
||||
}
|
||||
|
||||
private static class AuthenticatorsArrayAdapter extends ArrayAdapter<AuthenticatorDescription> {
|
||||
protected LayoutInflater mInflater;
|
||||
private static final int mResource = R.layout.authenticators_list_item;
|
||||
|
||||
public AuthenticatorsArrayAdapter(Context context, AuthenticatorDescription[] items) {
|
||||
super(context, mResource, items);
|
||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
TextView label;
|
||||
ImageView icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
// A ViewHolder keeps references to children views to avoid unneccessary calls
|
||||
// to findViewById() on each row.
|
||||
ViewHolder holder;
|
||||
|
||||
// When convertView is not null, we can reuse it directly, there is no need
|
||||
// to reinflate it. We only inflate a new View when the convertView supplied
|
||||
// by ListView is null.
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.authenticators_list_item, null);
|
||||
|
||||
// Creates a ViewHolder and store references to the two children views
|
||||
// we want to bind data to.
|
||||
holder = new ViewHolder();
|
||||
holder.label = (TextView) convertView.findViewById(
|
||||
R.id.accounts_tester_authenticator_label);
|
||||
holder.icon = (ImageView) convertView.findViewById(
|
||||
R.id.accounts_tester_authenticator_icon);
|
||||
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
// Get the ViewHolder back to get fast access to the TextView
|
||||
// and the ImageView.
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
final AuthenticatorDescription desc = getItem(position);
|
||||
final String packageName = desc.packageName;
|
||||
try {
|
||||
final Context authContext = getContext().createPackageContext(packageName, 0);
|
||||
|
||||
// Set text field
|
||||
holder.label.setText(authContext.getString(desc.labelId));
|
||||
|
||||
// Set resource icon
|
||||
holder.icon.setImageDrawable(authContext.getResources().getDrawable(desc.iconId));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.d(TAG, "error getting the Package Context for " + packageName, e);
|
||||
}
|
||||
|
||||
return convertView;
|
||||
}
|
||||
}
|
||||
|
||||
private void getAuthenticatorTypes() {
|
||||
mAuthenticatorDescs = mAccountManager.getAuthenticatorTypes();
|
||||
String[] names = new String[mAuthenticatorDescs.length];
|
||||
for (int i = 0; i < mAuthenticatorDescs.length; i++) {
|
||||
Context authContext;
|
||||
try {
|
||||
authContext = createPackageContext(mAuthenticatorDescs[i].packageName, 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
continue;
|
||||
}
|
||||
names[i] = authContext.getString(mAuthenticatorDescs[i].labelId);
|
||||
}
|
||||
|
||||
ArrayAdapter<String> adapter =
|
||||
new ArrayAdapter<String>(AccountsTester.this,
|
||||
android.R.layout.simple_spinner_item, names);
|
||||
mAccountTypesSpinner.setAdapter(adapter);
|
||||
|
||||
mAuthenticatorsListView.setAdapter(new AuthenticatorsArrayAdapter(
|
||||
AccountsTester.this, mAuthenticatorDescs));
|
||||
}
|
||||
|
||||
public void onAccountsUpdated(Account[] accounts) {
|
||||
Log.d(TAG, "onAccountsUpdated: \n " + TextUtils.join("\n ", accounts));
|
||||
String[] accountNames = new String[accounts.length];
|
||||
for (int i = 0; i < accounts.length; i++) {
|
||||
accountNames[i] = accounts[i].name;
|
||||
}
|
||||
ArrayAdapter<String> adapter =
|
||||
new ArrayAdapter<String>(AccountsTester.this,
|
||||
android.R.layout.simple_list_item_1, accountNames);
|
||||
mAccountsListView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
final Handler mainHandler = new Handler(getMainLooper());
|
||||
mAccountManager.addOnAccountsUpdatedListener(this, mainHandler,
|
||||
true /* updateImmediately */);
|
||||
}
|
||||
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mAccountManager.removeOnAccountsUpdatedListener(this);
|
||||
}
|
||||
|
||||
class ButtonClickListener implements View.OnClickListener {
|
||||
public void onClick(View v) {
|
||||
if (R.id.accounts_tester_get_all_accounts == v.getId()) {
|
||||
onAccountsUpdated(mAccountManager.getAccounts());
|
||||
} else if (R.id.accounts_tester_get_accounts_by_type == v.getId()) {
|
||||
String type = getSelectedAuthenticator().type;
|
||||
onAccountsUpdated(mAccountManager.getAccountsByType(type));
|
||||
} else if (R.id.accounts_tester_add_account == v.getId()) {
|
||||
AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
try {
|
||||
Bundle bundle = future.getResult();
|
||||
bundle.keySet();
|
||||
Log.d(TAG, "account added: " + bundle);
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.d(TAG, "addAccount was canceled");
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "addAccount failed: " + e);
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.d(TAG, "addAccount failed: " + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
String authTokenType = mDesiredAuthTokenTypeEditText.getText().toString();
|
||||
if (TextUtils.isEmpty(authTokenType)) {
|
||||
authTokenType = null;
|
||||
}
|
||||
String featureString = mDesiredFeaturesEditText.getText().toString();
|
||||
String[] requiredFeatures = TextUtils.split(featureString, " ");
|
||||
if (requiredFeatures.length == 0) {
|
||||
requiredFeatures = null;
|
||||
}
|
||||
mAccountManager.addAccount(getSelectedAuthenticator().type,
|
||||
authTokenType, requiredFeatures, null /* options */,
|
||||
AccountsTester.this, callback, null /* handler */);
|
||||
} else if (R.id.accounts_tester_edit_properties == v.getId()) {
|
||||
mAccountManager.editProperties(getSelectedAuthenticator().type,
|
||||
AccountsTester.this, new EditPropertiesCallback(), null /* handler */);
|
||||
} else {
|
||||
// unknown button
|
||||
}
|
||||
}
|
||||
|
||||
private class EditPropertiesCallback implements AccountManagerCallback<Bundle> {
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
try {
|
||||
Bundle bundle = future.getResult();
|
||||
bundle.keySet();
|
||||
Log.d(TAG, "editProperties succeeded: " + bundle);
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.d(TAG, "editProperties was canceled");
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "editProperties failed: ", e);
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.d(TAG, "editProperties failed: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AuthenticatorDescription getSelectedAuthenticator() {
|
||||
return mAuthenticatorDescs[mAccountTypesSpinner.getSelectedItemPosition()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenu.ContextMenuInfo menuInfo) {
|
||||
menu.setHeaderTitle(R.string.accounts_tester_account_context_menu_title);
|
||||
|
||||
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
|
||||
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.layout.account_list_context_menu, menu);
|
||||
mLongPressedAccount = ((TextView)info.targetView).getText().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.accounts_tester_remove_account) {
|
||||
final Account account = new Account(mLongPressedAccount, COM_GOOGLE);
|
||||
mAccountManager.removeAccount(account, new AccountManagerCallback<Boolean>() {
|
||||
public void run(AccountManagerFuture<Boolean> future) {
|
||||
try {
|
||||
Log.d(TAG, "removeAccount(" + account + ") = " + future.getResult());
|
||||
} catch (OperationCanceledException e) {
|
||||
} catch (IOException e) {
|
||||
} catch (AuthenticatorException e) {
|
||||
}
|
||||
}
|
||||
}, null /* handler */);
|
||||
} else if (item.getItemId() == R.id.accounts_tester_get_auth_token) {
|
||||
showDialog(GET_AUTH_TOKEN_DIALOG_ID);
|
||||
} else if (item.getItemId() == R.id.accounts_tester_invalidate_auth_token) {
|
||||
showDialog(INVALIDATE_AUTH_TOKEN_DIALOG_ID);
|
||||
} else if (item.getItemId() == R.id.accounts_tester_update_credentials) {
|
||||
showDialog(UPDATE_CREDENTIALS_DIALOG_ID);
|
||||
} else if (item.getItemId() == R.id.accounts_tester_confirm_credentials) {
|
||||
mAccountManager.confirmCredentials(new Account(mLongPressedAccount, COM_GOOGLE), null,
|
||||
AccountsTester.this, new ConfirmCredentialsCallback(), null /* handler */);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(final int id) {
|
||||
if (id == GET_AUTH_TOKEN_DIALOG_ID || id == INVALIDATE_AUTH_TOKEN_DIALOG_ID
|
||||
|| id == UPDATE_CREDENTIALS_DIALOG_ID) {
|
||||
final View view = LayoutInflater.from(this).inflate(R.layout.get_auth_token_view, null);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setPositiveButton(R.string.accounts_tester_do_get_auth_token,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
EditText value = (EditText) view.findViewById(
|
||||
R.id.accounts_tester_auth_token_type);
|
||||
|
||||
String authTokenType = value.getText().toString();
|
||||
AccountManagerCallback<Bundle> callback = new AccountManagerCallback<Bundle>() {
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
try {
|
||||
Bundle bundle = future.getResult();
|
||||
bundle.keySet();
|
||||
Log.d(TAG, "dialog " + id + " success: " + bundle);
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.d(TAG, "dialog " + id + " canceled");
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "dialog " + id + " failed: " + e);
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.d(TAG, "dialog " + id + " failed: " + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
final Account account = new Account(mLongPressedAccount,
|
||||
COM_GOOGLE);
|
||||
if (id == GET_AUTH_TOKEN_DIALOG_ID) {
|
||||
mAccountManager.getAuthToken(account, authTokenType,
|
||||
null /* loginOptions */, AccountsTester.this,
|
||||
callback, null /* handler */);
|
||||
} else if (id == INVALIDATE_AUTH_TOKEN_DIALOG_ID) {
|
||||
mAccountManager.getAuthToken(account, authTokenType, false,
|
||||
new GetAndInvalidateAuthTokenCallback(), null);
|
||||
} else {
|
||||
mAccountManager.updateCredentials(
|
||||
account,
|
||||
authTokenType, null /* loginOptions */,
|
||||
AccountsTester.this, callback, null /* handler */);
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setView(view);
|
||||
return builder.create();
|
||||
}
|
||||
return super.onCreateDialog(id);
|
||||
}
|
||||
|
||||
AccountManagerCallback<Bundle> newAccountsCallback(String type, String[] features) {
|
||||
return new GetAccountsCallback(type, features);
|
||||
}
|
||||
|
||||
class GetAccountsCallback implements AccountManagerCallback<Bundle> {
|
||||
final String[] mFeatures;
|
||||
final String mAccountType;
|
||||
|
||||
public GetAccountsCallback(String type, String[] features) {
|
||||
mFeatures = features;
|
||||
mAccountType = type;
|
||||
}
|
||||
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
Log.d(TAG, "GetAccountsCallback: type " + mAccountType
|
||||
+ ", features "
|
||||
+ (mFeatures == null ? "none" : TextUtils.join(",", mFeatures)));
|
||||
try {
|
||||
Bundle result = future.getResult();
|
||||
Parcelable[] accounts = result.getParcelableArray(AccountManager.KEY_ACCOUNTS);
|
||||
Log.d(TAG, "found " + accounts.length + " accounts");
|
||||
for (Parcelable account : accounts) {
|
||||
Log.d(TAG, " " + account);
|
||||
}
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.d(TAG, "failure", e);
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "failure", e);
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.d(TAG, "failure", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AccountManagerCallback<Bundle> newAuthTokensCallback(String type, String authTokenType, String[] features) {
|
||||
return new GetAuthTokenCallback(type, authTokenType, features);
|
||||
}
|
||||
|
||||
class GetAuthTokenCallback implements AccountManagerCallback<Bundle> {
|
||||
final String[] mFeatures;
|
||||
final String mAccountType;
|
||||
final String mAuthTokenType;
|
||||
|
||||
public GetAuthTokenCallback(String type, String authTokenType, String[] features) {
|
||||
mFeatures = features;
|
||||
mAccountType = type;
|
||||
mAuthTokenType = authTokenType;
|
||||
}
|
||||
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
Log.d(TAG, "GetAuthTokenCallback: type " + mAccountType
|
||||
+ ", features "
|
||||
+ (mFeatures == null ? "none" : TextUtils.join(",", mFeatures)));
|
||||
try {
|
||||
Bundle result = future.getResult();
|
||||
result.keySet();
|
||||
Log.d(TAG, " result: " + result);
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.d(TAG, "failure", e);
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "failure", e);
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.d(TAG, "failure", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class GetAndInvalidateAuthTokenCallback implements AccountManagerCallback<Bundle> {
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
try {
|
||||
Bundle bundle = future.getResult();
|
||||
String authToken = bundle.getString(AccountManager.KEY_AUTHTOKEN);
|
||||
mAccountManager.invalidateAuthToken(COM_GOOGLE, authToken);
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.d(TAG, "invalidate: interrupted while getting authToken");
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "invalidate: error getting authToken", e);
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.d(TAG, "invalidate: error getting authToken", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ConfirmCredentialsCallback implements AccountManagerCallback<Bundle> {
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
try {
|
||||
Bundle bundle = future.getResult();
|
||||
bundle.keySet();
|
||||
Log.d(TAG, "confirmCredentials success: " + bundle);
|
||||
} catch (OperationCanceledException e) {
|
||||
Log.d(TAG, "confirmCredentials canceled");
|
||||
} catch (AuthenticatorException e) {
|
||||
Log.d(TAG, "confirmCredentials failed: " + e);
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, "confirmCredentials failed: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,14 @@
|
||||
|
||||
package com.android.development;
|
||||
|
||||
import com.android.development.PackageBrowser.MyPackageInfo;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.ListActivity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
@@ -29,10 +32,12 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -67,96 +72,67 @@ public class AppPicker extends ListActivity
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id)
|
||||
{
|
||||
ApplicationInfo app = mAdapter.appForPosition(position);
|
||||
MyApplicationInfo app = mAdapter.itemForPosition(position);
|
||||
Intent intent = new Intent();
|
||||
if (app != null) intent.setAction(app.packageName);
|
||||
if (app.info != null) intent.setAction(app.info.packageName);
|
||||
setResult(RESULT_OK, intent);
|
||||
|
||||
/* This is a temporary fix for 824637 while it is blocked by 805226. When 805226 is resolved, please remove this. */
|
||||
try {
|
||||
boolean waitForDebugger = Settings.System.getInt(
|
||||
getContentResolver(), Settings.System.WAIT_FOR_DEBUGGER, 0) != 0;
|
||||
ActivityManagerNative.getDefault().setDebugApp(
|
||||
app != null ? app.packageName : null, waitForDebugger, true);
|
||||
app.info != null ? app.info.packageName : null, waitForDebugger, true);
|
||||
} catch (RemoteException ex) {
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
private final class AppListAdapter extends BaseAdapter
|
||||
{
|
||||
public AppListAdapter(Context context)
|
||||
{
|
||||
mContext = context;
|
||||
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
class MyApplicationInfo {
|
||||
ApplicationInfo info;
|
||||
String label;
|
||||
}
|
||||
|
||||
public class AppListAdapter extends ArrayAdapter<MyApplicationInfo> {
|
||||
private List<MyApplicationInfo> mPackageInfoList = new ArrayList<MyApplicationInfo>();
|
||||
|
||||
mList = context.getPackageManager().getInstalledApplications(0);
|
||||
if (mList != null) {
|
||||
Collections.sort(mList, sDisplayNameComparator);
|
||||
mList.add(0, null);
|
||||
public AppListAdapter(Context context) {
|
||||
super(context, R.layout.package_list_item);
|
||||
List<ApplicationInfo> pkgs = context.getPackageManager().getInstalledApplications(0);
|
||||
for (int i=0; i<pkgs.size(); i++) {
|
||||
MyApplicationInfo info = new MyApplicationInfo();
|
||||
info.info = pkgs.get(i);
|
||||
info.label = info.info.loadLabel(getPackageManager()).toString();
|
||||
mPackageInfoList.add(info);
|
||||
}
|
||||
Collections.sort(mPackageInfoList, sDisplayNameComparator);
|
||||
MyApplicationInfo info = new MyApplicationInfo();
|
||||
info.label = "(none)";
|
||||
mPackageInfoList.add(0, info);
|
||||
setSource(mPackageInfoList);
|
||||
}
|
||||
|
||||
public ApplicationInfo appForPosition(int position)
|
||||
{
|
||||
if (mList == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mList.get(position);
|
||||
}
|
||||
|
||||
public int getCount()
|
||||
{
|
||||
return mList != null ? mList.size() : 0;
|
||||
}
|
||||
|
||||
public Object getItem(int position)
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
public long getItemId(int position)
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent)
|
||||
{
|
||||
View view;
|
||||
if (convertView == null) {
|
||||
view = mInflater.inflate(
|
||||
android.R.layout.simple_list_item_1, parent, false);
|
||||
@Override
|
||||
public void bindView(View view, MyApplicationInfo info) {
|
||||
ImageView icon = (ImageView)view.findViewById(R.id.icon);
|
||||
TextView name = (TextView)view.findViewById(R.id.name);
|
||||
TextView description = (TextView)view.findViewById(R.id.description);
|
||||
name.setText(info.label);
|
||||
if (info.info != null) {
|
||||
icon.setImageDrawable(info.info.loadIcon(getPackageManager()));
|
||||
description.setText(info.info.packageName);
|
||||
} else {
|
||||
view = convertView;
|
||||
icon.setImageDrawable(null);
|
||||
description.setText("");
|
||||
}
|
||||
bindView(view, mList.get(position));
|
||||
return view;
|
||||
}
|
||||
|
||||
private final void bindView(View view, ApplicationInfo info)
|
||||
{
|
||||
TextView text = (TextView)view.findViewById(android.R.id.text1);
|
||||
|
||||
text.setText(info != null ? info.packageName : "(none)");
|
||||
}
|
||||
|
||||
protected final Context mContext;
|
||||
protected final LayoutInflater mInflater;
|
||||
|
||||
protected List<ApplicationInfo> mList;
|
||||
|
||||
}
|
||||
|
||||
private final static Comparator sDisplayNameComparator = new Comparator() {
|
||||
private final static Comparator<MyApplicationInfo> sDisplayNameComparator
|
||||
= new Comparator<MyApplicationInfo>() {
|
||||
public final int
|
||||
compare(Object a, Object b)
|
||||
{
|
||||
CharSequence sa = ((ApplicationInfo) a).packageName;
|
||||
CharSequence sb = ((ApplicationInfo) b).packageName;
|
||||
|
||||
return collator.compare(sa, sb);
|
||||
compare(MyApplicationInfo a, MyApplicationInfo b) {
|
||||
return collator.compare(a.label, b.label);
|
||||
}
|
||||
|
||||
private final Collator collator = Collator.getInstance();
|
||||
|
||||
@@ -38,6 +38,7 @@ import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Toast;
|
||||
import android.widget.AdapterView.OnItemSelectedListener;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
@@ -58,6 +59,7 @@ public class DevelopmentSettings extends Activity {
|
||||
private CheckBox mShowBackgroundCB;
|
||||
private CheckBox mShowSleepCB;
|
||||
private CheckBox mShowXmppCB;
|
||||
private CheckBox mCompatibilityModeCB;
|
||||
private Spinner mMaxProcsSpinner;
|
||||
private Spinner mWindowAnimationScaleSpinner;
|
||||
private Spinner mTransitionAnimationScaleSpinner;
|
||||
@@ -69,6 +71,7 @@ public class DevelopmentSettings extends Activity {
|
||||
private int mProcessLimit;
|
||||
private boolean mShowSleep;
|
||||
private boolean mShowXmpp;
|
||||
private boolean mCompatibilityMode;
|
||||
private AnimationScaleSelectedListener mWindowAnimationScale
|
||||
= new AnimationScaleSelectedListener(0);
|
||||
private AnimationScaleSelectedListener mTransitionAnimationScale
|
||||
@@ -106,6 +109,8 @@ public class DevelopmentSettings extends Activity {
|
||||
mShowSleepCB.setOnClickListener(mShowSleepClicked);
|
||||
mShowXmppCB = (CheckBox)findViewById(R.id.show_xmpp);
|
||||
mShowXmppCB.setOnClickListener(mShowXmppClicked);
|
||||
mCompatibilityModeCB = (CheckBox)findViewById(R.id.compatibility_mode);
|
||||
mCompatibilityModeCB.setOnClickListener(mCompatibilityModeClicked);
|
||||
mMaxProcsSpinner = (Spinner)findViewById(R.id.max_procs);
|
||||
mMaxProcsSpinner.setOnItemSelectedListener(mMaxProcsChanged);
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
|
||||
@@ -168,7 +173,8 @@ public class DevelopmentSettings extends Activity {
|
||||
updateSharedOptions();
|
||||
updateFlingerOptions();
|
||||
updateSleepOptions();
|
||||
updateXmppOptions();
|
||||
updateXmppOptions();
|
||||
updateCompatibilityOptions();
|
||||
|
||||
try {
|
||||
FileInputStream in = new FileInputStream( FONT_HINTING_FILE );
|
||||
@@ -235,6 +241,17 @@ public class DevelopmentSettings extends Activity {
|
||||
Settings.System.SHOW_PROCESSES, 0) != 0);
|
||||
}
|
||||
|
||||
private void writeCompatibilityOptions() {
|
||||
Settings.System.putInt(getContentResolver(),
|
||||
Settings.System.COMPATIBILITY_MODE, mCompatibilityMode ? 0 : 1);
|
||||
}
|
||||
|
||||
private void updateCompatibilityOptions() {
|
||||
mCompatibilityMode = Settings.System.getInt(
|
||||
getContentResolver(), Settings.System.COMPATIBILITY_MODE, 1) == 0;
|
||||
mCompatibilityModeCB.setChecked(mCompatibilityMode);
|
||||
}
|
||||
|
||||
private void updateFlingerOptions() {
|
||||
// magic communication with surface flinger.
|
||||
try {
|
||||
@@ -332,6 +349,19 @@ public class DevelopmentSettings extends Activity {
|
||||
}
|
||||
};
|
||||
|
||||
private View.OnClickListener mCompatibilityModeClicked =
|
||||
new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
mCompatibilityMode = ((CheckBox)v).isChecked();
|
||||
writeCompatibilityOptions();
|
||||
updateCompatibilityOptions();
|
||||
Toast toast = Toast.makeText(DevelopmentSettings.this,
|
||||
R.string.development_settings_compatibility_mode_toast,
|
||||
Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
}
|
||||
};
|
||||
|
||||
private View.OnClickListener mShowLoadClicked = new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
boolean value = ((CheckBox)v).isChecked();
|
||||
|
||||
@@ -31,27 +31,38 @@ import android.os.Handler;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class PackageBrowser extends ListActivity
|
||||
{
|
||||
public class PackageBrowser extends ListActivity {
|
||||
static class MyPackageInfo {
|
||||
PackageInfo info;
|
||||
String label;
|
||||
}
|
||||
|
||||
private PackageListAdapter mAdapter;
|
||||
private List<PackageInfo> mPackageInfoList = null;
|
||||
private List<MyPackageInfo> mPackageInfoList = new ArrayList<MyPackageInfo>();
|
||||
private Handler mHandler;
|
||||
private BroadcastReceiver mRegisteredReceiver;
|
||||
|
||||
public class PackageListAdapter extends ArrayAdapter<PackageInfo>
|
||||
{
|
||||
public class PackageListAdapter extends ArrayAdapter<MyPackageInfo> {
|
||||
|
||||
public PackageListAdapter(Context context)
|
||||
{
|
||||
super(context, android.R.layout.simple_list_item_1);
|
||||
mPackageInfoList = context.getPackageManager().getInstalledPackages(0);
|
||||
public PackageListAdapter(Context context) {
|
||||
super(context, R.layout.package_list_item);
|
||||
List<PackageInfo> pkgs = context.getPackageManager().getInstalledPackages(0);
|
||||
for (int i=0; i<pkgs.size(); i++) {
|
||||
MyPackageInfo info = new MyPackageInfo();
|
||||
info.info = pkgs.get(i);
|
||||
info.label = info.info.applicationInfo.loadLabel(getPackageManager()).toString();
|
||||
mPackageInfoList.add(info);
|
||||
}
|
||||
if (mPackageInfoList != null) {
|
||||
Collections.sort(mPackageInfoList, sDisplayNameComparator);
|
||||
}
|
||||
@@ -59,10 +70,13 @@ public class PackageBrowser extends ListActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, PackageInfo info)
|
||||
{
|
||||
TextView text = (TextView)view.findViewById(android.R.id.text1);
|
||||
text.setText(info.packageName);
|
||||
public void bindView(View view, MyPackageInfo info) {
|
||||
ImageView icon = (ImageView)view.findViewById(R.id.icon);
|
||||
TextView name = (TextView)view.findViewById(R.id.name);
|
||||
TextView description = (TextView)view.findViewById(R.id.description);
|
||||
icon.setImageDrawable(info.info.applicationInfo.loadIcon(getPackageManager()));
|
||||
name.setText(info.label);
|
||||
description.setText(info.info.packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,13 +92,11 @@ public class PackageBrowser extends ListActivity
|
||||
}
|
||||
}
|
||||
|
||||
private final static Comparator sDisplayNameComparator = new Comparator() {
|
||||
private final static Comparator<MyPackageInfo> sDisplayNameComparator
|
||||
= new Comparator<MyPackageInfo>() {
|
||||
public final int
|
||||
compare(Object a, Object b)
|
||||
{
|
||||
CharSequence sa = ((PackageInfo) a).packageName;
|
||||
CharSequence sb = ((PackageInfo) b).packageName;
|
||||
return collator.compare(sa, sb);
|
||||
compare(MyPackageInfo a, MyPackageInfo b) {
|
||||
return collator.compare(a.label, b.label);
|
||||
}
|
||||
|
||||
private final Collator collator = Collator.getInstance();
|
||||
@@ -98,6 +110,14 @@ public class PackageBrowser extends ListActivity
|
||||
registerIntentReceivers();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mRegisteredReceiver != null) {
|
||||
unregisterReceiver(mRegisteredReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupAdapter() {
|
||||
mAdapter = new PackageListAdapter(this);
|
||||
setListAdapter(mAdapter);
|
||||
@@ -119,9 +139,9 @@ public class PackageBrowser extends ListActivity
|
||||
final int curSelection = getSelectedItemPosition();
|
||||
if (curSelection >= 0) {
|
||||
// todo: verification dialog for package deletion
|
||||
final PackageInfo packageInfo = mAdapter.itemForPosition(curSelection);
|
||||
final MyPackageInfo packageInfo = mAdapter.itemForPosition(curSelection);
|
||||
if (packageInfo != null) {
|
||||
getPackageManager().deletePackage(packageInfo.packageName,
|
||||
getPackageManager().deletePackage(packageInfo.info.packageName,
|
||||
new IPackageDeleteObserver.Stub() {
|
||||
public void packageDeleted(boolean succeeded) throws RemoteException {
|
||||
if (succeeded) {
|
||||
@@ -133,7 +153,7 @@ public class PackageBrowser extends ListActivity
|
||||
});
|
||||
|
||||
// todo: verification dialog for data directory
|
||||
final String dataPath = packageInfo.applicationInfo.dataDir;
|
||||
final String dataPath = packageInfo.info.applicationInfo.dataDir;
|
||||
// todo: delete the data directory
|
||||
} else {
|
||||
mHandler.post(new Runnable() {
|
||||
@@ -159,17 +179,17 @@ public class PackageBrowser extends ListActivity
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
|
||||
filter.addDataScheme("package");
|
||||
registerReceiver(new ApplicationsIntentReceiver(), filter);
|
||||
mRegisteredReceiver = new ApplicationsIntentReceiver();
|
||||
registerReceiver(mRegisteredReceiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id)
|
||||
{
|
||||
PackageInfo info =
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
MyPackageInfo info =
|
||||
mAdapter.itemForPosition(position);
|
||||
if (info != null) {
|
||||
Intent intent = new Intent(
|
||||
null, Uri.fromParts("package", info.packageName, null));
|
||||
null, Uri.fromParts("package", info.info.packageName, null));
|
||||
intent.setClass(this, PackageSummary.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.content.pm.ServiceInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
@@ -90,7 +91,8 @@ public class PackageSummary extends Activity {
|
||||
info = pm.getPackageInfo(mPackageName,
|
||||
PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS
|
||||
| PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS
|
||||
| PackageManager.GET_INSTRUMENTATION);
|
||||
| PackageManager.GET_INSTRUMENTATION
|
||||
| PackageManager.GET_DISABLED_COMPONENTS);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
|
||||
@@ -192,6 +194,7 @@ public class PackageSummary extends Activity {
|
||||
ActivityInfo ai = info.receivers[i];
|
||||
Button view = (Button)inflate.inflate(
|
||||
R.layout.package_item, null, false);
|
||||
Log.i("foo", "Receiver #" + i + " of " + N + ": " + ai);
|
||||
setItemText(view, info, ai.name);
|
||||
receivers.addView(view, lp);
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Paint.FontMetricsInt;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
@@ -47,16 +47,9 @@ public class PointerLocation extends Activity {
|
||||
getWindow().setAttributes(lp);
|
||||
}
|
||||
|
||||
public class MyView extends View {
|
||||
private final Paint mTextPaint;
|
||||
private final Paint mTextBackgroundPaint;
|
||||
private final Paint mTextLevelPaint;
|
||||
private final Paint mPaint;
|
||||
private final Paint mTargetPaint;
|
||||
private final FontMetricsInt mTextMetrics = new FontMetricsInt();
|
||||
public static class PointerState {
|
||||
private final ArrayList<Float> mXs = new ArrayList<Float>();
|
||||
private final ArrayList<Float> mYs = new ArrayList<Float>();
|
||||
private int mHeaderBottom;
|
||||
private boolean mCurDown;
|
||||
private int mCurX;
|
||||
private int mCurY;
|
||||
@@ -64,12 +57,31 @@ public class PointerLocation extends Activity {
|
||||
private float mCurSize;
|
||||
private int mCurWidth;
|
||||
private VelocityTracker mVelocity;
|
||||
}
|
||||
|
||||
public class MyView extends View {
|
||||
private final ViewConfiguration mVC;
|
||||
private final Paint mTextPaint;
|
||||
private final Paint mTextBackgroundPaint;
|
||||
private final Paint mTextLevelPaint;
|
||||
private final Paint mPaint;
|
||||
private final Paint mTargetPaint;
|
||||
private final Paint mPathPaint;
|
||||
private final FontMetricsInt mTextMetrics = new FontMetricsInt();
|
||||
private int mHeaderBottom;
|
||||
private boolean mCurDown;
|
||||
private int mCurNumPointers;
|
||||
private int mMaxNumPointers;
|
||||
private final ArrayList<PointerState> mPointers
|
||||
= new ArrayList<PointerState>();
|
||||
|
||||
public MyView(Context c) {
|
||||
super(c);
|
||||
mVC = ViewConfiguration.get(c);
|
||||
mTextPaint = new Paint();
|
||||
mTextPaint.setAntiAlias(true);
|
||||
mTextPaint.setTextSize(10);
|
||||
mTextPaint.setTextSize(10
|
||||
* getResources().getDisplayMetrics().density);
|
||||
mTextPaint.setARGB(255, 0, 0, 0);
|
||||
mTextBackgroundPaint = new Paint();
|
||||
mTextBackgroundPaint.setAntiAlias(false);
|
||||
@@ -84,9 +96,16 @@ public class PointerLocation extends Activity {
|
||||
mPaint.setStrokeWidth(2);
|
||||
mTargetPaint = new Paint();
|
||||
mTargetPaint.setAntiAlias(false);
|
||||
mTargetPaint.setARGB(192, 0, 0, 255);
|
||||
mTargetPaint.setARGB(255, 0, 0, 192);
|
||||
mPathPaint = new Paint();
|
||||
mPathPaint.setAntiAlias(false);
|
||||
mPathPaint.setARGB(255, 0, 96, 255);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mPaint.setStrokeWidth(1);
|
||||
|
||||
PointerState ps = new PointerState();
|
||||
ps.mVelocity = VelocityTracker.obtain();
|
||||
mPointers.add(ps);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,58 +122,119 @@ public class PointerLocation extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
int w = getWidth()/5;
|
||||
int base = -mTextMetrics.ascent+1;
|
||||
int bottom = mHeaderBottom;
|
||||
canvas.drawRect(0, 0, w-1, bottom, mTextBackgroundPaint);
|
||||
canvas.drawText("X: " + mCurX, 1, base, mTextPaint);
|
||||
canvas.drawRect(w, 0, (w * 2) - 1, bottom, mTextBackgroundPaint);
|
||||
canvas.drawText("Y: " + mCurY, 1 + w, base, mTextPaint);
|
||||
canvas.drawRect(w * 2, 0, (w * 3) - 1, bottom, mTextBackgroundPaint);
|
||||
canvas.drawRect(w * 2, 0, (w * 2) + (mCurPressure * w) - 1, bottom, mTextLevelPaint);
|
||||
canvas.drawText("Pres: " + mCurPressure, 1 + w * 2, base, mTextPaint);
|
||||
canvas.drawRect(w * 3, 0, (w * 4) - 1, bottom, mTextBackgroundPaint);
|
||||
canvas.drawRect(w * 3, 0, (w * 3) + (mCurSize * w) - 1, bottom, mTextLevelPaint);
|
||||
canvas.drawText("Size: " + mCurSize, 1 + w * 3, base, mTextPaint);
|
||||
canvas.drawRect(w * 4, 0, getWidth(), bottom, mTextBackgroundPaint);
|
||||
int velocity = mVelocity == null ? 0 : (int) (mVelocity.getYVelocity() * 1000);
|
||||
canvas.drawText("yVel: " + velocity, 1 + w * 4, base, mTextPaint);
|
||||
final int w = getWidth();
|
||||
final int itemW = w/7;
|
||||
final int base = -mTextMetrics.ascent+1;
|
||||
final int bottom = mHeaderBottom;
|
||||
|
||||
final int N = mXs.size();
|
||||
float lastX=0, lastY=0;
|
||||
mPaint.setARGB(255, 0, 255, 255);
|
||||
for (int i=0; i<N; i++) {
|
||||
float x = mXs.get(i);
|
||||
float y = mYs.get(i);
|
||||
if (i > 0) {
|
||||
canvas.drawLine(lastX, lastY, x, y, mTargetPaint);
|
||||
canvas.drawPoint(lastX, lastY, mPaint);
|
||||
final int NP = mPointers.size();
|
||||
|
||||
if (NP > 0) {
|
||||
final PointerState ps = mPointers.get(0);
|
||||
canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint);
|
||||
canvas.drawText("P: " + mCurNumPointers + " / " + mMaxNumPointers,
|
||||
1, base, mTextPaint);
|
||||
|
||||
final int N = ps.mXs.size();
|
||||
if ((mCurDown && ps.mCurDown) || N == 0) {
|
||||
canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint);
|
||||
canvas.drawText("X: " + ps.mCurX, 1 + itemW, base, mTextPaint);
|
||||
canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint);
|
||||
canvas.drawText("Y: " + ps.mCurY, 1 + itemW * 2, base, mTextPaint);
|
||||
} else {
|
||||
float dx = ps.mXs.get(N-1) - ps.mXs.get(0);
|
||||
float dy = ps.mYs.get(N-1) - ps.mYs.get(0);
|
||||
canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom,
|
||||
Math.abs(dx) < mVC.getScaledTouchSlop()
|
||||
? mTextBackgroundPaint : mTextLevelPaint);
|
||||
canvas.drawText("dX: " + String.format("%.1f", dx), 1 + itemW, base, mTextPaint);
|
||||
canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom,
|
||||
Math.abs(dy) < mVC.getScaledTouchSlop()
|
||||
? mTextBackgroundPaint : mTextLevelPaint);
|
||||
canvas.drawText("dY: " + String.format("%.1f", dy), 1 + itemW * 2, base, mTextPaint);
|
||||
}
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
}
|
||||
if (mVelocity != null) {
|
||||
mPaint.setARGB(255, 255, 0, 0);
|
||||
float xVel = mVelocity.getXVelocity() * (1000/60);
|
||||
float yVel = mVelocity.getYVelocity() * (1000/60);
|
||||
canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint);
|
||||
} else {
|
||||
canvas.drawPoint(lastX, lastY, mPaint);
|
||||
|
||||
canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint);
|
||||
int velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getXVelocity() * 1000);
|
||||
canvas.drawText("Xv: " + velocity, 1 + itemW * 3, base, mTextPaint);
|
||||
|
||||
canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint);
|
||||
velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getYVelocity() * 1000);
|
||||
canvas.drawText("Yv: " + velocity, 1 + itemW * 4, base, mTextPaint);
|
||||
|
||||
canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint);
|
||||
canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCurPressure * itemW) - 1,
|
||||
bottom, mTextLevelPaint);
|
||||
canvas.drawText("Prs: " + String.format("%.2f", ps.mCurPressure), 1 + itemW * 5,
|
||||
base, mTextPaint);
|
||||
|
||||
canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint);
|
||||
canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCurSize * itemW) - 1,
|
||||
bottom, mTextLevelPaint);
|
||||
canvas.drawText("Size: " + String.format("%.2f", ps.mCurSize), 1 + itemW * 6,
|
||||
base, mTextPaint);
|
||||
}
|
||||
|
||||
if (mCurDown) {
|
||||
canvas.drawLine(0, (int)mCurY, getWidth(), (int)mCurY, mTargetPaint);
|
||||
canvas.drawLine((int)mCurX, 0, (int)mCurX, getHeight(), mTargetPaint);
|
||||
int pressureLevel = (int)(mCurPressure*255);
|
||||
mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel);
|
||||
canvas.drawPoint(mCurX, mCurY, mPaint);
|
||||
canvas.drawCircle(mCurX, mCurY, mCurWidth, mPaint);
|
||||
for (int p=0; p<NP; p++) {
|
||||
final PointerState ps = mPointers.get(p);
|
||||
|
||||
if (mCurDown && ps.mCurDown) {
|
||||
canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint);
|
||||
canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint);
|
||||
int pressureLevel = (int)(ps.mCurPressure*255);
|
||||
mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel);
|
||||
canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint);
|
||||
canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint);
|
||||
}
|
||||
}
|
||||
|
||||
for (int p=0; p<NP; p++) {
|
||||
final PointerState ps = mPointers.get(p);
|
||||
|
||||
final int N = ps.mXs.size();
|
||||
float lastX=0, lastY=0;
|
||||
boolean haveLast = false;
|
||||
boolean drawn = false;
|
||||
mPaint.setARGB(255, 128, 255, 255);
|
||||
for (int i=0; i<N; i++) {
|
||||
float x = ps.mXs.get(i);
|
||||
float y = ps.mYs.get(i);
|
||||
if (Float.isNaN(x)) {
|
||||
haveLast = false;
|
||||
continue;
|
||||
}
|
||||
if (haveLast) {
|
||||
canvas.drawLine(lastX, lastY, x, y, mPathPaint);
|
||||
canvas.drawPoint(lastX, lastY, mPaint);
|
||||
drawn = true;
|
||||
}
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
haveLast = true;
|
||||
}
|
||||
|
||||
if (drawn) {
|
||||
if (ps.mVelocity != null) {
|
||||
mPaint.setARGB(255, 255, 64, 128);
|
||||
float xVel = ps.mVelocity.getXVelocity() * (1000/60);
|
||||
float yVel = ps.mVelocity.getYVelocity() * (1000/60);
|
||||
canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint);
|
||||
} else {
|
||||
canvas.drawPoint(lastX, lastY, mPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
int action = event.getAction();
|
||||
|
||||
//Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action)
|
||||
// + " pointers=" + event.getPointerCount());
|
||||
|
||||
int NP = mPointers.size();
|
||||
|
||||
//mRect.set(0, 0, getWidth(), mHeaderBottom+1);
|
||||
//invalidate(mRect);
|
||||
//if (mCurDown) {
|
||||
@@ -164,26 +244,91 @@ public class PointerLocation extends Activity {
|
||||
// mRect.setEmpty();
|
||||
//}
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
mXs.clear();
|
||||
mYs.clear();
|
||||
mVelocity = VelocityTracker.obtain();
|
||||
for (int p=0; p<NP; p++) {
|
||||
final PointerState ps = mPointers.get(p);
|
||||
ps.mXs.clear();
|
||||
ps.mYs.clear();
|
||||
ps.mVelocity = VelocityTracker.obtain();
|
||||
ps.mCurDown = false;
|
||||
}
|
||||
mPointers.get(0).mCurDown = true;
|
||||
mMaxNumPointers = 0;
|
||||
Log.i("Pointer", "Pointer 1: DOWN");
|
||||
}
|
||||
mVelocity.addMovement(event);
|
||||
mVelocity.computeCurrentVelocity(1);
|
||||
final int N = event.getHistorySize();
|
||||
for (int i=0; i<N; i++) {
|
||||
mXs.add(event.getHistoricalX(i));
|
||||
mYs.add(event.getHistoricalY(i));
|
||||
|
||||
if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
|
||||
final int id = (action&MotionEvent.ACTION_POINTER_ID_MASK)
|
||||
>> MotionEvent.ACTION_POINTER_ID_SHIFT;
|
||||
while (NP <= id) {
|
||||
PointerState ps = new PointerState();
|
||||
ps.mVelocity = VelocityTracker.obtain();
|
||||
mPointers.add(ps);
|
||||
NP++;
|
||||
}
|
||||
final PointerState ps = mPointers.get(id);
|
||||
ps.mVelocity = VelocityTracker.obtain();
|
||||
ps.mCurDown = true;
|
||||
Log.i("Pointer", "Pointer " + (id+1) + ": DOWN");
|
||||
}
|
||||
mXs.add(event.getX());
|
||||
mYs.add(event.getY());
|
||||
mCurDown = action == MotionEvent.ACTION_DOWN
|
||||
|| action == MotionEvent.ACTION_MOVE;
|
||||
mCurX = (int)event.getX();
|
||||
mCurY = (int)event.getY();
|
||||
mCurPressure = event.getPressure();
|
||||
mCurSize = event.getSize();
|
||||
mCurWidth = (int)(mCurSize*(getWidth()/3));
|
||||
|
||||
final int NI = event.getPointerCount();
|
||||
|
||||
mCurDown = action != MotionEvent.ACTION_UP
|
||||
&& action != MotionEvent.ACTION_CANCEL;
|
||||
mCurNumPointers = mCurDown ? NI : 0;
|
||||
if (mMaxNumPointers < mCurNumPointers) {
|
||||
mMaxNumPointers = mCurNumPointers;
|
||||
}
|
||||
|
||||
for (int i=0; i<NI; i++) {
|
||||
final PointerState ps = mPointers.get(event.getPointerId(i));
|
||||
ps.mVelocity.addMovement(event);
|
||||
ps.mVelocity.computeCurrentVelocity(1);
|
||||
final int N = event.getHistorySize();
|
||||
for (int j=0; j<N; j++) {
|
||||
Log.i("Pointer", "Pointer " + (i+1) + ": ("
|
||||
+ event.getHistoricalX(i, j)
|
||||
+ ", " + event.getHistoricalY(i, j) + ")"
|
||||
+ " Prs=" + event.getHistoricalPressure(i, j)
|
||||
+ " Size=" + event.getHistoricalSize(i, j));
|
||||
ps.mXs.add(event.getHistoricalX(i, j));
|
||||
ps.mYs.add(event.getHistoricalY(i, j));
|
||||
}
|
||||
Log.i("Pointer", "Pointer " + (i+1) + ": ("
|
||||
+ event.getX(i) + ", " + event.getY(i) + ")"
|
||||
+ " Prs=" + event.getPressure(i)
|
||||
+ " Size=" + event.getSize(i));
|
||||
ps.mXs.add(event.getX(i));
|
||||
ps.mYs.add(event.getY(i));
|
||||
ps.mCurX = (int)event.getX(i);
|
||||
ps.mCurY = (int)event.getY(i);
|
||||
//Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX
|
||||
// + "," + ps.mCurY + ")");
|
||||
ps.mCurPressure = event.getPressure(i);
|
||||
ps.mCurSize = event.getSize(i);
|
||||
ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3));
|
||||
}
|
||||
|
||||
if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) {
|
||||
final int id = (action&MotionEvent.ACTION_POINTER_ID_MASK)
|
||||
>> MotionEvent.ACTION_POINTER_ID_SHIFT;
|
||||
final PointerState ps = mPointers.get(id);
|
||||
ps.mXs.add(Float.NaN);
|
||||
ps.mYs.add(Float.NaN);
|
||||
ps.mCurDown = false;
|
||||
Log.i("Pointer", "Pointer " + (id+1) + ": UP");
|
||||
}
|
||||
|
||||
if (action == MotionEvent.ACTION_UP) {
|
||||
for (int i=0; i<NI; i++) {
|
||||
final PointerState ps = mPointers.get(event.getPointerId(i));
|
||||
if (ps.mCurDown) {
|
||||
ps.mCurDown = false;
|
||||
Log.i("Pointer", "Pointer " + (i+1) + ": UP");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (mCurDown) {
|
||||
// mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
|
||||
// mCurX+mCurWidth+3, mCurY+mCurWidth+3);
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.development;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Dialog;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.pm.RegisteredServicesCache;
|
||||
import android.content.pm.RegisteredServicesCacheListener;
|
||||
import android.content.SyncAdapterType;
|
||||
import android.content.ISyncAdapter;
|
||||
import android.content.ISyncContext;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.ComponentName;
|
||||
import android.content.SyncResult;
|
||||
import android.content.Intent;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ListView;
|
||||
import android.util.AttributeSet;
|
||||
import android.provider.Settings;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.view.View;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class SyncAdapterDriver extends Activity
|
||||
implements RegisteredServicesCacheListener<SyncAdapterType>,
|
||||
AdapterView.OnItemClickListener {
|
||||
private Spinner mSyncAdapterSpinner;
|
||||
|
||||
private Button mBindButton;
|
||||
private Button mUnbindButton;
|
||||
private TextView mBoundAdapterTextView;
|
||||
private Button mStartSyncButton;
|
||||
private Button mCancelSyncButton;
|
||||
private TextView mStatusTextView;
|
||||
private Object[] mSyncAdapters;
|
||||
private SyncAdaptersCache mSyncAdaptersCache;
|
||||
private final Object mSyncAdaptersLock = new Object();
|
||||
|
||||
private static final int DIALOG_ID_PICK_ACCOUNT = 1;
|
||||
private ListView mAccountPickerView = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mSyncAdaptersCache = new SyncAdaptersCache(this);
|
||||
setContentView(R.layout.sync_adapter_driver);
|
||||
|
||||
mSyncAdapterSpinner = (Spinner) findViewById(R.id.sync_adapters_spinner);
|
||||
mBindButton = (Button) findViewById(R.id.bind_button);
|
||||
mUnbindButton = (Button) findViewById(R.id.unbind_button);
|
||||
mBoundAdapterTextView = (TextView) findViewById(R.id.bound_adapter_text_view);
|
||||
|
||||
mStartSyncButton = (Button) findViewById(R.id.start_sync_button);
|
||||
mCancelSyncButton = (Button) findViewById(R.id.cancel_sync_button);
|
||||
|
||||
mStatusTextView = (TextView) findViewById(R.id.status_text_view);
|
||||
|
||||
getSyncAdapters();
|
||||
mSyncAdaptersCache.setListener(this, null /* Handler */);
|
||||
}
|
||||
|
||||
protected void onDestroy() {
|
||||
mSyncAdaptersCache.close();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private void getSyncAdapters() {
|
||||
Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> all =
|
||||
mSyncAdaptersCache.getAllServices();
|
||||
synchronized (mSyncAdaptersLock) {
|
||||
mSyncAdapters = new Object[all.size()];
|
||||
String[] names = new String[mSyncAdapters.length];
|
||||
int i = 0;
|
||||
for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> item : all) {
|
||||
mSyncAdapters[i] = item;
|
||||
names[i] = item.type.authority + " - " + item.type.accountType;
|
||||
i++;
|
||||
}
|
||||
|
||||
ArrayAdapter<String> adapter =
|
||||
new ArrayAdapter<String>(this,
|
||||
R.layout.sync_adapter_item, names);
|
||||
mSyncAdapterSpinner.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
void updateUi() {
|
||||
boolean isBound;
|
||||
boolean hasServiceConnection;
|
||||
synchronized (mServiceConnectionLock) {
|
||||
hasServiceConnection = mActiveServiceConnection != null;
|
||||
isBound = hasServiceConnection && mActiveServiceConnection.mBoundSyncAdapter != null;
|
||||
}
|
||||
mStartSyncButton.setEnabled(isBound);
|
||||
mCancelSyncButton.setEnabled(isBound);
|
||||
mBindButton.setEnabled(!hasServiceConnection);
|
||||
mUnbindButton.setEnabled(hasServiceConnection);
|
||||
}
|
||||
|
||||
public void startSyncSelected(View view) {
|
||||
synchronized (mServiceConnectionLock) {
|
||||
ISyncAdapter syncAdapter = null;
|
||||
if (mActiveServiceConnection != null) {
|
||||
syncAdapter = mActiveServiceConnection.mBoundSyncAdapter;
|
||||
}
|
||||
|
||||
if (syncAdapter != null) {
|
||||
removeDialog(DIALOG_ID_PICK_ACCOUNT);
|
||||
|
||||
mAccountPickerView = (ListView) LayoutInflater.from(this).inflate(
|
||||
R.layout.account_list_view, null);
|
||||
mAccountPickerView.setOnItemClickListener(this);
|
||||
Account accounts[] = AccountManager.get(this).getAccountsByType(
|
||||
mActiveServiceConnection.mSyncAdapter.type.accountType);
|
||||
String[] accountNames = new String[accounts.length];
|
||||
for (int i = 0; i < accounts.length; i++) {
|
||||
accountNames[i] = accounts[i].name;
|
||||
}
|
||||
ArrayAdapter<String> adapter =
|
||||
new ArrayAdapter<String>(SyncAdapterDriver.this,
|
||||
android.R.layout.simple_list_item_1, accountNames);
|
||||
mAccountPickerView.setAdapter(adapter);
|
||||
|
||||
showDialog(DIALOG_ID_PICK_ACCOUNT);
|
||||
}
|
||||
}
|
||||
updateUi();
|
||||
}
|
||||
|
||||
private void startSync(String accountName) {
|
||||
synchronized (mServiceConnectionLock) {
|
||||
ISyncAdapter syncAdapter = null;
|
||||
if (mActiveServiceConnection != null) {
|
||||
syncAdapter = mActiveServiceConnection.mBoundSyncAdapter;
|
||||
}
|
||||
|
||||
if (syncAdapter != null) {
|
||||
try {
|
||||
mStatusTextView.setText(
|
||||
getString(R.string.status_starting_sync_format, accountName));
|
||||
Account account = new Account(accountName,
|
||||
mActiveServiceConnection.mSyncAdapter.type.accountType);
|
||||
syncAdapter.startSync(mActiveServiceConnection,
|
||||
mActiveServiceConnection.mSyncAdapter.type.authority,
|
||||
account, new Bundle());
|
||||
} catch (RemoteException e) {
|
||||
mStatusTextView.setText(
|
||||
getString(R.string.status_remote_exception_while_starting_sync));
|
||||
}
|
||||
}
|
||||
}
|
||||
updateUi();
|
||||
}
|
||||
|
||||
public void cancelSync(View view) {
|
||||
synchronized (mServiceConnectionLock) {
|
||||
ISyncAdapter syncAdapter = null;
|
||||
if (mActiveServiceConnection != null) {
|
||||
syncAdapter = mActiveServiceConnection.mBoundSyncAdapter;
|
||||
}
|
||||
|
||||
if (syncAdapter != null) {
|
||||
try {
|
||||
mStatusTextView.setText(getString(R.string.status_canceled_sync));
|
||||
syncAdapter.cancelSync(mActiveServiceConnection);
|
||||
} catch (RemoteException e) {
|
||||
mStatusTextView.setText(
|
||||
getString(R.string.status_remote_exception_while_canceling_sync));
|
||||
}
|
||||
}
|
||||
}
|
||||
updateUi();
|
||||
}
|
||||
|
||||
public void onServiceChanged(SyncAdapterType type, boolean removed) {
|
||||
getSyncAdapters();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(final int id) {
|
||||
if (id == DIALOG_ID_PICK_ACCOUNT) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(R.string.select_account_to_sync);
|
||||
builder.setInverseBackgroundForced(true);
|
||||
builder.setView(mAccountPickerView);
|
||||
return builder.create();
|
||||
}
|
||||
return super.onCreateDialog(id);
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
TextView item = (TextView) view;
|
||||
final String accountName = item.getText().toString();
|
||||
dismissDialog(DIALOG_ID_PICK_ACCOUNT);
|
||||
startSync(accountName);
|
||||
}
|
||||
|
||||
private class MyServiceConnection extends ISyncContext.Stub implements ServiceConnection {
|
||||
private volatile ISyncAdapter mBoundSyncAdapter;
|
||||
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> mSyncAdapter;
|
||||
|
||||
public MyServiceConnection(
|
||||
RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter) {
|
||||
mSyncAdapter = syncAdapter;
|
||||
}
|
||||
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mBoundSyncAdapter = ISyncAdapter.Stub.asInterface(service);
|
||||
final SyncAdapterType type = mActiveServiceConnection.mSyncAdapter.type;
|
||||
mBoundAdapterTextView.setText(getString(R.string.binding_connected_format,
|
||||
type.authority, type.accountType));
|
||||
updateUi();
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mBoundAdapterTextView.setText(getString(R.string.binding_not_connected));
|
||||
mBoundSyncAdapter = null;
|
||||
updateUi();
|
||||
}
|
||||
|
||||
public void sendHeartbeat() {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
uiThreadSendHeartbeat();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void uiThreadSendHeartbeat() {
|
||||
mStatusTextView.setText(getString(R.string.status_received_heartbeat));
|
||||
}
|
||||
|
||||
public void uiThreadOnFinished(SyncResult result) {
|
||||
if (result.hasError()) {
|
||||
mStatusTextView.setText(
|
||||
getString(R.string.status_sync_failed_format, result.toString()));
|
||||
} else {
|
||||
mStatusTextView.setText(
|
||||
getString(R.string.status_sync_succeeded_format, result.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
public void onFinished(final SyncResult result) throws RemoteException {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
uiThreadOnFinished(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
final Object mServiceConnectionLock = new Object();
|
||||
MyServiceConnection mActiveServiceConnection;
|
||||
|
||||
public void initiateBind(View view) {
|
||||
synchronized (mServiceConnectionLock) {
|
||||
if (mActiveServiceConnection != null) {
|
||||
mStatusTextView.setText(getString(R.string.status_already_bound));
|
||||
return;
|
||||
}
|
||||
|
||||
RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter =
|
||||
getSelectedSyncAdapter();
|
||||
if (syncAdapter == null) {
|
||||
mStatusTextView.setText(getString(R.string.status_sync_adapter_not_selected));
|
||||
return;
|
||||
}
|
||||
|
||||
mActiveServiceConnection = new MyServiceConnection(syncAdapter);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction("android.content.SyncAdapter");
|
||||
intent.setComponent(syncAdapter.componentName);
|
||||
intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
|
||||
com.android.internal.R.string.sync_binding_label);
|
||||
intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
|
||||
this, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0));
|
||||
if (!bindService(intent, mActiveServiceConnection, Context.BIND_AUTO_CREATE)) {
|
||||
mBoundAdapterTextView.setText(getString(R.string.binding_bind_failed));
|
||||
mActiveServiceConnection = null;
|
||||
return;
|
||||
}
|
||||
mBoundAdapterTextView.setText(getString(R.string.binding_waiting_for_connection));
|
||||
}
|
||||
updateUi();
|
||||
}
|
||||
|
||||
public void initiateUnbind(View view) {
|
||||
synchronized (mServiceConnectionLock) {
|
||||
if (mActiveServiceConnection == null) {
|
||||
return;
|
||||
}
|
||||
mBoundAdapterTextView.setText("");
|
||||
unbindService(mActiveServiceConnection);
|
||||
mActiveServiceConnection = null;
|
||||
}
|
||||
updateUi();
|
||||
}
|
||||
|
||||
private RegisteredServicesCache.ServiceInfo<SyncAdapterType> getSelectedSyncAdapter() {
|
||||
synchronized (mSyncAdaptersLock) {
|
||||
final int position = mSyncAdapterSpinner.getSelectedItemPosition();
|
||||
if (position == AdapterView.INVALID_POSITION) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
//noinspection unchecked
|
||||
return (RegisteredServicesCache.ServiceInfo<SyncAdapterType>)
|
||||
mSyncAdapters[position];
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class SyncAdaptersCache extends RegisteredServicesCache<SyncAdapterType> {
|
||||
private static final String SERVICE_INTERFACE = "android.content.SyncAdapter";
|
||||
private static final String SERVICE_META_DATA = "android.content.SyncAdapter";
|
||||
private static final String ATTRIBUTES_NAME = "sync-adapter";
|
||||
|
||||
SyncAdaptersCache(Context context) {
|
||||
super(context, SERVICE_INTERFACE, SERVICE_META_DATA, ATTRIBUTES_NAME, null);
|
||||
}
|
||||
|
||||
public SyncAdapterType parseServiceAttributes(String packageName, AttributeSet attrs) {
|
||||
TypedArray sa = mContext.getResources().obtainAttributes(attrs,
|
||||
com.android.internal.R.styleable.SyncAdapter);
|
||||
try {
|
||||
final String authority =
|
||||
sa.getString(com.android.internal.R.styleable.SyncAdapter_contentAuthority);
|
||||
final String accountType =
|
||||
sa.getString(com.android.internal.R.styleable.SyncAdapter_accountType);
|
||||
if (authority == null || accountType == null) {
|
||||
return null;
|
||||
}
|
||||
final boolean userVisible = sa.getBoolean(
|
||||
com.android.internal.R.styleable.SyncAdapter_userVisible, true);
|
||||
final boolean supportsUploading = sa.getBoolean(
|
||||
com.android.internal.R.styleable.SyncAdapter_supportsUploading, true);
|
||||
return new SyncAdapterType(authority, accountType, userVisible, supportsUploading);
|
||||
} finally {
|
||||
sa.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user