From: Wootak Jung Date: Tue, 4 Oct 2022 01:21:50 +0000 (+0900) Subject: Add searched device view and scan button X-Git-Tag: accepted/tizen/unified/20221005.090825~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=83f38b919440a0e7300f67dbb34c548bdacee079;p=profile%2Fiot%2Fapps%2Fdotnet%2Fsetting-bluetooth.git Add searched device view and scan button add platform privilege Change-Id: If6abb35aa4f81d4e010d3e6446aca8fe895f63c4 Signed-off-by: Wootak Jung --- diff --git a/SettingBluetooth/SettingBluetooth/Device.cs b/SettingBluetooth/SettingBluetooth/Device.cs new file mode 100644 index 0000000..13c77f8 --- /dev/null +++ b/SettingBluetooth/SettingBluetooth/Device.cs @@ -0,0 +1,186 @@ +using System; +using System.ComponentModel; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Tizen.NUI.BaseComponents; +using Tizen.NUI.Components; +using Tizen.NUI.Binding; +using Tizen; +using Tizen.Network.Bluetooth; +using SettingBluetooth.res.locale; + +namespace SettingBluetooth +{ + public class Device : INotifyPropertyChanged + { + string iconDir = Tizen.Applications.Application.Current.DirectoryInfo.Resource + "icon.png"; + private string name; + private bool connected; + private bool registered; + private BluetoothAppearanceType appearance; + public event PropertyChangedEventHandler PropertyChanged; + + private void OnPropertyChanged(string propertyName) + { + + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + public Device(string deviceName, bool con, bool reg) + { + name = deviceName; + connected = con; + registered = reg; + } + + public Device(string deviceName, BluetoothAppearanceType deviceAppearance) + { + Log.Debug(Program.LogTag, "Device added. deviceName: " + deviceName + ", deviceAppearance: " + deviceAppearance); + name = deviceName; + appearance = deviceAppearance; + } + + public string Name + { + get + { + return name; + } + set + { + name = value; + OnPropertyChanged("Name"); + } + } + + public string ImageUrl + { + get + { + return iconDir; + } + } + + public bool Connected + { + get + { + return connected; + } + set + { + connected = value; + OnPropertyChanged("Connected"); + } + } + public bool Registered + { + get + { + return registered; + } + set + { + registered = value; + OnPropertyChanged("Registered"); + } + } + public BluetoothAppearanceType Appearance + { + get + { + return appearance; + } + set + { + appearance = value; + OnPropertyChanged("Appearance"); + } + } + }; + + public class DeviceCollection : ObservableCollection + { + string[] devicePool = { + "Galaxy Buds2 Pro", + "Galaxy Fold 4", + }; + + private string title; + + public DeviceCollection(string groupTitle) + { + title = groupTitle; + //UpdateDevices(); + } + + public string Title + { + get + { + return title; + } + set + { + title = value; + OnPropertyChanged(new PropertyChangedEventArgs("Title")); + } + } + + public void UpdateDevices() + { + // Clear method have some issue about asynchronous actions, + // so call Remove for all item is recommanded. + Log.Info(Program.LogTag, "count: " + this.Count + ", pool count: " + devicePool.Length); + while (this.Count > 0) + { + this.RemoveAt(this.Count - 1); + } + + int count = devicePool.Length; + + for (int i = 0; i < count; i++) + { + this.Add(new Device(devicePool[i], false, false)); + } + } + + public void AddDevice(string deviceName, BluetoothAppearanceType deviceAppearance) + { + this.Add(new Device(deviceName, deviceAppearance)); + } + } + + public class DeviceSource : ObservableCollection + { + private DeviceCollection collection; + + public DeviceSource() + { + Log.Info(Program.LogTag, "DeviceSource created"); + collection = new DeviceCollection(Resources.IDS_BT_BODY_SCANNING_FOR_DEVICES_ING); + this.Add(collection); + } + + public void UpdateTitle(string title) + { + collection.Title = title; + } + + public void AddDevice(string deviceName, BluetoothAppearanceType deviceAppearance) + { + collection.AddDevice(deviceName, deviceAppearance); + } + + public int GetCount() + { + Log.Debug(Program.LogTag, "count: " + collection.Count); + return collection.Count; + } + + public void UpdateDevices() + { + collection.UpdateDevices(); + } + } +} \ No newline at end of file diff --git a/SettingBluetooth/SettingBluetooth/SettingBluetooth.cs b/SettingBluetooth/SettingBluetooth/SettingBluetooth.cs index 1c2bc5a..aa14589 100644 --- a/SettingBluetooth/SettingBluetooth/SettingBluetooth.cs +++ b/SettingBluetooth/SettingBluetooth/SettingBluetooth.cs @@ -6,6 +6,8 @@ namespace SettingBluetooth { public class Program : NUIWidgetApplication { + public static readonly string LogTag = "SettingBluetooth"; + public Program(Dictionary widgetSet) : base(widgetSet) { } diff --git a/SettingBluetooth/SettingBluetooth/WidgetSettingBluetooth.cs b/SettingBluetooth/SettingBluetooth/WidgetSettingBluetooth.cs index d227bc9..e044252 100644 --- a/SettingBluetooth/SettingBluetooth/WidgetSettingBluetooth.cs +++ b/SettingBluetooth/SettingBluetooth/WidgetSettingBluetooth.cs @@ -8,101 +8,256 @@ using Tizen.NUI.Components; using Tizen.Network.Bluetooth; using Tizen; using SettingBluetooth.res.locale; +using Tizen.NUI.Binding; namespace SettingBluetooth { internal class WidgetSettingBluetooth : Widget { - internal static readonly string LogTag = "SettingBluetooth"; - protected View mRootView; + ContentPage mainPage; + View mainView; + CollectionView deviceView = null; + DeviceSource deviceSource; + static Button scanButton = null; + bool isEnabled = false; + bool isScanning = false; + bool deviceSourceInit = false; public WidgetSettingBluetooth() : base() { } - DefaultLinearItem CreateItem(string text, string subText = null, bool icon = false, bool extra = false) + public void DeviceSelectionChanged(object obj, SelectionChangedEventArgs ev) { - var item = new DefaultLinearItem() + Log.Debug(Program.LogTag, "DeviceSelectionChanged called"); + + //SingleSelection Only have 1 or nil object in the list. + foreach (object item in ev.PreviousSelection) + { + if (item == null) break; + if (item is Device device) + { + device.Connected = false; + } + } + foreach (object item in ev.CurrentSelection) + { + if (item == null) break; + if (item is Device device) + { + device.Connected = true; + device.Registered = true; + } + } + } + + private void AddDeviceView() + { + deviceSource = new DeviceSource(); + deviceView = new CollectionView() { + ItemsSource = deviceSource, + ItemsLayouter = new LinearLayouter(), + ItemTemplate = new DataTemplate(() => + { + DefaultLinearItem item = new DefaultLinearItem() + { + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + item.Label.SetBinding(TextLabel.TextProperty, "Name"); + item.Label.HorizontalAlignment = HorizontalAlignment.Begin; + item.Icon.SetBinding(ImageView.ResourceUrlProperty, "ImageUrl"); + item.Icon.WidthSpecification = 40; + item.Icon.HeightSpecification = 40; + return item; + }), + + GroupHeaderTemplate = new DataTemplate(() => + { + DefaultTitleItem group = new DefaultTitleItem() + { + WidthSpecification = LayoutParamPolicies.MatchParent, + }; + group.Label.SetBinding(TextLabel.TextProperty, "Title"); + group.Label.HorizontalAlignment = HorizontalAlignment.Begin; + + return group; + }), + + IsGrouped = true, + ScrollingDirection = ScrollableBase.Direction.Vertical, WidthSpecification = LayoutParamPolicies.MatchParent, - Text = text, + HeightSpecification = LayoutParamPolicies.MatchParent, + SelectionMode = ItemSelectionMode.Single, }; + deviceView.SelectionChanged += DeviceSelectionChanged; + mainView.Add(deviceView); + } - if (subText != null) item.SubText = subText; - if (icon) item.Icon = new CheckBox(); - //if (extra) item.Extra = new RadioButton(); - var onoffSwitch = new Switch(); - if (extra) item.Extra = onoffSwitch; - onoffSwitch.SelectedChanged += (object obj, SelectedChangedEventArgs ev) => + private void AddScanButton() + { + scanButton = new Button + { + Text = Resources.IDS_BT_SK_STOP, + //WidthSpecification = 300, + //HeightSpecification = 80, + }; + scanButton.Clicked += (object obj, ClickedEventArgs ev) => { - Log.Info(LogTag, "onoffSwitch clicked. isSelected: " + ev.IsSelected); + Log.Debug(Program.LogTag, "scanButton clicked. isScanning: " + isScanning); + // check isScanning + // scan stop + if (isScanning == true) + { + BluetoothAdapter.StopDiscovery(); + } + else + { + BluetoothAdapter.StartDiscovery(); + } }; - item.IsSelectable = true; - return item; + mainView.Add(scanButton); } + internal static void UpdateScanButton(string text) + { + scanButton.Text = text; + } - void CreateItems(View parent, string text, string subText = null, bool icon = false, bool extra = false) + private void RemoveDeviceView() { - var newItem = CreateItem(text, subText, icon, extra); - newItem.Clicked += (object obj, ClickedEventArgs ev) => + if (deviceView) { - Log.Info(LogTag, "newItem clicked"); - }; - parent.Add(newItem); + mainView.Remove(deviceView); + } } + private void RemoveScanButton() + { + if (scanButton) + { + mainView.Remove(scanButton); + } + } + + private void EventHandlerDiscoveryChanged(object obj, DiscoveryStateChangedEventArgs ev) + { + if (ev.DiscoveryState == BluetoothDeviceDiscoveryState.Started) + { + Log.Debug(Program.LogTag, "Device discovery started"); + } + else if (ev.DiscoveryState == BluetoothDeviceDiscoveryState.Found) + { + if (deviceSourceInit == false) + { + AddDeviceView(); + AddScanButton(); + deviceSourceInit = true; + } + + Log.Debug(Program.LogTag, "Device found. Address: " + ev.DeviceFound.Address + ", Appearance: " + ev.DeviceFound.AppearanceType); + deviceSource.AddDevice(ev.DeviceFound.Name, ev.DeviceFound.AppearanceType); + } + else + { + Log.Debug(Program.LogTag, "Device discovery finished"); + isScanning = false; + deviceSource.UpdateTitle(Resources.IDS_BT_BODY_AVAILABLE_DEVICES); + UpdateScanButton(Resources.IDS_BT_SK_SCAN); + } + } + + private void EventHandlerStateChanged(object obj, StateChangedEventArgs ev) + { + if (ev.BTState == BluetoothState.Enabled) + { + Log.Info(Program.LogTag, "BT enabled. Start discovery"); + isEnabled = true; + BluetoothAdapter.StartDiscovery(); + isScanning = true; + } + else + { + Log.Info(Program.LogTag, "BT disabled"); + isEnabled = false; + RemoveDeviceView(); + RemoveScanButton(); + deviceSourceInit = false; + } + } protected override void OnCreate(string contentInfo, Window window) { - Bundle bundle = Bundle.Decode(contentInfo); + window = NUIApplication.GetDefaultWindow(); + window.BackgroundColor = Color.White; - mRootView = new View(); - mRootView.BackgroundColor = Color.White; - mRootView.Size2D = window.Size; - mRootView.PivotPoint = PivotPoint.Center; - window.GetDefaultLayer().Add(mRootView); + var appBar = new AppBar() + { + Title = Resources.IDS_BT_BODY_BLUETOOTH, + }; - // Example root content view. - // you can decorate, add children on this view. - View rootContent = new ScrollableBase() + mainView = new View() { - WidthSpecification = LayoutParamPolicies.MatchParent, - HeightSpecification = LayoutParamPolicies.MatchParent, - ScrollingDirection = ScrollableBase.Direction.Vertical, - HideScrollbar = false, Layout = new LinearLayout() { LinearOrientation = LinearLayout.Orientation.Vertical, HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - CellPadding = new Size2D(10, 20), }, + WidthSpecification = LayoutParamPolicies.MatchParent, + HeightSpecification = LayoutParamPolicies.MatchParent, }; - CreateItems(rootContent, Resources.IDS_BT_BODY_BLUETOOTH, null, false, true); + isEnabled = BluetoothAdapter.IsBluetoothEnabled; + BluetoothAdapter.StateChanged += EventHandlerStateChanged; + BluetoothAdapter.DiscoveryStateChanged += EventHandlerDiscoveryChanged; + + var onOffItem = new DefaultLinearItem + { + WidthSpecification = LayoutParamPolicies.MatchParent, + Text = Resources.IDS_BT_BODY_BLUETOOTH, + }; + onOffItem.Label.HorizontalAlignment = HorizontalAlignment.Begin; - try + var onOffSwitch = new Switch() + { + IsSelected = isEnabled, + }; + onOffSwitch.SelectedChanged += (object obj, SelectedChangedEventArgs ev) => { - if (BluetoothAdapter.IsBluetoothEnabled == true) + Log.Debug(Program.LogTag, "btOnOffSwitch clicked. IsSelected: " + ev.IsSelected + ", isEnabled: " + isEnabled); + if (ev.IsSelected == true && isEnabled == false) { - Log.Info(LogTag, "bt enabled"); - CreateItems(rootContent, BluetoothAdapter.Name, null, false, false); + Log.Info(Program.LogTag, "Enable BT adapter"); + BluetoothAdapter.Enable(); + } + else if (ev.IsSelected == false && isEnabled == true) + { + Log.Info(Program.LogTag, "Disable BT adapter"); + BluetoothAdapter.Disable(); } else { - Log.Info(LogTag, "bt disabled"); + Log.Error(Program.LogTag, "Invalid state"); } - } - catch - { + }; + onOffItem.Extra = onOffSwitch; + mainView.Add(onOffItem); - Log.Error(LogTag, "exception occured"); + if (isEnabled) + { + AddDeviceView(); + AddScanButton(); } - window.GetDefaultLayer().Add(rootContent); + mainPage = new ContentPage() + { + AppBar = appBar, + Content = mainView, + }; + + window.GetDefaultNavigator().Push(mainPage); } } } diff --git a/SettingBluetooth/SettingBluetooth/tizen-manifest.xml b/SettingBluetooth/SettingBluetooth/tizen-manifest.xml index 52e48b5..102867f 100644 --- a/SettingBluetooth/SettingBluetooth/tizen-manifest.xml +++ b/SettingBluetooth/SettingBluetooth/tizen-manifest.xml @@ -11,5 +11,6 @@ http://tizen.org/privilege/bluetooth + http://tizen.org/privilege/bluetooth.admin