Android藍牙開發(二)---界面設計

前言


在上一篇博文中,針對Android的藍牙基礎知識作了一個簡單的梳理。在正式的APP開發過程中,知識轉換成成用戶能夠看得見、摸得著的才能生產力最大化。本章主要針對藍牙設備的搜索界面作簡要的設計、開發。


一、藍牙搜索界面


通常在APP內的藍牙搜索中,選擇Dialog+listview的方式來顯示藍牙設備的搜索即簡潔又美觀。常用的Dialog、Listview無法滿足需求,因此需要客制化自行封裝,以后也可以將這些方法作為一個簡易的封裝類供其他的項目或者代碼參考。


藍牙搜索界面

1.1 MyDialog封裝


Dialog的封裝主要包含兩個方面,style和尺寸的封裝。

  1. style
    style的封裝主要是對Dialog的顯示作簡要的修改,在res\values\styles.xml中添加以下代碼:
    <style name="my_dialog" parent="android:Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowBackground">@color/white</item>
    </style>
  1. list item
    btDevice_list_item.xml主要用于Dialog中的Listview的item布局,每一個item共有三種屬性:name,address,bonded,即藍牙設備名,藍牙地址,是否綁定。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/bt_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="藍牙名稱"
        android:layout_marginStart="43dp"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:id="@+id/bt_addr"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="藍牙地址"
        android:layout_alignParentTop="true"
        android:layout_alignStart="@+id/bt_name"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="5dp"/>

    <TextView
        android:id="@+id/bt_bonded"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="已綁定"
        android:layout_marginEnd="23dp"
        android:layout_centerVertical="true"
        android:layout_alignParentEnd="true" />
</RelativeLayout>
  1. MyDialog封裝
    此自定義的Dialog可以作為后續的其他項目或者其他類型的Dialog類的封裝,根據不同的需求,設定其theme即可。
public class MyDialog extends Dialog{
    // 這種適合通用
    public MyDialog(Context context) {
        super(context);
    }
    // 自定義提醒框樣式
    public MyDialog(Context context, int themeResId) {
        super(context, themeResId);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}
  1. MyDialog的尺寸大小
    自定義一個合適的尺寸,滿足需求即可,用戶或者愛好者可以根據自己的需求及喜好自定義類似的Dialog框圖大小及樣式。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:background="@color/white"
    android:orientation="vertical">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:textColor="@color/aliceblue"
        android:text="藍牙設備"
        android:textSize="20sp"
        android:textStyle="bold"
        android:background="@color/purple"/>
    <ListView
        android:id="@+id/bt_device_list"
        android:divider="@color/blue"
        android:dividerHeight="0.5dp"
        android:padding="10dp"
        android:clickable="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/bt_dialog_cancel"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="取消"
        android:textColor="@color/aliceblue"
        android:background="@color/purple"
        android:textStyle="bold"
        android:textSize="20sp"
        android:gravity="center"/>
</LinearLayout>

至此,顯示界面已經完成。


二、藍牙設備搜索


2.1 藍牙設備的適配器

因添加Listview類,對listview的添加、點擊、構建、移除等數據都需要綁定適配器,因此首要的任務根據業務需求自定義適配器。

public class BTDeviceAdapter extends BaseAdapter{
    private static final String TAG = "first";
    private Context context;
    private LayoutInflater mInflater;
    private List<BluetoothDevice> list;
    private BluetoothDevice device;

    private static class ViewHolder{
        TextView btNameView;
        TextView btAddrView;
        TextView btBondedView;
    }

    //構造函數
    public BTDeviceAdapter(final Context context, final List<BluetoothDevice> list){
        super();
        this.context = context;
        this.list = list;
        mInflater = LayoutInflater.from(context);
    }
    //device list大小
    @Override
    public int getCount() {
        return list.size();
    }
    //device在list中的位置
    @Override
    public Object getItem(int position) {
        return list.get(position);
    }
    //device在list中的id
    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        //設備是否已經綁定
        device = list.get(position);
        //如果緩存convertView為空,則需要創建View
        if (convertView == null) {
            // view創建
            convertView = mInflater.inflate(R.layout.btdevice_list_item, null);
            holder = new ViewHolder();

            holder.btNameView = (TextView) convertView.findViewById(R.id.bt_name);
            holder.btAddrView = (TextView) convertView.findViewById(R.id.bt_addr);
            holder.btBondedView = (TextView) convertView.findViewById(R.id.bt_bonded);

            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }
        //view屬性設置
        holder.btNameView.setText(device.getName());
        holder.btAddrView.setText(device.getAddress());

        if (device.getBondState() == BluetoothDevice.BOND_BONDED){
            Log.i(TAG, "設備:" + device.getName() + "已綁定");
            holder.btBondedView.setVisibility(View.VISIBLE);
            holder.btBondedView.setTextColor(Color.RED);
        }else {
            holder.btBondedView.setVisibility(View.INVISIBLE);
        }
        return convertView;
    }
}

2.2 藍牙設備搜索

在所有的工作準備完成后,進入Activity或者fragment中進行藍牙button的點擊搜索工作。
手機藍牙因為會保存之前已經配對的藍牙設備,因此可以選擇對這些已配對的設備添加到list中,下方附上主要部分的代碼。

2.2.1 添加已配對的藍牙設備

//將已經存在的配對設備先加入列表
 Set<BluetoothDevice> bondedDevices = adapter.getBondedDevices();
  Log.e(TAG, "已綁定設備數為:" + bondedDevices.size());

  if (bondedDevices.size() != 0) {
        Iterator<BluetoothDevice> iterator = bondedDevices.iterator();
         while (iterator.hasNext()) {
           mlist.add((BluetoothDevice) iterator.next());
      }
  }
 Log.e(TAG,"mlist:" + mlist);//搜索前先將手機以前配對的藍牙設備列表打印

2.2.2 藍牙設備搜索并添加

首先將dialog中的listview初始化,并關聯適配器。

deviceAdapter = new BTDeviceAdapter(mActivity, mlist);
bt_device_list = (ListView) dialog.findViewById(R.id.bt_device_list);
bt_device_list.setAdapter(deviceAdapter);
adapter.startDiscovery();

2.2.3 藍牙設備開啟廣播并添加藍牙設備到listview

此過程是一個動態添加的過程,在此代碼中包括搜索和完成的intent判斷。

/**
     * 設置靜態廣播,主要用于接收藍牙搜索的結果
     */
    @Override
    public void onResume() {
        super.onResume();
        //廣播過濾
        filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        filter.setPriority(Integer.MAX_VALUE);//設置廣播的優先級最大

        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                try{
                    String action = intent.getAction();
                    Log.e(TAG,"接收到藍牙廣播!" + "action = " + action);
                    switch (action) {
                        case BluetoothDevice.ACTION_FOUND:
                            final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                            if (device.getName() != null && device != null) {
                                Log.i(TAG, "device Name: " + device.getName());
                                Log.i(TAG, "device Addr: " + device.getAddress());
                             
                                    mActivity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            Log.e(TAG, "開始添加設備!");
                                            addDevice(device);
                                        }
                                    });
                            }
                            break;
                        case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                            System.out.println("ACTION_DISCOVERY_FINISHED");
                            Log.e(TAG, "掃描完成!");
                            if (mActivity instanceof Activity) {
                                mActivity.runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        Log.e(TAG, "finished 開始添加設備!");
                                        Set<BluetoothDevice> paired = adapter.getBondedDevices();
                                        Log.e(TAG, "paired = " + paired);
                                        if (paired != null && paired.size() > 0) {
                                            for (BluetoothDevice bonded : paired) {
                                                if (mlist.indexOf(bonded) == -1) {
                                                    mlist.add(bonded);
                                                    deviceAdapter.notifyDataSetChanged();
                                                }
                                            }
                                        }
                                        Log.e(TAG, "掃描完成后的list: " + mlist);
                                    }
                                });
                            }
                            Log.e(TAG, "掃描完成后的list: " + mlist);
                            break;
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        };
        //注冊藍牙搜索結果的receiver
        mActivity.registerReceiver(receiver, filter);
    }

添加設備的關鍵代碼

private void addDevice(final BluetoothDevice device) {
        boolean deviceFound = false;
        for (final BluetoothDevice listDev : mlist) {
            if (listDev.getAddress().equals(device.getAddress())) {               
                deviceFound = true;
                break;
            }
        }
        if (!deviceFound) {
            if (mlist.indexOf(device) == -1) { //判斷設備是否存在list中,不存返回-1
                mlist.add(device);
                deviceAdapter.notifyDataSetChanged();
            }
        }
    }

2.3 藍牙搜索結果

通過以上關鍵部分的代碼及搜索過程,可以完成對于藍牙設備的搜索及添加,當然可以根據個人的需求及愛好針對搜索過程中的一些客制化工作,如將搜索的結果放置在Activity中,dialog加入搜索狀態,如正在搜索,搜索完成等,具體添加的位置在btdevice_list_item.xml和BTDeviceAdapter.class中添加狀態的判斷。
下圖為藍牙設備的搜索結果


藍牙設備搜索結果
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,737評論 25 708
  • afinalAfinal是一個android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,485評論 2 45
  • ¥開啟¥ 【iAPP實現進入界面執行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,494評論 0 17
  • 不知是生活委屈了她,還是她委屈了生活,她的人生,四十才剛剛開始。
    樓頂那片海閱讀 236評論 0 0
  • 第一,要有合伙人思維,一家公司不能一個人說了算。盛希泰認為,一個項目沒有合伙人那就是沒有未來,如果找不到合伙人那就...
    田園牧歌928閱讀 193評論 0 0