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

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

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

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

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

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

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

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

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

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

 然而,事情并没有这么简单,当我再将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版本号。

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

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

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

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

这是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了!经多次试验,应用当前解决方案,大部分项目都可以在平板/手机/智慧屏上完美工作,感谢大家的阅读~

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

上一篇:导致OGG进程中断Time Since Chkpt 50个小时后.VERH后天热键


下一篇:自学鸿蒙应用开发(16)- ListContainer