0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

鸿蒙开发(Harmonyos兼容与Harmonyos适配)

jf_46214456 来源:jf_46214456 作者:jf_46214456 2024-01-26 17:49 次阅读

布局的实现

Layout_ability_main.xml布局:

< ?xml version="1.0" encoding="utf-8"? >
< DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
    ohos:orientation="vertical" >

    < TextField
        ohos:id="$+id:content"
        ohos:height="0vp"
        ohos:weight="1"
        ohos:width="match_parent"
        ohos:enabled="false"
        ohos:padding="20vp"
        ohos:text="0"
        ohos:text_alignment="center"
        ohos:text_size="30"/ >

    < ScrollView
        ohos:height="0vp"
        ohos:weight="1.8"
        ohos:width="match_parent" >

        < DirectionalLayout
            ohos:height="match_content"
            ohos:width="match_parent"
            ohos:alignment="horizontal_center"
            ohos:orientation="vertical" >

            < DirectionalLayout
                ohos:height="match_content"
                ohos:width="match_parent"
                ohos:orientation="horizontal" >

                

                

                

                

            < /DirectionalLayout >

            < DirectionalLayout
                ohos:height="match_content"
                ohos:width="match_parent"
                ohos:orientation="horizontal" >

                

                

                

                

            < /DirectionalLayout >

            < DirectionalLayout
                ohos:height="match_content"
                ohos:width="match_parent"
                ohos:orientation="horizontal" >

                

                

                

                

            < /DirectionalLayout >

            < DirectionalLayout
                ohos:height="match_content"
                ohos:width="match_parent"
                ohos:orientation="horizontal" >

                

                

                

                

            < /DirectionalLayout >

            < DirectionalLayout
                ohos:height="match_content"
                ohos:width="match_parent"
                ohos:orientation="horizontal" >


                

                

                

            < /DirectionalLayout >

        < /DirectionalLayout >
    < /ScrollView >
< /DirectionalLayout >
< /DirectionalLayout >
< /DirectionalLayout >

background_button1.xml背景样式:

< ?xml version="1.0" encoding="utf-8"? >
< shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="rectangle" >
    < solid ohos:color="#CCF1F1F1"/ >
    < corners ohos:radius="20vp"/ >
< /shape >
< /shape >
< /shape >

background_button2.xml背景样式:

< shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="rectangle" >
    < solid ohos:color="#FFE4F2FE"/ >
    < corners ohos:radius="20vp"/ >
< /shape >
< /shape >
< /shape >

background_button3.xml背景样式:

< ?xml version="1.0" encoding="utf-8"? >
< shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="rectangle" >
    < solid ohos:color="#FF007CFD"/ >
    < corners ohos:radius="20vp"/ >
< /shape >
< /shape >
< /shape >

嗯,编写布局页面不难、稍微难点的是电视、车载设备、Pad、手机、手表五个端的屏幕适配。

界面编写完,发现各个端的屏幕高度还没有做适配,一开始认为AndroidHarmonyOSJava语言都可以编写,HarmonyOS也可以使用Android的相关框架,便想着如何在HarmonyOS上去使用Android的屏幕适配方案,在用了今日头条的屏幕适配方案开刀后,发现压根行不通,今日头条的屏幕适配方案用的单位是dp,这个单位在HarmonyOS上并没有,只有类似的vp,看来还是我太天真了。

Android屏幕单位有dp、in、mm、pt、px、sp,HarmonOS屏幕单位有fp、px、vp。

其中两者相同的单位是px,Android的dp与HarmonOS的vp都是为各自设备量身打造的单位,若想要搞一个两者都可以用的屏幕适配框架,也许,只能从px找突破口。今日头条的屏幕适配方案用的单位虽然是HarmonyOS所没有的dp,但其实它最终都是要拿dp来转换成px的喔~

Java代码逻辑

继承AbilitySlice的MainAbilitySlice类:

public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener {
    private Utils utils = Utils.getInstance();
    private TextField content;
    private String formula = "";

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        initView();
        highlyAdaptive();
    }

    /**
     * 各个按钮点击事件
     * @param component
     */
    @Override
    public void onClick(Component component) {
        switch (component.getId()) {
            case ResourceTable.Id_one:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "1");
                else formula = "1";
                break;
            case ResourceTable.Id_two:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "2");
                else formula = "2";
                break;
            case ResourceTable.Id_three:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "3");
                else formula = "3";
                break;
            case ResourceTable.Id_four:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "4");
                else formula = "4";
                break;
            case ResourceTable.Id_five:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "5");
                else formula = "5";
                break;
            case ResourceTable.Id_six:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "6");
                else formula = "6";
                break;
            case ResourceTable.Id_seven:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "7");
                else formula = "7";
                break;
            case ResourceTable.Id_eight:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "8");
                else formula = "8";
                break;
            case ResourceTable.Id_nine:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "9");
                else formula = "9";
                break;
            case ResourceTable.Id_zero:
                if (utils.isNumStart(formula)) formula = utils.isZero(formula, "0");
                else formula = "0";
                break;
            case ResourceTable.Id_reset:
                formula = "0";
                break;
            case ResourceTable.Id_except:
                if (utils.isNumEnd(formula)) formula += "÷";
                else if (!formula.substring(formula.length() - 1, formula.length()).equals("."))
                    formula = formula.substring(0, formula.length() - 1) + "÷";
                break;
            case ResourceTable.Id_ride:
                formula = utils.isNum(formula, "x");
                break;
            case ResourceTable.Id_percentage:
                formula = utils.isNum(formula, "%");
                break;
            case ResourceTable.Id_decimal_point:
                if (utils.isNumEnd(formula) && !utils.isDecimals(formula)) formula += ".";
                break;
            case ResourceTable.Id_delete:
                if (!formula.equals("") && !formula.equals("0")) {
                    formula = formula.substring(0, formula.length() - 1);
                    if (formula.equals("")) formula = "0";
                }
                break;
            case ResourceTable.Id_reduce:
                if (utils.isNumEnd(formula)) formula += "-";
                else formula = formula.substring(0, formula.length() - 1) + "-";
                break;
            case ResourceTable.Id_add:
                if (utils.isNumEnd(formula)) formula += "+";
                else formula =
                        formula.substring(0, formula.length() - 1) + "+";
                break;
            case ResourceTable.Id_equal:
                equal();
                break;
            default:
                break;
        }
        if (component.getId() != ResourceTable.Id_equal) {
            content.setText(formula);
        }
    }

    private void equal() {
        if (formula.equals("")) {
            // 如果没有输入公式
            utils.toast(this, "还没输入公式呢");
            return;
        } else if (!utils.isNumEnd(formula)) {
            // 如果公式的最后一位数非数字
            utils.toast(this, "计算器表示没见过这样的数学公式,运算不出来");
            return;
        }
        String[] split;
        if (!utils.isContains(formula, ".")) {
            // 计算整数
            if (utils.isContains(formula, "-")) {
                // 减法
                split = formula.split("-");
                if (split.length > 1)
                    result((Integer.parseInt(split[0]) + Integer.parseInt(split[1])) + "");
            } else if (utils.isContains(formula, "+")) {
                // 加法
                split = formula.split("+");
                if (split.length > 1)
                    result((Integer.parseInt(split[0]) + Integer.parseInt(split[1])) + "");
            } else if (utils.isContains(formula, "x")) {
                // 乘法
                split = formula.split("x");
                if (split.length > 1)
                    result((Integer.parseInt(split[0]) + Integer.parseInt(split[1])) + "");
            } else if (utils.isContains(formula, "÷")) {
                // 除法
                split = formula.split("÷");
                if (split.length > 1)
                    result((Integer.parseInt(split[0]) + Integer.parseInt(split[1])) + "");
            } else if (utils.isContains(formula, "%")) {
                // 取余
                split = formula.split("%");
                if (split.length > 1)
                    result((Integer.parseInt(split[0]) + Integer.parseInt(split[1])) + "");
            }
        } else {
            // 计算小数
            if (utils.isContains(formula, "-")) {
                // 减法
                split = formula.split("-");
                if (split.length > 1)
                    result((Double.parseDouble(split[0]) - Double.parseDouble(split[1])) + "");
            } else if (utils.isContains(formula, "+")) {
                // 加法
                split = formula.split("+");
                if (split.length > 1)
                    result((Double.parseDouble(split[0]) - Double.parseDouble(split[1])) + "");
            } else if (utils.isContains(formula, "x")) {
                // 乘法
                split = formula.split("x");
                if (split.length > 1)
                    result((Double.parseDouble(split[0]) - Double.parseDouble(split[1])) + "");
            } else if (utils.isContains(formula, "÷")) {
                // 除法`
                split = formula.split("÷");
                if (split.length > 1)
                    result((Double.parseDouble(split[0]) - Double.parseDouble(split[1])) + "");
            } else if (utils.isContains(formula, "%")) {
                // 取余
                split = formula.split("%");
                if (split.length > 1)
                    result((Double.parseDouble(split[0]) - Double.parseDouble(split[1])) + "");
            }
        }
    }

    private void result(String value) {
        formula = value;
        content.setText(value);
    }

    /**
     * 根据不同设备调整高度
     */
    private void highlyAdaptive() {
        if (DeviceInfo.getDeviceType().equals("phone")) {
            // 手机设备
            ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig();
            layoutConfig.height = 1100;
            content.setLayoutConfig(layoutConfig);
        } else if (DeviceInfo.getDeviceType().equals("tablet")) {
            // 平板设备
            ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig();
            layoutConfig.height = 1200;
            content.setLayoutConfig(layoutConfig);
        } else if (DeviceInfo.getDeviceType().equals("tv")) {
            // TV设备
            ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig();
            layoutConfig.height = 160;
            content.setLayoutConfig(layoutConfig);
        } else if (DeviceInfo.getDeviceType().equals("wearable")) {
            // 可穿戴设备
            ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig();
            layoutConfig.height = 150;
            content.setLayoutConfig(layoutConfig);
        } else if (DeviceInfo.getDeviceType().equals("car")) {
            // 车载设备
            ComponentContainer.LayoutConfig layoutConfig = new ComponentContainer.LayoutConfig();
            layoutConfig.height = 500;
            content.setLayoutConfig(layoutConfig);
        }
    }

    /**
     * 初始化xml布局控件
     */
    private void initView() {
        content = (TextField) findComponentById(ResourceTable.Id_content);
        ((Button) findComponentById(ResourceTable.Id_one)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_two)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_three)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_four)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_five)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_six)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_seven)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_eight)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_nine)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_zero)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_reset)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_except)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_ride)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_delete)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_reduce)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_add)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_equal)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_decimal_point)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_percentage)).setClickedListener(this);
    }
}
}
}

由于在编写xml UI时屏幕适配只能做到宽度适配或高度适配,没办法在一个xml界面同时适配宽度与高度,为此写了一个highlyAdaptive方法处理xml没能完成的高度适配,方法通过DeviceInfo.getDeviceType()来得到设备的类型,根据不同的设备去修改它的高度,也算是实现了高度适配。

Utils类:

public class Utils {
    private static Utils utils = new Utils();
    private static ToastDialog toastDialog;
    private String[] symbol = new String[]{"+", "-", "x", "÷", "%"};

    public static Utils getInstance() {
        return utils;
    }

    public void toast(Context context, String text) {
        if (toastDialog == null) {
            toastDialog = new ToastDialog(context);
        }
        toastDialog.setAlignment(LayoutAlignment.CENTER);
        toastDialog.setText(text);
        toastDialog.show();
    }

    /**
     * 判断最后一位是否数字
     * @param content
     */
    public boolean isNumber(String content){
        char[] chars = content.substring(content.length() - 1, content.length()).toCharArray();
        return Character.isDigit(chars[0]);
    }

    /**
     * 判断是否是小数
     */
    public boolean isDecimals(String str) {
        if (isDecimal(str)) {
            for (String s : symbol) {
                if (isContains(str, s)) {
                    String[] split = str.split(s);
                    if (split != null){
                        if (!isDecimal(split[split.length - 1])) {
                            return false;
                        } else {
                            return true;
                        }
                    }
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 判断一位数是否是小数
     */
    public boolean isDecimal(String str) {
        if (isContains(str, "."))
            return true;
        else
            return false;
    }

    /**
     * 是否包含某一个运算符
     */
    public boolean isContains(String value, String contain) {
        if (value.indexOf(contain) == -1)
            return false;
        else
            return true;
    }

    /**
     * 最后一个值是数字就加符号,不是数字则替换它
     * @param str 符号
     */
    public String isNum(String content,String str) {
        if (isNumEnd(content)) content += str;
        else content = content.substring(0, content.length() - 1) + str;
        return content;
    }

    /**
     * 第一个值是0,输入整数则替换掉
     */
    public String isZero(String content,String str) {
        if (content.equals("0")) {
            content = str;
        } else {
            content += str;
        }
        return content;
    }

    /**
     * 得到第一个值是否是数字
     */
    public boolean isNumStart(String str) {
        if (str.startsWith("+") || str.startsWith("x") || str.startsWith("÷") || str.startsWith("%") || str.equals("")) {
            return false;
        }
        return true;
    }

    /**
     * 得到最后一个值是否是数字
     */
    public boolean isNumEnd(String str) {
        char[] chars = str.substring(str.length() - 1, str.length()).toCharArray();
        if (!Character.isDigit(chars[chars.length - 1])) {
            return false;
        }
        return true;
    }
}
}
}

GIF演示实现效果

  • Phone 设备实现效果
  • Pad 设备实现效果
  • TV 设备实现效果
  • Wearable 设备实现效果
    目前所有设备中,Wearable是几个设备中最不好适配、最难适配的设备,但,想实现也并非不可能。
    如果继续适配Wearable,目前能想到Wearable屏幕适配的方法有三种:
    1、需要将背景换成一个圆,按钮都放进一个自动换行的组件。只是,这个想法不是很现实,Android的RecycleView组件也只是一行固定多少个才会换行,HarmonyOS的ListContainer组件能否实现效果还是个未知数。
    2、使用他人开源的屏幕适配框架。不过,这个很遗憾,截止至发稿,还未能了解到有相关的适配框架。
    3、另外写一个适配Wearable的布局。在onState方法执行super.setUIContent前更换专门为Wearable而写的xml,如:
@Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        // wearable设备换一个布局
        if (DeviceInfo.getDeviceType().equals("wearable")){
            super.setUIContent(Wearable布局);
        }else{
            super.setUIContent(ResourceTable.Layout_ability_main);
        }
    }
    }
}

Car 实现效果

截止至发稿,Car还没有开放对应的机型,没能使用远程真机进行测试查看最终效果。这个效果图也只是点击Previewer进行查看的样式及效果。

Previewer注意事项:

1、点击Previewer查看xml,偶尔点击xml的一些样式并不会有响应,需要关闭Previewer并重新打开。

2、Previewer展示的样式不会显示ToastDialog等对话框、不会打印日志、不能点击Debug进行测试,还是使用真机测试真机测试香。

此次是我自HarmonyOS的DevEco Studio开发工具发布以来第一次开发的APP,身为一个Android开发工程师,做起HarmonyOS开发并不是很难,其中有很多东西都类似。DevEco Studio的远程真机测试与Previewer,效果杠杠的,要知道网上很多远程真机测试可都是收费制,且按使用时间收费,这一功能的出现可降低了不少开发费用。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 测试
    +关注

    关注

    8

    文章

    5157

    浏览量

    126466
  • 开发
    +关注

    关注

    0

    文章

    366

    浏览量

    40807
  • 鸿蒙
    +关注

    关注

    57

    文章

    2307

    浏览量

    42737
  • HarmonyOS
    +关注

    关注

    79

    文章

    1967

    浏览量

    30013
收藏 人收藏

    评论

    相关推荐

    AWTK 最新动态:支持鸿蒙系统(HarmonyOS Next)

    导读HarmonyOS是全球第三大移动操作系统,有巨大的市场潜力,在国产替代的背景下,机会多多,AWTK支持HarmonyOS,让AWTK开发者也能享受HarmonyOS生态的红利。A
    的头像 发表于 11-06 08:03 151次阅读
    AWTK 最新动态:支持<b class='flag-5'>鸿蒙</b>系统(<b class='flag-5'>HarmonyOS</b> Next)

    【书籍评测活动NO.47】HarmonyOS NEXT启程:零基础构建纯血鸿蒙应用

    应用需要单独进行适配,以开发对应的鸿蒙原生应用。 鸿蒙开发者抢手 目前,鸿蒙系统
    发表于 10-14 14:36

    华为“纯血”鸿蒙系统 HarmonyOS NEXT 将于9月底推出正式版

    HarmonyOS NEXT 将于今年 9 月底推出正式版本。 “从发布第一个版本到今年的 9 月份,这个(9 月)月底我们会正式发布 HarmonyOS NEXT,这一版本是完全独立开发、独立自主的,而且是不
    的头像 发表于 09-14 14:27 899次阅读

    庆科信息获HarmonyOS高级应用开发能力认证!助力品牌快速打造鸿蒙原生应用

    近日,上海庆科信息技术有限公司荣获HarmonyOS应用开发者高级认证,公司在华为鸿蒙生态的开发能力得到进一步拓展,能够帮助客户快速开发基于
    的头像 发表于 07-17 13:24 547次阅读
    庆科信息获<b class='flag-5'>HarmonyOS</b>高级应用<b class='flag-5'>开发</b>能力认证!助力品牌快速打造<b class='flag-5'>鸿蒙</b>原生应用

    华为鸿蒙HarmonyOS NEXT 9月启动,下半年全场景布局

    早前这位博主曾在4月29日发表文章称,尽管鸿蒙NEXT在常见App适配方面已取得显著进展,但仍有部分功能尚未完全开发完成,可能导致系统显示暂不支持相关内容。此外,新版本在流畅度方面已基本与现有
    的头像 发表于 05-20 16:07 883次阅读

    MobTech袤博科技旗下核心SDK产品已全面适配HarmonyOS NEXT鸿蒙星河版

    日前,华为在鸿蒙生态春季沟通会上宣布,目前已有超4000个应用加入鸿蒙生态,鸿蒙生态再次迎来新的里程碑。作为应用开发的重要组件,MobTech袤博科技旗下核心SDK产品已全面完成
    的头像 发表于 05-14 17:41 438次阅读

    拓维信息及旗下开鸿智谷同获华为HarmonyOS开发服务商认证

    近日,拓维信息及旗下开鸿智谷双双通过华为HarmonyOS开发服务商认证,成为华为“鸿蒙服务商先锋计划”认证级伙伴。秉持共同发展、共创价值的合作理念,拓维信息、开鸿智谷将携手华为打造
    的头像 发表于 03-29 08:13 477次阅读
    拓维信息及旗下开鸿智谷同获华为<b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发</b>服务商认证

    鸿蒙新篇章,领航新征程 I 软通动力荣膺首批“HarmonyOS开发服务商”

    HarmonyOS开发服务商”,成为华为该领域首批认证服务商。 软通动力高级副总裁石蓉(右),华为终端云开发者服务与平台部总裁望岳(左) HarmonyOS
    的头像 发表于 03-14 17:19 492次阅读
    <b class='flag-5'>鸿蒙</b>新篇章,领航新征程 I 软通动力荣膺首批“<b class='flag-5'>HarmonyOS</b><b class='flag-5'>开发</b>服务商”

    2024款鸿蒙OS 最新HarmonyOS Next_HarmonyOS4.0系列教程分享

    鸿蒙的出现,标志着中国科技的崛起。HarmonyOS就是我们说的华为鸿蒙系统,截止到2023年8月4日已有超过7亿台设备搭载了鸿蒙OS系统。据多家媒体报道,2024年国内有21所985
    发表于 02-28 10:29

    华为宣布HarmonyOS NEXT鸿蒙星河版开发者预览面向开发者开放申请

    华为宣布HarmonyOS NEXT鸿蒙星河版开发者预览面向开发者开放申请,这意味着鸿蒙生态进入第二阶段,将加速千行百业的应用
    的头像 发表于 01-29 16:42 1365次阅读
    华为宣布<b class='flag-5'>HarmonyOS</b> NEXT<b class='flag-5'>鸿蒙</b>星河版<b class='flag-5'>开发</b>者预览面向<b class='flag-5'>开发</b>者开放申请

    淘宝与华为合作将基于HarmonyOS NEXT启动鸿蒙原生应用开发

    1月25日,淘宝与华为举办鸿蒙合作签约仪式,宣布将基于HarmonyOS NEXT启动鸿蒙原生应用开发
    的头像 发表于 01-26 16:14 1053次阅读

    今日看点丨华为 HarmonyOS NEXT 鸿蒙星河版第四季度商用;博世计划2026年底前裁员1200人

    开发者预览版 Beta 招募,当前支持华为 Mate 60、Mate 60 Pro、Mate X5 机型报名。HarmonyOS NEXT 开发者预览版将不再兼容安卓开源应用,仅支持
    发表于 01-19 10:47 1205次阅读

    HarmonyOS SDK,助力开发者打造焕然一新的鸿蒙原生应用

    鸿蒙星河版重磅发布,带来了全新架构、全新体验、全新生态。作为支撑鸿蒙原生应用开发的技术源动力,HarmonyOS SDK 将系统级能力全面对外开放,覆盖了应用框架、应用服务、系统、媒
    发表于 01-19 10:31

    免费学习鸿蒙HarmonyOS开发,一些地址分享

    国内一流高校。通过鸿蒙班的设立,高校可以为学生提供专业的鸿蒙OS学习环境和丰富的实践机会,培养出更多的鸿蒙开发人才,为鸿蒙OS系统的生态建设
    发表于 01-12 20:48

    HarmonyOS应用兼容稳定性云测试

    兼容性测试 兼容性测试主要验证 HarmonyOS 应用在华为真机设备上运行的兼容性问题,包括首次安装、再次安装、启动、卸载、崩溃、黑白屏、闪退、运行错误、无法回退、无响应、设计约束场
    发表于 12-25 10:56