ParanoidSystemUI: Implement Bluetooth dialog
Based on Internet dialog code. Change-Id: Iff63a49ff6a49c535b63a430bee8d7c55e78cbcc Signed-off-by: Mesquita <mesquita@aospa.co> Signed-off-by: Omkar Chandorkar <gotenksIN@aospa.co>
This commit is contained in:
parent
7eaccb6268
commit
715fa3012f
|
@ -0,0 +1,226 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2021 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"
|
||||||
|
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||||
|
android:id="@+id/bluetooth_dialog"
|
||||||
|
android:layout_width="@dimen/large_dialog_width"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/Widget.SliceView.Panel"
|
||||||
|
android:gravity="center_vertical|center_horizontal"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:layout_marginBottom="@dimen/internet_dialog_network_layout_margin"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bluetooth_dialog_title"
|
||||||
|
android:text="@string/quick_settings_bluetooth_label"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical|center_horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/TextAppearance.InternetDialog"
|
||||||
|
android:textSize="24sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bluetooth_dialog_subtitle"
|
||||||
|
android:gravity="center_vertical|center_horizontal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textAppearance="@style/TextAppearance.InternetDialog.Secondary"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="@dimen/internet_dialog_progress_bar_width"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginBottom="@dimen/internet_dialog_network_layout_margin"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/divider"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:layout_gravity="center_vertical|center_horizontal"
|
||||||
|
android:background="?androidprv:attr/colorSurfaceVariant"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/bluetooth_progress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:visibility="gone"
|
||||||
|
style="@style/TrimmedHorizontalProgressBar"
|
||||||
|
android:indeterminate="true"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/turn_on_bluetooth_layout"
|
||||||
|
style="@style/InternetDialog.Network"
|
||||||
|
android:layout_height="@dimen/internet_dialog_wifi_network_height"
|
||||||
|
android:gravity="center"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:clickable="false">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bluetooth_toggle_title"
|
||||||
|
android:text="@string/turn_on_bluetooth"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
|
android:textAppearance="@style/TextAppearance.InternetDialog"
|
||||||
|
android:textSize="16sp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="@dimen/settingslib_switch_track_width"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:layout_marginBottom="10dp">
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/bluetooth_toggle"
|
||||||
|
android:contentDescription="@string/turn_on_bluetooth"
|
||||||
|
android:switchMinWidth="@dimen/settingslib_switch_track_width"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_width="@dimen/settingslib_switch_track_width"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:track="@drawable/settingslib_track_selector"
|
||||||
|
android:thumb="@drawable/settingslib_thumb_selector"
|
||||||
|
android:theme="@style/MainSwitch.Settingslib"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/scroll_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/scroll_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/bluetooth_list_layout"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
android:nestedScrollingEnabled="false"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/see_all_layout"
|
||||||
|
style="@style/InternetDialog.Network"
|
||||||
|
android:layout_height="56dp"
|
||||||
|
android:paddingStart="20dp">
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:clickable="false"
|
||||||
|
android:layout_gravity="center_vertical|start">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/arrow_forward"
|
||||||
|
android:src="@drawable/ic_arrow_forward"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:clickable="false"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="@dimen/internet_dialog_network_layout_margin">
|
||||||
|
<TextView
|
||||||
|
android:text="@string/see_all_networks"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="start|center_vertical"
|
||||||
|
android:textAppearance="@style/TextAppearance.InternetDialog"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/button_layout"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginStart="@dimen/dialog_side_padding"
|
||||||
|
android:layout_marginEnd="@dimen/dialog_side_padding"
|
||||||
|
android:layout_marginBottom="@dimen/dialog_bottom_padding"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/settings_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/controls_media_settings_button"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
style="@style/Widget.Dialog.Button.BorderButton"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_gravity="end|center_vertical">
|
||||||
|
<Button
|
||||||
|
android:id="@+id/done_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/inline_done_button"
|
||||||
|
style="@style/Widget.Dialog.Button"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,78 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2021 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:id="@+id/bluetooth_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/bluetooth_list"
|
||||||
|
style="@style/InternetDialog.Network"
|
||||||
|
android:layout_height="@dimen/internet_dialog_wifi_network_height"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingEnd="24dp">
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:clickable="false"
|
||||||
|
android:layout_gravity="center_vertical|start">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/bluetooth_icon"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerInside"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/bluetooth_device_layout"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:clickable="false"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="start|center_vertical">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bluetooth_title"
|
||||||
|
style="@style/InternetDialog.NetworkTitle"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:maxLines="1"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bluetooth_summary"
|
||||||
|
style="@style/InternetDialog.NetworkSummary"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="false"
|
||||||
|
android:layout_gravity="end|center_vertical">
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/bluetooth_end_icon"
|
||||||
|
android:src="@drawable/ic_settings_24dp"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
|
@ -49,4 +49,9 @@
|
||||||
<string name="quick_settings_powershare_off_low_battery_label">Battery Share off\nBattery too low</string>
|
<string name="quick_settings_powershare_off_low_battery_label">Battery Share off\nBattery too low</string>
|
||||||
<string name="quick_settings_powershare_enabled_label">Battery Share is enabled</string>
|
<string name="quick_settings_powershare_enabled_label">Battery Share is enabled</string>
|
||||||
|
|
||||||
|
<!-- Bluetooth dialog -->
|
||||||
|
<string name="turn_on_bluetooth">Bluetooth</string>
|
||||||
|
<string name="bluetooth_is_off">Bluetooth is off</string>
|
||||||
|
<string name="tap_a_device_to_connect">Tap a device to connect/disconnect</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -19,6 +19,7 @@ package co.aospa.systemui.qs.tileimpl;
|
||||||
import com.android.systemui.qs.tileimpl.QSTileImpl
|
import com.android.systemui.qs.tileimpl.QSTileImpl
|
||||||
|
|
||||||
import co.aospa.systemui.qs.tiles.AlwaysOnDisplayTile;
|
import co.aospa.systemui.qs.tiles.AlwaysOnDisplayTile;
|
||||||
|
import co.aospa.systemui.qs.tiles.BluetoothDialogTile;
|
||||||
import co.aospa.systemui.qs.tiles.CaffeineTile;
|
import co.aospa.systemui.qs.tiles.CaffeineTile;
|
||||||
import co.aospa.systemui.qs.tiles.DataSwitchTile;
|
import co.aospa.systemui.qs.tiles.DataSwitchTile;
|
||||||
import co.aospa.systemui.qs.tiles.DcDimmingTile;
|
import co.aospa.systemui.qs.tiles.DcDimmingTile;
|
||||||
|
@ -38,6 +39,12 @@ interface ParanoidQSModule {
|
||||||
@StringKey(AlwaysOnDisplayTile.TILE_SPEC)
|
@StringKey(AlwaysOnDisplayTile.TILE_SPEC)
|
||||||
fun bindAlwaysOnDisplayTile(alwaysOnDisplayTile: AlwaysOnDisplayTile): QSTileImpl<*>
|
fun bindAlwaysOnDisplayTile(alwaysOnDisplayTile: AlwaysOnDisplayTile): QSTileImpl<*>
|
||||||
|
|
||||||
|
/** Inject BluetoothDialogTile into tileMap in QSModule */
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@StringKey(BluetoothDialogTile.TILE_SPEC)
|
||||||
|
fun bindBluetoothDialogTile(bluetoothDialogTile: BluetoothDialogTile): QSTileImpl<*>
|
||||||
|
|
||||||
/** Inject CaffeineTile into tileMap in QSModule */
|
/** Inject CaffeineTile into tileMap in QSModule */
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 StatiXOS
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Changes from Qualcomm Innovation Center are provided under the following license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||||
|
*/
|
||||||
|
|
||||||
|
package co.aospa.systemui.qs.tiles;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.internal.logging.MetricsLogger;
|
||||||
|
|
||||||
|
import com.android.systemui.dagger.qualifiers.Background;
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.plugins.FalsingManager;
|
||||||
|
import com.android.systemui.plugins.qs.QSTile.BooleanState;
|
||||||
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
|
import com.android.systemui.qs.QSHost;
|
||||||
|
import com.android.systemui.qs.logging.QSLogger;
|
||||||
|
import com.android.systemui.qs.tiles.BluetoothTile;
|
||||||
|
import com.android.systemui.statusbar.policy.BluetoothController;
|
||||||
|
|
||||||
|
import co.aospa.systemui.qs.tiles.dialog.BluetoothDialogFactory;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class BluetoothDialogTile extends BluetoothTile {
|
||||||
|
|
||||||
|
public static final String TILE_SPEC = "bt";
|
||||||
|
|
||||||
|
private final Handler mHandler;
|
||||||
|
private final BluetoothDialogFactory mBluetoothDialogFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public BluetoothDialogTile(
|
||||||
|
QSHost host,
|
||||||
|
@Background Looper backgroundLooper,
|
||||||
|
@Main Handler mainHandler,
|
||||||
|
FalsingManager falsingManager,
|
||||||
|
MetricsLogger metricsLogger,
|
||||||
|
StatusBarStateController statusBarStateController,
|
||||||
|
ActivityStarter activityStarter,
|
||||||
|
QSLogger qsLogger,
|
||||||
|
BluetoothController bluetoothController,
|
||||||
|
BluetoothDialogFactory bluetoothDialogFactory
|
||||||
|
) {
|
||||||
|
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
|
||||||
|
statusBarStateController, activityStarter, qsLogger, bluetoothController);
|
||||||
|
mHandler = mainHandler;
|
||||||
|
mBluetoothDialogFactory = bluetoothDialogFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BooleanState newTileState() {
|
||||||
|
BooleanState s = new BooleanState();
|
||||||
|
s.forceExpandIcon = true;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void handleClick(@Nullable View view) {
|
||||||
|
mHandler.post(() -> mBluetoothDialogFactory.create(true, view));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,287 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
* (C) 2022 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Changes from Qualcomm Innovation Center are provided under the following license:
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||||
|
*/
|
||||||
|
|
||||||
|
package co.aospa.systemui.qs.tiles.dialog;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.text.Layout;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.Switch;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.MainThread;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
import androidx.annotation.WorkerThread;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.android.settingslib.Utils;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
import com.android.systemui.Prefs;
|
||||||
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||||
|
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||||
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
|
import com.android.systemui.dagger.qualifiers.Background;
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.plugins.ActivityStarter;
|
||||||
|
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
||||||
|
import com.android.systemui.statusbar.policy.BluetoothController;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog for bluetooth
|
||||||
|
*/
|
||||||
|
@SysUISingleton
|
||||||
|
public class BluetoothDialog extends SystemUIDialog implements Window.Callback {
|
||||||
|
private static final String TAG = "BluetoothDialog";
|
||||||
|
private static final boolean DEBUG = true;
|
||||||
|
|
||||||
|
public static final int MAX_DEVICES_COUNT = 4;
|
||||||
|
private static final String SAVED_DEVICES_INTENT = "android.settings.SAVED_DEVICES";
|
||||||
|
|
||||||
|
private BluetoothViewAdapter mAdapter;
|
||||||
|
private BluetoothController mBluetoothController;
|
||||||
|
private BluetoothDialogFactory mBluetoothDialogFactory;
|
||||||
|
private Context mContext;
|
||||||
|
private Handler mHandler;
|
||||||
|
private View mDialogView;
|
||||||
|
private TextView mBluetoothDialogTitle;
|
||||||
|
private TextView mBluetoothDialogSubTitle;
|
||||||
|
private TextView mBluetoothToggleText;
|
||||||
|
private Switch mBluetoothToggle;
|
||||||
|
private ProgressBar mProgressBar;
|
||||||
|
private View mDivider;
|
||||||
|
private LinearLayout mTurnOnLayout;
|
||||||
|
private LinearLayout mSeeAllLayout;
|
||||||
|
private RecyclerView mBluetoothRecyclerView;
|
||||||
|
private Button mDoneButton;
|
||||||
|
private Button mSettingsButton;
|
||||||
|
private DialogLaunchAnimator mDialogLaunchAnimator;
|
||||||
|
private ActivityStarter mActivityStarter;
|
||||||
|
|
||||||
|
private Drawable mBackgroundOn;
|
||||||
|
private Drawable mBackgroundOff;
|
||||||
|
|
||||||
|
private final BluetoothController.Callback mCallback = new BluetoothController.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onBluetoothStateChange(boolean enabled) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(TAG, "onBluetoothStateChange enabled=" + enabled);
|
||||||
|
}
|
||||||
|
mBluetoothToggle.setChecked(enabled);
|
||||||
|
mHandler.post(() -> updateDialog());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBluetoothDevicesChanged() {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.i(TAG, "onBluetoothDevicesChanged");
|
||||||
|
}
|
||||||
|
mHandler.post(() -> updateDialog());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public BluetoothDialog(Context context, BluetoothDialogFactory bluetoothDialogFactory,
|
||||||
|
boolean aboveStatusBar, @Main Handler handler, ActivityStarter activityStarter,
|
||||||
|
DialogLaunchAnimator dialogLaunchAnimator, BluetoothController bluetoothController) {
|
||||||
|
super(context);
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "Init BluetoothDialog");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the context that is wrapped with our theme.
|
||||||
|
mContext = getContext();
|
||||||
|
mHandler = handler;
|
||||||
|
mBluetoothDialogFactory = bluetoothDialogFactory;
|
||||||
|
mBluetoothController = bluetoothController;
|
||||||
|
mActivityStarter = activityStarter;
|
||||||
|
mDialogLaunchAnimator = dialogLaunchAnimator;
|
||||||
|
mAdapter = new BluetoothViewAdapter(this);
|
||||||
|
|
||||||
|
if (!aboveStatusBar) {
|
||||||
|
getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "onCreate");
|
||||||
|
}
|
||||||
|
mDialogView = LayoutInflater.from(mContext).inflate(R.layout.bluetooth_dialog, null);
|
||||||
|
mDialogView.setAccessibilityPaneTitle(
|
||||||
|
mContext.getText(R.string.accessibility_desc_quick_settings));
|
||||||
|
final Window window = getWindow();
|
||||||
|
window.setContentView(mDialogView);
|
||||||
|
window.setWindowAnimations(R.style.Animation_InternetDialog);
|
||||||
|
|
||||||
|
mBluetoothDialogTitle = mDialogView.requireViewById(R.id.bluetooth_dialog_title);
|
||||||
|
mBluetoothDialogSubTitle = mDialogView.requireViewById(R.id.bluetooth_dialog_subtitle);
|
||||||
|
mProgressBar = mDialogView.requireViewById(R.id.bluetooth_progress);
|
||||||
|
mDivider = mDialogView.requireViewById(R.id.divider);
|
||||||
|
mBluetoothToggle = mDialogView.requireViewById(R.id.bluetooth_toggle);
|
||||||
|
mBluetoothToggleText = mDialogView.requireViewById(R.id.bluetooth_toggle_title);
|
||||||
|
mBluetoothRecyclerView = mDialogView.requireViewById(R.id.bluetooth_list_layout);
|
||||||
|
mSeeAllLayout = mDialogView.requireViewById(R.id.see_all_layout);
|
||||||
|
mTurnOnLayout = mDialogView.requireViewById(R.id.turn_on_bluetooth_layout);
|
||||||
|
mDoneButton = mDialogView.requireViewById(R.id.done_button);
|
||||||
|
mSettingsButton = mDialogView.requireViewById(R.id.settings_button);
|
||||||
|
mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on);
|
||||||
|
mBackgroundOff = mContext.getDrawable(R.drawable.internet_dialog_selected_effect);
|
||||||
|
|
||||||
|
mBluetoothToggle.setOnCheckedChangeListener(
|
||||||
|
(buttonView, isChecked) -> {
|
||||||
|
mBluetoothController.setBluetoothEnabled(isChecked);
|
||||||
|
});
|
||||||
|
mSeeAllLayout.setOnClickListener(v -> {
|
||||||
|
startActivity(new Intent(SAVED_DEVICES_INTENT)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), v);
|
||||||
|
});
|
||||||
|
mDoneButton.setOnClickListener(v -> dismissDialog());
|
||||||
|
mSettingsButton.setOnClickListener(v -> {
|
||||||
|
startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), v);
|
||||||
|
});
|
||||||
|
mBluetoothRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
|
||||||
|
mBluetoothRecyclerView.setAdapter(mAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "onStart");
|
||||||
|
}
|
||||||
|
mBluetoothController.addCallback(mCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "onStop");
|
||||||
|
}
|
||||||
|
mBluetoothController.removeCallback(mCallback);
|
||||||
|
mSeeAllLayout.setOnClickListener(null);
|
||||||
|
mBluetoothToggle.setOnCheckedChangeListener(null);
|
||||||
|
mDoneButton.setOnClickListener(null);
|
||||||
|
mSettingsButton.setOnClickListener(null);
|
||||||
|
mBluetoothDialogFactory.destroyDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dismissDialog() {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "dismissDialog");
|
||||||
|
}
|
||||||
|
mBluetoothDialogFactory.destroyDialog();
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
void startActivity(Intent intent, View view) {
|
||||||
|
ActivityLaunchAnimator.Controller controller =
|
||||||
|
mDialogLaunchAnimator.createActivityLaunchController(view);
|
||||||
|
|
||||||
|
if (controller == null) {
|
||||||
|
dismissDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
mActivityStarter.postStartActivityDismissingKeyguard(intent, 0, controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the bluetooth dialog when receiving the callback.
|
||||||
|
*/
|
||||||
|
void updateDialog() {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "updateDialog");
|
||||||
|
}
|
||||||
|
// subtitle
|
||||||
|
int subtitle = R.string.bluetooth_is_off;
|
||||||
|
boolean enabled = mBluetoothController.isBluetoothEnabled();
|
||||||
|
boolean connecting = mBluetoothController.isBluetoothConnecting();
|
||||||
|
boolean turningOn =
|
||||||
|
mBluetoothController.getBluetoothState() == BluetoothAdapter.STATE_TURNING_ON;
|
||||||
|
if (connecting) {
|
||||||
|
subtitle = R.string.quick_settings_connecting;
|
||||||
|
} else if (turningOn) {
|
||||||
|
subtitle = R.string.quick_settings_bluetooth_secondary_label_transient;
|
||||||
|
} else if (enabled) {
|
||||||
|
subtitle = R.string.tap_a_device_to_connect;
|
||||||
|
}
|
||||||
|
mBluetoothDialogSubTitle.setText(mContext.getString(subtitle));
|
||||||
|
mBluetoothDialogSubTitle.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
|
||||||
|
|
||||||
|
// progress bar
|
||||||
|
boolean showProgress = connecting || turningOn;
|
||||||
|
mProgressBar.setVisibility(showProgress ? View.VISIBLE : View.GONE);
|
||||||
|
mDivider.setVisibility(showProgress ? View.GONE : View.VISIBLE);
|
||||||
|
|
||||||
|
// devices
|
||||||
|
Collection<CachedBluetoothDevice> devices = mBluetoothController.getDevices();
|
||||||
|
if (!enabled || devices == null) {
|
||||||
|
mBluetoothRecyclerView.setVisibility(View.GONE);
|
||||||
|
mSeeAllLayout.setVisibility(View.GONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean isOnCall = Utils.isAudioModeOngoingCall(mContext);
|
||||||
|
CachedBluetoothDevice activeDevice =
|
||||||
|
devices.stream()
|
||||||
|
.filter(device ->
|
||||||
|
(device.isActiveDevice(BluetoothProfile.HEADSET) && isOnCall)
|
||||||
|
|| (device.isActiveDevice(BluetoothProfile.A2DP) && !isOnCall)
|
||||||
|
|| device.isActiveDevice(BluetoothProfile.HEARING_AID)
|
||||||
|
|| device.isActiveDevice(BluetoothProfile.LE_AUDIO)
|
||||||
|
)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
mBluetoothRecyclerView.setVisibility(View.VISIBLE);
|
||||||
|
mAdapter.setBluetoothDevices(new ArrayList(devices));
|
||||||
|
mAdapter.setActiveDevice(activeDevice);
|
||||||
|
mSeeAllLayout.setVisibility(devices.size() > MAX_DEVICES_COUNT ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
* (C) 2022 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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 co.aospa.systemui.qs.tiles.dialog
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Handler
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import com.android.systemui.animation.DialogLaunchAnimator
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.dagger.qualifiers.Background
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main
|
||||||
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
|
import com.android.systemui.statusbar.policy.BluetoothController
|
||||||
|
import java.util.concurrent.Executor
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
private const val TAG = "BluetoothDialogFactory"
|
||||||
|
private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory to create [BluetoothDialog] objects.
|
||||||
|
*/
|
||||||
|
@SysUISingleton
|
||||||
|
class BluetoothDialogFactory @Inject constructor(
|
||||||
|
@Main private val handler: Handler,
|
||||||
|
private val context: Context,
|
||||||
|
private val dialogLaunchAnimator: DialogLaunchAnimator,
|
||||||
|
private val activityStarter: ActivityStarter,
|
||||||
|
private val bluetoothController: BluetoothController
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
var bluetoothDialog: BluetoothDialog? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a [BluetoothDialog]. The dialog will be animated from [view] if it is not null. */
|
||||||
|
fun create(
|
||||||
|
aboveStatusBar: Boolean,
|
||||||
|
view: View?
|
||||||
|
) {
|
||||||
|
if (bluetoothDialog != null) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "BluetoothDialog is showing, do not create it twice.")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
bluetoothDialog = BluetoothDialog(context, this, aboveStatusBar, handler,
|
||||||
|
activityStarter, dialogLaunchAnimator, bluetoothController)
|
||||||
|
if (view != null) {
|
||||||
|
dialogLaunchAnimator.showFromView(bluetoothDialog!!, view,
|
||||||
|
animateBackgroundBoundsChange = true)
|
||||||
|
} else {
|
||||||
|
bluetoothDialog?.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun destroyDialog() {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "destroyDialog")
|
||||||
|
}
|
||||||
|
bluetoothDialog = null
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,222 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
* (C) 2022 Paranoid Android
|
||||||
|
*
|
||||||
|
* 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 co.aospa.systemui.qs.tiles.dialog;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.android.settingslib.Utils;
|
||||||
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
import com.android.systemui.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter for showing bluetooth devices.
|
||||||
|
*/
|
||||||
|
public class BluetoothViewAdapter extends
|
||||||
|
RecyclerView.Adapter<BluetoothViewAdapter.BluetoothViewHolder> {
|
||||||
|
|
||||||
|
private static final String TAG = "BluetoothViewAdapter";
|
||||||
|
|
||||||
|
private static final String DEVICE_DETAIL_INTENT =
|
||||||
|
"com.android.settings.BLUETOOTH_DEVICE_DETAIL_SETTINGS";
|
||||||
|
private static final String KEY_DEVICE_ADDRESS = "device_address";
|
||||||
|
private static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":settings:show_fragment_args";
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private List<CachedBluetoothDevice> mDevices;
|
||||||
|
protected int mDevicesCount;
|
||||||
|
protected int mMaxDevicesCount = BluetoothDialog.MAX_DEVICES_COUNT;
|
||||||
|
private CachedBluetoothDevice mActiveDevice;
|
||||||
|
|
||||||
|
private BluetoothDialog mDialog;
|
||||||
|
|
||||||
|
protected View mHolderView;
|
||||||
|
protected Context mContext;
|
||||||
|
|
||||||
|
public BluetoothViewAdapter(BluetoothDialog dialog) {
|
||||||
|
mDialog = dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BluetoothViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
|
||||||
|
int viewType) {
|
||||||
|
mContext = viewGroup.getContext();
|
||||||
|
mHolderView = LayoutInflater.from(mContext).inflate(R.layout.bluetooth_list_item,
|
||||||
|
viewGroup, false);
|
||||||
|
return new BluetoothViewHolder(mHolderView, mDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull BluetoothViewHolder viewHolder, int position) {
|
||||||
|
if (mDevices == null || position >= mDevicesCount) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CachedBluetoothDevice device = mDevices.get(position);
|
||||||
|
boolean isActive = mActiveDevice != null && position == 0;
|
||||||
|
if (isActive) {
|
||||||
|
device = mActiveDevice;
|
||||||
|
} else if (device == mActiveDevice) {
|
||||||
|
device = mDevices.get(0);
|
||||||
|
}
|
||||||
|
viewHolder.onBind(device, isActive);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the connected bluetooth devices.
|
||||||
|
*
|
||||||
|
* @param devices the updated bluetooth devices.
|
||||||
|
*/
|
||||||
|
public void setBluetoothDevices(List<CachedBluetoothDevice> devices) {
|
||||||
|
if (mDevices != devices) {
|
||||||
|
mDevices = devices;
|
||||||
|
mDevicesCount = Math.min(devices.size(), mMaxDevicesCount);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveDevice(@Nullable CachedBluetoothDevice device) {
|
||||||
|
if (mActiveDevice != device) {
|
||||||
|
mActiveDevice = device;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the total number of bluetooth devices.
|
||||||
|
*
|
||||||
|
* @return The total number of bluetooth devices.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mDevicesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewHolder for binding bluetooth view.
|
||||||
|
*/
|
||||||
|
static class BluetoothViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
final LinearLayout mContainerLayout;
|
||||||
|
final LinearLayout mBluetoothListLayout;
|
||||||
|
final LinearLayout mBluetoothDeviceLayout;
|
||||||
|
final ImageView mBluetoothIcon;
|
||||||
|
final TextView mBluetoothTitleText;
|
||||||
|
final TextView mBluetoothSummaryText;
|
||||||
|
final ImageView mBluetoothEndIcon;
|
||||||
|
final Context mContext;
|
||||||
|
|
||||||
|
final Drawable mBackgroundOn;
|
||||||
|
final Drawable mBackgroundOff;
|
||||||
|
|
||||||
|
final BluetoothDialog mDialog;
|
||||||
|
|
||||||
|
BluetoothViewHolder(View view, BluetoothDialog dialog) {
|
||||||
|
super(view);
|
||||||
|
mContext = view.getContext();
|
||||||
|
mDialog = dialog;
|
||||||
|
mContainerLayout = view.requireViewById(R.id.bluetooth_container);
|
||||||
|
mBluetoothListLayout = view.requireViewById(R.id.bluetooth_list);
|
||||||
|
mBluetoothDeviceLayout = view.requireViewById(R.id.bluetooth_device_layout);
|
||||||
|
mBluetoothIcon = view.requireViewById(R.id.bluetooth_icon);
|
||||||
|
mBluetoothTitleText = view.requireViewById(R.id.bluetooth_title);
|
||||||
|
mBluetoothSummaryText = view.requireViewById(R.id.bluetooth_summary);
|
||||||
|
mBluetoothEndIcon = view.requireViewById(R.id.bluetooth_end_icon);
|
||||||
|
mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on);
|
||||||
|
|
||||||
|
TypedArray typedArray = mContext.obtainStyledAttributes(
|
||||||
|
new int[]{android.R.attr.selectableItemBackground});
|
||||||
|
try {
|
||||||
|
mBackgroundOff = typedArray.getDrawable(0 /* index */);
|
||||||
|
} finally {
|
||||||
|
typedArray.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onBind(@NonNull CachedBluetoothDevice device, boolean isActive) {
|
||||||
|
if (device == null || !device.hasHumanReadableName()) {
|
||||||
|
mBluetoothListLayout.setVisibility(View.GONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mBluetoothListLayout.setVisibility(View.VISIBLE);
|
||||||
|
mBluetoothListLayout.setBackground(isActive ? mBackgroundOn : mBackgroundOff);
|
||||||
|
mBluetoothListLayout.setOnClickListener(v -> {
|
||||||
|
if (isActive) {
|
||||||
|
device.disconnect();
|
||||||
|
} else if (device.isConnected()) {
|
||||||
|
device.setActive();
|
||||||
|
} else {
|
||||||
|
device.connect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// device icon
|
||||||
|
mBluetoothIcon.setImageDrawable(device.getDrawableWithDescription().first);
|
||||||
|
|
||||||
|
// title
|
||||||
|
mBluetoothTitleText.setText(device.getName());
|
||||||
|
mBluetoothTitleText.setTextAppearance(isActive
|
||||||
|
? R.style.TextAppearance_InternetDialog_Active
|
||||||
|
: R.style.TextAppearance_InternetDialog);
|
||||||
|
|
||||||
|
// summary
|
||||||
|
String summary = device.getConnectionSummary();
|
||||||
|
boolean showSummary = !TextUtils.isEmpty(summary);
|
||||||
|
if (showSummary) {
|
||||||
|
mBluetoothSummaryText.setText(summary);
|
||||||
|
mBluetoothSummaryText.setTextAppearance(isActive
|
||||||
|
? R.style.TextAppearance_InternetDialog_Secondary_Active
|
||||||
|
: R.style.TextAppearance_InternetDialog_Secondary);
|
||||||
|
}
|
||||||
|
mBluetoothSummaryText.setVisibility(showSummary ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
int iconColor = isActive ? mContext.getColor(R.color.connected_network_primary_color)
|
||||||
|
: Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal);
|
||||||
|
mBluetoothEndIcon.setColorFilter(iconColor);
|
||||||
|
|
||||||
|
final Bundle args = new Bundle();
|
||||||
|
args.putString(KEY_DEVICE_ADDRESS, device.getAddress());
|
||||||
|
mBluetoothEndIcon.setOnClickListener(v -> {
|
||||||
|
mDialog.startActivity(new Intent(DEVICE_DETAIL_INTENT)
|
||||||
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args), v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue