主頁 > 移動端開發 > HarmonyOS USB DDK助你輕松實作USB驅動開發

HarmonyOS USB DDK助你輕松實作USB驅動開發

2022-03-29 08:08:18 移動端開發

HDF(Hardware Driver Foundation)驅動框架是HarmonyOS硬體生態開放的基礎,為開發者提供了驅動加載、驅動服務管理和驅動訊息機制等驅動能力,讓開發者能精準且高效地開發驅動程式,

 

本期,我們將為大家帶來HDF驅動框架中USB DDK的決議與指導,

 

一、USB DDK介紹


USB(Universal Serial Bus)通用串行總線,用于規范電腦與外部設備的連接和通訊,包含了主機端(Host)和設備端(Device),其中,主機端負責USB總線中的資料傳輸及埠管理,設備端則可以連接各種外設,所以USB驅動開發又分為主機端驅動開發和設備端驅動開發, 

 

由于基于內核態開發的USB驅動功能擴展性較差,目前開發者通常選擇Libusb庫進行USB驅動開發,該庫是一種跨平臺的用戶態開源USB通信庫,可以滿足開發者基于用戶態開發功能驅動的需求,但是,由于Libusb庫是完全按照USB協議來封裝介面的,所以需要開發者對USB協議要有較深的了解才能很好的使用,對開發者的要求相對較高,讓很多比較初級的開發者望而卻步,為了讓更多的開發者都能進行基于用戶態的USB驅動開發,HDF引入了USB DDK開發套件, 

 

USB DDK(USB DriverDevelop Kit)是HDF驅動框架為開發者提供的USB驅動程式開發套件,包括USB Host DDK及USB Device DDK兩部分,支持基于用戶態開發USB設備驅動的同時,還提供了豐富的USB驅動開發能力,讓廣大開發者能精準且高效的開發USB驅動程式,

 

下面,我們將一一道來,  

 

1)USB Host DDK


USB Host DDK給開發者提供了主機端USB驅動開發能力,按照功能分類三大類,分別是DDK初始化類、interface物件操作類及request物件操作類,并為開發者提供了普通模式和專家模式兩種開發模式,普通模式下,開發者可通過USBDDK API直接完成相關USB資料讀寫操作,不需要過多關注底層傳輸細節,

 

專家模式下,開發者通過USB RAW API直接訪問OS平臺USB通道的介面,自定義實作更加復雜的功能,目的是給驅動層留有更靈活,更強大的擴展方案,同時也能夠兼容現有驅動,便于移植,USBHost DDK架構如圖1所示:

 

圖1 USB Host DDK架構

 

(1)USB Interface Pool負責USBInterface管理,提供USB Interface申請和回收,USB Interface記錄設備埠資訊以及資源,USB Interface Pool按照USB Port對USB Interface進行分類管理,同時,此模塊還提供了USB DDK API,方便開發者USB資料讀寫操作, 

 

(2)USB Protocol Layer提供USB協議封裝,根據USB協議對設備IO/控制命令的“翻譯/決議”,同時負責設備描述符的管理,根據USB Device上報的列舉資訊,匹配對應的描述符,并構建對應的USB Interface,并加入到USB Interface Pool中管理, 

 

(3)Device IO Manager負責USBIO請求管理,提供了同步IO和異步IO管理機制,對于異步IO,IO Manager負責將該請求記錄下來,然后通過Raw API Library提供的介面依次處理待發送的IO請求;當收到USB控制器應答的處理結果后,IO接收執行緒負責決議并上報處理結果給上層呼叫者, 

 

(4)Raw API Library抽象了底層OS能力,定義了統一的OS能力介面,對外提供了USB RAW API,讓開發者自定義實作更加復雜的驅動功能, 

 

(5)OS Adapter用于封裝與平臺(Linux和LiteOS)相關的操作,根據不同平臺配置編譯對應平臺的封裝介面,在Linux平臺上,訪問USBFS的操作,全部都封裝在這個模塊中;而在LiteOS平臺上,基于FreeBSD USB框架的設備訪問操作,對應的也都全部封裝在這個模塊中, 

 

(6)PNP Notify用于動態監測USB狀態變化,當有新設備添加/移除時,變化設備資訊,同時將所有USB設備資訊都通過KHDF上報給UHDF側的PNPNotify Manager模塊來完成加載/卸載第三方功能驅動, 

 

2)USB Device DDK


USB Device DDK給開發者提供了設備端USB驅動開發能力,例如,USB埠動態注冊和去注冊能力,開發者可以基于能力實作USB埠的動態添加和組合;動態實體化能力,支持根據動態下發設備、配置、介面及端點描述符創建設備實體及傳輸通道;用戶態的資料發送及接收能力,支持用戶態下發送及接收資料;復合設備能力,支持一個物理設備上多個邏輯設備,實作多個邏輯設備間隔離,并支持不同邏輯設備同時被不同的應用行程訪問,

 

USB Device DDK架構如圖2所示: 

 

圖2 USB Device DDK架構

 

(1)SDK IF負責將USB設備按照設備、介面、管道進行邏輯劃分,對配置管理、設備管理、IO管理進行封裝,此模塊還向開發者提供了設備創建、獲取介面、接收Event事件、收發資料等設備測驅動開發的能力介面,

 

(2)Configuration Manager負責決議HCS檔案描述的USB描述符資訊,得到的USB描述符資訊用于設備創建,同時模塊還提供了自定義屬性的讀取、創建、洗掉、修改等操作,

 

(3)Device Manager負責根據配置模塊決議的USB描述符,并根據USB描述符創建設備,同時模塊還負責獲取設備、洗掉設備、獲取設備狀態,獲取設備上面介面資訊, 

 

(4)IO Manager負責資料的讀寫,包括Events事件、資料讀寫完成事件的接受,支持同步和異步模式資料讀寫, 

 

(5)Adapter IF主要是對復合設備配置驅動及通用功能驅動設備節點操作進行封裝,為上層提供統一的設備管理介面, 

 

(6)Adapter該模塊由復合設備配置驅動及通用功能驅動提供,  

 

二、USB DDK開發指導


相信大家已對USB DDK已經有了一定的認識,下面,我們來看看如何使用USB DDK來開發USB Host和USB Device驅動程式吧, 

 

1)USB Host的開發


USB Host(主機端驅動)主要完成協議封裝、設備管理、驅動安裝與卸載等,通過上文的介紹,開發者可通過USB DDK API和USB RAW API來實作主機端驅動, 

 

1. USB DDK API的使用

 

USB DDK API主要實作主機端USB資料讀寫操作,如圖3所示,是USB DDK API提供的部分介面,                                              

 

圖3 USB DDK API部分介面

 

使用步驟如下:

 

(1) 配置驅動匹配表,完成主機端驅動總體資訊的配置,具體如下:

 

struct UsbPnpMatchIdTable {
//驅動模塊名,該欄位的值必須和驅動入口結構的moduleName一致
const char *moduleName;
//驅動對外發布服務的名稱,必須唯一
const char *serviceName;
//驅動私有資料匹配關鍵字
const char *deviceMatchAttr;
//從該欄位開始(包含該欄位)之后資料長度,以byte為單位
uint8_t length;
//USB驅動匹配規則
uint16_t matchFlag;
//廠商編號
uint16_t vendorId;
//產品編號
uint16_t productId;
//設備出廠編號,低16位
uint16_t bcdDeviceLow;
//設備出廠編號,高16位
uint16_t bcdDeviceHigh;  
//USB分配的設備類代碼
uint8_t deviceClass;
//USB分配的子類代碼
uint8_t deviceSubClass;
//USB分配的設備協議代碼
uint8_t deviceProtocol;
//介面型別,根據實際需要可填寫多個
uint8_t interfaceClass[USB_PNP_INFO_MAX_INTERFACES];
//介面子型別,根據實際需要可填寫多個
uint8_t interfaceSubClass[USB_PNP_INFO_MAX_INTERFACES];
//介面所遵循的協議,根據實際需要可填寫多個
uint8_t interfaceProtocol[USB_PNP_INFO_MAX_INTERFACES];
//介面的編號,根據實際需要可填寫多個
uint8_t interfaceNumber[USB_PNP_INFO_MAX_INTERFACES];
};

 

其中matchFlag表示驅動匹配規則,每個bit表示一種匹配方式,其取值如下: 

 

enum {
    USB_PNP_NOTIFY_MATCH_VENDOR = 0x0001,
    USB_PNP_NOTIFY_MATCH_PRODUCT = 0x0002,
    USB_PNP_NOTIFY_MATCH_DEV_LOW = 0x0004,
    USB_PNP_NOTIFY_MATCH_DEV_HIGH = 0x0008,
    USB_PNP_NOTIFY_MATCH_DEV_CLASS = 0x0010,
    USB_PNP_NOTIFY_MATCH_DEV_SUBCLASS = 0x0020,
    USB_PNP_NOTIFY_MATCH_DEV_PROTOCOL = 0x0040,
    USB_PNP_NOTIFY_MATCH_INT_CLASS = 0x0080,
    USB_PNP_NOTIFY_MATCH_INT_SUBCLASS = 0x0100,
    USB_PNP_NOTIFY_MATCH_INT_PROTOCOL = 0x0200,
    USB_PNP_NOTIFY_MATCH_INT_NUMBER = 0x0400,
};


(2) USB主機端驅動開發工具包初始化,使用如下介面: 

 

int32_t UsbInitHostSdk(struct UsbSession **session)


(3) 待步驟2初始化完后獲取UsbInterface物件,使用如下介面: 

 

const struct UsbInterface *UsbClaimInterface(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr, uint8_t interfaceIndex);


(4) 打開步驟3獲取到的UsbInterface介面物件,獲取對應介面的UsbInterfaceHandle物件,使用如下介面: 

 

UsbInterfaceHandle *UsbOpenInterface(const struct UsbInterface *interfaceObj);


(5) 根據步驟4獲取到的UsbInterfaceHandle物件,獲取指定索引為pinpeIndex的pipeInfo資訊,使用如下介面: 

 

int32_t UsbGetPipeInfo(const UsbInterfaceHandle *interfaceHandle, uint8_t settingIndex, uint8_t pipeId, struct UsbPipeInfo *pipeInfo);


(6) 為步驟4獲取到的UsbInterfaceHandle預先分配待發送的IO Request物件,使用如下介面: 

 

struct UsbRequest *UsbAllocRequest(const UsbInterfaceHandle *interfaceHandle, int isoPackets, int length);


(7) 根據輸入引數params填充步驟6預先分配的IO Request,使用如下介面: 

 

int32_t UsbFillRequest(const struct UsbRequest *request, const UsbInterfaceHandle *interfaceHandle, const struct UsbRequestParams *params);


(8) 提交IO Request物件,可以選擇同步或異步兩種模式,使用如下介面: 

 

int32_t UsbSubmitRequestSync(const struct UsbRequest *request);//發送同步IO請求
int32_t UsbSubmitRequestAsync(const struct UsbRequest *request);//發送異步IO請求


2. USB RAW API 的使用

 

USB RAW API主要實作USB更加復雜的功能,如獲取描述符資訊、獲取設備指標、復位設備、提交傳輸請求等,如圖4所示,是USB RAW API提供的部分介面, 

 

圖4 USB RAW API

 

使用步驟如下:

 

(1) 同USB DDK API的步驟1一樣,需先進行驅動匹配表配置, 

 

(2) 初始化Host RAW,使用如下介面: 

 

int32_t UsbRawInit(struct UsbSession **session);


(3) 待步驟2完成后打開USB設備,使用如下介面: 

 

UsbRawHandle *UsbRawOpenDevice(const struct UsbSession *session, uint8_t busNum, uint8_t usbAddr);


(4) 待步驟3完成后獲取描述符,通過描述符獲取介面、端點資訊,使用如下介面: 

 

int32_t UsbRawGetConfigDescriptor(const UsbRawDevice *rawDev, uint8_t configIndex, struct UsbRawConfigDescriptor **config);


(5) 分配Request,并根據不同的傳輸型別使用相應的介面對Request進行填充: 

 

int32_t UsbRawFillBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);// 填充用于批量傳輸的請求
int32_t UsbRawFillControlSetup(const unsigned char *setup, const struct UsbControlRequestData *requestData);
int32_t UsbRawFillControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);// 填充用于控制傳輸的請求
int32_t UsbRawFillInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);// 填充用于中斷傳輸的請求
int32_t UsbRawFillIsoRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRawFillRequestData *fillData);// 填充用于同步傳輸的請求


(6) 提交IO Request物件,可以選擇同步或異步兩種模式,分別使用如下介面: 

 

int32_t UsbRawSendControlRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbControlRequestData *requestData);//發送同步USB控制傳輸請求
int32_t UsbRawSendBulkRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);//發送同步USB批量傳輸請求
int32_t UsbRawSendInterruptRequest(const struct UsbRawRequest *request, const UsbRawHandle *devHandle, const struct UsbRequestData *requestData);//發送同步執行USB中斷傳輸請求
int32_t UsbRawSubmitRequest(const struct UsbRawRequest *request);//提交異步IO請求


感興趣的小伙伴可點擊下方鏈接查看完整的USB Host開發代碼: 

https://gitee.com/openharmony/drivers_peripheral/tree/master/usb/serial/src 

 

2)USB Device的開發


USB Device(設備端驅動)主要實作設備管理、配置管理、IO管理、資料通信等,USB Deivce DDK給開發者提供了設備創建、獲取介面、接收Event事件、收發資料等驅動能力介面,如圖5所示: 

 

圖5 USB Device DDK開放的API

 

下面,我們將根據USB Deivce DDK提供的驅動能力介面來開發設備端驅動, 

 

1. 構造描述符

 

首先,需構造描述符來說明設備的總體資訊,開發者可以通過設備功能代碼及設備私有資料HCS兩種途徑進行配置,下面將分別介紹, 

 

(1) 在設備功能代碼中配置描述符,配置代碼如下: 

 

static struct UsbFnFunction g_acmFunction = {//功能描述符
    .enable         = true,
    .funcName       = "f_generic.a",
    .strings        = g_acmStrings,
    .fsDescriptors  = g_acmFsFunction,
    .hsDescriptors  = g_acmHsFunction,
    .ssDescriptors  = g_acmSsFunction,
.sspDescriptors = NULL,
};
struct UsbFnFunction *g_functions[] = {
#ifdef CDC_ECM
    &g_ecmFunction,
#endif
#ifdef CDC_ACM
    &g_acmFunction,
#endif
NULL
};
static struct UsbFnConfiguration g_masterConfig = {//配置描述符
    .configurationValue = https://www.cnblogs.com/HarmonyOSDev/archive/2022/03/28/1,
    .iConfiguration     = USB_FUNC_CONFIG_IDX,
    .attributes         = USB_CFG_BUS_POWERED,
    .maxPower           = POWER,
    .functions          = g_functions,
};
static struct UsbFnConfiguration *g_configs[] = {
    &g_masterConfig,
    NULL,
};
static struct UsbDeviceDescriptor g_cdcMasterDeviceDesc = {//設備描述符
    .bLength            = sizeof(g_cdcMasterDeviceDesc),
    .bDescriptorType    = USB_DDK_DT_DEVICE,
    .bcdUSB             = CpuToLe16(BCD_USB),
    .bDeviceClass       = 0,
    .bDeviceSubClass    = 0,
    .bDeviceProtocol    = 0,
    .bMaxPacketSize0    = USB_MAX_PACKET_SIZE,
    .idVendor           = CpuToLe16(DEVICE_VENDOR_ID),
    .idProduct          = CpuToLe16(DEVICE_PRODUCT_ID),
    .bcdDevice          = CpuToLe16(DEVICE_VERSION),
    .iManufacturer      = USB_FUNC_MANUFACTURER_IDX,
    .iProduct           = USB_FUNC_PRODUCT_IDX,
    .iSerialNumber      = USB_FUNC_SERIAL_IDX,
    .bNumConfigurations = 1,
};
static struct UsbFnDeviceDesc g_masterFuncDevice = {//描述符入口
    .deviceDesc    = &g_cdcMasterDeviceDesc,
    .deviceStrings = g_devStrings,
    .configs       = g_configs,
};


(2) 在設備私有資料HCS中配置,配置代碼如下: 

 

root {
    module = "master";
master_config {
        match_attr         = "usbfn_master_driver";//該欄位與device中deviceMatchAttr
                                                             保持一致,否則無法找到的這個節點的資訊,
    use_hcs            = 1;                         //用戶可以用該值決定是否使用hcs配置資訊
    udc_name           = "100e0000.hidwc3_0";   //UDC的名字
        usb_dev_desc       = "UsbDeviceDescriptor";//設備描述符的節點UsbDeviceDescriptor
        usb_dev_string     = "UsbDeviceStrings";   //設備字串的節點為UsbDeviceStrings
        usb_configuration = "UsbConfigs";           //配置描述符的節點為UsbConfigs
        ...
   }
}


設備描述符的節點為UsbDeviceDescriptor,配置如下: 

 

UsbDeviceDescriptor {
            bLength            = 18;
            bDescriptorType  = 0x01;
            bcdUSB             = 0x0200;
            bDeviceClass      = 0;
            bDeviceSubClass  = 0;
            bDeviceProtocol  = 0;
            bMaxPacketSize0  = 0x40;
            idVendor           = 0x0525;
            idProduct          = 0xA4A7;
            bcdDevice          = 0x0100;
            manufacturer       = 0;
            product             = 1;
            serialnumber       = 2;
            numConfigurations = 1; 
 }


2. 創建設備

 

描述符構造完成后,使用UsbFnDeviceCreate函式創建一個USB設備,并傳入UDC控制器名和UsbFnDescriptorData結構體,實作代碼如下: 

 

if (useHcs == 0) {//使用代碼撰寫的描述符
        descData.type        = USBFN_DESC_DATA_TYPE_DESC;
        descData.descriptor = &g_acmFuncDevice;
    } else {             //使用hcs撰寫的描述符
        descData.type         = USBFN_DESC_DATA_TYPE_PROP;
        descData.property    = acm->device->property;
}
   //創建設備
    fnDev = (struct UsbFnDevice *) UsbFnCreateDevice(acm->udcName, &descData);


3.獲取介面

 

設備創建后,使用UsbFnDeviceGetInterface函式獲取UsbInterface介面物件,并通過UsbFnGetInterfacePipeInfo函式獲取USB管道資訊,實作代碼如下: 

 

//獲取介面
fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
//獲取Pipe資訊
UsbFnGetInterfacePipeInfo(fnIface, i, &pipeInfo);
//獲取Handle
handle = UsbFnOpenInterface(fnIface);
//獲取控制(EP0)Request
req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle,
            sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));
//獲取Request
req = UsbFnAllocCtrlRequest(acm->ctrlIface.handle,
            sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding));


4. 接收Event事件

 

通過UsbFnStartRecvInterfaceEvent函式接收Event事件,并通過UsbFnEventCallback回呼函式對Event事件做出回應,實作代碼如下: 

 

//開始接收Event事件
ret = UsbFnStartRecvInterfaceEvent(acm->ctrlIface.fn, 0xff, UsbAcmEventCallback, acm);
//Event處理回呼函式
static void UsbAcmEventCallback(struct UsbFnEvent *event)
{
struct UsbAcmDevice *acm = NULL;


    if (event == NULL || event->context == NULL) {
        HDF_LOGE("%s: event is null", __func__);
        return;
    }


    acm = (struct UsbAcmDevice *)event->context;
    switch (event->type) {
        case USBFN_STATE_BIND:
            HDF_LOGI("%s: receive bind event", __func__);
            break;
        case USBFN_STATE_UNBIND:
            HDF_LOGI("%s: receive unbind event", __func__);
            break;
        case USBFN_STATE_ENABLE:
            HDF_LOGI("%s: receive enable event", __func__);
            AcmEnable(acm);
            break;
        case USBFN_STATE_DISABLE:
            HDF_LOGI("%s: receive disable event", __func__);
            AcmDisable(acm);
            acm->enableEvtCnt = 0;
            break;
        case USBFN_STATE_SETUP:
            HDF_LOGI("%s: receive setup event", __func__);
            if (event->setup != NULL) {
                AcmSetup(acm, event->setup);
            }
            break;
        case USBFN_STATE_SUSPEND:
            HDF_LOGI("%s: receive suspend event", __func__);
            AcmSuspend(acm);
            break;
        case USBFN_STATE_RESUME:
            HDF_LOGI("%s: receive resume event", __func__);
            AcmResume(acm);
            break;
        default:
            break;
    }
}


5. 收發資料

 

可以選擇同步異步發送模式,實作代碼如下: 

 

notify = (struct UsbCdcNotification *)req->buf;
    ...
    if (memcpy_s((void *)(notify + 1), length, data, length)  != EOK) {
        return HDF_FAILURE;
    }
ret = UsbFnSubmitRequestAsync(req);//異步發送


感興趣的小伙伴可點擊下方鏈接查看完整的設備測開發代碼, 

 

完整設備測開發代碼:https://gitee.com/openharmony/drivers_peripheral/tree/master/usb/gadget/function/ 

 

以上就是本期全部內容,通過本文的介紹相信你已經對USB DDK有了深刻的認識,期待廣大的開發者加入我們,一起豐富基于USB DDK的第三方驅動,

 

 

掃碼添加開發者小助手微信

獲取更多HarmonyOS開發資源和開發者活動資訊

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/451362.html

標籤:其他

上一篇:Android BLE 藍牙開發——掃碼槍基于BLESSED

下一篇:如何從不是宣告根視窗的QML的QML檔案中獲取Qt應用程式視窗大小?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more