• KaiOS APN Settings模块代码


    一、模块简介

    APN界面在Settings应用菜单实现,代码归属gaia/apps/settings。

    KaiOS panel 生命周期:onInit->onBeforeShow->onShow->onBeforeHide->onHide

    官方参考文档:Gaia/Settings/docs - MozillaWiki

    二、KaiO3.1应用通用目录结构

    源码路径gaia/apps(感觉就是个网站网页开发),手机目录

    文件(夹)作用说明
    manifest.webapp该文件作用类似于AndroidManifest.xml文件,在其中进行应用名称,默认语言,所需权限,开发者等信息的设置
    index.html主页,相当于MainActivity.java,应用启动的第一个页面,需要在manifest.webapp文件中配置
    js/src文件夹

    module;

    JavaScript源代码、模块化代码文件、模块间交互引用

    element文件夹html文件
    style文件夹资源文件,如css样式,image图片,icons图标等
    locales文件夹

    string资源。

    如Settings应用用到字符串位置:gaia/locales/en-US/apps/settings/settings.properties

    resources文件夹资源文件,类似Android res目录
    test文件夹

    包含单元测试等功能文件

    三、代码路径

    1、【UI】APN列表页:

    • gaia/apps/settings/elements/apn_list.html 界面结构和布局
    • gaia/apps/settings/js/panels/apn_list/panel.js 逻辑
      • createApnSettingsPanel函数创建并返回SettingsPanel面板对象
    • gaia/apps/settings/elements/apn_settings.html
    • gaia/apps/settings/js/panels/apn_settings/panel.js

    Kai基原生行为:apn_list(左)和apn_settings(右)是两个不同的界面

    • apn_list:Data Settings,卡匹配的一套APN,以每条APN形式展示
    • apn_settings:APN Settings,针对不同类型的APN分类展示

    Note:定制APN菜单项registerSoftkey()——比如运营商需求不可添加APN

    2、【UI】APN编辑页:新增、修改APN

    • gaia/apps/settings/elements/apn_editor.html 界面
    • gaia/apps/settings/js/panels/apn_editor/panel.js 逻辑


    3、【功能逻辑】

    更新数据库APN:/gaia/apps/settings/js/modules/apn/apn_settings.js

    gaia/apps/settings/js/modules/apn/apn_settings_manager.js

    四 、实现逻辑

    KaiOS的APN设置界面是使用HTML和JavaScript动态生成的:

    1. "apn_settings.html"文件中包含APN设置界面的HTML代码,其中包括单选按钮的代码。

    2. "apn_settings.js"文件中包含用于生成和操作单选按钮的JavaScript代码。这个文件中的代码使用模板引擎来生成HTML代码,然后将其插入到页面中。

    (一)【UI】卡APN列表:apn_list 

    panels.js 实际用APN列表界面
    1. gaia/apps/settings/elements/apn_lists.html 定义了 APN Settings界面的结构和布局
    2. gaia/apps/settings/js/panels/apn_list/panel.js 
    3. gaia/apps/settings/js/panels/apn_list/apn_template_factory.js 界面模板
    1. <element name="apn_list" extends="section">
    2. <template>
    3. <gaia-header data-href="#apn_settings">
    4. <h1 slot="text">h1>
    5. gaia-header>
    6. <div class ="panel">
    7. <ul role="menu" class="apn-list">ul>
    8. <ul>
    9. ul>
    10. div>
    11. <panel data-path="panels/apn_list/panel"><panel>
    12. template>
    13. element>
    apn_lists/panel.js接口说明
    createApnSettingsPanel()

    最外层返回的方法,其他功能函数都嵌套在内。

    getFocusPos
    registerSoftkey
    resetApnWarningDialog
    resetApn
    updateSoftkey
    updateUI
    getElementByType
    onApnDeleteAfter we deleted an apn , we should remove it from apn-list and reset focus && navigation map && refresh softkeys
    SettingsPanel
    apn_template_factory.js 字段介绍

    gaia/apps/settings/js/panels/apn_list/apn_template_factory.js

    要注意const变量的定义,避免引起undefined报错。此模板用于创建DOM节点。

    1. const rawApn = item.apn;
    2. const input = document.createElement('input');     // Create an element
    3. const radioSpan = document.createElement('span');      //单选按钮  
    4. const radioLabel = document.createElement('label');     //标签
    5. const nameSpan = document.createElement('span');    
    6. const nameLabel = document.createElement('label');
    7. const li = document.createElement('li');      //每一行
    1. //item参数包含了APN具体信息
    2. function apnTemplate(apnType, onItemclick, onRadioClick, itemsOBJ, item) {
    3. const rawApn = item.apn; //从item获取APN对象
    4. // Create an element
    5. const input = document.createElement('input'); //创建input元素
    6. input.type = 'radio'; //设置input元素类型是radio(Radio Button控件)
    7. input.checked = item.active; //并根据item.active布尔属性值设置是否选中
    8. input.name = apnType;
    9. // Include the radio button element in a list item
    10. const radioSpan = document.createElement('span'); //创建span元素,用于显示Radio Button空间的样式
    11. const radioLabel = document.createElement('label'); //创建lable元素
    12. radioLabel.classList.add('pack-radio-large');
    13. radioLabel.appendChild(input); //将input元素添加到lable元素中
    14. radioLabel.appendChild(radioSpan);
    15. //创建包含APN名称的span元素,并添加其到nameLable元素中
    16. const nameSpan = document.createElement('span');
    17. const nameLabel = document.createElement('label');
    18. nameSpan.classList.add('full-string');
    19. nameLabel.classList.add('pack-radio-large');
    20. nameLabel.classList.add('my_radio');
    21. nameLabel.setAttribute('data-id', item.id); //为nameLabel元素设置一个data-id属性,用于后续操作中能够识别APN列表项
    22. itemsOBJ[item.id] = item;
    23. if (!rawApn.carrier) {
    24. nameSpan.textContent = rawApn.apn;
    25. } else {
    26. nameSpan.textContent = rawApn.carrier;
    27. }
    28. nameLabel.appendChild(input);
    29. nameLabel.appendChild(nameSpan);
    30. const li = document.createElement('li');
    31. li.appendChild(nameLabel); //最后将lable添加到新的列表项返回
    32. return li;
    33. }
    apn_list 业务逻辑

    /gaia/apps/settings/js/modules/apn/apn_list.js

    apn_lists.js接口说明
    ApnList(key)

    ApnList.prototype =包含下列增删查改的方法
    schedule(task)As the operations should not be performed concurrently. We use this function to enusre the operations are performed one by one.

    export()

    commit()
    addInternal(apn, category)
    removeInternal(id)
    updateInternal(id, apn)
    items()
    item(id)
    add(apn, category)
    remove(id)
    update(id, apn) 
    updateByWap(id, apn)
    apnList(key)

    (二)【UI】分类APN菜单:apn_settings

    panels.js

    gaia/apps/settings/js/panels/apn_settings/panel.js是KaiOS APN设置界面,包含了生成和操作APN设置界面的所有JavaScript代码,主要功能如下:

    1. 初始化界面:当APN设置界面被加载时,会调用init函数进行初始化。在init函数中,首先检查是否支持APN设置,如果不支持,则显示错误消息并返回。如果支持,则加载APN列表和默认设置,并将其显示在界面上。

    2. 加载APN列表:loadAPNs函数用于从设备中读取APN列表。该函数使用navigator.mozMobileConnections API来获取当前设备上的移动连接,并使用其getAvailableNetworks方法获取APN列表。如果成功获取APN列表,则将其存储在apnList变量中。

    3. 加载默认设置:loadDefaultSetting函数用于加载当前的默认设置。该函数使用navigator.mozSettings API获取当前设备的APN设置,并将其存储在defaultSetting变量中。

    4. 显示APN设置列表:displayAPNList函数用于将APN设置列表显示在界面上。该函数使用Handlebars.js模板引擎生成每个APN设置项目的HTML代码,并将其插入到HTML文档中的相应元素中。

    5. 更新选项状态:updateOptionState函数用于根据用户的选择更新APN设置项的状态。该函数将用户选择的APN设置ID存储在selectedAPN变量中,并使用jQuery选择器更新相应的单选按钮状态。

    6. 保存设置:saveSetting函数用于将用户的选择保存到设备中。该函数使用navigator.mozSettings API将用户选择的APN设置保存到设备的APN设置中。

    apn_settings/panels.js接口说明
    createApnSettingsPanel()

    最外层返回的方法,其他功能函数都嵌套在内,这样内部函数可以访问外部函数createApnSettingsPanel的所有变量和参数。

    const APN_KEYS = [

    'ril.data.dm.apnSettings.sim1',

    'ril.data.dm.apnSettings.sim2'

    ];

    initSoftKey(hasSelect)

    接口=界面右侧菜单Options(Edit&Delete&Reset)

    menuClassName: 'menu-button',

    updateSoftKey(evt)
    resetApnWarningDialog()
    resetApn()
    browseApnItems(evt)

    用于处理“浏览APN”按钮的点击事件,打开“浏览APN”面板,即APN编辑页详情。

    1、首先检查触发事件的元素是否包含数据集中的“apnType”属性。如果没有,则退出函数。

    2、如果存在“apnType”属性,则获取该属性的值,并将其与当前设备的服务ID一起传递给 Settings.setCurrentPanel 函数。

    3、Settings.setCurrentPanel 函数用于打开“浏览APN”面板,并设置面板的当前类型和服务ID。

    NOTE:在打开编辑面板之前,需要先检查当前设备是否支持APN设置。如果不支持,则应禁用Edit选项。

    addClickEventListener()

    给apnSettingsList中可见的APN添加click监听

    apnSettingsList[i].addEventListener('click', browseApnItems);

    removeClickEventListener()移除可见apnSettingsList的click监听
    initUI(panel)

    用于初始化 APN 设置面板的用户界面。可隐藏Message/A-GPS/Tethering类型的APN项。

    1、从 ApiManager.connections 对象中获取与当前服务 ID 相对应的连接信息。
    2、创建一个 Promise 数组,将连接信息的 getSupportedNetworkTypes 方法调用添加到其中。

    promises.push(conn.getSupportedNetworkTypes());
    3、调用 Promise.all 方法,等待所有 Promise 都完成后执行后续操作。

    4、在 Promise.all 方法的回调函数中,获取 getSupportedNetworkTypes 方法返回的值,即当前连接支持的网络类型列表。(Note:使用promise异步方法中获取支持的网络类型列表,首次进入界面可能会存在延迟)

    Promise.all(promises).then(values => {});

    5、获取界面中 ID 为“ims”的元素,并检查该元素是否存在。如果存在,则根据当前连接支持的网络类型决定是否显示该元素。

    SettingsPanel()

    createApnSettingsPanel最后return SettingsPanel()。

    实现了onInit(panel)、onBeforeShow(panel, options)和onHide()接口。

    1、onInit:数据查询apnSettingsList = panel.querySelectorAll('a[data-apn-type]');

    2、onBeforeShow:调用initSoftKey和initUI初始化界面,并添加监听addClickEventListener()

    3、onHide():调用removeClickEventListener()移除监听

    apn_settings.js

    (三)【功能】增删查改 APN:apn_settings_manager.js

    otegaia/apps/settings/js/modules/apn/apn_settings_manager.jsN

    Note:JS接口可以形参和实参个数不同,如果只输入一个参数就是第一个参数,第二个参数默认是undefined。

    apn_settings_manager.js接口

    ApnSettingsManager.prototype =

    功能
     ready(serviceId)

    Ensures the current apn items are up-to-date. When the current plmn does not equal to the cached plmn, we should restore the apn items.

    确保当前 apn 项目是最新的。当当前 plmn 不等于缓存的 plmn 时,我们应该恢复 apn 项。

    addObservers(serviceId) 

    Register default APN changed observer

    注册default APN观察者。

    getPlmnAndMvnoInfo(serviceId)

    Get current mcc/mnc information

    获取当前卡MCCMNC信息。

    deriveActiveApnIdFromItems(serviceId, apnType)

    Returns the id of the first preset apn item.

    返回第一个预设的 APN 项的ID。

    deriveActiveApnIdFromSettings(serviceId, apnType)

    Returns the id of the apn item that matches the current apn setting of the specified apn type.

    从指定的 APN 类型的当前 APN 设置中返回匹配的 APN 项的 ID。

    getApnAppliedType(serviceId, apnId)

    Return the apn type an apn that is actively being used for.

    返回正在使用的 APN 类型。

    storeApnSettingByType(serviceId, apnType)

    Store the current apn selection to apn settings to the settings database.

    将当前 APN 选择的 APN 设置存储到设置数据库中。

    apnList(serviceId)

    Get the apn item list of a sim slot.

    获取 SIM 卡槽的 APN 项列表。

    apnItems(serviceId, apnType) 

    Get the apn items of an apn type for a sim slot.

    获取 SIM 卡槽指定 APN 类型的 APN 项列表。

    restoreApnItemsOfCategory(apnList, apnsForRestoring, category)Restore the apn items of a category.
    getServiceIdMcc(serviceId) Get current carrier mcc code by service Id
    restore(serviceId, mode)

    Restore the apn items and apn settings to the default. Apn items of the category ApnItem.APN_CATEGORY.PRESET and ApnItem.APN_CATEGORY.EU are restored. User created apn items (custom apns) will be delete. Therestored. User created apn items (custom apns) will be delete. The preset apn items are from the apn.json database and client provisioning messages.

    将 apn 项和 apn 设置恢复为默认值。类别 ApnItem.APN_CATEGORY 的 APN 项。PRESET 和 ApnItem.APN_CATEGORY.EU 已恢复。用户创建的 apn 项(自定义 apns)将被删除。那里存储。用户创建的 apn 项(自定义 apns)将被删除。预设的 apn 项来自 apn.json 数据库和客户端预配消息。

    queryApns(serviceId, apnType)查询一张卡的APN。查询匹配 apn.json 数据库中的 mcc/mnc 代码和通过客户端配置消息接收到的代码的 APN 项。返回ApnItem数组。
    addApn(serviceId, apn, category)向SIM卡新增一条APN,并指定 APN 项的分类。如果未指定分类,则默认将 APN 项分类为自定义。
    removeApn(serviceId, id)删除一条APN
    updateApn(serviceId, id, apn)更新一条APN
    getActiveApnId(serviceId, apnType)获取正在激活使用的APN。
    setActiveApnId(serviceId, apnType, id)将指定id的 APN 设置为使用APN。

    定义名为ApnSettingsManager的类,包含多个属性(this)

    1. /**
    2. * @class ApnSettingsManager
    3. * @requires module:modules/async_storage
    4. * @requires module:modules/apn/apn_const
    5. * @requires module:modules/apn/apn_utils
    6. * @requires module:modules/apn/apn_item
    7. * @requires module:modules/apn/apn_settings
    8. * @requires module:modules/apn/apn_list
    9. * @requires module:modules/apn/apn_selections
    10. * @returns {ApnSettingsManager} 注释指出,该实例会被返回给调用者
    11. */
    12. function ApnSettingsManager() {
    13. this._apnLists = {}; //APN列表
    14. this._apnSelections = ApnSelections(); //存储APN选择
    15. this._apnSettings = ApnSettings(); //存储APN设置设置
    16. //可自定义新增属性,如下:
    17. //this.apnSelectedId = ''; //存储选中的APN的ID
    18. this._readyPromises = {};
    19. //客制化
    20. //this.defaultApnSettingChanged = {};
    21. //定义RESTORE_MODE只读属性,其值是常量RESTORE_MODE,是一个外部模块或变量的引用。
    22. Object.defineProperty(this, 'RESTORE_MODE', {
    23. configurable: false,
    24. get: function() { //等同 get() {get() {
    25. return RESTORE_MODE;
    26. }
    27. });
    28. }

    (四)【UI】APN编辑页:apn_editor

    APN编辑页面 apn_editor/apn_editor.js 
    1. /**
    2. * The apn editor module
    3. */
    4. 'use strict';
    5. define(function(require) { //eslint-disable-line
    6. const ApnEditorConst = require('panels/apn_editor/apn_editor_const');
    7. const ApnEditorSession = require('panels/apn_editor/apn_editor_session');
    8. const { APN_PROPERTIES } = ApnEditorConst;
    9. const { APN_PROPERTY_DEFAULTS } = ApnEditorConst;
    10. const { VALUE_CONVERTERS } = ApnEditorConst;
    11. function ApnEditor(rootElement) {}
    12. ApnEditor.prototype = {};
    13. return function apnEditor(rootElement) {
    14. return new ApnEditor(rootElement);
    15. };
    16. });
    ApnEditor.prototype功能
    convertValue
    fillInputElements定制APN 每一项参数的可编辑性
    createApn
    editApn
    编辑业务功能 apn_editor/panels.js 

    gaia/apps/settings/js/panels/apn_editor/panel.js

    1. //结构组成
    2. 'use strict';
    3. define(function(require) { //eslint-disable-line
    4. const SettingsPanel = require('modules/settings_panel');
    5. const ApnSettingsManager = require('modules/apn/apn_settings_manager');
    6. return function apnEditorPanel(){
    7. const DM_PROTOCOL = 'dm.apnSettings.protocol';
    8. //多个业务功能方法,主要都是编辑和保存功能
    9. return SettingsPanel{};
    10. };
    11. });

    五、用户功能

    将apn_list和apn_settings融合定制

    界面文字提示功能介绍
    Add APN左上功能键:添加APN
    Options右上功能键:菜单选项(包含编辑、删除、重置APN)
    Seleted上下键移动APN列表光标,点击ok可切换选中APN,右边单选按钮变化 

    六、其他

    卡和运营商相关文件operator_variant

    1. <variant version="1">
    2. <operator
    3. name="Movistar"
    4. mcc="214"
    5. mnc="07"
    6. enableStrict7BitEncodingForSms="true"
    7. operatorSizeLimitation="512000"
    8. />
    9. variant>

    apnItem结构

    1. //提交APN信息的结构,apnItem
    2. {
    3. "itemId":"mlxfslzn2",
    4. "itemCategory":"preset",
    5. "itemApn":{
    6. "apn":"tad",
    7. "authtype":"notDefined",
    8. "carrier":"tad",
    9. "category":"custom",
    10. "id":"zdd2mblgk",
    11. "mmsc":"",
    12. "mmsport":"",
    13. "mmsproxy":"",
    14. "password":"",
    15. "port":"",
    16. "protocol":"notDefined",
    17. "proxy":"",
    18. "roaming_protocol":"notDefined",
    19. "types":["default"],
    20. "user":""
    21. }
    22. }

    itemId和iitemApn里面的id是不同的

  • 相关阅读:
    vue3左树的全选和反选
    【大话设计模式】开放-封闭原则
    【Python性能优化】元素极少时list和set的查找速度
    常见大厂面试题(SQL)02
    企业搬迁 四通搬家再为市场树立行业新标准
    无代码开发提醒设置入门教程
    3个变化3秒区别MT4和MT5
    图论基础知识 深度优先(Depth First Search, 简称DFS),广度优先(Breathe First Search, 简称DFS)
    小代码 - Python 读取iOS导出照片,修改名称为照片拍摄时间
    基于xlsx的B+树索引实现
  • 原文地址:https://blog.csdn.net/qq_38666896/article/details/133770929