帶你了解鴻蒙開發(fā)基本流程
來源于:傷心的豬大腸
https://juejin.im/user/4441682709326958
/? ?前言? ?/
2020年9月10號,鴻蒙2.0(HarmonyOS 2.0)系統(tǒng)正式發(fā)布,鴻蒙2.0面向應(yīng)用開發(fā)者發(fā)布Beta版本,
在2020年9月10發(fā)布大屏,手表,車機版鴻蒙,2020年12月發(fā)布手機版鴻蒙。在2020年9月10日,鴻蒙開源路標(biāo)面向內(nèi)存128KB-128MB終端設(shè)備;2021年10月,將面向4GB以上所有設(shè)備。
/? ?背景? ?/
作為一個安卓開發(fā)者,能夠看到國產(chǎn)的操作系統(tǒng)的發(fā)布確實很興奮,興奮之余,更想要看看具體是怎么一回事,首先打開官網(wǎng),看看官網(wǎng)該系統(tǒng)的定義:HarmonyOS是一款“面向未來”、面向全場景(移動辦公、運動健康、社交通信、媒體娛樂等)的分布式操作系統(tǒng)。在傳統(tǒng)的單設(shè)備系統(tǒng)能力的基礎(chǔ)上,HarmonyOS提出了基于同一套系統(tǒng)能力、適配多種終端形態(tài)的分布式理念,能夠支持多種終端設(shè)備。
對應(yīng)用開發(fā)者而言,HarmonyOS采用了多種分布式技術(shù),使得應(yīng)用程序的開發(fā)實現(xiàn)與不同終端設(shè)備的形態(tài)差異無關(guān),降低了開發(fā)難度和成本。這能夠讓開發(fā)者聚焦上層業(yè)務(wù)邏輯,更加便捷、高效地開發(fā)應(yīng)用。該優(yōu)點在5G這個萬物互聯(lián)的時代具有著巨大的優(yōu)勢。
/? ?安裝DevEco Studio? ?/
接下來下載DevEco Studio(IDE/開發(fā)工具)來進行體驗一下軟件的開發(fā),在這里可以看到目前的IDE只有Windows系統(tǒng)的(windows 10 64位),安裝過程可能中會出現(xiàn)gradle的安裝失敗,記得添加代理,在用戶目錄(打開“此電腦”,在文件夾地址欄中輸入%userprofile%,進入個人數(shù)據(jù)界面。)下創(chuàng)建gradle.properties文件,文件中添加,端口是代理的端口。
systemProp.https.proxyPort=63729
systemProp.http.proxyHost=127.0.0.1
systemProp.https.proxyHost=127.0.0.1
systemProp.http.proxyPort=63729
gradle安裝成功,但在編譯過程中可能出現(xiàn)build失敗,錯誤如下:
ERROR:?Cause:?mirrors.huaweicloud.com:443?failed?to?respond
解決方式就是把所有的代理先關(guān)掉,然后你就會發(fā)現(xiàn)如絲般順滑。安裝完DevEco Studio后,打開后可以看到界面和Android Studio非常相似。

布局開發(fā)
一切看起來非常的熟悉,可以使用Java或JS等語言進行開發(fā),布局可以通過XML創(chuàng)建,size單位是vp。
<DirectionalLayout
????xmlns:ohos="http://schemas.huawei.com/res/ohos"
????ohos:width="match_parent"
????ohos:height="match_parent"
????ohos:orientation="vertical"
????ohos:padding="32">
????<Text
????????ohos:id="$+id:text"
????????ohos:width="match_content"
????????ohos:height="match_content"
????????ohos:layout_alignment="horizontal_center"
????????ohos:text="My?name?is?Jackie."
????????ohos:text_size="25vp"/>
????<Button
????????ohos:id="$+id:button"
????????ohos:width="match_content"
????????ohos:height="match_content"
????????ohos:layout_alignment="horizontal_center"
????????ohos:text="My?name?is?Jackie."
????????ohos:text_size="50"/>
DirectionalLayout>
也可以通過Java代碼直接創(chuàng)建,點擊事件都是如此的親切。
@Override
public?void?onStart(Intent?intent)?{
????super.onStart(intent);
????//?步驟1?聲明布局
????DirectionalLayout?directionalLayout?=?new?DirectionalLayout(context);
????//?步驟2?設(shè)置布局大小
????directionalLayout.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);
????directionalLayout.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);
????//?步驟3?設(shè)置布局屬性及ID(ID視需要設(shè)置即可)
????directionalLayout.setOrientation(Component.VERTICAL);
????directionalLayout.setPadding(32,?32,?32,?32);
????Text?text?=?new?Text(context);
????text.setText("My?name?is?Text.");
????text.setTextSize(50);
????text.setId(100);
????//?步驟4.1?為組件添加對應(yīng)布局的布局屬性
????DirectionalLayout.LayoutConfig?layoutConfig?=?new?DirectionalLayout.LayoutConfig(LayoutConfig.MATCH_CONTENT,
????????LayoutConfig.MATCH_CONTENT);
????layoutConfig.alignment?=?LayoutAlignment.HORIZONTAL_CENTER;
????text.setLayoutConfig(layoutConfig);
????//?步驟4.2?將Text添加到布局中
????directionalLayout.addComponent(text);
????//?類似的添加一個Button
????Button?button?=?new?Button(context);
????layoutConfig.setMargins(0,?50,?0,?0);
????button.setLayoutConfig(layoutConfig);
????button.setText("My?name?is?Jackie.");
????button.setTextSize(50);
????button.setId(100);
????ShapeElement?background?=?new?ShapeElement();
????background.setRgbColor(new?RgbColor(0,?125,?255));
????background.setCornerRadius(25);
????button.setBackground(background);
????button.setPadding(10,?10,?10,?10);
????button.setClickedListener(new?Component.ClickedListener()?{
????????@Override
????????//?在組件中增加對點擊事件的檢測
????????public?void?onClick(Component?Component)?{
????????????//?此處添加按鈕被點擊需要執(zhí)行的操作
????????}
????});
????directionalLayout.addComponent(button);
????//?步驟5?將布局作為根布局添加到視圖樹中
????super.setUIContent(directionalLayout);
}
首頁的布局如下,通過Java代碼創(chuàng)建。
????@Override
????public?void?onStart(Intent?intent)?{
????????super.onStart(intent);
????????System.out.println("onStart");
????????LayoutConfig?config?=?new?LayoutConfig(LayoutConfig.MATCH_PARENT,?LayoutConfig.MATCH_PARENT);
????????myLayout.setLayoutConfig(config);
????????ShapeElement?element?=?new?ShapeElement();
????????element.setRgbColor(new?RgbColor(255,?255,?255));
????????myLayout.setBackground(element);
????????Text?text?=?new?Text(this);
????????text.setLayoutConfig(config);
????????text.setText("CT?Jackie");
????????text.setTextColor(new?Color(0xFF000000));
????????text.setTextSize(50);
????????text.setTextAlignment(TextAlignment.CENTER);
????????myLayout.addComponent(text);
????????super.setUIContent(myLayout);
????}
效果如下:

生命周期
下面再來看看主界面的生命周期,實現(xiàn)了ILifecycle接口,生命周期狀態(tài)一共有七種。
public?static?enum?Event?{
????????UNDEFINED,
????????ON_START,
????????ON_INACTIVE,
????????ON_ACTIVE,
????????ON_BACKGROUND,
????????ON_FOREGROUND,
????????ON_STOP;
????????private?Event()?{
????????}
????}
界面啟動時調(diào)用onStart()和onActive()。
2020-09-13?21:42:10.266?25547-25547[表情]?I/System.out:?onStart
2020-09-13?21:42:10.284?25547-25547[表情]?I/System.out:?onActive
點擊返回鍵時調(diào)用。
2020-09-13?21:42:35.847?25547-25547/com.example.helloworld?I/System.out:?onInactive
2020-09-13?21:42:35.917?25547-25547/com.example.helloworld?I/System.out:?onBackground
2020-09-13?21:42:35.920?25547-25547/com.example.helloworld?I/System.out:?onStop
至于UNDEFINED和ON_FOREGROUND暫時還不了解。
Gradle任務(wù)(Task)
甚至連gradle的Task都非常類似,打包命令是assembleDebug/Release。
>?Task?:entry:preBuild
>?Task?:entry:compileDebugNativeWithCmake
>?Task?:entry:collectDebugDependencies
>?Task?:entry:mergeDebugResources
>?Task?:entry:mergeDebugProfile
>?Task?:entry:compileDebugResources
>?Task?:entry:compileDebugIdl
>?Task?:entry:compileDebugRFile
>?Task?:entry:processDebugJavaResource
>?Task?:entry:compileDebugJavaWithJavac
>?Task?:entry:mergeDebugJavaResource
>?Task?:entry:generateDebugClassesJar
>?Task?:entry:mergeDebugProjectDex
>?Task?:entry:generateDebugShell
>?Task?:entry:processDebugShellManifest
>?Task?:entry:compileDebugShellResources
>?Task?:entry:linkDebugShellResources
>?Task?:entry:compileDebugShellJavaWithJavac
>?Task?:entry:mergeDebugShellDex
>?Task?:entry:packageDebugShell
>?Task?:entry:packageDebugSimplifyShell
>?Task?:entry:validateDebugSigning
>?Task?:entry:signDebugShell
>?Task?:entry:packageDebugHap
>?Task?:entry:signDebugHap
>?Task?:entry:assembleDebug
配置文件
配置文件是一個命名為config.json的文件,配置應(yīng)用的一些信息。
{
??"app":?{
????"bundleName":?"com.example.helloworld",
????"vendor":?"example",
????"version":?{
??????"code":?1,
??????"name":?"1.0"
????},
????"apiVersion":?{
??????"compatible":?3,
??????"target":?3
????}
??},
??"deviceConfig":?{
????"default":?{
????}
??},
??"module":?{
????"package":?"com.example.helloworld",
????"name":?".HelloWorld",
????"reqCapabilities":?[
??????"video_support"
????],
????"deviceType":?[
??????"wearable"
????],
????"distro":?{
??????"deliveryWithInstall":?true,
??????"moduleName":?"entry",
??????"moduleType":?"entry"
????},
????"abilities":?[
??????{
????????"skills":?[
??????????{
????????????"entities":?[
??????????????"entity.system.home"
????????????],
????????????"actions":?[
??????????????"action.system.home"
????????????]
??????????}
????????],
????????"orientation":?"landscape",
????????"formEnabled":?false,
????????"name":?"com.example.helloworld.MainAbility",
????????"icon":?"$media:icon",
????????"description":?"$string:mainability_description",
????????"label":?"HelloWorld",
????????"type":?"page",
????????"launchType":?"standard"
??????}
????]
??}
}
仔細看這個文件會越來越覺得這就是AndroidManifest.xml的json翻譯版。
/? ?反編譯角度看鴻蒙? ?/
既然看起來這么像安卓,我看來看看它編譯后的產(chǎn)物是什么,是不是也能像android一樣反編譯得到dex文件?

編譯后得到的是一個xxx.hap文件。

修改它的后綴名為.zip,解壓后可以看到里面有熟悉的assets,dex,apk文件等,把這個apk文件安裝后發(fā)現(xiàn)并不能使用。

下面我們先反編譯這個classes.dex文件第一個dex反編譯后出現(xiàn)錯誤。
~/Desktop/fanbianyi/dex2jar-2.0???sh?d2j-dex2jar.sh?classes3.dex
dex2jar?classes3.dex?->?./classes3-dex2jar.jar
com.googlecode.d2j.DexException:?not?support?version.
????at?com.googlecode.d2j.reader.DexFileReader.<init>(DexFileReader.java:151)
????at?com.googlecode.d2j.reader.DexFileReader.<init>(DexFileReader.java:211)
????at?com.googlecode.dex2jar.tools.Dex2jarCmd.doCommandLine(Dex2jarCmd.java:104)
????at?com.googlecode.dex2jar.tools.BaseCmd.doMain(BaseCmd.java:288)
????at?com.googlecode.dex2jar.tools.Dex2jarCmd.main(Dex2jarCmd.java:32)
原因是我們的工具版本太低了,解決方案就是升級,升級版本后反編譯成功后為classes3-dex2jar.jar,打開可以看到:

這里多了個ResourceTable文件,就是我們的資源id表。這里的dex文件包含的是我們開發(fā)的代碼。
下面我們來反編譯apk文件,解壓后可以看到,里面是我們熟悉的內(nèi)容:

AndroidManifest.xml文件如下:

反編譯該dex文件可以看到,MainAbilityShellActivity最終是繼承了AbilityShellActivity:

ShellHelloWorld其實一個Application。

至此感覺.hap文件像是對apk的一個包裝,最終的邏輯看起來好像還是android那套,或者說android開發(fā)人員上手會非常快,可能也是為將來兼容android系統(tǒng)做準備。
/? ?分布式,跨設(shè)備遷移? ?/
跨設(shè)備遷移
下面來看看該系統(tǒng)的一些亮點,比如跨設(shè)備遷移,聽起來是個很牛逼炫酷的功能,比如把你的手機屏幕直接遷移到電腦或者pad上面以及進行一些操作等等。
跨設(shè)備遷移(下文簡稱“遷移”)支持將Page在同一用戶的不同設(shè)備間遷移,以便支持用戶無縫切換的訴求。以Page從設(shè)備A遷移到設(shè)備B為例,遷移動作主要步驟如下:?
設(shè)備A上的Page請求遷移。
HarmonyOS處理遷移任務(wù),并回調(diào)設(shè)備A上Page的保存數(shù)據(jù)方法,用于保存遷移必須的數(shù)據(jù)。
HarmonyOS在設(shè)備B上啟動同一個Page,并回調(diào)其恢復(fù)數(shù)據(jù)方法。
開發(fā)者可以參考以下詳細步驟開發(fā)具有遷移功能的Page。
分布式任務(wù)調(diào)度
在HarmonyOS中,分布式任務(wù)調(diào)度平臺對搭載HarmonyOS的多設(shè)備構(gòu)筑的“超級虛擬終端”提供統(tǒng)一的組件管理能力,為應(yīng)用定義統(tǒng)一的能力基線、接口形式、數(shù)據(jù)結(jié)構(gòu)、服務(wù)描述語言,屏蔽硬件差異;支持遠程啟動、遠程調(diào)用、業(yè)務(wù)無縫遷移等分布式任務(wù)。
分布式任務(wù)調(diào)度平臺在底層實現(xiàn)Ability。
啟動和關(guān)閉:向開發(fā)者提供管理遠程Ability的能力,即支持啟動Page模板的Ability,以及啟動、關(guān)閉Service和Data模板的Ability。
連接和斷開連接:向開發(fā)者提供跨設(shè)備控制服務(wù)(Service和Data模板的Ability)的能力,開發(fā)者可以通過與遠程服務(wù)連接及斷開連接實現(xiàn)獲取或注銷跨設(shè)備管理服務(wù)的對象,達到和本地一致的服務(wù)調(diào)度。
遷移能力:向開發(fā)者提供跨設(shè)備業(yè)務(wù)的無縫遷移能力,開發(fā)者可以通過調(diào)用Page模板Ability的遷移接口,將本地業(yè)務(wù)無縫遷移到指定設(shè)備中,打通設(shè)備間壁壘。
/? ?總結(jié)? ?/
個人感覺鴻蒙的開發(fā)是很接近Android開發(fā)者的習(xí)慣,對于Android開發(fā)人員來說極易上手,但是Android現(xiàn)有的多設(shè)備協(xié)同支持做的很差,鴻蒙做了一些封裝和擴展屏蔽掉底層的差異,在多設(shè)備,萬物互聯(lián)的時代具有很大的優(yōu)勢,越是多設(shè)備協(xié)同,鴻蒙越具有優(yōu)勢。
推薦閱讀:
Java 15 正式發(fā)布, 好多新特性,刷新你的認知!!
鍵盤敲入 A 字母時,操作系統(tǒng)期間發(fā)生了什么...
歡迎關(guān)注我的公眾號

長按上圖,識別圖中二維碼即可關(guān)注
