鴻蒙開(kāi)發(fā)初體驗(yàn)(Android開(kāi)發(fā)必看)

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)可以看到

image

<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)作主要步驟如下:

  1. 設(shè)備A上的Page請(qǐng)求遷移议忽。
  2. HarmonyOS處理遷移任務(wù),并回調(diào)設(shè)備A上Page的保存數(shù)據(jù)方法十减,用于保存遷移必須的數(shù)據(jù)栈幸。
  3. 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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末壳影,一起剝皮案震驚了整個(gè)濱河市拱层,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌态贤,老刑警劉巖舱呻,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡箱吕,警方通過(guò)查閱死者的電腦和手機(jī)芥驳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)茬高,“玉大人兆旬,你說(shuō)我怎么就攤上這事≡踉裕” “怎么了丽猬?”我有些...
    開(kāi)封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)熏瞄。 經(jīng)常有香客問(wèn)我脚祟,道長(zhǎng),這世上最難降的妖魔是什么强饮? 我笑而不...
    開(kāi)封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任由桌,我火速辦了婚禮,結(jié)果婚禮上邮丰,老公的妹妹穿的比我還像新娘行您。我一直安慰自己,他們只是感情好剪廉,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布娃循。 她就那樣靜靜地躺著,像睡著了一般斗蒋。 火紅的嫁衣襯著肌膚如雪捌斧。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天吹泡,我揣著相機(jī)與錄音骤星,去河邊找鬼。 笑死爆哑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的舆吮。 我是一名探鬼主播揭朝,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼色冀!你這毒婦竟也來(lái)了潭袱?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锋恬,失蹤者是張志新(化名)和其女友劉穎屯换,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡彤悔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年嘉抓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晕窑。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抑片,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杨赤,到底是詐尸還是另有隱情敞斋,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布疾牲,位于F島的核電站植捎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏阳柔。R本人自食惡果不足惜焰枢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盔沫。 院中可真熱鬧医咨,春花似錦、人聲如沸架诞。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谴忧。三九已至很泊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沾谓,已是汗流浹背委造。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留均驶,地道東北人昏兆。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像妇穴,于是被迫代替她去往敵國(guó)和親爬虱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348