damoshayu.cn,苍井空浴缸大战猛男120分钟,网址你懂的,中国女人内射6XXXXXWWW

聯(lián)想yoga13s電源鍵亮但黑屏,聯(lián)想休眠后黑屏無(wú)法啟動(dòng)

大家好,今天小編來(lái)為大家解答聯(lián)想yoga13s電源鍵亮但黑屏,聯(lián)想休眠后黑屏無(wú)法啟動(dòng)這個(gè)問(wèn)題,聯(lián)想yoga13s電源鍵亮但黑屏,聯(lián)想休眠后黑屏無(wú)法啟動(dòng)很多人還不知道,現(xiàn)在讓我們一起來(lái)看看吧!YOGA新電腦到手該怎么設(shè)置?小白教程告訴你購(gòu)前需知#1聯(lián)想保修政策1.聯(lián)想對(duì)原廠部件進(jìn)行保修。2.如果原廠部件產(chǎn)生了非損

大家好,今天小編來(lái)為大家解答聯(lián)想yoga13s電源鍵亮但黑屏,聯(lián)想休眠后黑屏無(wú)法啟動(dòng)這個(gè)問(wèn)題,聯(lián)想yoga13s電源鍵亮但黑屏,聯(lián)想休眠后黑屏無(wú)法啟動(dòng)很多人還不知道,現(xiàn)在讓我們一起來(lái)看看吧!

YOGA新電腦到手該怎么設(shè)置?小白教程告訴你

購(gòu)前需知#1 聯(lián)想保修政策

1.聯(lián)想對(duì)原廠部件進(jìn)行保修。2.如果原廠部件產(chǎn)生了非損,則無(wú)法保修。3.自行加裝的第三方部件不保修,如鍵盤,屏幕,內(nèi)存,固態(tài)等,加裝部件不影響機(jī)器原有保修 (除非機(jī)器故障是因?yàn)榧友b部件引發(fā))。4.如果自行拆部件時(shí),把主板拆壞了,主板也會(huì)喪失保修。5.預(yù)裝系統(tǒng),一年內(nèi)送至服務(wù)站免費(fèi)恢復(fù)。6.拯救者自購(gòu)符合規(guī)格和兼容性的內(nèi)存、硬盤帶至服務(wù)站,可以免費(fèi)加裝。但是如果涉及到系統(tǒng)遷移,重新安裝系統(tǒng)至新加裝硬盤,需要付費(fèi)。

購(gòu)前需知#2 7天無(wú)理由退換貨條件

1.建議您在收到產(chǎn)品后,先檢查外包裝是否完好,如有暴力物流的跡象,可以拒收或者及時(shí)反饋給商家進(jìn)行處理。2.首次開機(jī)之前可先檢查產(chǎn)品外觀是否正常,如有瑕疵請(qǐng)盡快反饋給商家。3.收到機(jī)器后,請(qǐng)檢查新機(jī)外觀是否有問(wèn)題,若無(wú)問(wèn)題可進(jìn)行正常通電開機(jī),按流程完成Windows的設(shè)置向?qū)АS捎赪indows 11的設(shè)置向?qū)?qiáng)制機(jī)器聯(lián)網(wǎng),聯(lián)網(wǎng)后會(huì)自動(dòng)進(jìn)行激活,激活后不支持7天無(wú)理由退換貨。如果您確定機(jī)器正常無(wú)誤后,再聯(lián)網(wǎng)激活Windows以及后續(xù)的Office使用。但激活后發(fā)現(xiàn)產(chǎn)品有任何質(zhì)量問(wèn)題,均可通過(guò)售后渠道正常退換維修,無(wú)需擔(dān)心。4.進(jìn)行以上**作前,強(qiáng)烈建議您先聯(lián)系**平臺(tái)的官網(wǎng)售后,確認(rèn)下是否有其他影響產(chǎn)品7天無(wú)理由退貨的條款和要求,可以參考《網(wǎng)絡(luò)購(gòu)買商品七日無(wú)理由退貨暫行辦法》中主要相關(guān)內(nèi)容。

購(gòu)前需知#3 退換貨**

1.針對(duì)退換貨,7/15天的三包退換貨請(qǐng)直接聯(lián)系經(jīng)銷商(京東官方客服,天貓官方客服、聯(lián)想商城官方客服、線下專賣店店長(zhǎng)),如果超過(guò)15天,有特殊情況的退換貨,請(qǐng)撥打投訴電話,400-990-8888,轉(zhuǎn)9轉(zhuǎn)3。2.針對(duì)保修,建議聯(lián)系官方售后客服400-990-8888或聯(lián)想服務(wù)微信**人工咨詢或者在電腦預(yù)裝的聯(lián)想電腦管家點(diǎn)擊客戶服務(wù)咨詢。3.針對(duì)售后店面和**,在服務(wù)官網(wǎng)、聯(lián)想服務(wù)微信**中都可以查詢維修網(wǎng)點(diǎn)和**。

到手需知

1.機(jī)器出廠后將開啟運(yùn)輸模式,全新機(jī)器不插電是無(wú)法開機(jī)的,請(qǐng)插上電源再開機(jī)。2.新機(jī)在工廠組裝完畢后會(huì)導(dǎo)入系統(tǒng)并進(jìn)行檢測(cè),這會(huì)讓SSD產(chǎn)生一定的通電時(shí)間、使用次數(shù)和讀寫量,如果開機(jī)使用工具檢測(cè)到新機(jī)的SSD有通電時(shí)間、使用次數(shù)和讀寫量,屬于正常情況,聯(lián)想的通電時(shí)間標(biāo)準(zhǔn)在300小時(shí)內(nèi)。3.新機(jī)的屏幕(B面)與鍵盤(C面)之間會(huì)有一張無(wú)紡布,上面印有簡(jiǎn)單的使用說(shuō)明,還請(qǐng)閱讀。4.首次開機(jī)會(huì)進(jìn)行系統(tǒng)初始化,需要等待一段時(shí)間,期間可能會(huì)多次重啟,為正常情況。5.Windows 11的設(shè)置向?qū)?qiáng)制機(jī)器聯(lián)網(wǎng),聯(lián)網(wǎng)后會(huì)自動(dòng)進(jìn)行激活,激活后會(huì)影響7天無(wú)理由退換貨。6.預(yù)裝office需要您能聯(lián)網(wǎng)激活Windows之后6個(gè)月內(nèi)兌換激活,否則可能會(huì)無(wú)**常兌換激活。7.國(guó)行機(jī)器中預(yù)裝的Windows和Office需要在**大陸境內(nèi)網(wǎng)絡(luò)下激活,新機(jī)出國(guó)會(huì)影響Windows和Office的激活。

使用小技巧#1 使用Fn+Q一鍵切換散熱模式

YOGA和小新目前的機(jī)型均搭載Fn+Q一鍵切換散熱模式的功能,按住Fn鍵再按Q鍵可以在安靜模式——均衡模式——野獸模式間進(jìn)行循環(huán)切換,成功切換時(shí),屏幕上會(huì)顯示當(dāng)前的模式圖標(biāo)。

安靜模式下機(jī)器將會(huì)主動(dòng)限制風(fēng)扇的轉(zhuǎn)速,同時(shí)會(huì)限制整機(jī)功耗;均衡模式顧名思義,比較均衡,會(huì)根據(jù)當(dāng)前的負(fù)載自動(dòng)調(diào)節(jié)風(fēng)扇轉(zhuǎn)速;野獸模式將會(huì)讓機(jī)器以最大性能發(fā)揮,但是會(huì)增加風(fēng)扇轉(zhuǎn)速。大家可以根據(jù)自己的需求選擇運(yùn)行模式。

#2 使用Fn+R一鍵切換屏幕刷新率

我們的高刷屏機(jī)型,如YOGA 14s 2021、YOGA 16s 2022、小新Pro 14 高刷版和小新 Pro 16 銳龍獨(dú)顯版等都具備Fn+R一鍵切換屏幕刷新率功能,可以一鍵在高刷新率和60Hz之間進(jìn)行切換,使用方法非常簡(jiǎn)單,直接按Fn+R即可,屏幕上會(huì)顯示切換后對(duì)應(yīng)的刷新率圖標(biāo)。

如果沒(méi)有起效,請(qǐng)手動(dòng)運(yùn)行一次預(yù)裝的Lenovo Hotkeys軟件,之后將會(huì)持續(xù)起效。

#3 按Fn+空格調(diào)整鍵盤背光燈亮度

目前YOGA和小新機(jī)型均配備鍵盤背光燈,可以按Fn+空格調(diào)整它的開關(guān)及亮度,屏幕上會(huì)出現(xiàn)圖標(biāo)提示。

對(duì)于小新Pro 14、YOGA 14s 2021、YOGA 13s 2021、YOGA Pro 13s 2021、YOGA Pro 14s 2021和YOGA Pro 14s Carbon 2022這些機(jī)型,一共有四擋背光可調(diào),分別為關(guān)——50%亮度——100%亮度——自動(dòng)亮度。對(duì)于其他機(jī)型,則是有三擋可調(diào),分別為關(guān)——亮——更亮。

#4 快速進(jìn)入BIOS

有時(shí)候需要進(jìn)入BIOS修改一些設(shè)置,可以在重啟后黑屏?xí)r按F2鍵進(jìn)入,如果無(wú)法進(jìn)入,可以嘗試在完全關(guān)機(jī)的情況下按Delete左側(cè)第二個(gè)鍵,機(jī)器會(huì)自行啟動(dòng)并顯示啟動(dòng)菜單,用方向鍵移動(dòng)到BIOS Setup,用回車確定后會(huì)進(jìn)入。

#5 開啟人走自動(dòng)鎖屏功能

配備人臉識(shí)別前置攝像頭的機(jī)型支持人走自動(dòng)鎖屏功能,該功能通過(guò)前置攝像頭內(nèi)置的ToF傳感器實(shí)現(xiàn),軟件上需要在預(yù)裝的聯(lián)想電腦管家中開啟。

打開電腦管家,在工具箱頁(yè)面中找到智能感知。

**攝像頭自動(dòng)登錄功能可以讓您坐到電腦前時(shí)自動(dòng)亮屏并觸發(fā)人臉解鎖,無(wú)需**作即可解鎖;自動(dòng)鎖定屏幕可以在您離開電腦時(shí)自動(dòng)鎖定賬戶,保護(hù)隱私不泄漏。按需開啟相關(guān)功能即可。

#6 如何關(guān)閉/開啟開蓋開機(jī)

新的機(jī)器默認(rèn)開啟開蓋開機(jī)功能,不管在關(guān)機(jī)、休眠還是睡眠狀態(tài)下,掀開上蓋都可以喚醒機(jī)器,如果需要修改這個(gè)功能的狀態(tài),可以在聯(lián)想電腦管家的工具箱中找到開蓋開機(jī)功能,開關(guān)它即可。

#7 F1~F12對(duì)應(yīng)的快捷鍵都是啥?

輕薄本默認(rèn)將F1~F12鍵映射為功能快捷鍵,這排功能鍵的具體功能如下表:

原始按鍵功能Esc切換F1~F12功能F1靜音F2音量減F3音量增F4關(guān)閉/開啟麥克風(fēng)F5亮度減F6亮度增F7擴(kuò)展屏幕F8飛行模式F9系統(tǒng)設(shè)置F10鎖屏F11多任務(wù)切換F12計(jì)算器Insert聯(lián)想電腦管家PrtSc截圖工具

其中Fn+Esc可以快速切換功能鍵的映射狀態(tài),Esc旁有指示燈,與拯救者機(jī)型相反,亮著的時(shí)候功能鍵恢復(fù)為傳統(tǒng)F1~F12,燈滅時(shí)為默認(rèn)的功能快捷鍵。

#8 如何啟用/禁用觸控板

目前可以通過(guò)Windows系統(tǒng)設(shè)置來(lái)控制觸控板工作狀態(tài),Windows 10中這個(gè)開關(guān)位于“設(shè)備-觸摸板”中,Windows 11中位于“藍(lán)牙和其他設(shè)備-觸摸板”中。

需要說(shuō)明兩點(diǎn):

1.如果設(shè)置觸摸板關(guān)閉,重新開機(jī)后觸摸板不會(huì)自動(dòng)打開,并非觸控板故障。2.“連接鼠標(biāo)時(shí)讓觸摸板保持打開狀態(tài)”:取消勾選此項(xiàng)可實(shí)現(xiàn)插入鼠標(biāo)自動(dòng)禁用觸摸板功能。部分鼠標(biāo)驅(qū)動(dòng)軟件,即使沒(méi)有連接鼠標(biāo),也會(huì)使系統(tǒng)誤以為接通鼠標(biāo)狀態(tài)。沒(méi)插鼠標(biāo)但后臺(tái)有鼠標(biāo)軟件運(yùn)行時(shí),取消勾選此功能,觸摸板不會(huì)自動(dòng)啟用。

#9 如何修改電池充電模式

Windows 10下可直接點(diǎn)擊任務(wù)欄上的聯(lián)想電腦管家小掛件,在彈出的窗口里可以快速切換電池充電模式。

Windows 11下因?yàn)槿蝿?wù)欄的修改,需要打開聯(lián)想電腦管家,在設(shè)備狀態(tài)頁(yè)面中點(diǎn)擊耗電排行,充電模式位于彈出的側(cè)邊窗口的右上角。

#10 如何更新驅(qū)動(dòng)

更新驅(qū)動(dòng)推薦使用聯(lián)想電腦管家的驅(qū)動(dòng)更新功能,它的驅(qū)動(dòng)版本和官網(wǎng)同步。部分公版驅(qū)動(dòng)版本可能會(huì)新,但可能存在一些穩(wěn)定性和兼容性問(wèn)題,推薦使用官方驅(qū)動(dòng)。

#11 如何重置系統(tǒng)

如果需要還原出廠自帶的系統(tǒng),推薦通過(guò)系統(tǒng)自帶的重置功能進(jìn)行,Windows 10該功能位于“系統(tǒng)設(shè)置——更新和安全——恢復(fù)”,點(diǎn)擊“重置此電腦”的開始即可。Windows 11中該功能位于“系統(tǒng)設(shè)置——系統(tǒng)——恢復(fù)——重置此電腦”,點(diǎn)擊“重置此電腦”的開始即可。

Office 2021激活相關(guān)

Office 2021的激活信息改成了和設(shè)備綁定,不再和微軟賬戶綁定,所以在完成系統(tǒng)激活之后,打開Office就會(huì)進(jìn)入激活流程,部分出廠稍早的機(jī)器在這里會(huì)提示您更新Office,更新過(guò)后Office也會(huì)自動(dòng)激活。

#聯(lián)想##聯(lián)想服務(wù)#

鴻蒙分布式相機(jī)“踩坑”分享

實(shí)現(xiàn)分布式相機(jī)其實(shí)很簡(jiǎn)單,正如官方介紹的一樣,當(dāng)被控端相機(jī)被連接成功后,可以像使用本地設(shè)備一樣使用遠(yuǎn)程相機(jī)。

我們先看下效果:

上一篇已經(jīng)完整的介紹了如何開發(fā)一個(gè)本地相機(jī),對(duì)于分布式相機(jī)我們需要完成以下幾個(gè)步驟。

前置條件:兩臺(tái)帶攝像頭的設(shè)備建議使用相同版本的 OH 系統(tǒng),本案例使用 OpenHarmony 3.2 beta5連接在同一個(gè)網(wǎng)絡(luò)開發(fā)步驟:引入設(shè)備管理(@ohos.distributedHardware.deviceManager)通過(guò) deviceManager 發(fā)現(xiàn)周邊設(shè)備通過(guò) pin 碼完成設(shè)備認(rèn)證獲取和展示可信設(shè)備在可信設(shè)備直接選擇切換不同設(shè)備的攝像頭在主控端查看被控端的攝像頭圖像

以上描述的功能在應(yīng)用開發(fā)時(shí)可以使用一張草圖來(lái)表示,草圖中切換設(shè)備->彈窗顯示設(shè)備列表的過(guò)程,草圖如下:

代碼

①RemoteDeviceModel.ts

說(shuō)明: 遠(yuǎn)程設(shè)備業(yè)務(wù)處理類,包括獲取可信設(shè)備列表、獲取周邊設(shè)備列表、**設(shè)備狀態(tài)(上線、下線、狀態(tài)變化)、**設(shè)備連接失敗、設(shè)備授信認(rèn)證、卸載設(shè)備狀態(tài)**等。

代碼如下:

import deviceManager from ‘@ohos.distributedHardware.deviceManager’import Logger from ‘./util/Logger’const TAG: string = ‘RemoteDeviceModel’let subscribeId: number = -1export class RemoteDeviceModel { private deviceList: Array<deviceManager.DeviceInfo> = [] private discoverList: Array<deviceManager.DeviceInfo> = [] private callback: () => void private authCallback: () => void private deviceManager: deviceManager.DeviceManager constructor() { } public registerDeviceListCallback(bundleName : string, callback) { if (typeof (this.deviceManager) !== ‘undefined’) { this.registerDeviceListCallbackImplement(callback) return } Logger.info(TAG, `deviceManager.createDeviceManager begin`) try { deviceManager.createDeviceManager(bundleName, (error, value) => { if (error) { Logger.info(TAG, `createDeviceManager failed.`) return } this.deviceManager = value this.registerDeviceListCallbackImplement(callback) Logger.info(TAG, `createDeviceManager callback returned, error= ${error},value= ${value}`) }) } catch (err) { Logger.error(TAG, `createDeviceManager failed, code is ${err.code}, message is ${err.message}`) } Logger.info(TAG, `deviceManager.createDeviceManager end`) } private deviceStateChangeActionOffline(device) { if (this.deviceList.length <= 0) { this.callback() return } for (let j = 0; j < this.deviceList.length; j++) { if (this.deviceList[j ].deviceId === device.deviceId) { this.deviceList[j] = device break } } Logger.info(TAG, `offline, device list= ${JSON.stringify(this.deviceList)}`) this.callback() } private registerDeviceListCallbackImplement(callback) { Logger.info(TAG, `registerDeviceListCallback`) this.callback = callback if (this.deviceManager === undefined) { Logger.info(TAG, `deviceManager has not initialized`) this.callback() return } Logger.info(TAG, `getTrustedDeviceListSync begin`) try { let list = this.deviceManager.getTrustedDeviceListSync() Logger.info(TAG, `getTrustedDeviceListSync end, deviceList= ${JSON.stringify(list)}`) if (typeof (list) !== ‘undefined’ && typeof (list.length) !== ‘undefined’) { this.deviceList = list } } catch (err) { Logger.error(`getTrustedDeviceListSync failed, code is ${err.code}, message is ${err.message}`) } this.callback() Logger.info(TAG, `callback finished`) this.deviceManager.on(‘deviceStateChange’, (data) => { if (data === null) { return } Logger.info(TAG, `deviceStateChange data= ${JSON.stringify(data)}`) switch (data.action) { case deviceManager.DeviceStateChangeAction.READY: this.discoverList = [] this.deviceList.push(data.device) try { let list = this.deviceManager.getTrustedDeviceListSync() if (typeof (list) !== ‘undefined’ && typeof (list.length) !== ‘undefined’) { this.deviceList = list } this.callback() } catch (err) { Logger.error(TAG, `getTrustedDeviceListSync failed, code is ${err.code}, message is ${err.message}`) } break case deviceManager.DeviceStateChangeAction.OFFLINE: case deviceManager.DeviceStateChangeAction.CHANGE: this.deviceStateChangeActionOffline(data.device) break default: break } }) this.deviceManager.on(‘deviceFound’, (data) => { if (data === null) { return } Logger.info(TAG, `deviceFound data= ${JSON.stringify(data)}`) this.deviceFound(data) }) this.deviceManager.on(‘discoverFail’, (data) => { Logger.info(TAG, `discoverFail data= ${JSON.stringify(data)}`) }) this.deviceManager.on(‘serviceDie’, () => { Logger.info(TAG, `serviceDie`) }) this.startDeviceDiscovery() } private deviceFound(data) { for (var i = 0;i < this.discoverList.length; i++) { if (this.discoverList[i].deviceId === data.device.deviceId) { Logger.info(TAG, `device founded ignored`) return } } this.discoverList[this.discoverList.length] = data.device Logger.info(TAG, `deviceFound self.discoverList= ${this.discoverList}`) this.callback() } private startDeviceDiscovery() { if (subscribeId >= 0) { Logger.info(TAG, `started DeviceDiscovery`) return } subscribeId = Math.floor(65536 * Math.random()) let info = { subscribeId: subscribeId, mode: deviceManager.DiscoverMode.DISCOVER_MODE_ACTIVE, medium: deviceManager.ExchangeMedium.COAP, freq: deviceManager.ExchangeFreq.HIGH, isSameAccount: false, isWakeRemote: true, capability: deviceManager.SubscribeCap.SUBSCRIBE_CAPABILITY_DDMP } Logger.info(TAG, `startDeviceDiscovery ${subscribeId}`) try { // todo 多次啟動(dòng)發(fā)現(xiàn)周邊設(shè)備有什么影響嗎? this.deviceManager.startDeviceDiscovery(info) } catch (err) { Logger.error(TAG, `startDeviceDiscovery failed, code is ${err.code}, message is ${err.message}`) } } public unregisterDeviceListCallback() { Logger.info(TAG, `stopDeviceDiscovery $subscribeId}`) this.deviceList = [] this.discoverList = [] try { this.deviceManager.stopDeviceDiscovery(subscribeId) } catch (err) { Logger.error(TAG, `stopDeviceDiscovery failed, code is ${err.code}, message is ${err.message}`) } this.deviceManager.off(‘deviceStateChange’) this.deviceManager.off(‘deviceFound’) this.deviceManager.off(‘discoverFail’) this.deviceManager.off(‘serviceDie’) } public authenticateDevice(device, extraInfo, callBack) { Logger.info(TAG, `authenticateDevice ${JSON.stringify(device)}`) for (let i = 0; i < this.discoverList.length; i++) { if (this.discoverList[i].deviceId !== device.deviceId) { continue } let authParam = { ‘authType’: 1, ‘appIcon’: ”, ‘appThumbnail’: ”, ‘extraInfo’: extraInfo } try { this.deviceManager.authenticateDevice(device, authParam, (err, data) => { if (err) { Logger.error(TAG, `authenticateDevice error: ${JSON.stringify(err)}`) this.authCallback = null return } Logger.info(TAG, `authenticateDevice succeed: ${JSON.stringify(data)}`) this.authCallback = callBack }) } catch (err) { Logger.error(TAG, `authenticateDevice failed, code is ${err.code}, message is ${err.message}`) } } } /** * 已認(rèn)證設(shè)備列表 */ public getDeviceList(): Array<deviceManager.DeviceInfo> { return this.deviceList } /** * 發(fā)現(xiàn)設(shè)備列表 */ public getDiscoverList(): Array<deviceManager.DeviceInfo> { return this.discoverList }}

getDeviceList() :獲取已認(rèn)證的設(shè)備列表;getDiscoverList:發(fā)現(xiàn)周邊設(shè)備的列表。

②DeviceDialog.ets

說(shuō)明:通過(guò) RemoteDeviceModel.getDiscoverList() 和通過(guò) RemoteDeviceModel.getDeviceList() 獲取到所有周邊設(shè)備列表,用戶通過(guò)點(diǎn)擊”切換設(shè)備”按鈕彈窗顯示所有設(shè)備列表信息。

import deviceManager from ‘@ohos.distributedHardware.deviceManager’;const TAG = ‘DeviceDialog’// 分布式設(shè)備選擇彈窗@CustomDialogexport struct DeviceDialog { private controller?: CustomDialogController // 彈窗控制器 @Link deviceList: Array<deviceManager.DeviceInfo> // 設(shè)備列表 @Link selectIndex: number // 選中的標(biāo)簽 build() { Column() { List() { ForEach(this.deviceList, (item: deviceManager.DeviceInfo, index) => { ListItem() { Row() { Text(item.deviceName) .fontSize(22) .width(350) .fontColor(Color.Black) Image(index === this.selectIndex ? $r(‘app.media.checked’) : $r(‘app.media.uncheck’)) .width(35) .objectFit(ImageFit.Contain) } .height(55) .onClick(() => { console.info(`${TAG} select device ${item.deviceId}`) if (index === this.selectIndex) { console.info(`${TAG} device not change`) } else { this.selectIndex = index } this.controller.close() }) } }, item => item.deviceName) } .width(‘100%’) .height(150) Button() { Text($r(‘app.string.cancel’)) .width(‘100%’) .height(45) .fontSize(18) .fontColor(Color.White) .textAlign(TextAlign.Center) }.onClick(() => { this.controller.close() }) .backgroundColor(‘#ed3c13’) } .width(‘100%’) .padding(20) .backgroundColor(Color.White) .border({ color: Color.White, radius: 20 }) }}

③打開設(shè)備列表彈窗

說(shuō)明:在 index.ets 頁(yè)面中,點(diǎn)擊“切換設(shè)備”按鈕即可以開啟設(shè)備列表彈窗,通過(guò) @Watch(‘selectedIndexChange’) **用戶選擇的設(shè)備標(biāo)簽,在 devices 中獲取到具體的 DeviceInfo 對(duì)象。

代碼如下:

@State @Watch(‘selectedIndexChange’) selectIndex: number = 0 // 設(shè)備列表 @State devices: Array<deviceManager.DeviceInfo> = [] // 設(shè)備選擇彈窗 private dialogController: CustomDialogController = new CustomDialogController({ builder: DeviceDialog({ deviceList: $devices, selectIndex: $selectIndex, }), autoCancel: true, alignment: DialogAlignment.Center }) showDialog() { console.info(`${TAG} RegisterDeviceListCallback begin`) distributed.registerDeviceListCallback(BUNDLE_NAME, () => { console.info(`${TAG} RegisterDeviceListCallback callback entered`) this.devices = [] // 添加本地設(shè)備 this.devices.push({ deviceId: Constant.LOCAL_DEVICE_ID, deviceName: Constant.LOCAL_DEVICE_NAME, deviceType: 0, networkId: ”, range: 1 // 發(fā)現(xiàn)設(shè)備的距離 }) let discoverList = distributed.getDiscoverList() let deviceList = distributed.getDeviceList() let discoveredDeviceSize = discoverList.length let deviceSize = deviceList.length console.info(`${TAG} discoveredDeviceSize:${discoveredDeviceSize} deviceSize:${deviceSize}`) let deviceTemp = discoveredDeviceSize > 0 ? discoverList : deviceList for (let index = 0; index < deviceTemp.length; index++) { this.devices.push(deviceTemp[index]) } }) this.dialogController.open() console.info(`${TAG} RegisterDeviceListCallback end`) }async selectedIndexChange() { console.info(`${TAG} select device index ${this.selectIndex}`) let discoverList: Array<deviceManager.DeviceInfo> = distributed.getDiscoverList() if (discoverList.length <= 0) { this.mCurDeviceID = this.devices[this.selectIndex].deviceId await this.switchDevice() this.devices = [] return } let selectDeviceName = this.devices[this.selectIndex].deviceName let extraInfo = { ‘targetPkgName’: BUNDLE_NAME, ‘appName’: APP_NAME, ‘appDescription’: APP_NAME, ‘business’: ‘0’ } distributed.authenticateDevice(this.devices[this.selectIndex], extraInfo, async () => { // 獲取到相關(guān)的設(shè)備ID,啟動(dòng)遠(yuǎn)程應(yīng)用 for (var index = 0; index < distributed.getDeviceList().length; index++) { let deviceName = distributed.getDeviceList()[index].deviceName if (deviceName === selectDeviceName) { this.mCurDeviceID = distributed.getDeviceList()[index].deviceId await this.switchDevice() } } }) this.devices = [] }④重新加載相機(jī)

說(shuō)明:根據(jù)用戶選擇的設(shè)備標(biāo)簽獲取到當(dāng)前用戶需要切換的相機(jī)設(shè)備對(duì)象,重新加載相機(jī),重新加載需要釋放原有的相機(jī)資源,然后重新構(gòu)建 createCameraInput、createPreviewOutput、createSession。

可能你注意到這里好像沒(méi)有執(zhí)行 createPhotoOutput,這是因?yàn)樵趯?shí)踐過(guò)程中發(fā)現(xiàn),添加了一個(gè)當(dāng)前設(shè)備所支持的拍照配置到會(huì)話管理(CaptureSession.addOutput())時(shí),系統(tǒng)會(huì)返回當(dāng)前拍照配置流不支持,并關(guān)閉相機(jī),導(dǎo)致相機(jī)預(yù)覽黑屏,所以這里沒(méi)有添加。

issues:遠(yuǎn)程相機(jī)拍照失敗 not found in supported streams。

mCameraService:這個(gè)是相機(jī)管理類,代碼可以查看上一篇:OpenHarmony 分布式相機(jī)(上)中查看。

代碼如下:

/** * 切換攝像頭 * 同一臺(tái)設(shè)備上切換不同攝像頭 */ async switchCamera() { console.info(`${TAG} switchCamera`) let cameraList = this.mCameraService.getDeviceCameras(this.mCurDeviceID) if (cameraList && cameraList.length > 1) { let cameraCount: number = cameraList.length console.info(`${TAG} camera list ${cameraCount}}`) if (this.mCurCameraIndex < cameraCount – 1) { this.mCurCameraIndex += 1 } else { this.mCurCameraIndex = 0 } await this.reloadCamera() } else { this.showToast($r(‘app.string.only_one_camera_hint’)) } } /** * 重新加載攝像頭 */ async reloadCamera() { // 顯示切換loading this.isSwitchDeviceing = true // 先關(guān)閉當(dāng)前**,再切換新的** await this.mCameraService.releaseCamera() await this.startPreview() }private async startPreview() { console.info(`${TAG} startPreview`) await this.mCameraService.createCameraInput(this.mCurCameraIndex, this.mCurDeviceID) await this.mCameraService.createPreviewOutput(this.surfaceId, this.previewImpl) if (this.mCurDeviceID === Constant.LOCAL_DEVICE_ID) { // fixme xjs 如果是遠(yuǎn)程相機(jī),則不支持拍照,添加拍照輸出流會(huì)導(dǎo)致相機(jī)黑屏 await this.mCameraService.createPhotoOutput(this.functionBackImpl) } await this.mCameraService.createSession(this.surfaceId) }⑤加載過(guò)度動(dòng)畫

說(shuō)明:在相機(jī)切換中會(huì)需要釋放原相機(jī)的資源,在重啟新相機(jī),在通過(guò)軟總線通道同步遠(yuǎn)程相機(jī)的預(yù)覽數(shù)據(jù)。

這里需要一些時(shí)間,根據(jù)目前測(cè)試,在網(wǎng)絡(luò)穩(wěn)定狀態(tài)下,切換時(shí)間 3~5s,網(wǎng)絡(luò)不穩(wěn)定狀態(tài)下,切換最長(zhǎng)需要 13s,當(dāng)然有時(shí)候會(huì)出現(xiàn)無(wú)法切換成功,這種情況可能是遠(yuǎn)程設(shè)備已經(jīng)下線,無(wú)法再獲取到數(shù)據(jù)。

代碼如下:

@State isSwitchDeviceing: boolean = false // 是否正在切換相機(jī) if (this.isSwitchDeviceing) { Column() { Image($r(‘app.media.load_switch_camera’)) .width(400) .height(306) .objectFit(ImageFit.Fill) Text($r(‘app.string.switch_camera’)) .width(‘100%’) .height(50) .fontSize(16) .fontColor(Color.White) .align(Alignment.Center) } .width(‘100%’) .height(‘100%’) .backgroundColor(Color.Black) .justifyContent(FlexAlign.Center) .alignItems(HorizontalAlign.Center) .onClick(() => { }) }

至此,分布式相機(jī)的整體流程就已實(shí)現(xiàn)完成。下面我們介紹下分布式相機(jī)開發(fā)中所遇到的問(wèn)題。

分布式相機(jī)問(wèn)題一覽

對(duì)于開發(fā)過(guò)程中所遇到的一些坑,前面多少有簡(jiǎn)單的提到一些,這里做一次規(guī)整,也算是一次回顧。

①首次授權(quán)成功無(wú)法顯示相機(jī)預(yù)覽

解析:我們正常會(huì)在 MainAbility.ts 的 onCreate() 函數(shù)加載的時(shí)候執(zhí)行申請(qǐng)授權(quán),在 index.ets 頁(yè)面中,當(dāng) XComponent 組件 onLoad() 回調(diào)后執(zhí)行初始化相機(jī)**作,代碼如下:

MainAbility.ts:

const TAG: string = ‘[DistributedCamera]’let permissionList: Array<string> = [ “ohos.permission.MEDIA_LOCATION”, “ohos.permission.READ_MEDIA”, “ohos.permission.WRITE_MEDIA”, “ohos.permission.CAMERA”, “ohos.permission.MICROPHONE”, “ohos.permission.DISTRIBUTED_DATASYNC”]export default class MainAbility extends Ability { async onCreate(want, launchParam) { console.info(`${TAG} onCreate`) globalThis.cameraAbilityContext = this.context await globalThis.cameraAbilityContext.requestPermissionsFromUser(permissionList) } }

index.ets:

// …// 截取部分主要代碼Column() { XComponent({ id: ‘componentId’, type: ‘surface’, controller: this.XComponentController }).onLoad(async () => { console.info(`${TAG} XComponent onLoad is called`) this.XComponentController.setXComponentSurfaceSize({ surfaceWidth: Resolution.DEFAULT_WIDTH, surfaceHeight: Resolution.DEFAULT_HEIGHT }) this.surfaceId = this.XComponentController.getXComponentSurfaceId() console.info(`${TAG} surfaceId: ${this.surfaceId}`) await this.initCamera() }).height(‘100%’) .width(‘100%’) } .width(‘100%’) .height(‘75%’) .margin({ bottom: 20 })// …

應(yīng)用啟動(dòng)后,調(diào)用了 requestPermissionsFromUser() 請(qǐng)求權(quán)限后,但未手動(dòng)授權(quán)時(shí),查看相關(guān)日志:

日志告訴我們,page 的生命周期已啟動(dòng)到 onShow,并且頁(yè)面布局也完成了加載,XComponent 組件回調(diào) onLoad()。

但是由于還未授權(quán),導(dǎo)致無(wú)法初始化相機(jī),此時(shí)即便授權(quán)成功,也不會(huì)再進(jìn)行初始化,導(dǎo)致相機(jī)無(wú)法啟動(dòng),無(wú)預(yù)覽視圖。

知道原因后,我們可以有多種方式解決,重點(diǎn)就是在授權(quán)完成后,需要再次觸發(fā)初始化相機(jī),讓相機(jī)啟動(dòng)才可以正常預(yù)覽。

我的處理方式:在 index.ets 頁(yè)面中處理授權(quán)定義是否已授權(quán)的標(biāo)識(shí),用于判斷是否可以初始化相機(jī)定義是否已經(jīng)初始化相機(jī)標(biāo)識(shí),防止對(duì)此初始化在 page 頁(yè)面初始化函數(shù) aboutToAppear() 中請(qǐng)求權(quán)限,并在權(quán)限申請(qǐng)結(jié)果中添加初始化相機(jī)**作XComponent 組件回調(diào) onLoad() 初始化相機(jī)**作不變index.ets:

private isInitCamera: boolean = false // 是否已初始化相機(jī) private isPermissions: boolean = false // 是否完成授權(quán) async aboutToAppear() { console.info(`${TAG} aboutToAppear`) globalThis.cameraAbilityContext.requestPermissionsFromUser(permissionList).then(async (data) => { console.info(`${TAG} data permissions: ${JSON.stringify(data.permissions)}`) console.info(`${TAG} data authResult: ${JSON.stringify(data.authResults)}`) // 判斷授權(quán)是否完成 let resultCount: number = 0 for (let result of data.authResults) { if (result === 0) { resultCount += 1 } } if (resultCount === permissionList.length) { this.isPermissions = true } await this.initCamera() // 獲取縮略圖 this.mCameraService.getThumbnail(this.functionBackImpl) }) }

②相機(jī)應(yīng)用未關(guān)閉,系統(tǒng)息屏后重新點(diǎn)亮,重新返回相機(jī)應(yīng)用,無(wú)預(yù)覽輸出流返回

解析:從現(xiàn)象看,預(yù)覽畫面卡在息屏前的狀態(tài),需要退出應(yīng)用后,重啟應(yīng)用才能正常預(yù)覽。從日志上看沒(méi)有查看到具體的原因,只是 camera_host 的數(shù)據(jù)量日志消失。

猜想:相機(jī)在系統(tǒng)息屏后強(qiáng)制關(guān)閉,需要重新加載相機(jī)才能正常預(yù)覽,實(shí)現(xiàn)方式如下:

在 page 的 onPageShow() 回調(diào)函數(shù)中重新初始化相機(jī)。在 page 的 onPageHide() 函數(shù)中釋放相機(jī)資源,減少系統(tǒng)資源不必要的消耗。index.ets:

async onPageShow() { console.info(`${TAG} onPageShow`) await this.initCamera() } onPageHide() { console.info(`${TAG} onPageHide`) this.isSwitchDeviceing = false this.isInitCamera = false this.mCameraService.releaseCamera() }

結(jié)論: 實(shí)踐驗(yàn)證此方法有效解決息屏后點(diǎn)亮返回相機(jī)無(wú)法預(yù)覽的問(wèn)題。

③加載遠(yuǎn)程相機(jī),在會(huì)話管理中添加拍照輸出流,無(wú)法拍照,預(yù)覽黑屏

解析:兩臺(tái)設(shè)備 pin 碼認(rèn)證通過(guò),連接成功,在主控端選擇一臺(tái)被控端設(shè)備時(shí),加載相機(jī),流程與加載本地相機(jī)相同。

流程如下:

createCameraInput()createPreviewOutput()createPhotoOutput()createSession()* createSession.beginConfig()* createSession.addInput(CameraInput)* createSession.addOutput(PreviewOutput)* createSession.addOutput(PhotoOutput)* createSession.commitConfig()* createSession.start()

經(jīng)過(guò)排查,發(fā)現(xiàn)日志中返回異常 not found in supported streams,詳情可以查看關(guān)聯(lián) issues。

原因:在創(chuàng)建 PhotoOutput 時(shí)需要傳遞支持的拍照配置信息 Profile,這里的 Profile 可以通過(guò) CmeraManager.getSupportedOutputCapability() 返回的相機(jī)輸出能力 CameraOutputCapability 對(duì)象獲取,但遠(yuǎn)程相機(jī)設(shè)備拍照輸出能力列表返回空。

但通過(guò)查看本地相機(jī)拍照輸出能力可知 DAYU200 設(shè)備支持的 Profile 信息:

photoProfile {“format”:2000,”size”:{“width”:1280,”height”:960}}

通過(guò)此將 photoProfile 作為遠(yuǎn)程相機(jī)設(shè)備構(gòu)建拍照輸出流的入?yún)?chǎng)景拍照輸出流,并把此添加到拍照會(huì)話管理中,但是界面出現(xiàn)不支持此相機(jī)配置,最終關(guān)閉了相機(jī),導(dǎo)致黑屏。

解決方案:根據(jù)此問(wèn)題,目前只能根據(jù)場(chǎng)景判斷是否需要添加拍照輸出流到會(huì)話管理,對(duì)于本地相機(jī)則可以添加拍照輸出流,執(zhí)行拍照業(yè)務(wù),遠(yuǎn)程相機(jī)則不添加拍照輸出流,這也就不能執(zhí)行拍照業(yè)務(wù),希望社區(qū)有解決方案。

④切換不同設(shè)備上的相機(jī),相機(jī)預(yù)覽輸出流出現(xiàn)異常,無(wú)法顯示遠(yuǎn)程相機(jī)的畫面

解析: 此問(wèn)題存在的原因可能有多種,這里我說(shuō)下我遇到的情況。

(1)分布式連接被斷開,但是因?yàn)榈讓訖C(jī)制,設(shè)備之間下線需要在一段時(shí)間內(nèi)才能上報(bào)(預(yù)計(jì) 5 分鐘),所以在應(yīng)用層看到可以連接的遠(yuǎn)端設(shè)備,其實(shí)已經(jīng)下線了,這時(shí)當(dāng)然不能切換到遠(yuǎn)程相機(jī)。

(2)與問(wèn)題 3 中描述的相同,因?yàn)樘砑恿艘粋€(gè)無(wú)法支持的拍照配置信息導(dǎo)致相機(jī)被關(guān)閉。

解決方案:

等待線下通知,再重新連接設(shè)備,或者等待設(shè)備自動(dòng)完成重連,簡(jiǎn)單粗暴就是重啟設(shè)備。待社區(qū)反饋。⑤相機(jī)業(yè)務(wù)在主線程執(zhí)行,需要將業(yè)務(wù)移動(dòng)到子線程,防止 UI 線程堵塞

解析:如題描述,目前可能存在堵塞 UI 線程的可能,需要將一些耗時(shí)的**作移動(dòng)到子線程,比如預(yù)覽、拍照保存圖片等。

目前正在修改優(yōu)化,關(guān)于 ets 的異步線程 worker 可以查看之前寫的一篇關(guān)于:??OpenHarmony stage worker 多線程??。

⑥遠(yuǎn)程相機(jī)預(yù)覽數(shù)據(jù)傳輸存在 500ms 的延遲

解析:在 wifi 環(huán)境下,被控端相機(jī)將預(yù)覽數(shù)據(jù)通過(guò)軟總線傳輸?shù)街骺囟孙@示,有 500ms 左右的延遲,此問(wèn)題待排查,具體是那個(gè)環(huán)境出現(xiàn)的延遲。

⑦no permission for function call

解析:用戶動(dòng)態(tài)授予:允許不同設(shè)備間的數(shù)據(jù)(ohos.permission.DISTRIBUTED_DATASYNC) 交換權(quán)限后,DeviceManager.startDeviceDiscovery() 啟動(dòng)發(fā)現(xiàn)周邊設(shè)備總會(huì)出現(xiàn)異常。

日志中提示:

discoverFail data= {“subscribeId”:26386,”reason”:-20007,”errInfo”:”no permission for function call.”}

原因: 非系統(tǒng)應(yīng)用無(wú)法使用 DeviceManager,詳細(xì)可查看:issues。

解決方案:系統(tǒng)應(yīng)用和普通應(yīng)用是通過(guò)簽名來(lái)區(qū)分,那只要通過(guò)修改簽名 UnsgnedReleasedProfileTemplate.json 文件中的 app-feature 值為 ohos_system_app,即為系統(tǒng)應(yīng)用。

聯(lián)想yoga13s電源鍵亮但黑屏,聯(lián)想休眠后黑屏無(wú)法啟動(dòng)和聯(lián)想yoga13s電源鍵亮但黑屏,聯(lián)想休眠后黑屏無(wú)法啟動(dòng)的問(wèn)題分享結(jié)束啦,以上的文章解決了您的問(wèn)題嗎?歡迎您下次再來(lái)哦!

原創(chuàng)文章,作者:Admin,如若轉(zhuǎn)載,請(qǐng)注明出處:http:///195413.html