主頁 > 移動端開發 > android treble專案&&HIDL學習總結

android treble專案&&HIDL學習總結

2021-09-05 08:30:06 移動端開發

文章目錄

    • 概念介紹
      • Treble專案---HIDL產生背景,獨立升級framework需求
      • HIDL概念---HAL 介面定義語言,目標framework和HAL解耦
      • HIDL的兩種模式---Passthrough直通 / Binderized系結
    • HIDL設計分析
      • HAL模塊與package軟體包(包含.hal檔案)
      • .hal檔案 語法簡介
      • .hal檔案 (hidl-gen工具)編譯轉換.h/.cpp檔案
      • .hal檔案hash值與多版本匹配
    • HIDL設計舉例---hwc composer的分析
      • composer相關原始碼分析
      • composer相關權限配置分析
      • composer相關編譯檔案分析
      • composer啟動流程分析
    • 新增基于HIDL的HAL模塊流程
      • 1. 建立模塊包目錄、撰寫.hal檔案創建HIDL介面
      • 2. 執行構建腳本,生成對應makefile和default目錄與檔案
      • 3. 在xml檔案添加介面宣告、在current.txt添加版本hash值
      • 4. 實作service服務端hal注冊與功能實作代碼
      • 5. 實作client客戶端呼叫hal模塊代碼
      • 6. 配置新增hal模塊Selinux配置權限
      • 7. 在mk檔案添加編譯關系
    • 參考

概念介紹

Treble專案—HIDL產生背景,獨立升級framework需求

Android O(8.0) 重新設計了 Android 作業系統框架,在一個名為Treble的專案中,以便讓制造商能夠以更低的成本更輕松、更快速地將設備更新到新版 Android 系統,在這種新架構中,HAL 介面定義語言HIDL指定了 HAL 和其用戶之間的介面,讓用戶能夠替換 android framework,而無需重新編譯 HAL,
在這里插入圖片描述

HIDL概念—HAL 介面定義語言,目標framework和HAL解耦

HIDL: HAL 介面定義語言HAL interface definition language,在 Android 8.0 中被全面使用,用于在可以獨立編譯的代碼庫之間進行通信的系統,定義Android Framework與Android HAL實作之間的介面,把framework和hal隔離,目的是使 Android 可以在不重新編譯 HAL 的情況下對 Framework 進行 OTA 升級(OTA:Over The Air,一種遠程無線升級技術,在線升級系統),
在這里插入圖片描述
HIDL與AIDL比較類似,底層也是基于binder機制,但是也有稍微不一樣的地方,為了支持HIDL,Android 對BInder做了一定程度的修改,/dev/hwbinder,

HIDL的兩種模式—Passthrough直通 / Binderized系結

為了將以往設備的 Android 版本更新到 Android O,開發者需要將傳統的 HAL 封裝到新的 HIDL 介面中,這個介面為 HAL 提供了 Binder 模式以及 Passthrough 模式,
(1)Passthrough直通模式:對原先HAL的包裝,老版本HAL的兼容,最終的binder service 跟binder client都是活在同一個行程當中,僅對 C++ 客戶端與實作適用,
(2)Binderized系結模式:Binder化的HAL,HAL都被寫成了binder service,Android framework是binder client,兩者再不同的背景關系,
推出時即搭載了 Android 8.0 或后續版本的設備都必須只支持系結式 HAL,如下圖:
在這里插入圖片描述

HIDL設計分析

基于HIDL介面的HAL模塊整體流程如下:呼叫者需要包含Client端對應so,通過getService獲取服務端實體,通過對client的操作對服務端Service行程發出申請,而Serive端是開機時init行程 通過rc啟動腳本執行service對應可執行檔案 創建行程,并在啟動程序中向HwServiceManager注冊服務,來回應client的訪問,而實際專案程序,往往service可執行檔案并不會包含過多的業務實作,而是通過鏈接impl.so共享庫來實作,impl.so中為真正的業務實作代碼,并呼叫Vender底層SDK,涉及硬體驅動就通過kernel中內核驅動模塊提供支持,
在這里插入圖片描述
整個設計android的HIDL機制主要就是client與service之間的訪問介面設計, HIDL的原理大致如下:android提供了一種特定撰寫規則的.hal檔案(類似c++和java),然后通過特定的hidl-gen工具和一些構建腳本 把.hal轉換為可以編譯的.cpp/.h檔案、android.bp構建檔案,這些生成的檔案已經實作了client對應so,service可執行檔案(包含了注冊service程序),而接下來只需要在對應.cpp實作內部細節,然后添加對應權限配置,加入編譯程序等就完成了hal模塊新增,

HAL模塊與package軟體包(包含.hal檔案)

每個HAL模塊設計一個介面軟體包package,可以具有子級,如 package.subpackage,已發布的 HIDL 軟體包的根目錄為 hardware/interfaces 或 vendor/vendorName,軟體包名稱在根目錄下形成一個或多個子目錄;定義同一個軟體包的所有檔案都位于同一目錄下,
在這里插入圖片描述軟體包目擴展名為 .hal 的檔案,每個檔案均必須包含一個指定檔案所屬的軟體包和版本的 package 陳述句,types.hal 檔案(如果存在)并不定義介面,而是定義軟體包中每個介面可以訪問的資料型別,

.hal檔案 語法簡介

https://source.android.google.cn/devices/architecture/hidl/code-style
HIDL 語言與 C 語言類似,

注釋:/** */ 表示檔案注釋(只用于型別、方法、欄位和列舉值宣告);/* */ 表示多行注釋;// 表示注釋一直持續到行尾;
[empty] 表示該字詞可能為空,
? 跟在文本或字詞后,表示它是可選的,
... 表示包含零個或多個項、使用指定的分隔符號分隔的序列,HIDL 中不含可變引數,
逗號用于分隔序列元素,
分號用于終止各個元素,包括最后的元素,
大寫字母是非終止符,
italics 是一個令牌系列,如 integer 或 identifier(標準 C 決議規則),
constexpr 是 C 樣式的常量運算式(例如 1 + 11L << 3),
import_name 是軟體包或介面名稱,按 HIDL 版本控制中所述的方式加以限定,
小寫 words 是文本令牌,

.hal檔案 (hidl-gen工具)編譯轉換.h/.cpp檔案

hidl-gen 編譯器會將 .hal 檔案編譯成一組 .h 和 .cpp 檔案, 這些自動生成的檔案可用來構建客戶端/服務器實作鏈接到的共享庫,用于構建此共享庫的 Android.bp 檔案由 hardware/interfaces/update-makefiles.sh 腳本自動生成,
在這里插入圖片描述
IFoo.h :描述 C++ 類中的純 IFoo 介面;它包含 IFoo.hal 檔案中的 IFoo 介面中所定義的方法和型別,類的命名空間包含軟體包名稱和版本號,客戶端和服務器都包含此標頭:客戶端用它來呼叫方法,服務器用它來實作這些方法,
IHwFoo.h :其中包含用于對介面中使用的資料型別進行序列化的函式的宣告,開發者不得直接包含其標頭(它不包含任何類),
BpFoo.h : 從 IFoo 繼承的類,可描述介面的 HwBinder 代理(客戶端)實作,開發者不得直接參考此類,
BnFoo.h: 保存對 IFoo 實作的參考的類,可描述介面的 HwBinder 服務器端實作,開發者不得直接參考此類,
FooAll.cpp :包含 HwBinder 客戶端和 HwBinder 服務器端的實作的類,當客戶端呼叫介面方法時,代理會自動從客戶端封送引數,并將事務發送到系結內核驅動程式,該內核驅動程式會將事務傳送到另一端的服務器端實作,

.hal檔案hash值與多版本匹配

HIDL的設計目標就是 把 framework 與 vender之間 的介面固定下來,HIDL用的方法就是給每個hal檔案生成一個hash值,記錄到current.txt檔案中,類似如下composer模塊的hash值,在編譯的時候就可以校驗,當需要新增介面的時候,就新增一個版本,繼承上一個版本的hal介面進行擴展,同時生成新版本對應的hash值,
在這里插入圖片描述

HIDL設計舉例—hwc composer的分析

hwc composer是android里面對疊加器的加速,相關概念參考:https://blog.csdn.net/runafterhit/article/details/118884165
代碼:http://androidxref.com/9.0.0_r3/xref/hardware/interfaces/graphics/composer/2.2/

composer相關原始碼分析

/hardware/interfaces/graphics/composer/2.2/
IComposer.hal:定義了composer模塊的hal介面,

package android.hardware.graphics.composer@2.2;; // 指定檔案所屬的軟體包和版本
import @2.1::IComposer; // 匯入2.1的類
interface IComposer extends @2.1::IComposer {
	// 完全繼承2.1包定義的IComposer
}
// 2.1包定義的IComposer 如下:
interface IComposer {
	getCapabilities() generates (vec<Capability> capabilities); // 獲取能力級別
	dumpDebugInfo() generates (string debugInfo); // 列印debug資訊
	createClient() generates (Error error, IComposerClient client); // 創建clenit實體
}

IComposerClient.hal:定義了composer的client的hal介面:

package android.hardware.graphics.composer@2.1; // 指定檔案所屬的軟體包和版本
interface IComposerClient extends @2.2::IComposerClient {
	// 繼承2.1包定義的IComposerClient ,同時專門新增了2.2相關功能介面,部分如下:
	getReadbackBufferFence(Display display) generates (Error error,handle acquireFence); // 獲取buf的fence
}
// 2.1包定義的IComposerClient 如下:
interface IComposerClient {
	// 重點相關函式如下:
	registerCallback(IComposerCallback callback); // 回呼注冊介面
	createVirtualDisplay(/* 省略*/); // 創建虛擬display通道
 	createLayer(Display display, uint32_t bufferSlotCount) generates (Error error,Layer layer);	// 創建layer
 	destroyLayer(Display display, Layer layer) generates (Error error); // 銷毀layer
 	setVsyncEnabled(Display display, Vsync enabled) generates (Error error); // 使能通道vsync
 	setInputCommandQueue(fmq_sync<uint32_t> descriptor) generates (Error error);// 設定輸入命令到queue
 	executeCommands(/* 省略*/); // 直行命令queue中命令
 	// 還有各種設定屬性介面
}

IComposerCallback.hal:定義client注冊的回呼型別,定義在2.1包中

package android.hardware.graphics.composer@2.1;
interface IComposerCallback {
	onHotplug(Display display, Connection connected); // display通路的拔插 回呼
	oneway onRefresh(Display display); // display的重繪回呼,強制重繪
	oneway onVsync(Display display, int64_t timestamp); // display的vsync信號回呼
}

composer相關權限配置分析

Selinux相關概念可以參考: https://blog.csdn.net/runafterhit/article/details/119920733
composer要能被訪問,或者要訪問其他資源,需要進行selinux相關權限配置,這里完全是更具具體產品專案的權限設定,往往需要設定:1、對應服務service行程的權限管理(可以訪問那些資源,包括binder);2、service可執行檔案的安全背景關系,誰能訪問它也需要添加allow權限;3、涉及硬體設備節點訪問,需要在service追加相關權限,
舉例如下:
/device/google/marlin/sepolicy/hal_graphics_composer_default.te :主要設定service的檔案訪問、binder訪問等

userdebug_or_eng(`
  allow hal_graphics_composer_default diag_device:chr_file rw_file_perms;
')
dontaudit hal_graphics_composer_default diag_device:chr_file rw_file_perms;

# misc
typeattribute hal_graphics_composer_default data_between_core_and_vendor_violators;
allow hal_graphics_composer_default display_data_file:dir create_dir_perms;
allow hal_graphics_composer_default display_data_file:file create_file_perms;

# persist
allow hal_graphics_composer_default persist_file:dir search;

# persist/display
allow hal_graphics_composer_default persist_display_file:dir r_dir_perms;
allow hal_graphics_composer_default persist_display_file:file create_file_perms;

vndbinder_use(hal_graphics_composer_default);
add_service(hal_graphics_composer_default, qdisplay_service)

# HWC_UeventThread
allow hal_graphics_composer_default self:netlink_kobject_uevent_socket create_socket_perms_no_ioctl;

# Access /sys/devices/virtual/graphics/fb0/mdp/caps and maybe others
r_dir_file(hal_graphics_composer_default, sysfs_type)

composer相關編譯檔案分析

在/hardware/interfaces/graphics/composer/目錄下mm編譯,會生成:
1、android.hardware.graphics.composer@2.2-service. rc : 啟動配置腳本,直接從copy到vendor/etc/init,
2、android.hardware.graphics.composer@2.*. so:客戶端client使用時需要鏈接的客戶端so,
3、android.hardware.graphics.composer@2.2-service :service的可執行檔案,生成在vendor/bin/hw/,見2.2/default/Android.mk中編譯規則,service 服務的作用就是向 hwservicemanager 注冊 HAL,并鏈接impl .so呼叫實作,
4、 android.hardware.graphics.composer@2.1-impl .so :service編譯時鏈接的共享庫,在service行程加載時會鏈接進去,

composer啟動流程分析

1、開機init行程會讀取vendor/etc/init下的xxx_service. rc初始腳本檔案,執行vendor/bin/hw/xx_service可執行檔案,從而啟動service行程:

// 腳本內容:
service vendor.hwcomposer-2-2 /vendor/bin/hw/android.hardware.graphics.composer@2.2-service
    class hal animation
    user system
    group graphics drmrpc
    capabilities SYS_NICE
    onrestart restart surfaceflinger

行程狀態:

1|HWRVL:/vendor/etc/init $ ps -A | grep composer
system         610     1 2248748   2824 0                   0 S android.hardware.graphics.composer@2.2-service

2、行程啟動后,servie執行main函式,建立Binder IPC 通信
/hardware/interfaces/graphics/composer/2.2/default/service.cpp,HIDL 框架為了支持供應商 HAL 行程,提供了 libbinder 用戶空間庫用于操作 Binder 設備節點(hwbinder & vndbinder),然后呼叫HwcLoader::load()進行hwc模塊加載

int main() {
    // the conventional HAL might start binder services
    android::ProcessState::initWithDriver("/dev/vndbinder");
    android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
    android::ProcessState::self()->startThreadPool();
    // same as SF main thread
    struct sched_param param = {0};
    param.sched_priority = 2;
    if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO: %d", errno);
    }
    android::hardware::configureRpcThreadpool(4, true /* will join */);
    android::sp<IComposer> composer = HwcLoader::load();
    if (composer == nullptr) {
        return 1;
    }
    if (composer->registerAsService() != android::NO_ERROR) {
        ALOGE("failed to register service");
        return 1;
    }
    return 1;
}

3、HWC模塊load,這里最終呼叫到createComposer,其中主要實作呼叫hal::Composer::create(std::move(hal)) 來呼叫到ComposerHal 類中的
composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h

class HwcLoader : public V2_1::passthrough::HwcLoader {
   public:
    static IComposer* load() {
        const hw_module_t* module = loadModule();
        if (!module) {
            return nullptr;
        }
        auto hal = createHalWithAdapter(module);
        if (!hal) {
            return nullptr;
        }
        return createComposer(std::move(hal)).release();
    }
    /* 省略 */
    static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) {
        return hal::Composer::create(std::move(hal));
    }
}

新增基于HIDL的HAL模塊流程

以下梳理添加一個基于hidl的hal模塊test的大致流程,作為開發參考,具體例子可以看參考中的實體,
整個流程大致為:寫.hal檔案通過工具和組態檔生成hidl相關編譯檔案,實作內部細節,添加xml的介面配置和current介面hash版本,按使用需求撰寫client訪問,設定selinux配置權限,添加包編譯構建關系,

1. 建立模塊包目錄、撰寫.hal檔案創建HIDL介面

在介面目錄添加對應模塊目錄,如hardware/interfaces/test/1.0/,表示新增test模塊,默認版本號1.0,創建檔案ITest.hal,參考內容如下(如果有必要,還可以types.hal定義復雜結構體,或者拆解為多個.hal檔案):

package android.hardware.test@1.0; // 宣告包的名稱test,版本1.0
interface ITest {
    init(TestID id);
    //無回傳值
    helloWorld(string name) generates (string result);
};

2. 執行構建腳本,生成對應makefile和default目錄與檔案

使用hidl-gen生成default目錄 里的C++檔案

PACKAGE=android.hardware.test@1.0
LOC=hardware/interfaces/test/1.0/default
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport $PACKAGE

根目錄使用update-makefiles.sh生成1.0目錄下的Android.bp

./hardware/interfaces/update-makefiles.sh

生成檔案如下:

├── 1.0
│   ├── default
│   │   ├── Android.bp
│   │   ├── Test.cpp // 需要實作service的實作代碼
│   │   ├── Test.h
│   ├── Android.bp
│   ├── ITest.hal

再新增android.hardware.test@1.0-service. rc啟動腳本檔案

service test_service /vendor/bin/hw/android.hardware.test@1.0-service
    class hal
    user system
    group system

3. 在xml檔案添加介面宣告、在current.txt添加版本hash值

在manifest.xml檔案中添加新增hal模塊的介面ITest宣告,

	<hal format="hidl">
        <name>android.hardware.test</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>ITest</name>
            <instance>default</instance>
        </interface>
    </hal>

在current.txt中添加對應軟體版本的hash值,用hidl-gen -L hash命令生成,

// 參考命令,xxx為供應商vender名稱,和產品使用具體版本相關:
hidl-gen -L hash -r vendor.xxx.harware:vendor/xxx/hardware -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport vendor.xxx.harware.test@1.0

生成后寫入current.txt,類似如下composer模塊的hash值:
在這里插入圖片描述

4. 實作service服務端hal注冊與功能實作代碼

在工具生成的Test.cpp中實作service的內部實作,實際專案中,經常再單獨實作一個impl .so,service本身是一個輕量級的可執行檔案,service編譯時鏈接的共享庫impl .so包含真正的實作,在service行程加載時會鏈接進去,

// 部分代碼如下
Return<void> Test::init(const ::android::hardware::test::V1_0::TestID& id) {
    mExit = false;
	mName = id.name;
	mID = id.id;
	ALOGD("init:");
    return Void();
}
Return<void> Test::helloWorld(const hidl_string& name, helloWorld_cb _hidl_cb) {
	ALOGD("helloWorld:");
	char buf[100];
	::memset(buf,0x00,100);
	::snprintf(buf,100,"Hello World,%s",name.c_str());
	hidl_string result(buf);
	_hidl_cb(result);
    return Void();
}

5. 實作client客戶端呼叫hal模塊代碼

從framework層 當需要呼叫的對應hal介面,Android.bp添加test編譯時鏈接對應.so的模塊,
然后通過getService獲取client實體,參考類似如下:

private ITest halService ;
halService = ITest.getService();//獲取service對應實體
halService.helloWorld(str); // 呼叫對應client方法,向service發出申請

6. 配置新增hal模塊Selinux配置權限

Selinux相關概念可以參考: https://blog.csdn.net/runafterhit/article/details/119920733
一般新增一個模塊,往往需要添加已下幾處典型selinux配置:
1)新增一個hal_xxx安全策略檔案,定義服務進行,追加服務對binder使用等權限等(若涉及property寫需要自己添加);
2)在file_contexts中,新增service可執行檔案的安全背景關系;
3)在hwservice_context中,新增服務相關安全背景關系,及其關聯type型別;
4)如果涉及設備節點的訪問,還需要對應hal_xxx安全策略檔案添加回應訪問權限;

7. 在mk檔案添加編譯關系

在對應的包(專案不同組態檔有差異)編譯檔案添加新增hal模塊相關包,舉例:/build/target/product/emulator.mk

PRODUCT_PACKAGES += \
	/* 省略 */
    android.hardware.test@1.0-impl \
    android.hardware.test@1.0-service \

參考

官方檔案:
https://source.android.google.cn/devices/architecture/hidl
https://source.android.google.cn/devices/architecture/hidl/code-style
HIDL概述:https://blog.csdn.net/u013357557/article/details/84561457
AndroidO Treble架構下Hal行程啟動及HIDL服務注冊程序:https://blog.csdn.net/yangwen123/article/details/79854267
Android P HAL層添加HIDL實體: https://blog.csdn.net/sinat_18179367/article/details/95940030
https://blog.csdn.net/qq_19923217/article/details/88398660
https://blog.csdn.net/qq_19923217/article/details/89173162
https://blog.csdn.net/kuang_tian_you/article/details/86599869

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

標籤:其他

上一篇:iOS底層學習——KVC

下一篇:記一次Android App逆向入門實戰(逆向思路&工具使用&CrackMe)

標籤雲
其他(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