ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【鸿蒙开发笔记】JS API6以后不再维护旧的数据存储接口,我们可以这样做,同时兼顾新老接口的鸿蒙设备!

2021-09-09 16:35:08  阅读:367  来源: 互联网

标签:API6 鸿蒙 接口 js private ohos import public


最近,羊羊乐儿在开发一款HarmonyOS2.0的软件,采用的js+java混合开发模式,js与hml主要用于页面UI设计,java则主要用于提供软件所需要的能力!但是,在实现记录是否已完成软件初次开启,不再推送初次启动页的时候,却遇到了一些小问题,不过最终还是解决了,下面就来给大家分享一下我的经验吧!

事情是这样子的,羊羊乐儿将已在自己鸿蒙设备上测试通过的版本,放到了云端的mate30测试,却发现运行以后,界面一片空白,什么也不加载,于是去鸿蒙官网又仔细查了一下:

 原来是API6已经不再维护之前的数据存储接口了,而云端的mate30鸿蒙则正是这个API版本!

 于是呢,羊羊乐儿就在自己的启动代码,里引入了新的'@ohos.data.storage'类,并使用新的方式,制作了一份用于判断初次启动页是否完成的验证!

 就这样,羊羊乐儿再一次将新生成的hap包,推至了云端API6接口的mate30,看起来好像是成功了,可以显示出页面了!

 然而,事情并没有这么简单,当我再将hap包推至自己的鸿蒙设备时,我发现我自己的鸿蒙设备又不能加载出页面了!而且,我将try和catch的内容对调,重新打包推至自己的鸿蒙设备也是如此,并且这样的版本连云端api6的mate30也不能用了 !大概分析了一下原因:

一旦你在page所对应的js里import了'@ohos.data.storage'这个新类,那低于API6的鸿蒙设备就会造成加载不出这个页面,而如果是在API6的环境里import'@system.storage'这个旧类,你不去调用里面的参数的话,那么它不会影响到。可是这样的话,引入新的类旧的没发工作,不引入新的类那新的Api6又不能调用之前的存取代码,那不就无解了么?

在这里,羊羊乐儿也是纳闷了很久,不过还是想到了解决办法:

既然这样的话,那我就不把这个需要调用存取,判断是否完成初次启动的页面,作为第一个page了!我先来检查一下当前设备的API版本,然后再推送不同的数据检测页和相应的pages方案不就好了么,分两个版本做pages,一个版本只import新类,一个只引用旧的类! 

好,马上行动,很快羊羊乐儿就在官网找到了ohos.system.version.SystemVersion,这样一个类,它可以检测出当前鸿蒙设备的Api版本号。

 不过呢,它这是一个java api,js它是没办法直接用的,但是没有关系,鸿蒙它提供了js调用PA能力的方式:

 具体怎么操作,大家可以去鸿蒙开发者官网了解,这里就直接上代码了!

这是java端的代码,这里用的是Internal Ability方式:

package com.agger.harmonyosthemeseditor;

import ohos.ace.ability.AceInternalAbility;
import ohos.app.AbilityContext;
import ohos.rpc.IRemoteObject;
import ohos.rpc.MessageOption;
import ohos.rpc.MessageParcel;
import ohos.rpc.RemoteException;
import ohos.utils.zson.ZSONObject;
import ohos.system.version.SystemVersion;

import java.util.HashMap;
import java.util.Map;

public class AGIModuleInternalAbility extends AceInternalAbility {

    //使用代码时,请自行更换为您项目的BundleName与AbilityName
    private static final String BUNDLE_NAME = "com.agger.harmonyosthemeseditor";
    private static final String ABILITY_NAME = "com.agger.harmonyosthemeseditor.AGIModuleInternalAbility";
    private static final int SUCCESS = 0;
    private static final int ERROR = 1;
    private static final int GetAPIVersion = 101;
    private static AGIModuleInternalAbility instance;
    private AbilityContext abilityContext;

    //用于读取js端传递的data数据,本js调用PA能力,js端无需传递任何数据
    /*public class RequestParam_GetAPIVersion {
        private int targetApi;
        private int minApi;

        public int getTargetApi() {
            return targetApi;
        }

        public void setTargetApi(int targetApi) {
            this.targetApi = targetApi;
        }

        public int getMinApi() {
            return minApi;
        }

        public void setMinApi(int minApi) {
            this.minApi = minApi;
        }
    }*/

    public AGIModuleInternalAbility()
    {
        super(BUNDLE_NAME, ABILITY_NAME);
    }

    public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option)
    {
        switch (code)
        {
            case GetAPIVersion:
            {
                /*用于解析js端传递的数据,本js调用PA能力,js端无需传递任何数据
                String zsonStr = data.readString();
                RequestParam param = ZSONObject.stringToClass(zsonStr, RequestParam.class);
                try {param = ZSONObject.stringToClass(dataStr, RequestParam.class);}
                catch (RuntimeException e) {}*/
                Map<String, Object> result = new HashMap<String, Object>();
                result.put("code", SUCCESS);
                int API_Version_Code = 0;
                try{
                    SystemVersion _SystemVersion = new SystemVersion();
                    API_Version_Code = _SystemVersion.getApiVersion();
                }catch (Exception ex){}
                result.put("abilityResult", API_Version_Code);

                if (option.getFlags() == MessageOption.TF_SYNC) {
                    reply.writeString(ZSONObject.toZSONString(result));
                } else {
                    // ASYNC
                    MessageParcel responseData = MessageParcel.obtain();
                    responseData.writeString(ZSONObject.toZSONString(result));
                    IRemoteObject remoteReply = reply.readRemoteObject();
                    try {
                        remoteReply.sendRequest(0, responseData, MessageParcel.obtain(), new MessageOption());
                    } catch (RemoteException exception) {
                        return false;
                    } finally {
                        responseData.reclaim();
                    }
                }
                break;
            }
            default:
            {
                Map<String, Object> result = new HashMap<String, Object>();
                result.put("abilityError", ERROR);
                reply.writeString("service not defined");
            }
        }
        return true;
    }

    /**
     * Internal ability 注册接口。
     */
    public static void register(AbilityContext abilityContext) {
        instance = new AGIModuleInternalAbility();
        instance.onRegister(abilityContext);
    }

    private void onRegister(AbilityContext abilityContext) {
        this.abilityContext = abilityContext;
        this.setInternalAbilityHandler((code, data, reply, option) -> {
            return this.onRemoteRequest(code, data, reply, option);
        });
    }

    /**
     * Internal ability 注销接口。
     */
    public static void unregister() {
        instance.onUnregister();
    }

    private void onUnregister() {
        abilityContext = null;
        this.setInternalAbilityHandler(null);
    }
}

到了这里,别忘了修改您的MainAbility,分别在onStart和onStop里面增添register和unregister!

@Override
    public void onStart(Intent intent)
    {
        AGIModuleInternalAbility.register(this);

        super.onStart(intent);
        this.getWindow().addFlags(WindowManager.LayoutConfig.MARK_TRANSLUCENT_STATUS);
        if (verifySelfPermission("ohos.permission.DISTRIBUTED_DATA") != IBundleManager.PERMISSION_GRANTED || verifySelfPermission("ohos.permission.DISTRIBUTED_DATASYNC") != IBundleManager.PERMISSION_GRANTED) {
            // 应用未被授予权限
            requestPermissionsFromUser(new String[] { "ohos.permission.DISTRIBUTED_DATA","ohos.permission.DISTRIBUTED_DATASYNC"} ,1);
        } else {
            // 权限已被授予
        }

    }

    @Override
    public void onStop() {
        AGIModuleInternalAbility.unregister();

        super.onStop();
    }

这是js端的代码,如果您采用的不是Internal Ability方式,须自行修改action.abilityType

import router from '@system.router';
import prompt from '@system.prompt';

// abilityType: 0-Ability; 1-Internal Ability
const ABILITY_TYPE_EXTERNAL = 0;
const ABILITY_TYPE_INTERNAL = 1;
// syncOption(Optional, default sync): 0-Sync; 1-Async
const ACTION_SYNC = 0;
const ACTION_ASYNC = 1;
const ACTION_MESSAGE_CODE_GetAPIVersion = 101;

export default {
    onShow : async function()
    {
        var actionData = {};
        actionData.targetApi = 6;
        actionData.minApi = 4;

        var action = {};
        //使用代码时,请自行更换为您项目的BundleName与AbilityName
        action.bundleName = 'com.agger.harmonyosthemeseditor';
        action.abilityName = 'com.agger.harmonyosthemeseditor.AGIModuleInternalAbility';
        action.messageCode = ACTION_MESSAGE_CODE_GetAPIVersion;
        action.data = actionData;
        action.abilityType = ABILITY_TYPE_INTERNAL;
        action.syncOption = ACTION_SYNC;

        var result = await FeatureAbility.callAbility(action);
        var ret = JSON.parse(result);

        /*可以写个toast试验一下,是不是真的可以检查版本
        prompt.showToast
        (
            {
                message: '当前鸿蒙API版本是:' + JSON.stringify(ret.abilityResult)
            }
        );*/


        if(ret.abilityResult >= 6)
        {
            router.push ({uri:'pages/index/api_6/index'});
        }else
        {
            router.push ({uri:'pages/index/api_lower6/index'});
        }
    },

}

好啦,这样就能根据不同API版本的设备,推送不同的pages了!经多次试验,应用当前解决方案,大部分项目都可以在平板/手机/智慧屏上完美工作,感谢大家的阅读~

标签:API6,鸿蒙,接口,js,private,ohos,import,public
来源: https://blog.csdn.net/jubhjnk/article/details/120201666

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有