Add searched device view and scan button 39/282439/1
authorWootak Jung <wootak.jung@samsung.com>
Tue, 4 Oct 2022 01:21:50 +0000 (10:21 +0900)
committerWootak Jung <wootak.jung@samsung.com>
Tue, 4 Oct 2022 01:29:10 +0000 (10:29 +0900)
add platform privilege

Change-Id: If6abb35aa4f81d4e010d3e6446aca8fe895f63c4
Signed-off-by: Wootak Jung <wootak.jung@samsung.com>
SettingBluetooth/SettingBluetooth/Device.cs [new file with mode: 0644]
SettingBluetooth/SettingBluetooth/SettingBluetooth.cs
SettingBluetooth/SettingBluetooth/WidgetSettingBluetooth.cs
SettingBluetooth/SettingBluetooth/tizen-manifest.xml

diff --git a/SettingBluetooth/SettingBluetooth/Device.cs b/SettingBluetooth/SettingBluetooth/Device.cs
new file mode 100644 (file)
index 0000000..13c77f8
--- /dev/null
@@ -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<Device>
+    {
+        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<DeviceCollection>
+    {
+        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
index 1c2bc5a7273d335abbabcaecf3778aff7752833c..aa14589a467ed19ba9160fcaa8998fc1b8dce755 100644 (file)
@@ -6,6 +6,8 @@ namespace SettingBluetooth
 {
     public class Program : NUIWidgetApplication
     {
+        public static readonly string LogTag = "SettingBluetooth";
+
         public Program(Dictionary<System.Type, string> widgetSet) : base(widgetSet)
         {
         }
index d227bc964ba84a78fc594357b7ef2f6a5fc08e86..e0442521fb00f5d3770447f98852785019a0cf52 100644 (file)
@@ -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);
         }
     }
 }
index 52e48b5cf69f6b502e09267dbcabfde07b71bc11..102867fff929c96ef1b8af780dc3d140181a0659 100644 (file)
@@ -11,5 +11,6 @@
   </widget-application>
   <privileges>
     <privilege>http://tizen.org/privilege/bluetooth</privilege>
+    <privilege>http://tizen.org/privilege/bluetooth.admin</privilege>
   </privileges>
 </manifest>