会员登录 - 用户注册 - 设为首页 - 加入收藏 - 网站地图 卡片服务开发之如何开发一个地图服务卡片!

卡片服务开发之如何开发一个地图服务卡片

时间:2025-11-04 23:32:23 来源:益强数据堂 作者:人工智能 阅读:263次

想了解更多内容,卡片开发开请访问:

和华为官方合作共建的服务鸿蒙技术社区

https://harmonyos.51cto.com

前言

处于隐私保护借用熊猫基地定位,代码层实现了获取实时定位功能。个地

效果图

卡片效果2x2+2x44x4缩放

关键技术及实现原理

卡片现有支持的图服基础组件有:button、calendar、卡片开发开chart、服务clock、个地divider、图服image、卡片开发开input、服务progress、个地span、图服text

可以看到现有的卡片开发开卡片组件并不支持地图的开发,那么如何在卡片上显示地图尼?服务

通过image组件+高德地图WebAPI的静态地图即可实现地图的显示。

-以上方便有开发卡片经验的个地开发者提供思路,具体方式方法如下

从零开始

创建项目

打开DevEco Studio工具,点击File->New->New Project创建一个Empty Ability(JS)如下图:

SDK选用API 5

创建后的结构:

首先修改程序的配置文件:

打开config.json,IT技术网修改卡片支持类型情况:

添加权限:

配置完成还需要在MainAbility中显示的申明使用权限信息,详情参考文档配置相关内容:

打开MainAbility添加方法:

//获取权限    private void requestPermission() {        String[] permission = {                "ohos.permission.LOCATION",                "ohos.permission.LOCATION_IN_BACKGROUND",        };        List<String> applyPermissions = new ArrayList<>();        for (String element : permission) {            if (verifySelfPermission(element) != 0) {                if (canRequestPermission(element)) {                    applyPermissions.add(element);                }            }        }        requestPermissionsFromUser(applyPermissions.toArray(new String[0]), 0);    } 

并在onStart方法中调用requestPermission();方法。

修改界面:

打开widget下的pages/index/imdex.hml

<div class="container">         <div class="container-inner" >             <div class="container-img">                 <stack>                     <image src="{{imgSrc}}" class="bg-img"></image>                     <div class="container-show-text" >                         <text class="show-text" >当前检索项:</text>                         <text class="show-text" style="color: coral;"  >{{searchText}}</text>                     </div>                     <div class="container-map-ctl">                         <button class="map-ctl-btn" @click="mapAddEvent"  type="circle">+</button>                         <button class="map-ctl-btn" @click="mapReduceEvent"  type="circle">-</button>                     </div>                     <div show="{{showCtlButton}}" class="container-ctl" >                         <button class="ctl-btn" @click="searchCheckedEvent0">{{searchBtns[0]}}</button>                         <button class="ctl-btn" @click="searchCheckedEvent1">{{searchBtns[1]}}</button>                         <button class="ctl-btn" @click="searchCheckedEvent2">{{searchBtns[2]}}</button>                         <button class="ctl-btn" @click="searchCheckedEvent3">{{searchBtns[3]}}</button>                         <button class="ctl-btn" @click="searchCheckedEvent4">{{searchBtns[4]}}</button>                     </div>                 </stack>             </div>         </div> </div> 

需要注意:卡片的事件不能使用表达式,不能使用for语句循环构建

样式调整文件pages/index/imdex.css:

.container {     flex-direction: column;     justify-content: center;     align-items: center; } .bg-img {     flex-shrink: 0;     height: 100%;     object-fit: cover; } .container-ctl{     opacity: 0.9;     width: 100%;     height: 100%;     justify-content: center;     flex-direction: row;     align-items: flex-end;     bottom: 3px; } .ctl-btn{     padding: 3px 6px;     margin:3px 6px;     font-size: 12px;     border-radius: 3px;     background-color: #409eff;     border: 1px solid #cbcbcb;     box-shadow: 1px 1px 3px #a8a8a8; } .container-map-ctl{     opacity: 0.8;     justify-content: flex-end;     margin-right: 3px; } .map-ctl-btn{     background-color: #409eff;     border: 1px solid #cbcbcb;     box-shadow: 1px 1px 3px #a8a8a8;     width: 24px;     height: 24px;     margin:3px; } .container-show-text{     padding: 9px; } .show-text{     font-size: 8px;     font-weight: bolder; } 

json配置信息修改pages/index/index.json:

{   "data": {     "showCtlButton": false,//是否显示button。由Java传值且在2x2的界面不显示     "imgSrc": "/common/ic_default_image@3x.png",//默认图片     "searchText": "",     "searchBtns": []//配置的button按钮信息   },   "actions": {     "searchCheckedEvent0": {       "action": "message",       "params": {         "index": 0,         "name": "checkSearch"       }     },     "searchCheckedEvent1": {       "action": "message",       "params": {         "index": 1,         "name": "checkSearch"       }     },     "searchCheckedEvent2": {       "action": "message",       "params": {         "index": 2,         "name": "checkSearch"       }     },     "searchCheckedEvent3": {       "action": "message",       "params": {         "index": 3,         "name": "checkSearch"       }     },     "searchCheckedEvent4": {       "action": "message",       "params": {         "index": 4,         "name": "checkSearch"       }     },     "mapAddEvent": {       "action": "message",       "params": {         "name": "mapAdd"       }     },     "mapReduceEvent": {       "action": "message",       "params": {         "name": "mapReduce"       }     }   } } 

后台逻辑

由于更新卡片时需要提供formId,我们对FormController及FormControllerManager这两个帮助类进行一个修改。

打开java目录下的FormController文件并添加受保护的属性 formId,并修改构造函数。

然后进入FormControllerManager找到createFormController、getController、newInstance进行修改。

createFormController:

在newInstance方法中添加参数formId,如下图:

getController:

在newInstance方法中添加参数formId,如下图:

newInstace:

该方法是动态的创建WidgetImpl方法,类似于IOC作用。

找到java目录下的widget/widget/widgetImpl,卡片的高防服务器所有逻辑都在该文件内

首先修改构造函数及定义基础属性等

因上述修改了FormController及FormControllerManager构造函数必须增加Long formId参数

private static Location slocation=null;//当前位置信息    private Boolean slocationChanged=false;//位置是否修改    private  int dimension=2;//当前卡片模式  2x2=2;2x4=3;4x4=4;    private List<String> defualtBtn=new ArrayList<>();//界面下方的按钮列表    private static Locator locator=null;//坐标获取类    private LocatorCallBack locatorCallBack=new LocatorCallBack();//坐标获取后返回调用类    private int mRoom=16;//静态地图显示层级    private String markType="";//静态地图周边搜索关键字    private String mSize="500*500";//静态地图大小    private List<String> mKeyLocation=new ArrayList<>();//静态地图获取周边标记的坐标    RequestParam requestParam = new RequestParam(RequestParam.PRIORITY_ACCURACY, 20, 0);    public WidgetImpl(Context context, String formName, Integer dimension,Long formId) {        super(context, formName, dimension,formId);        this.dimension=dimension;        //获取当前定位        if(locator==null){            locator=new Locator(context);            locator.startLocating(requestParam,locatorCallBack);        }        switch (dimension){            case 2:{                mSize="300*300";                mRoom=13;                break;            }            case 3:{              mSize="500*250";              mRoom=13;              break;            }            case 4:{                mSize="500*500";                mRoom=15;                break;            }        }    }    public class LocatorCallBack implements LocatorCallback{        @Override        public void onLocationReport(Location location) {            slocation=location;            //周边信息接口额度有限,限制为当坐标改变时刷新坐标mark信息,并更新卡片            if(location==slocation || slocation==null)                return;            refreshMark();            updateFormData(formId);        }        @Override        public void onStatusChanged(int i) {        }        @Override        public void onErrorReport(int i) {        }    } 

修改createFormController,该方法在卡片创建时调用,我们需要把页面需要的参数传递过去

注意网络图片需要使用“通过内存图片方式使用image组件”

@Override    public ProviderFormInfo bindFormData(){        defualtBtn=new ArrayList<>();        defualtBtn.add("酒店");        defualtBtn.add("餐饮");        defualtBtn.add("景点");        defualtBtn.add("加油站");        if(defualtBtn.size()<5){            for(int i=defualtBtn.size();i<5;i++){                defualtBtn.add("未设置");            }        }        this.markType=defualtBtn.get(0);        this.refreshMark();        FormBindingData formBindingData=null;        ZSONObject zsonObject =new ZSONObject();        zsonObject.put("imgSrc","memory://amap.png");        zsonObject.put("showCtlButton",this.dimension!=2);        zsonObject.put("searchBtns",defualtBtn);        zsonObject.put("searchText",markType);        formBindingData=new FormBindingData(zsonObject);        ProviderFormInfo formInfo = new ProviderFormInfo();        formInfo.setJsBindingData(formBindingData);        String amapUrl=getMapImageUrl(mKeyLocation);        byte[] bytes= HttpImageUtils.doGetRequestForFile(amapUrl);        formBindingData.addImageData("amap.png",bytes);        return formInfo;    } 

初始化卡片后改进onTriggerFormEvent

该方法为接收卡片事件,message为事件传递的params参数

@Override   public void onTriggerFormEvent(long formId, String message) {       ZSONObject request=ZSONObject.stringToZSON(message);       String EventName=request.getString("name");       switch (EventName){           case "checkSearch":{               int index=request.getIntValue("index");               markType=defualtBtn.get(index);               this.refreshMark();               break;           }           case "mapAdd":{               if(mRoom<17){                   mRoom+=1;               }               break;           }           case "mapReduce":{               if(mRoom>0){                   mRoom-=1;               }               break;           }       }       updateFormData(formId);   } 

修改更新卡片信息的方法(此方法不仅是系统会定时刷新,也有主动刷新的调用如:卡片事件改变后调用,坐标改变后的调用,这也是需要修改FormController、FormControllerManager增加formId属性的原因,因为在主动刷新时需要formId参数)

此处还有一个重点就是 ((Ability)context).updateForm(formId,bindingData);

@Override    public void updateFormData(long formId, Object... vars) {        ZSONObject zsonObject=new ZSONObject();        zsonObject.put("searchBtns",defualtBtn);        zsonObject.put("searchText",markType);        String mapName="amap"+System.currentTimeMillis()+".png";        zsonObject.put("imgSrc","memory://"+mapName);        FormBindingData bindingData = new FormBindingData(zsonObject);        String amapUrl=getMapImageUrl(mKeyLocation);        byte[] bytes= HttpImageUtils.doGetRequestForFile(amapUrl);        bindingData.addImageData(mapName,bytes);        try{            ((Ability)context).updateForm(formId,bindingData);        }catch (Exception ex){            ex.printStackTrace();        }    } 

其它一些上述方法中调用的私有方法及类

私有方法:

private void refreshMark(){       try{           this.mKeyLocation= HttpImageUtils.SearchByKeyUrl(getMapMarkUrl(10));       }catch (Exception ex){           ex.printStackTrace();       }   }   private String getMapImageUrl(List<String> Position){       String url="https://restapi.amap.com/v3/staticmap";       String params="key=";       params+="&zoom="+mRoom;       params+="&size="+mSize;       if(slocation!=null)           params+="&location="+slocation.getLongitude()+","+slocation.getLatitude();       params+="&markers=large,0xea7700,H:"+slocation.getLongitude()+","+slocation.getLatitude();       if(Position==null || Position.size()==0)           return  url+"?"+params;       String markers="|mid,0xFF0000,:";       for(int i=0;i<Position.size();i++){           markers+=Position.get(i)+";";       }       params+=markers.substring(0,markers.length()-1);       return url+"?"+params;   }   private  String getMapMarkUrl(int size){       String Url="https://restapi.amap.com/v5/place/around?key=";       Url+="&keywords="+(markType=="未设置"?"":markType);       if(slocation!=null)           Url+="&location="+slocation.getLongitude()+","+slocation.getLatitude();       Url+="&size="+size;       return Url;   } 

HttpImageUtils类

package com.panda_coder.amapcard.utils; import com.panda_coder.amapcard.MainAbility; import ohos.hiviewdfx.HiLog; import ohos.hiviewdfx.HiLogLabel; import ohos.utils.zson.ZSONArray; import ohos.utils.zson.ZSONObject; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; public class HttpImageUtils {     private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, MainAbility.class.getName());     public final static byte[] doGetRequestForFile(String urlStr) {         InputStream is = null;         HttpURLConnection conn = null;         byte[] buff = new byte[1024];         try {             URL url = new URL(urlStr);             conn = (HttpURLConnection) url.openConnection();             conn.setDoInput(true);             conn.setRequestMethod("GET");             conn.setReadTimeout(6000);             conn.connect();             is = conn.getInputStream();             if (conn.getResponseCode() == 200) {                 buff = readInputStream(is);             } else{                 buff=null;             }         } catch (Exception e) {             HiLog.error(TAG,"【获取图片异常】",e);         }         finally {             try {                 if(is != null){                     is.close();                 }             } catch (IOException e) {                 e.printStackTrace();             }             conn.disconnect();         }         return buff;     }     public static byte[] readInputStream(InputStream is) {         ByteArrayOutputStream baos = new ByteArrayOutputStream();         byte[] buffer = new byte[1024];         int length = -1;         try {             while ((length = is.read(buffer)) != -1) {                 baos.write(buffer, 0, length);             }             baos.flush();         } catch (IOException e) {             e.printStackTrace();         }         byte[] data = baos.toByteArray();         try {             is.close();             baos.close();         } catch (IOException e) {             e.printStackTrace();         }         return data;     }     public static String httpGet(String urlStr){         InputStream is = null;         HttpURLConnection conn = null;         String response="";         StringBuffer buffer = new StringBuffer();         try {             URL url = new URL(urlStr);             conn = (HttpURLConnection) url.openConnection();             conn.setDoInput(true);             conn.setRequestMethod("GET");             conn.setReadTimeout(6000);             conn.connect();             is = conn.getInputStream();             if (conn.getResponseCode() == 200) {                 String str=null;                 InputStreamReader isr = new InputStreamReader(is,"utf-8");                 BufferedReader br = new BufferedReader(isr);                 while((response = br.readLine())!=null){                     buffer.append(response);                 }             }             response=buffer.toString();         } catch (Exception e) {             HiLog.error(TAG,"【访问异常】",e);         }         finally {             try {                 if(is != null){                     is.close();                 }             } catch (IOException e) {                 e.printStackTrace();             }             conn.disconnect();         }         return response;     }     public final  static List<String> SearchByKeyUrl(String urlStr){         List<String> result=new ArrayList<>();         String response= httpGet(urlStr);         if(response==null || response=="")             return result;         ZSONObject zson=ZSONObject.stringToZSON(response);         if(zson.getIntValue("infocode")!=10000)             return result;         ZSONArray zsonArray=zson.getZSONArray("pois");         for(int i=0;i<zsonArray.size();i++){             ZSONObject child= (ZSONObject)zsonArray.get(i);             String location=child.getString("location");             result.add(location);         }         return result;     } } 

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

(责任编辑:IT科技类资讯)

推荐内容
  • 探索dostylesd805的风格魅力(发现dostylesd805独特设计与创新科技的奇妙融合)
  • windows 7安装中文软件显示乱码是什么原因(系统语言是中文)
  • 怎么用windows 7笔记本wifi热点 windows 7笔记本wifi热点设置图
  • windows 7搜索框不见了如何找回具体该怎么操作
  • 电脑wis系统安装教程(电脑wis系统安装详解,助你提升工作效率与便捷性)
  • windows 7系统CF截图后找不到怎么办?