2020年9月10號(hào)浅浮,鴻蒙2.0(HarmonyOS 2.0)系統(tǒng)正式發(fā)布秕硝,鴻蒙2.0面向應(yīng)用開(kāi)發(fā)者發(fā)布Beta版本芥映,在2020年9月10發(fā)布大屏,手表远豺,車機(jī)版鴻蒙奈偏,2020年12月發(fā)布手機(jī)版鴻蒙。在2020年9月10日躯护,鴻蒙開(kāi)源路標(biāo)面向內(nèi)存128KB-128MB終端設(shè)備惊来;2021年10月,將面向4GB以上所有設(shè)備棺滞。
背景
作為一個(gè)安卓開(kāi)發(fā)者裁蚁,能夠看到國(guó)產(chǎn)的操作系統(tǒng)的發(fā)布確實(shí)很興奮内狸,興奮之余,更想要看看具體是怎么一回事厘擂,首先打開(kāi)官網(wǎng)昆淡,看看官網(wǎng)該系統(tǒng)的定義:HarmonyOS是一款“面向未來(lái)”、面向全場(chǎng)景(移動(dòng)辦公刽严、運(yùn)動(dòng)健康昂灵、社交通信、媒體娛樂(lè)等)的分布式操作系統(tǒng)舞萄。在傳統(tǒng)的單設(shè)備系統(tǒng)能力的基礎(chǔ)上眨补,HarmonyOS提出了基于同一套系統(tǒng)能力、適配多種終端形態(tài)的分布式理念倒脓,能夠支持多種終端設(shè)備撑螺。
對(duì)應(yīng)用開(kāi)發(fā)者而言,HarmonyOS采用了多種分布式技術(shù)崎弃,使得應(yīng)用程序的開(kāi)發(fā)實(shí)現(xiàn)與不同終端設(shè)備的形態(tài)差異無(wú)關(guān)甘晤,降低了開(kāi)發(fā)難度和成本。這能夠讓開(kāi)發(fā)者聚焦上層業(yè)務(wù)邏輯饲做,更加便捷线婚、高效地開(kāi)發(fā)應(yīng)用。該優(yōu)點(diǎn)在5G這個(gè)萬(wàn)物互聯(lián)的時(shí)代具有著巨大的優(yōu)勢(shì)盆均。
安裝DevEco Studio
接下來(lái)下載DevEco Studio(IDE/開(kāi)發(fā)工具)來(lái)進(jìn)行體驗(yàn)一下軟件的開(kāi)發(fā)塞弊,在這里可以看到目前的IDE只有Windows系統(tǒng)的(windows 10 64位),安裝過(guò)程可能中會(huì)出現(xiàn)gradle的安裝失敗泪姨,記得添加代理游沿,在用戶目錄(打開(kāi)“此電腦”,在文件夾地址欄中輸入%userprofile%肮砾,進(jìn)入個(gè)人數(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
復(fù)制代碼
gradle安裝成功蔗草,但在編譯過(guò)程中可能出現(xiàn)build失敗,錯(cuò)誤如下:
ERROR: Cause: mirrors.huaweicloud.com:443 failed to respond
復(fù)制代碼
解決方式就是把所有的代理先關(guān)掉疆柔,然后你就會(huì)發(fā)現(xiàn)如絲般順滑咒精。
安裝完DevEco Studio后,打開(kāi)后可以看到界面和Android Studio非常相似
1.布局開(kāi)發(fā)
一切看起來(lái)非常的熟悉旷档,可以使用Java或JS等語(yǔ)言進(jìn)行開(kāi)發(fā)模叙,布局可以通過(guò)XML創(chuàng)建,size單位是vp
<?xml version="1.0" encoding="utf-8"?>
<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>
復(fù)制代碼
也可以通過(guò)Java代碼直接創(chuàng)建鞋屈,點(diǎn)擊事件都是如此的親切
@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 為組件添加對(duì)應(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);
// 類似的添加一個(gè)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
// 在組件中增加對(duì)點(diǎn)擊事件的檢測(cè)
public void onClick(Component Component) {
// 此處添加按鈕被點(diǎn)擊需要執(zhí)行的操作
}
});
directionalLayout.addComponent(button);
// 步驟5 將布局作為根布局添加到視圖樹(shù)中
super.setUIContent(directionalLayout);
}
復(fù)制代碼
首頁(yè)的布局如下范咨,通過(guò)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);
}
復(fù)制代碼
效果如下:
2.生命周期
下面再來(lái)看看主界面的生命周期故觅,實(shí)現(xiàn)了ILifecycle接口,生命周期狀態(tài)一共有七種
public static enum Event {
UNDEFINED,
ON_START,
ON_INACTIVE,
ON_ACTIVE,
ON_BACKGROUND,
ON_FOREGROUND,
ON_STOP;
private Event() {
}
}
復(fù)制代碼
界面啟動(dòng)時(shí)調(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
復(fù)制代碼
點(diǎn)擊返回鍵時(shí)調(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
復(fù)制代碼
至于UNDEFINED和ON_FOREGROUND暫時(shí)還不了解渠啊。
3.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
復(fù)制代碼
4.配置文件
配置文件是一個(gè)命名為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"
}
]
}
}
復(fù)制代碼
仔細(xì)看這個(gè)文件會(huì)越來(lái)越覺(jué)得這就是AndroidManifest.xml的json翻譯版替蛉。
反編譯角度看鴻蒙
既然看起來(lái)這么像安卓贯溅,我看來(lái)看看它編譯后的產(chǎn)物是什么,是不是也能像android一樣反編譯得到dex文件躲查?
編譯后得到的是一個(gè)xxx.hap文件
修改它的后綴名為.zip它浅,解壓后可以看到里面有熟悉的assets,dex镣煮,apk文件等姐霍,把這個(gè)apk文件安裝后發(fā)現(xiàn)并不能使用。
下面我們先反編譯這個(gè)classes.dex文件第一個(gè)dex反編譯后出現(xiàn)錯(cuò)誤
~/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)
復(fù)制代碼
原因是我們的工具版本太低了典唇,解決方案在這镊折,升級(jí)版本后反編譯成功后為classes3-dex2jar.jar,打開(kāi)可以看到
<figcaption style="display: block; text-align: center; font-size: 1rem; line-height: 1.6; color: rgb(144, 144, 144); margin-top: 2px;"></figcaption>
這里多了個(gè)ResourceTable文件蚓聘,就是我們的資源id表腌乡。這里的dex文件包含的是我們開(kāi)發(fā)的代碼。
下面我們來(lái)反編譯apk文件夜牡,解壓后可以看到,里面是我們熟悉的內(nèi)容
AndroidManifest.xml文件如下
反編譯該dex文件可以看到侣签,MainAbilityShellActivity最終是繼承了AbilityShellActivity
ShellHelloWorld其實(shí)一個(gè)Application
至此感覺(jué).hap文件像是對(duì)apk的一個(gè)包裝塘装,最終的邏輯看起來(lái)好像還是android那套,或者說(shuō)android開(kāi)發(fā)人員上手會(huì)非秤八快蹦肴,可能也是為將來(lái)兼容android系統(tǒng)做準(zhǔn)備。
分布式猴娩,跨設(shè)備遷移
跨設(shè)備遷移
下面來(lái)看看該系統(tǒng)的一些亮點(diǎn)阴幌,比如跨設(shè)備遷移,聽(tīng)起來(lái)是個(gè)很牛逼炫酷的功能卷中,比如把你的手機(jī)屏幕直接遷移到電腦或者pad上面以及進(jìn)行一些操作等等
跨設(shè)備遷移(下文簡(jiǎn)稱“遷移”)支持將Page在同一用戶的不同設(shè)備間遷移矛双,以便支持用戶無(wú)縫切換的訴求。以Page從設(shè)備A遷移到設(shè)備B為例蟆豫,遷移動(dòng)作主要步驟如下:
- 設(shè)備A上的Page請(qǐng)求遷移议忽。
- HarmonyOS處理遷移任務(wù),并回調(diào)設(shè)備A上Page的保存數(shù)據(jù)方法十减,用于保存遷移必須的數(shù)據(jù)栈幸。
- HarmonyOS在設(shè)備B上啟動(dòng)同一個(gè)Page愤估,并回調(diào)其恢復(fù)數(shù)據(jù)方法。
開(kāi)發(fā)者可以參考以下詳細(xì)步驟開(kāi)發(fā)具有遷移功能的Page速址。
分布式任務(wù)調(diào)度
在HarmonyOS中玩焰,分布式任務(wù)調(diào)度平臺(tái)對(duì)搭載HarmonyOS的多設(shè)備構(gòu)筑的“超級(jí)虛擬終端”提供統(tǒng)一的組件管理能力,為應(yīng)用定義統(tǒng)一的能力基線芍锚、接口形式震捣、數(shù)據(jù)結(jié)構(gòu)、服務(wù)描述語(yǔ)言闹炉,屏蔽硬件差異蒿赢;支持遠(yuǎn)程啟動(dòng)、遠(yuǎn)程調(diào)用渣触、業(yè)務(wù)無(wú)縫遷移等分布式任務(wù)羡棵。
分布式任務(wù)調(diào)度平臺(tái)在底層實(shí)現(xiàn) Ability
- 啟動(dòng)和關(guān)閉:向開(kāi)發(fā)者提供管理遠(yuǎn)程Ability的能力,即支持啟動(dòng)Page模板的Ability嗅钻,以及啟動(dòng)皂冰、關(guān)閉Service和Data模板的Ability。
- 連接和斷開(kāi)連接:向開(kāi)發(fā)者提供跨設(shè)備控制服務(wù)(Service和Data模板的Ability)的能力养篓,開(kāi)發(fā)者可以通過(guò)與遠(yuǎn)程服務(wù)連接及斷開(kāi)連接實(shí)現(xiàn)獲取或注銷跨設(shè)備管理服務(wù)的對(duì)象秃流,達(dá)到和本地一致的服務(wù)調(diào)度。
- 遷移能力:向開(kāi)發(fā)者提供跨設(shè)備業(yè)務(wù)的無(wú)縫遷移能力柳弄,開(kāi)發(fā)者可以通過(guò)調(diào)用Page模板Ability的遷移接口舶胀,將本地業(yè)務(wù)無(wú)縫遷移到指定設(shè)備中,打通設(shè)備間壁壘碧注。
總結(jié)
個(gè)人感覺(jué)鴻蒙的開(kāi)發(fā)是很接近Android開(kāi)發(fā)者的習(xí)慣嚣伐,對(duì)于Android開(kāi)發(fā)人員來(lái)說(shuō)極易上手,但是Android現(xiàn)有的多設(shè)備協(xié)同支持做的很差萍丐,鴻蒙做了一些封裝和擴(kuò)展屏蔽掉底層的差異轩端,在多設(shè)備,萬(wàn)物互聯(lián)的時(shí)代具有很大的優(yōu)勢(shì)逝变,越是多設(shè)備協(xié)同基茵,鴻蒙越具有優(yōu)勢(shì)。
作者:傷心的豬大腸
鏈接:https://juejin.im/post/6871999738720288781