国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

正規(guī)網(wǎng)店代運(yùn)營公司seo每日

正規(guī)網(wǎng)店代運(yùn)營公司,seo每日,百度小程序開發(fā)者工具,商務(wù)類網(wǎng)站設(shè)計(jì)Harmony Ble 藍(lán)牙App (一)掃描 前言正文一、創(chuàng)建工程二、工程配置① 權(quán)限配置② Debug配置③ UI配置 三、掃描① 掃描接口② 掃描類 四、業(yè)務(wù)處理① Slice的生命周期② 藍(lán)牙開關(guān)和動態(tài)權(quán)限請求 五、掃描設(shè)備六、顯示設(shè)備① 自定義藍(lán)牙類② 提供者③ 顯示…

Harmony Ble 藍(lán)牙App (一)掃描

  • 前言
  • 正文
    • 一、創(chuàng)建工程
    • 二、工程配置
      • ① 權(quán)限配置
      • ② Debug配置
      • ③ UI配置
    • 三、掃描
      • ① 掃描接口
      • ② 掃描類
    • 四、業(yè)務(wù)處理
      • ① Slice的生命周期
      • ② 藍(lán)牙開關(guān)和動態(tài)權(quán)限請求
    • 五、掃描設(shè)備
    • 六、顯示設(shè)備
      • ① 自定義藍(lán)牙類
      • ② 提供者
      • ③ 顯示設(shè)備
    • 七、源碼

前言

??關(guān)于Android的低功耗藍(lán)牙,我做了很多介紹了,那么對于Harmony來說這一塊我沒有做過介紹,而實(shí)際中我確實(shí)做過一個Harmony的BLE項(xiàng)目,所以這里分享一些內(nèi)容出來。

正文

??在Harmony中進(jìn)行Ble的藍(lán)牙開發(fā)實(shí)際上和Android中類似,但是又有一些不同,因?yàn)镠armony的SDK還在不斷的完善。而這里我們使用的是API 6進(jìn)行項(xiàng)目開發(fā),使用的語言是Java,至于為什么使用API 6而不是最新的API 9,因?yàn)槲屹I不起遙遙領(lǐng)先,所以只能用API 6的HUAWEI P30進(jìn)行真機(jī)測試。藍(lán)牙這種APP一定是要使用真機(jī)測試的,你用虛擬機(jī)是不行的,話不多說,我們開始吧。

在這里插入圖片描述

一、創(chuàng)建工程

??下面開始創(chuàng)建工程。

在這里插入圖片描述

選擇Empty Ability,點(diǎn)擊Next。我們創(chuàng)建一個名為HarmonyBle的項(xiàng)目,語言為Java。

在這里插入圖片描述

點(diǎn)擊Finish完成創(chuàng)建。

在這里插入圖片描述

默認(rèn)的工程就是這個樣子的,是不是很像Android創(chuàng)建的工程呢?

二、工程配置

① 權(quán)限配置

??Harmony中同樣有權(quán)限這個概念,也需要配置靜態(tài)權(quán)限和動態(tài)權(quán)限,只不過配置靜態(tài)權(quán)限的地方不一樣。Harmony是在config.json中,里面的代碼如下:

{"app": {"bundleName": "com.llw.ble","vendor": "example","version": {"code": 1000000,"name": "1.0.0"}},"deviceConfig": {},"module": {"package": "com.llw.ble","name": ".MyApplication","mainAbility": "com.llw.ble.MainAbility","deviceType": ["phone","tablet","tv","wearable","car"],"distro": {"deliveryWithInstall": true,"moduleName": "entry","moduleType": "entry","installationFree": false},"abilities": [{"skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home"]}],"name": "com.llw.ble.MainAbility","description": "$string:mainability_description","icon": "$media:icon","label": "$string:entry_MainAbility","launchType": "standard","orientation": "unspecified","visible": true,"type": "page"}]}
}

??你閱讀一下,你就會發(fā)現(xiàn),這和Android的AndroidManifest.xml配置文件好像差不多啊。只不過一個用的是json,一個用的是xml。

??所以我們配置權(quán)限也是在config.json中,例如掃描藍(lán)牙時我們需要定位權(quán)限??梢栽诶锩嬖黾尤缦麓a:

    "reqPermissions": [{"name": "ohos.permission.LOCATION"},{"name": "ohos.permission.USE_BLUETOOTH"},{"name": "ohos.permission.DISCOVER_BLUETOOTH"},{"name": "ohos.permission.MANAGE_BLUETOOTH"}]

如下圖所示,注意json中標(biāo)點(diǎn)符號。

在這里插入圖片描述

② Debug配置

??然后我們就應(yīng)該要來寫代碼了,不過在此之前,我們先了解一下Ability和Slice的區(qū)別,Ability就像一個畫框,而Slice就像一個畫布。我們可以在一個畫框里面加載多個畫布,就好像多個頁面之前的跳轉(zhuǎn),我們可以用Slice來進(jìn)行,下面我們增加一個掃描的Slice,我們復(fù)制一下MainAbilitySlice,再粘貼一下,出現(xiàn)的彈窗中改名字

在這里插入圖片描述
??為什么要通過這種方式來創(chuàng)建Java文件呢?因?yàn)镈evEco Studio我創(chuàng)建不了Java文件,可能是這個版本的DS沒有這個選項(xiàng)亦或是我沒有找到。

??下面我們需要創(chuàng)建對應(yīng)layout文件,再resources/base/layout下創(chuàng)建一個slice_scan.xml,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:alignment="center"ohos:orientation="vertical"><ListContainerohos:id="$+id:lc_device"ohos:height="match_parent"ohos:width="match_parent"/></DirectionalLayout>

??然后我們再修改ScanSlice中的內(nèi)容,讓它加載我們剛寫好的slice_scan.xml。修改onStart()方法,代碼如下所示:

    @Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setUIContent(ResourceTable.Layout_slice_scan);}

現(xiàn)在App打開之后默認(rèn)會運(yùn)行MainAbility,我們看一下這個里面。

public class MainAbility extends Ability {@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setMainRoute(MainAbilitySlice.class.getName());}
}

??可以看到,在setMainRoute()方法中,默認(rèn)加載的是MainAbilitySlice,將它改為我們剛寫好的ScanSlice,代碼:super.setMainRoute(ScanSlice.class.getName());

然后我們先運(yùn)行一下看看,通過USB鏈接到鴻蒙手機(jī)上。

在這里插入圖片描述

這里會提示報錯,瀏覽一下錯誤信息。

在這里插入圖片描述

??這里是說我們需要配置Signing。點(diǎn)擊Run下面或者右側(cè)彈窗的Open signing configs,會打開一個配置窗口,如下圖所示:

在這里插入圖片描述

我們點(diǎn)擊Signing Configs選項(xiàng),需要你進(jìn)行登錄,如下圖所示:

在這里插入圖片描述

??這里就需要你登錄華為的帳號了,我們當(dāng)前在本地運(yùn)行所以是Debug模式,旁邊有一個Release表示發(fā)布版本,它里面配置的東西和Debug模式一致,區(qū)別在于Debug模式下的配置信息只要我們登錄之后,DevEco Studio會幫助我們自動生成,而Release中的信息則需要開發(fā)者去華為開發(fā)者官網(wǎng)上去創(chuàng)建應(yīng)用并申請配置文件和證書,比較麻煩,但是如果你要上架應(yīng)用則必須做這一步,在國內(nèi),華為應(yīng)用市場上架應(yīng)用是最嚴(yán)格的。華為的你搞得定,其他的都是小趴菜,不值一提。

??下面我們先登錄,會打開一個網(wǎng)頁,登錄成功之后,你會看到這樣的頁面。

在這里插入圖片描述

??然后我們回到DS,就會自動配置Debug模式下的證書和配置文件,如下圖所示:

在這里插入圖片描述

??點(diǎn)擊OK,會在DS中進(jìn)行一個配置,配置好之后你可以在工程目錄下的build.gradle中看到debug的相關(guān)信息,如下圖所示。

在這里插入圖片描述

然后我們再運(yùn)行一下看看,這一次毫無疑問是可以運(yùn)行成功的。如下圖所示:

在這里插入圖片描述

③ UI配置

可以看到默認(rèn)的標(biāo)題欄就如同Android默認(rèn)的ActionBar,丑的很特別,我們?nèi)サ羲?#xff0c;在config.json中添加如下代碼:

        "metaData": {"customizeData": [{"extra": "","name": "hwc-theme","value": "androidhwext:style/Theme.Emui.Light.NoTitleBar"}]},

添加位置如下所示:

在這里插入圖片描述

下面我們再運(yùn)行一下看看。

在這里插入圖片描述
是不是Unbelievable! 同樣為了標(biāo)題好看,我們在element下創(chuàng)建一個color.json,里面的代碼如下所示:

{"color": [{"name": "white","value": "#FFF"},{"name": "black","value": "#000"},{"name": "blue","value": "#FFA7D3FF"},{"name": "bg_color","value": "#F8F8F8"},{"name": "gray","value": "#989898"}]
}

我們再修改一下scan_slice.xml中的代碼,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:alignment="center"ohos:background_element="$color:bg_color"ohos:orientation="vertical"><DirectionalLayoutohos:height="50vp"ohos:width="match_parent"ohos:alignment="vertical_center"ohos:background_element="$color:blue"ohos:orientation="horizontal"ohos:start_padding="12vp"><Textohos:id="$+id:title"ohos:height="match_content"ohos:width="match_content"ohos:text="選擇設(shè)備"ohos:text_color="#FFF"ohos:text_font="HwChinese-medium"ohos:text_size="18fp"ohos:weight="1"/><Textohos:id="$+id:tx_scan_status"ohos:height="match_content"ohos:width="match_content"ohos:end_margin="6vp"ohos:padding="8vp"ohos:text="搜索"ohos:text_color="#FFF"ohos:text_size="14fp"/></DirectionalLayout><ListContainerohos:id="$+id:lc_device"ohos:height="match_parent"ohos:width="match_parent"/></DirectionalLayout>

這個DirectionalLayout布局就是線性布局,我們可以點(diǎn)擊右側(cè)導(dǎo)航欄的Previewer進(jìn)行布局預(yù)覽,如下圖所示。

在這里插入圖片描述

右上角的T圖標(biāo),點(diǎn)擊之后可以查看當(dāng)前布局的層級。

在這里插入圖片描述

??這里說明一下,有時候在通過資源使用顏色值的時候會無法生效,所以就會直接使用#FFF,在代碼里也是如此,這應(yīng)該屬于編譯器的Bug。

標(biāo)題欄就寫好了,還有狀態(tài)欄我們沒有改,狀態(tài)欄我們在MainAbility中進(jìn)行修改,代碼如下所示:

    @Overridepublic void onStart(Intent intent) {Window window = WindowManager.getInstance().getTopWindow().get();window.setStatusBarColor(Color.getIntColor("#A7D3FF"));super.onStart(intent);super.setMainRoute(ScanSlice.class.getName());}

還是修改onStart()方法,然后我們運(yùn)行一下看看。

在這里插入圖片描述
好了,下面我們來寫掃描需要的內(nèi)容代碼。

三、掃描

??首先我們在com.llw.ble包下新建一個core包,core包下創(chuàng)建一個BleCore類,這里面就是控制Ble藍(lán)牙相關(guān)的一切,比如掃描,連接,讀寫數(shù)據(jù)等操作,我們先不寫代碼。下面在core包下創(chuàng)建一個scan包。

① 掃描接口

scan包下新建一個ScanCallback接口,代碼如下:

public interface ScanCallback {void onScanResult(BleScanResult result);default void onGroupScanResultsEvent(List<BleScanResult> results){}default void onScanFailed(String failed){}
}

② 掃描類

然后在scan包下新建一個BleScan類,代碼如下所示:

public class BleScan {private final BleCentralManager centralManager;private boolean isScanning = false;private ScanCallback scanCallback;// 創(chuàng)建掃描過濾器然后開始掃描private List<BleScanFilter> filters;private static volatile BleScan mInstance;//初始化public static BleScan getInstance(Context context) {if (mInstance == null) {synchronized (BleScan.class) {if (mInstance == null) {mInstance = new BleScan(context);}}}return mInstance;}public BleScan(Context context) {BleScanCallback centralManagerCallback = new BleScanCallback();centralManager = new BleCentralManager(context, centralManagerCallback);}/*** 當(dāng)前是否正在掃描* @return true 掃描中,false 未掃描*/public boolean isScanning() {return isScanning;}/*** 設(shè)置過濾信息* @param filters 藍(lán)牙掃描過濾列表*/public void setFilters(List<BleScanFilter> filters) {this.filters = filters;}/*** 設(shè)置掃描回調(diào),頁面需要實(shí)現(xiàn)才能獲取掃描到的設(shè)備* @param scanCallback 掃描回調(diào)*/public void setScanCallback(ScanCallback scanCallback) {this.scanCallback = scanCallback;}/*** 開始掃描*/public void startScan() {if (centralManager == null) {localScanFailed("Bluetooth not turned on.");return;}centralManager.startScan(filters);isScanning = true;}/*** 停止掃描*/public void stopScan() {if (!isScanning) {localScanFailed("Not currently scanning, your stop has no effect.");return;}centralManager.stopScan();isScanning = false;}/*** 實(shí)現(xiàn)掃描回調(diào)*/public class BleScanCallback implements BleCentralManagerCallback {@Overridepublic void scanResultEvent(BleScanResult bleScanResult) {if (scanCallback != null) {scanCallback.onScanResult(bleScanResult);}}@Overridepublic void scanFailedEvent(int resultCode) {if (scanCallback != null) {scanCallback.onScanFailed(String.valueOf(resultCode));}}@Overridepublic void groupScanResultsEvent(final List<BleScanResult> scanResults) {// 對掃描結(jié)果進(jìn)行處理if (scanCallback != null) {scanCallback.onGroupScanResultsEvent(scanResults);}}}/*** 本地掃描失敗處理* @param failed 錯誤信息*/private void localScanFailed(String failed) {if (scanCallback != null) {scanCallback.onScanFailed(failed);}}
}

??這里面采用單例模式,在初始化之后直接調(diào)用,然后再實(shí)現(xiàn)掃描回調(diào)接口,返回掃描信息,有開始、停止掃描和是否正在掃描方法。這個類你可以直接用,也可以再封裝到BleCore中,這里我們封裝到BleCore中,修改BleCore中的代碼,如下所示:

public class BleCore  {private static volatile BleCore mInstance;private final BleScan bleScan;public BleCore(Context context) {//藍(lán)牙掃描bleScan = BleScan.getInstance(context);}public static BleCore getInstance(Context context) {if (mInstance == null) {synchronized (BleCore.class) {if (mInstance == null) {mInstance = new BleCore(context);}}}return mInstance;}public void setPhyScanCallback(ScanCallback scanCallback) {bleScan.setScanCallback(scanCallback);}public boolean isScanning() {return bleScan.isScanning();}public void startScan() {bleScan.startScan();}public void stopScan() {bleScan.stopScan();}
}

四、業(yè)務(wù)處理

??這里的業(yè)務(wù)處理主要是兩個,第一個是藍(lán)牙開關(guān)監(jiān)聽,第二個動態(tài)權(quán)限申請。

再進(jìn)行業(yè)務(wù)處理之前,我們先修改一下MyApplication類的名字,修改為BleApp,修改后再改動里面的代碼,如下所示:

public class BleApp extends AbilityPackage {private static BleCore bleCore;@Overridepublic void onInitialize() {super.onInitialize();bleCore = BleCore.getInstance(getContext());}public static BleCore getBleCore() {return bleCore;}
}

① Slice的生命周期

??首先我們來看一下Slice的生命周期,這個就比較重要,下面我們首先在com.llw.ble下創(chuàng)建一個utils包,utils包下創(chuàng)建一個LogUtils類,代碼如下所示:

public class LogUtils {static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "HarmonyBle");private static HiLogLabel logLabel;public static void setLogLabel(HiLogLabel logLabel) {LogUtils.logLabel = logLabel;}public static void Log(String content) {HiLog.info(LABEL, content);}public static void LogI(String TAG, String content) {HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, TAG);HiLog.info(label, content);}public static void LogD(String TAG, String content) {HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, TAG);HiLog.debug(label, content);}public static void LogE(String TAG, String content) {HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, TAG);HiLog.error(label, content);}public static void LogW(String TAG, String content) {HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, TAG);HiLog.warn(label, content);}}

??這是因?yàn)镠armony中打印日志比較麻煩,所以寫一個工具類,封裝一下,下面我們修改一下ScanSlice類中的代碼,如下所示:

public class ScanSlice extends AbilitySlice {private final String TAG = ScanSlice.class.getSimpleName();@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setUIContent(ResourceTable.Layout_slice_scan);LogUtils.LogD(TAG, "onStart");}@Overridepublic void onActive() {LogUtils.LogD(TAG, "onActive");}@Overrideprotected void onInactive() {LogUtils.LogD(TAG, "onInactive");}@Overridepublic void onForeground(Intent intent) {LogUtils.LogD(TAG, "onForeground");}@Overrideprotected void onBackground() {LogUtils.LogD(TAG, "onBackground");}@Overrideprotected void onStop() {LogUtils.LogD(TAG, "onStop");}
}

然后我們運(yùn)行一下看看,檢查控制臺日志:

在這里插入圖片描述

然后我們通過Home鍵回到桌面,看看日志:

在這里插入圖片描述

然后我們點(diǎn)擊桌面上的圖標(biāo)回到應(yīng)用中,看看日志:

在這里插入圖片描述

再回到桌面,然后我們通過后臺的運(yùn)行程序進(jìn)入應(yīng)用,看看日志:

在這里插入圖片描述
這兩種回到應(yīng)用的方式日志一樣,然后我們按返回鍵回到桌面,看看日志:

在這里插入圖片描述
那么現(xiàn)在你對于Slice的生命周期就比較了解了,下面我們進(jìn)行代碼的編寫。

② 藍(lán)牙開關(guān)和動態(tài)權(quán)限請求

??首先處理藍(lán)牙相關(guān)的,在BleCore中添加如下代碼:

	private final BluetoothHost mBluetoothHost;

在構(gòu)造方法中實(shí)例化

    public BleCore(Context context) {...// 獲取藍(lán)牙本機(jī)管理對象mBluetoothHost = BluetoothHost.getDefaultHost(context);}

然后我們再寫兩個方法:

    public boolean isEnableBt() {return mBluetoothHost.getBtState() == BluetoothHost.STATE_ON;}public void enableBt() {mBluetoothHost.enableBt();}

??用于判斷是否打開藍(lán)牙和打開藍(lán)牙,回到ScanSlice中我們需要使用BleCore來處理藍(lán)牙相關(guān)的工作,代碼如下所示:

public class ScanSlice extends AbilitySlice {private final String TAG = ScanSlice.class.getSimpleName();private BleCore bleCore;private Text txScanStatus;private ListContainer lcDevice;@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setUIContent(ResourceTable.Layout_slice_scan);bleCore = BleApp.getBleCore();txScanStatus = (Text) findComponentById(ResourceTable.Id_tx_scan_status);lcDevice = (ListContainer) findComponentById(ResourceTable.Id_lc_device);//點(diǎn)擊監(jiān)聽txScanStatus.setClickedListener(component -> {});}@Overridepublic void onActive() {// 判斷是否打開藍(lán)牙if (!bleCore.isEnableBt()) {//打開藍(lán)牙bleCore.enableBt();return;}}
}

??首先在onStart()中對BleCore進(jìn)行實(shí)例化,findComponentById就如同findViewById,然后在onActive()中調(diào)用剛才我們所寫的方法。

    @Overridepublic void onActive() {// 判斷是否打開藍(lán)牙if (!bleCore.isEnableBt()) {//打開藍(lán)牙bleCore.enableBt();return;}}

然后是定位權(quán)限的處理,同樣在onActive()中,增加代碼如下所示:

    @Overridepublic void onActive() {// 判斷是否打開藍(lán)牙...// 是否獲取定位權(quán)限String locationPermission = "ohos.permission.LOCATION";if (verifySelfPermission(locationPermission) != IBundleManager.PERMISSION_GRANTED) {requestPermissionsFromUser(new String[]{locationPermission}, 100);return;}}

這里首先我們定義一個權(quán)限,然后判斷是否授予,沒有授予則進(jìn)行請求,下面運(yùn)行一下看看:

在這里插入圖片描述

??那么我們就完成了藍(lán)牙打開和定位權(quán)限動態(tài)申請,你可以在運(yùn)行一次,你會發(fā)現(xiàn),你還需要請求權(quán)限的,因?yàn)镈S默認(rèn)安裝時不會保留應(yīng)用的數(shù)據(jù),而藍(lán)牙打開了屬于系統(tǒng)層面的,所以你可以不用再打開藍(lán)牙,而需要重新請求定位權(quán)限,為了避免這一點(diǎn),我們點(diǎn)擊Run→ Edit Configurations...

在這里插入圖片描述

在彈出的窗口上勾選Keep Application Data

在這里插入圖片描述

點(diǎn)擊OK,再運(yùn)行即可。

五、掃描設(shè)備

??接下來我們進(jìn)行掃描的處理,在ScanSlice中增加如下方法代碼:

    private void startScan() {bleCore.startScan();txScanStatus.setText("停止");}private void stopScan() {bleCore.stopScan();txScanStatus.setText("搜索");}

??這里就是掃描和停止方法,同時修改一下Text文本,在onStart()中首先實(shí)現(xiàn)掃描回調(diào)監(jiān)聽,然后處理再處理txScanStatus文本的點(diǎn)擊事件,代碼如下所示:

    @Overridepublic void onStart(Intent intent) {...bleCore.setPhyScanCallback(this);//點(diǎn)擊監(jiān)聽txScanStatus.setClickedListener(component -> {if (bleCore.isScanning()) {stopScan();//掃描開關(guān)停止掃描} else {startScan();//開始掃描}});}

這里this會報錯,鼠標(biāo)放在上面,Alt + Enter,出現(xiàn)彈窗。

在這里插入圖片描述

選擇最后一個,就會給你實(shí)現(xiàn)ScanCallback中的onScanResult()方法,代碼如下所示:

    @Overridepublic void onScanResult(BleScanResult result) {LogUtils.LogD(TAG, result.getPeripheralDevice().getDeviceAddr());}

我們在里面打印一下掃描到的設(shè)備Mac地址,最后我們在onActive()中增加如下所示代碼:

    @Overridepublic void onActive() {...// 是否在掃描中if (!bleCore.isScanning()) {startScan();}}

下面運(yùn)行一下,看看控制臺日志:

在這里插入圖片描述

掃描出來了,只不過目前還看不到,所以我們要渲染一下,讓它可以看到。

六、顯示設(shè)備

要顯示設(shè)備,首先我們需要寫一個Bean。

① 自定義藍(lán)牙類

在core包下新建一個BleDevice類,里面的代碼如下所示:

public class BleDevice {private String realName = "Unknown device"; //藍(lán)牙設(shè)備真實(shí)名稱private String macAddress;                  //地址private int rssi;                           //信號強(qiáng)度private BlePeripheralDevice device;         //設(shè)備public BleDevice(BleScanResult scanResult) {this.device = scanResult.getPeripheralDevice();this.macAddress = device.getDeviceAddr();String name = device.getDeviceName().get();if (name != null || !name.isEmpty()) {this.realName = name;}this.rssi = scanResult.getRssi();}public String getRealName() {return realName;}public void setRealName(String realName) {this.realName = realName;}public String getMacAddress() {return macAddress;}public void setMacAddress(String macAddress) {this.macAddress = macAddress;}public int getRssi() {return rssi;}public void setRssi(int rssi) {this.rssi = rssi;}public BlePeripheralDevice getDevice() {return device;}public void setDevice(BlePeripheralDevice device) {this.device = device;}
}

??這個Bean沒有什么好說的,下面要做的就是列表Item的渲染,在Android中我們使用的是適配器Adapter,而在Harmony中使用的是提供者Provider

② 提供者

同樣我們先寫布局,在layout下新建一個item_scan_device.xml,代碼如下所示:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_content"ohos:width="match_parent"ohos:alignment="vertical_center"ohos:background_element="#FFF"ohos:bottom_padding="8vp"ohos:orientation="horizontal"ohos:right_padding="16vp"ohos:top_margin="1vp"ohos:top_padding="8vp"><Imageohos:height="match_content"ohos:width="match_content"ohos:end_margin="16vp"ohos:image_src="$graphic:ic_bluetooth"ohos:start_margin="16vp"/><DirectionalLayoutohos:height="match_content"ohos:width="match_content"ohos:orientation="vertical"ohos:weight="1"><Textohos:id="$+id:device_name"ohos:height="match_content"ohos:width="match_content"ohos:text="設(shè)備名稱"ohos:text_size="16fp"/><Textohos:id="$+id:device_address"ohos:height="match_content"ohos:width="match_content"ohos:text="設(shè)備地址"ohos:text_color="$color:gray"ohos:text_size="14fp"ohos:top_margin="4vp"/></DirectionalLayout><Textohos:id="$+id:rssi"ohos:height="match_content"ohos:width="match_content"ohos:align_parent_end="true"ohos:text_color="#000000"ohos:text_size="10fp"/></DirectionalLayout>

??幾個主要內(nèi)容,設(shè)備名稱、Mac地址、Rssi信號強(qiáng)度,然后這里有一個圖標(biāo),在graphic下創(chuàng)建一個ic_bluetooth.xml,代碼如下所示:

<?xml version="1.0" encoding="UTF-8"?><vectorxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="48vp"ohos:width="48vp"ohos:viewportHeight="1024"ohos:viewportWidth="1024"><pathohos:fillColor="#A7D3FF"ohos:pathData="M53.31,512a458.69,458.69 0,1 1,917.38 0A458.69,458.69 0,0 1,53.31 512zM584.96,301.82a356.16,356.16 0,0 0,-39.81 -26.69c-12.1,-6.34 -32,-13.89 -52.74,-3.01 -20.48,10.82 -25.86,31.23 -27.78,44.67 -1.92,13.18 -1.92,30.21 -1.92,48.45v77.18l-57.92,-49.6a32,32 0,0 0,-41.6 48.64L445.44,512 363.2,582.4a32,32 0,1 0,41.6 48.64l57.92,-49.6v77.18c0,18.24 0,35.33 1.92,48.51 1.92,13.44 7.23,33.86 27.78,44.61 20.74,10.88 40.64,3.33 52.74,-2.94a356.48,356.48 0,0 0,39.81 -26.69l39.42,-28.8c10.62,-7.74 21.31,-15.55 29.06,-23.1 8.64,-8.58 18.56,-21.57 18.56,-40.06 0,-18.56 -9.92,-31.55 -18.56,-40.06 -7.68,-7.55 -18.43,-15.36 -29.06,-23.17L548.99,512l75.39,-54.98c10.62,-7.74 21.31,-15.55 29.06,-23.17 8.64,-8.51 18.56,-21.5 18.56,-40 0,-18.56 -9.92,-31.55 -18.56,-40.06 -7.68,-7.62 -18.43,-15.36 -29.06,-23.17l-39.42,-28.8zM526.72,367.36v64.77c0,7.36 0,11.01 2.37,12.16 2.3,1.28 5.25,-0.9 11.2,-5.25l44.8,-32.7 8.32,-6.08c3.97,-2.94 5.95,-4.42 5.95,-6.53 0,-2.18 -1.98,-3.65 -5.95,-6.53l-8.32,-6.14 -36.1,-26.3a3344.06,3344.06 0,0 0,-9.34 -6.78c-5.44,-3.97 -8.19,-5.95 -10.5,-4.8 -2.37,1.15 -2.37,4.54 -2.37,11.33v12.86zM526.72,656.45L526.72,591.74c0,-7.36 0,-11.01 2.37,-12.16 2.3,-1.22 5.25,0.96 11.2,5.25l44.8,32.7 8.32,6.14c3.97,2.88 5.95,4.35 5.95,6.53 0,2.11 -1.98,3.58 -5.95,6.53l-8.32,6.08 -36.1,26.37 -9.34,6.78c-5.44,3.97 -8.19,5.95 -10.5,4.74 -2.37,-1.15 -2.37,-4.48 -2.37,-11.33v-12.8z"></path>
</vector>

??下面我們寫提供者,在com.llw.ble下創(chuàng)建一個provider包,包下創(chuàng)建一個ScanDeviceProvider類,代碼如下所示:

public class ScanDeviceProvider extends BaseItemProvider {private final List<BleDevice> deviceList;private final AbilitySlice slice;public ScanDeviceProvider(List<BleDevice> list, AbilitySlice slice) {this.deviceList = list;this.slice = slice;}@Overridepublic int getCount() {return deviceList == null ? 0 : deviceList.size();}@Overridepublic Object getItem(int position) {if (deviceList != null && position >= 0 && position < deviceList.size()) {return deviceList.get(position);}return null;}@Overridepublic long getItemId(int position) {return position;}@Overridepublic Component getComponent(int position, Component component, ComponentContainer componentContainer) {final Component cpt;ScanDeviceHolder holder;BleDevice device = deviceList.get(position);if (component == null) {cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_item_scan_device, null, false);holder = new ScanDeviceHolder(cpt);//將獲取到的子組件信息綁定到列表項(xiàng)的實(shí)例中cpt.setTag(holder);} else {cpt = component;// 從緩存中獲取到列表項(xiàng)實(shí)例后,直接使用綁定的子組件信息進(jìn)行數(shù)據(jù)填充。holder = (ScanDeviceHolder) cpt.getTag();}holder.deviceName.setText(device.getRealName());holder.deviceAddress.setText(device.getMacAddress());holder.rssi.setText(String.format(Locale.getDefault(), "%d dBm", device.getRssi()));return cpt;}/*** 用于保存列表項(xiàng)的子組件信息*/public static class ScanDeviceHolder {Text deviceName;Text deviceAddress;Text rssi;public ScanDeviceHolder(Component component) {deviceName = (Text) component.findComponentById(ResourceTable.Id_device_name);deviceAddress = (Text) component.findComponentById(ResourceTable.Id_device_address);rssi = (Text) component.findComponentById(ResourceTable.Id_rssi);}}
}

??通過提供者的代碼,可以看到它和適配器的寫法差不多,不同的是你得注意getComponent()方法中的處理,另外提供者默認(rèn)提供了Item的點(diǎn)擊方法,所以我們不用再自己去寫了。

③ 顯示設(shè)備

??我們回到ScanSlice中使用,首先我們創(chuàng)建幾個變量,代碼如下所示:

    private final List<BleDevice> mList = new ArrayList<>();private ScanDeviceProvider provider;

然后在onStart()方法中進(jìn)行初始化:

    @Overridepublic void onStart(Intent intent) {...provider = new ScanDeviceProvider(mList, this);lcDevice.setItemProvider(provider);//列表item點(diǎn)擊監(jiān)聽lcDevice.setItemClickedListener((listContainer, component, position, id) -> {});}

這里設(shè)置了列表提供者,然后添加item點(diǎn)擊監(jiān)聽,最后我們在掃描回調(diào)中渲染數(shù)據(jù),修改代碼如下所示:

private int findIndex(BleDevice bleDevice, List<BleDevice> deviceList) {int index = 0;for (final BleDevice devi : deviceList) {if (bleDevice.getMacAddress().equals(devi.getDevice().getDeviceAddr())) return index;index += 1;}return -1;}@Overridepublic void onScanResult(BleScanResult result) {BleDevice bleDevice = new BleDevice(result);int index = findIndex(bleDevice, mList);if (index == -1) {//添加新設(shè)備mList.add(bleDevice);} else {//更新已有設(shè)備的rssi和時間戳mList.get(index).setRssi(bleDevice.getRssi());}getUITaskDispatcher().syncDispatch(() -> provider.notifyDataChanged());}

這里添加一個findIndex()方法,用于添加設(shè)備和更新設(shè)備,最終通過UI線程同步刷新提供者,再修改一個開始掃描和停止掃描的方法代碼:

    private void startScan() {mList.clear();provider.notifyDataChanged();bleCore.startScan();txScanStatus.setText("停止");LogUtils.LogD(TAG,"開始掃描設(shè)備!");}private void stopScan() {bleCore.stopScan();txScanStatus.setText("搜索");LogUtils.LogD(TAG,"已經(jīng)停止掃描設(shè)備!");}

運(yùn)行一下看看:

在這里插入圖片描述

七、源碼

如果對你有所幫助的話,不妨 Star 或 Fork,山高水長,后會有期~

源碼地址:HarmonyBle-Java

http://aloenet.com.cn/news/29556.html

相關(guān)文章:

  • 豆瓣網(wǎng)站模板滕州今日頭條新聞
  • 自己的電腦做網(wǎng)站服務(wù)器seo的五個步驟
  • 找人做網(wǎng)站協(xié)議網(wǎng)站在線優(yōu)化檢測
  • 專業(yè)網(wǎng)站優(yōu)化外包百度seo推廣計(jì)劃類型包括
  • 怎么學(xué)做淘寶電商網(wǎng)站嗎關(guān)鍵詞搜索排行榜
  • html5 公眾號 網(wǎng)站開發(fā)百度seo優(yōu)化價格
  • 專業(yè)做根雕的網(wǎng)站廣州百度搜索優(yōu)化
  • 備案的網(wǎng)站名稱寫什么深圳整站全網(wǎng)推廣
  • 大眾點(diǎn)評怎么做團(tuán)購網(wǎng)站廣告軟文外鏈平臺
  • 做網(wǎng)站需要數(shù)據(jù)儲存么深圳網(wǎng)站設(shè)計(jì)三把火
  • 做網(wǎng)站十大公司哪家好短視頻推廣渠道
  • 92素材網(wǎng)安卓優(yōu)化大師官網(wǎng)
  • 手機(jī)微信網(wǎng)站怎么做的好深圳網(wǎng)站設(shè)計(jì)十年樂云seo
  • 最好的網(wǎng)站制作公司百度快照是怎么做上去的
  • 自己如何開自己的商城黑帽seo培訓(xùn)網(wǎng)
  • 杭州建立網(wǎng)站長沙企業(yè)網(wǎng)站建設(shè)報價
  • 動漫制作專業(yè)的高職實(shí)訓(xùn)室seo引擎搜索網(wǎng)站關(guān)鍵詞
  • 濟(jì)南外貿(mào)網(wǎng)站建設(shè)公司排名seo基礎(chǔ)入門免費(fèi)教程
  • 做網(wǎng)站和做軟件哪個賺錢丈哥seo博客工具
  • 網(wǎng)站投入費(fèi)用百度知道答題賺錢
  • 四川瑞通工程建設(shè)有限公司網(wǎng)站東莞谷歌推廣
  • 計(jì)算機(jī)做網(wǎng)站難嗎yandex搜索引擎
  • 河北省 政府網(wǎng)站 建設(shè)意見如何擁有自己的網(wǎng)站
  • 政府網(wǎng)站開發(fā)招標(biāo)文件山西免費(fèi)網(wǎng)站關(guān)鍵詞優(yōu)化排名
  • 做網(wǎng)站實(shí)驗(yàn)體會百度2022新版下載
  • 拼多多賣網(wǎng)站建設(shè)營銷活動策劃
  • 東莞正規(guī)的企業(yè)網(wǎng)站設(shè)計(jì)多少錢培訓(xùn)網(wǎng)站建設(shè)
  • 建設(shè)工程網(wǎng)站教程地推網(wǎng)app推廣平臺
  • wordpress建站更換圖片熱點(diǎn)新聞事件及評論
  • 做網(wǎng)站接專線費(fèi)用seo新方法