UI refresh on bluetooth list page

- xml layout clean up
- add "Device name" preference, tapping will bring up rename dialog
- Remove tap target from original device_name pref

Merged-In: I6e9764dbb6c51f94be6d6a61d5a6401141407409
Change-Id: I9cb67cc557a9b932d7cf795a8d4a6fb5215c4365
Fix: 62890841
Fix: 62891178
Test: robotests
This commit is contained in:
Fan Zhang
2017-07-12 10:18:54 -07:00
parent d1bac25518
commit 7b9568c10d
9 changed files with 205 additions and 76 deletions

View File

@@ -4,9 +4,9 @@
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.
@@ -14,20 +14,20 @@
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:paddingTop="16dp"
android:paddingBottom="12dp"
>
android:paddingBottom="12dp">
<EditText
android:id="@+id/edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textCapSentences"
android:maxLength="50"
android:singleLine="true"
/>
android:singleLine="true" />
</LinearLayout>

View File

@@ -16,22 +16,28 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
android:title="@string/bluetooth_settings">
<Preference
android:key="device_name"/>
android:key="device_name" />
<PreferenceCategory
android:key="paired_devices"
android:title="@string/bluetooth_paired_device_title"/>
android:title="@string/bluetooth_paired_device_title" />
<com.android.settings.DividerPreference
android:key="bt_received_files"
android:title="@string/bluetooth_show_received_files"
settings:allowDividerAbove="true"
settings:allowDividerBelow="true"/>
<PreferenceCategory>
<com.android.settingslib.widget.FooterPreference/>
<Preference
android:key="bt_rename_device"
android:title="@string/bluetooth_device_name"
android:summary="@string/summary_placeholder" />
<Preference
android:key="bt_received_files"
android:title="@string/bluetooth_show_received_files" />
</PreferenceCategory>
<com.android.settingslib.widget.FooterPreference />
</PreferenceScreen>

View File

@@ -16,12 +16,12 @@
package com.android.settings.bluetooth;
import android.app.Fragment;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.Spannable;
@@ -30,7 +30,6 @@ import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
@@ -48,15 +47,15 @@ public class BluetoothDeviceNamePreferenceController extends PreferenceControlle
private static final String TAG = "BluetoothNamePrefCtrl";
public static final String KEY_DEVICE_NAME = "device_name";
private int mAccentColor;
private Fragment mFragment;
private final int mAccentColor;
private LocalBluetoothManager mLocalManager;
private LocalBluetoothAdapter mLocalAdapter;
private Preference mPreference;
public BluetoothDeviceNamePreferenceController(Context context, Fragment fragment,
Lifecycle lifecycle) {
this(context, fragment, (LocalBluetoothAdapter) null);
public BluetoothDeviceNamePreferenceController(Context context, Lifecycle lifecycle) {
this(context, (LocalBluetoothAdapter) null);
mLocalManager = Utils.getLocalBtManager(context);
if (mLocalManager == null) {
@@ -68,17 +67,16 @@ public class BluetoothDeviceNamePreferenceController extends PreferenceControlle
}
@VisibleForTesting
BluetoothDeviceNamePreferenceController(Context context, Fragment fragment,
LocalBluetoothAdapter localAdapter) {
BluetoothDeviceNamePreferenceController(Context context, LocalBluetoothAdapter localAdapter) {
super(context);
mAccentColor = com.android.settingslib.Utils.getColorAccent(context);
mFragment = fragment;
mLocalAdapter = localAdapter;
}
@Override
public void displayPreference(PreferenceScreen screen) {
mPreference = screen.findPreference(KEY_DEVICE_NAME);
super.displayPreference(screen);
}
@Override
@@ -107,22 +105,11 @@ public class BluetoothDeviceNamePreferenceController extends PreferenceControlle
updateDeviceName(preference, mLocalAdapter.getName());
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (KEY_DEVICE_NAME.equals(preference.getKey())) {
LocalDeviceNameDialogFragment.newInstance()
.show(mFragment.getFragmentManager(), LocalDeviceNameDialogFragment.TAG);
return true;
}
return false;
}
/**
* Create preference to show bluetooth device name
*
* @param screen to add the preference in
* @param order to decide position of the preference
* @param order to decide position of the preference
* @return bluetooth preference that created in this method
*/
public Preference createBluetoothDeviceNamePreference(PreferenceScreen screen, int order) {
@@ -140,7 +127,7 @@ public class BluetoothDeviceNamePreferenceController extends PreferenceControlle
* @param preference to set the summary for
* @param deviceName bluetooth device name to show in the summary
*/
public void updateDeviceName(final Preference preference, final String deviceName) {
protected void updateDeviceName(final Preference preference, final String deviceName) {
if (deviceName == null) {
// TODO: show error message in preference subtitle
return;

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.bluetooth;
import android.app.Fragment;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class BluetoothDeviceRenamePreferenceController extends
BluetoothDeviceNamePreferenceController {
public static final String PREF_KEY = "bt_rename_device";
private final Fragment mFragment;
public BluetoothDeviceRenamePreferenceController(Context context, Fragment fragment,
Lifecycle lifecycle) {
super(context, lifecycle);
mFragment = fragment;
}
@VisibleForTesting
BluetoothDeviceRenamePreferenceController(Context context, Fragment fragment,
LocalBluetoothAdapter localAdapter) {
super(context, localAdapter);
mFragment = fragment;
}
@Override
public String getPreferenceKey() {
return PREF_KEY;
}
@Override
protected void updateDeviceName(final Preference preference, final String deviceName) {
preference.setSummary(deviceName);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (PREF_KEY.equals(preference.getKey())) {
LocalDeviceNameDialogFragment.newInstance()
.show(mFragment.getFragmentManager(), LocalDeviceNameDialogFragment.TAG);
return true;
}
return false;
}
}

View File

@@ -24,6 +24,7 @@ import android.content.res.Configuration;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -111,6 +112,9 @@ abstract class BluetoothNameDialogFragment extends InstrumentedDialogFragment
new Utf8ByteLengthFilter(BLUETOOTH_NAME_MAX_LENGTH_BYTES)
});
mDeviceNameView.setText(deviceName); // set initial value before adding listener
if (!TextUtils.isEmpty(deviceName)) {
mDeviceNameView.setSelection(deviceName.length());
}
mDeviceNameView.addTextChangedListener(this);
mDeviceNameView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override

View File

@@ -186,7 +186,7 @@ public class BluetoothPairingDetail extends DeviceListPreferenceFragment impleme
protected List<PreferenceController> getPreferenceControllers(Context context) {
List<PreferenceController> controllers = new ArrayList<>();
mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context,
this, getLifecycle());
getLifecycle());
controllers.add(mDeviceNamePrefController);
return controllers;

View File

@@ -22,7 +22,6 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.SystemProperties;
@@ -55,6 +54,8 @@ import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.FooterPreference;
import java.util.ArrayList;
@@ -66,7 +67,6 @@ import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
/**
* BluetoothSettings is the Settings screen for Bluetooth configuration and
* connection management.
*
*/
public class BluetoothSettings extends DeviceListPreferenceFragment implements Indexable {
private static final String TAG = "BluetoothSettings";
@@ -87,7 +87,6 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
private SwitchBar mSwitchBar;
private final IntentFilter mIntentFilter;
private BluetoothDeviceNamePreferenceController mDeviceNamePrefController;
@VisibleForTesting
BluetoothPairingPreferenceController mPairingPrefController;
@@ -98,7 +97,6 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
public BluetoothSettings() {
super(DISALLOW_CONFIG_BLUETOOTH);
mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
}
@Override
@@ -356,14 +354,15 @@ public class BluetoothSettings extends DeviceListPreferenceFragment implements I
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
List<PreferenceController> controllers = new ArrayList<>();
mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context,
this, getLifecycle());
final List<PreferenceController> controllers = new ArrayList<>();
final Lifecycle lifecycle = getLifecycle();
mDeviceNamePrefController = new BluetoothDeviceNamePreferenceController(context, lifecycle);
mPairingPrefController = new BluetoothPairingPreferenceController(context, this,
(SettingsActivity) getActivity());
controllers.add(mDeviceNamePrefController);
controllers.add(mPairingPrefController);
controllers.add(new BluetoothFilesPreferenceController(context));
controllers.add(new BluetoothDeviceRenamePreferenceController(context, this, lifecycle));
return controllers;
}

View File

@@ -17,33 +17,25 @@
package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@@ -56,17 +48,9 @@ public class BluetoothDeviceNamePreferenceControllerTest {
private static final int ORDER = 1;
private Context mContext;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Fragment mFragment;
@Mock
private Lifecycle mLifecycle;
@Mock
private LocalBluetoothAdapter mLocalAdapter;
@Mock
private FragmentManager mFragmentManager;
@Mock
private FragmentTransaction mFragmentTransaction;
@Mock
private PreferenceScreen mPreferenceScreen;
private Preference mPreference;
@@ -82,7 +66,7 @@ public class BluetoothDeviceNamePreferenceControllerTest {
mPreference = new Preference(mContext);
mPreference.setKey(BluetoothDeviceNamePreferenceController.KEY_DEVICE_NAME);
mController = new BluetoothDeviceNamePreferenceController(
mContext, mFragment, mLocalAdapter);
mContext, mLocalAdapter);
}
@Test
@@ -124,15 +108,4 @@ public class BluetoothDeviceNamePreferenceControllerTest {
mController.onStop();
verify(mContext).unregisterReceiver(mController.mReceiver);
}
@Test
public void testHandlePreferenceTreeClick_startDialogFragment() {
when(mFragment.getFragmentManager().beginTransaction()).thenReturn(mFragmentTransaction);
mController.handlePreferenceTreeClick(mPreference);
verify(mFragmentTransaction).add(any(), anyString());
verify(mFragmentTransaction).commit();
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.support.v7.preference.Preference;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class BluetoothDeviceRenamePreferenceControllerTest {
private static final String DEVICE_NAME = "Nightshade";
@Mock
private LocalBluetoothAdapter mLocalAdapter;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Fragment mFragment;
@Mock
private FragmentManager mFragmentManager;
@Mock
private FragmentTransaction mFragmentTransaction;
private Context mContext;
private Preference mPreference;
private BluetoothDeviceRenamePreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mPreference = new Preference(mContext);
mPreference.setKey(BluetoothDeviceRenamePreferenceController.PREF_KEY);
mController = new BluetoothDeviceRenamePreferenceController(
mContext, mFragment, mLocalAdapter);
}
@Test
public void testUpdateDeviceName_showSummaryWithDeviceName() {
mController.updateDeviceName(mPreference, DEVICE_NAME);
final CharSequence summary = mPreference.getSummary();
assertThat(summary.toString()).isEqualTo(DEVICE_NAME);
}
@Test
public void testHandlePreferenceTreeClick_startDialogFragment() {
when(mFragment.getFragmentManager().beginTransaction()).thenReturn(mFragmentTransaction);
mController.handlePreferenceTreeClick(mPreference);
verify(mFragmentTransaction).add(any(), anyString());
verify(mFragmentTransaction).commit();
}
}