Android APP开发KML轨迹导出教程示例

目录
  • 引言
  • 写入kml gps点
  • 奥森10km 轨迹图

引言

前两天在知乎上面找海外骑行、跑步软件Strava的时候,看到一个将运动轨迹从A App 导出,导入到B APP的工具 APP RunGap,恰巧之前给台湾、印度那边的测试同事处理他们的问题时,写过这样的一个工具,KML文件导出,然后在Mac下的 Google 地球上看轨迹是否偏差,是否存在坐标类型的转化错误等问题,能够比较快地定位问题。

KML文件,读者有不知道的可以Google一下,它是一种专门存GPS 点数据的xml文件格式。

将以下这个数据结构 PathRecord类的GPS点 List 转换成xml:

图 1.0 PathRecord

借用PathRecord的时间戳生成文件,存入SD卡,然后完文件里写 List 点, 文件带.kml 后缀。

图1.1 生成KML文件

写入kml gps点

public static String pullXMLCreate(String outDir, PathRecord pathRecord) {
        final String fileName = createKmlFile(outDir, pathRecord);
        StringWriter xmlWriter = new StringWriter();
        try {
//      // 方式一:使用Android提供的实用工具类android.util.Xml
//      XmlSerializer xmlSerializer = Xml.newSerializer();
            // 方式二:使用工厂类XmlPullParserFactory的方式
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlSerializer xmlSerializer = factory.newSerializer();
            xmlSerializer.setOutput(xmlWriter);                // 保存创建的xml
            xmlSerializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
            xmlSerializer.startDocument("utf-8", null);
            //给根节点kml添加属性
            xmlSerializer.setPrefix("xmlns", "http://www.opengis.net/kml/2.2");
            xmlSerializer.setPrefix("gx", "http://www.google.com/kml/ext/2.2");// <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
            xmlSerializer.startTag("", "kml");
            xmlSerializer.startTag("", "Document");
            xmlSerializer.startTag("", "Placemark");
            xmlSerializer.startTag("", "Style");
            xmlSerializer.startTag("", "LineStyle");
            xmlSerializer.startTag(null, "color");
            xmlSerializer.text("ff60ff00");//这里的颜色必须小写
            xmlSerializer.endTag(null, "color");
            xmlSerializer.startTag(null, "width");
            xmlSerializer.text("6");
            xmlSerializer.endTag(null, "width");
            xmlSerializer.endTag("", "LineStyle");
            xmlSerializer.endTag("", "Style");
            List<Gps> points = pathRecord.locationList;
            xmlSerializer.startTag(null, "LineString");
            xmlSerializer.startTag(null, "coordinates");
            xmlSerializer.text(createKMLPointStr(points));
            xmlSerializer.endTag(null, "coordinates");
            xmlSerializer.endTag(null, "LineString");
            xmlSerializer.endTag("", "Placemark");
            xmlSerializer.endTag("", "Document");
            xmlSerializer.endTag("", "kml");
            xmlSerializer.endDocument();
        } catch (XmlPullParserException e) {// XmlPullParserFactory.newInstance
            e.printStackTrace();
        } catch (IllegalArgumentException e) {    // xmlSerializer.setOutput
            e.printStackTrace();
        } catch (IllegalStateException e) {    // xmlSerializer.setOutput
            e.printStackTrace();
        } catch (IOException e) {// xmlSerializer.setOutput
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        String xmlStr = xmlWriter.toString();
        BaseFileUtil.writeStringToFile(fileName, xmlStr);
        return xmlStr;
    }public static String pullXMLCreate(String outDir, PathRecord pathRecord) {
        final String fileName = createKmlFile(outDir, pathRecord);
        StringWriter xmlWriter = new StringWriter();
        try {
//      // 方式一:使用Android提供的实用工具类android.util.Xml
//      XmlSerializer xmlSerializer = Xml.newSerializer();
            // 方式二:使用工厂类XmlPullParserFactory的方式
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            XmlSerializer xmlSerializer = factory.newSerializer();
            xmlSerializer.setOutput(xmlWriter);                // 保存创建的xml
            xmlSerializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
            xmlSerializer.startDocument("utf-8", null);
            //给根节点kml添加属性
            xmlSerializer.setPrefix("xmlns", "http://www.opengis.net/kml/2.2");
            xmlSerializer.setPrefix("gx", "http://www.google.com/kml/ext/2.2");// <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
            xmlSerializer.startTag("", "kml");
            xmlSerializer.startTag("", "Document");
            xmlSerializer.startTag("", "Placemark");
            xmlSerializer.startTag("", "Style");
            xmlSerializer.startTag("", "LineStyle");
            xmlSerializer.startTag(null, "color");
            xmlSerializer.text("ff60ff00");//这里的颜色必须小写
            xmlSerializer.endTag(null, "color");
            xmlSerializer.startTag(null, "width");
            xmlSerializer.text("6");
            xmlSerializer.endTag(null, "width");
            xmlSerializer.endTag("", "LineStyle");
            xmlSerializer.endTag("", "Style");
            List<Gps> points = pathRecord.locationList;
            xmlSerializer.startTag(null, "LineString");
            xmlSerializer.startTag(null, "coordinates");
            xmlSerializer.text(createKMLPointStr(points));
            xmlSerializer.endTag(null, "coordinates");
            xmlSerializer.endTag(null, "LineString");
            xmlSerializer.endTag("", "Placemark");
            xmlSerializer.endTag("", "Document");
            xmlSerializer.endTag("", "kml");
            xmlSerializer.endDocument();
        } catch (XmlPullParserException e) {// XmlPullParserFactory.newInstance
            e.printStackTrace();
        } catch (IllegalArgumentException e) {    // xmlSerializer.setOutput
            e.printStackTrace();
        } catch (IllegalStateException e) {    // xmlSerializer.setOutput
            e.printStackTrace();
        } catch (IOException e) {// xmlSerializer.setOutput
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        String xmlStr = xmlWriter.toString();
        BaseFileUtil.writeStringToFile(fileName, xmlStr);
        return xmlStr;
    }

下面是生成的KML文件内容,其实还可以添加更多辅助信息到KML文件的,这里就略去了,直接上轨迹点,超级简单是不是?

奥森10km 轨迹图

<?xml version='1.0' encoding='utf-8' ?>
<kml xmlns:xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
  <Document>
    <Placemark>
      <Style>
        <LineStyle>
          <color>ff60ff00</color>
          <width>6</width>
        </LineStyle>
      </Style>
      <LineString>
        <coordinates>
116.39348170420259,40.01190507680628
116.39450478868154,40.012104086029254
116.39481726475313,40.01208005324708
116.39511694229225,40.012009991578616
116.39580711364755,40.012061307700286
116.39665653452886,40.01188178384924
116.39678459102021,40.01180961243906
116.39697500459975,40.011471523134674
116.39698255521978,40.01139207409671
116.39687616848552,40.01126881996522
116.39665872919042,40.01115435968396
116.39654356043086,40.010968925696965
116.39653036511537,40.01087789762913
116.39672981870783,40.01052734936534
116.39679748281328,40.010473202401144
116.39692033865322,40.010438560155386
116.3970594302593,40.010440049486185
116.39828339172043,40.010934908063696
116.39863967684049,40.01092802652802
116.39877681138297,40.010968163634566
116.39884061062688,40.01101526404847
116.39949397735265,40.0116962557429
116.39977521437439,40.01226687974138
116.39979220644383,40.01244346676338
116.39962584946927,40.0140293256145
116.39972371868366,40.014678886558045
116.39971123165043,40.01485719187152
116.39974182919752,40.01538365587216
116.39986029319218,40.01568891586989
116.39984761902082,40.015855796079926
116.39970110475406,40.01616080496559
116.39949771774168,40.016405945115984
116.39898637007946,40.01675670390317
116.39884901289405,40.01702368683029
116.39881364730593,40.01733363430368
116.39885737654727,40.01767704020805
116.39896483813365,40.017832335703275
116.39920906138865,40.018005075484304
116.39977262893389,40.01828128985266
116.4001293621636,40.01854417073119
116.40024600409684,40.0187790824643
116.40025302343724,40.01904506378034
116.40017707385432,40.01930156925365
116.39972544746195,40.01994119262449
116.39953253408908,40.02013039614219
116.39945339405541,40.0203165783437
116.39938534895795,40.02059900688997
116.39932082475124,40.02067721242125
116.39712181065607,40.021466155528515
116.39632046855411,40.021754982909044
116.39588490369638,40.02183523343371
116.39575806415249,40.021825101555315
116.39536108668436,40.02172348883348
116.39460444986831,40.02177640361667
116.39376968562837,40.02165166688106
116.39329756827145,40.021515681327294
116.39273766645447,40.021472114042524
116.39265326821067,40.021494349557514
116.39242167784626,40.02175818736408
116.39207742840834,40.02219158932
116.39192142766977,40.02279171647535
116.39193652967609,40.02286602701059
116.3920743534718,40.023216753780545
116.39205810508224,40.02372507555831
116.39209734787802,40.0238278322195
116.39237426468247,40.024091182716106
116.3924143511756,40.02416918438945
116.3924137492412,40.024426061584705
116.39236005104893,40.02544972918901
116.39240701372273,40.025617222117184
116.39249862697335,40.02571240631482
116.39263106342825,40.02577377724534
116.39446638889551,40.02605859524811
116.39556776298676,40.02613580758347
116.39986655759832,40.02675503943772
116.4003386161378,40.026775097861645
116.40096447049662,40.02690883827291
116.40104995984294,40.026981077766145
116.4010789726778,40.0270805462986
116.40086147101938,40.0279336357706
116.40051182038502,40.028538691496564
116.39987329113715,40.029088053832275
116.39962006427466,40.02915865707772
116.39936196461215,40.029161070837674
116.39808724055626,40.02897535982718
116.3973751891038,40.028671500090525
116.39720199786572,40.028660897288304
116.39592890605488,40.028925593909754
116.3949549714303,40.02934906630121
116.39426274832482,40.029812589403946
116.39359856312939,40.030140254691155
116.39311998007548,40.03048394400153
116.39231593389374,40.030749786322964
116.39135698306774,40.03097689480288
116.39115736525918,40.030977533521146
116.3899641069909,40.030828225135366
116.38724540646109,40.03071910713684
116.38690936921729,40.03074932895987
116.38399932313702,40.03057491549396
116.382732199911,40.03028076317685
116.38232732000661,40.030273442065464
116.38178406586397,40.030347550190456
116.38004988336155,40.03029280366401
116.37868235429923,40.02999310215089
116.37781129913705,40.02941602190564
116.37740685573442,40.02900829910359
116.37716828025704,40.02863924607626
116.37710907935389,40.02841664526807
116.37711648422665,40.02796653249694
116.37761035005897,40.02720564002145
116.3778745522578,40.02661433982844
116.37792292072456,40.02635183106591
116.3779858111328,40.02627825292592
116.37803246374106,40.02625756508067
116.37865896305186,40.026307899488955
116.38380012351521,40.02664506513687
116.38459080353836,40.02654754473037
116.38511995328854,40.02655356352237
116.38539647713071,40.02649301625595
116.3861919918598,40.026104293086775
116.38654234571378,40.02600614611209
116.3866338093969,40.025957590924484
116.38672014682825,40.02583003774208
116.386740697838,40.025679200810224
116.38664415798256,40.025228954645016
116.38672106046344,40.02490401542579
116.3870002268534,40.02457311756562
116.38731333514906,40.02441831382311
116.38788048310829,40.02431032769093
116.3887489909213,40.023693376556196
116.38939818197309,40.02355381496369
116.38991352017877,40.02359576125264
116.39039377072802,40.023822207341794
116.39081846015574,40.0238742986498
116.39145986377808,40.02382136038134
116.39185339522352,40.02384709999533
116.3919177078651,40.02382293264885
116.39197144094236,40.02374542639035
116.39199927528868,40.023488792984324
116.39187416774469,40.02268095802571
116.39197886108005,40.022063071021684
116.39171654631168,40.02172855589577
116.39140278212987,40.02144381146428
116.39126100966841,40.021385122037486
116.39061960251743,40.02136014626356
116.38977723994557,40.02150844188777
116.38957680101326,40.0216013167516
116.38899516369777,40.02199609093532
116.38893513690786,40.022012503206525
116.38886896687934,40.02200998202478
116.38698200432371,40.02114631860147
116.38596860838122,40.020230854001255
116.38439567558511,40.01972331387241
116.38337920153049,40.01958496871191
116.38282185085899,40.0193637650231
116.3824242992586,40.01908289343984
116.38191190105081,40.01867549790632
116.38141602572355,40.018416172212554
116.38115991387069,40.018214148963764
116.38109009763927,40.01811210773365
116.38084115034782,40.01750139655885
116.38082895824479,40.01714392311205
116.38103503217111,40.01660707187263
116.38141557803576,40.01619777547733
116.38169056363917,40.01601114322713
116.3833226075677,40.01520028174043
116.3837791672884,40.01486717300946
116.38395244586614,40.014793776737235
116.38472978628388,40.01465909444237
116.38553764219313,40.014426595403116
116.38578952999165,40.01428578085227
116.38611016849502,40.01401904350985
116.3863572913299,40.013700150804
116.38688680798133,40.012687209893826
116.387643979247,40.012053604798794
116.38836363506562,40.011955982458204
116.38994930228544,40.012122471921515
116.39204826869613,40.01169536122755
116.3926362705122,40.011811400930924
116.39317629112587,40.011809775046174
116.39336336314635,40.0119145377369
116.39341299039299,40.01191266234115
116.39236427879013,40.01129695167011
116.39224654958639,40.011281305673876
116.39247366922483,40.01038227793181 </coordinates>
      </LineString>
    </Placemark>
  </Document>
</kml>

直接将kml文件拖到Google 地球上,铛铛铛当就展现出来啦。

图1.2 Google地球展示kml文件

生成的kml标准文件,理论上可以导入到其它支持Share的APP,就可以进行数据迁移了。

以上就是Android APP开发KML轨迹导出教程示例的详细内容,更多关于Android APP导出KML轨迹的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android实现简单的自定义ViewGroup流式布局

    目录 前言 一.基本的测量与布局 二.流式的布局的layout 三.流式的布局的Measure 后记 前言 前面几篇我们简单的复习了一下自定义 View 的测量与绘制,并且回顾了常见的一些事件的处理方式. 那么如果我们想自定义 ViewGroup 的话,它和自定义View又有什么区别呢?其实我们把 ViewGroup 当做 View 来用的话也不是不可以.但是既然我们用到了容器 ViewGroup 当时是想用它的一些特殊的特性了. 比如 ViewGroup 的测量,ViewGroup的布局,Vi

  • MPAndroidChart绘制自定义运动数据图表示例详解

    目录 引言 TimeAxis SportYAxis CustomLineChart 引言 声明:文中的MPChart代指MPAndroidChart. 本系列之前的文章介绍的MPChart中BarChart相关的一些绘制,接下来我们看看LineChart相关的绘制. 这里以实际的运动相关的图表数据做业务支撑来讲解.MPChart图表支持多指触控方法,这里所有的图表自定义都关掉了这个属性,这样就减少Transformer,以及绘制过程中的更多的变动,相当于一个静态的图. 通常图表在放大的过程中,坐

  • Android开发X Y轴Board的绘制教程示例

    目录 正文 1. X轴的绘制 2. Y轴的绘制 绘制RightYAxisLabel 3. Board 绘制 正文 上篇大致介绍了RecyclerChart能够绘制的图表,以及一些特有的功能.从这节开始具体地介绍图表的绘制,本节先介绍RcyclerChart中一些图表的相关辅助的绘制,X.Y轴,以及Board的绘制. 上一章节有介绍绘制的逻辑都在ItemDecoration中实现的,而各种图表基本都有X.Y轴.Board相关的绘制,所以把他们的相关逻辑抽象到上层的基类BaseChartItemDe

  • Android MPChart自定义睡眠泳道图教程示例

    目录 声明 SleepItemEntry SleepBuffer SleepRender 声明 本文MPChart 代表的就是 MPAndroidChart. 本章节继续上次的自定义绘制,不同之前的图形, 日历下边的睡眠泳道图,每个item不同于之前的图形,会均等的width, 相反的是均等的高度的矩形,不等的宽度,就是所占X轴的比重不一样,见1.1睡眠泳道图. 1.0 睡眠泳道图 首先跳出MPChart自定义这层概念,我们来绘制这个图形,本身来说还是蛮简单的,绘制四种不同的Rect, 根据不同

  • Android画图实现MPAndroidchart折线图示例详解

    目录 效果图 依赖 activity.xml MainActivity MyMarkerView 自定义class maekertextview .xml 常用属性 效果图 用的是3.1.0的依赖 依赖 allprojects { repositories { jcenter() maven { url "https://jitpack.io" } } } //依赖 dependencies{ implementation 'com.github.PhilJay:MPAndroidCh

  • Android MPAndroidChart绘制原理

    目录 前言 1. Chart整体结构 2.Chart 绘制参与的业务组件 Render Buffer Entry.DataSet Attribute 3. 整体Chart绘制流程 前言 官方demo地址:github.com/PhilJay/MPA… 笔者接下来的文章里MPChart 代表的就是 MPAndroidChart. 下载后AS里运行,可以看到demo里面有 Line Charts, Bar Charts, Pie Charts, Radar Charts, Other Charts.

  • MPAndroidChart 自定义图表绘制使用实例

    目录 引言 1. LineGradientChart 2. 散点图 3. SteppedChart 引言 声明:文中的MPChart代指MPAndroidChart. 本文主要讲解LineChart中的三个变种Chart,第一个是渐变的LineGradientChart, 第二个是频率散点图,游泳阶梯图,其实MPChart本身也有阶梯图的,DataSet.isDrawSteppedEnabled()这个属性来控制. 1. LineGradientChart 原理:每个Entry中的 Yvalue

  • Android APP开发KML轨迹导出教程示例

    目录 引言 写入kml gps点 奥森10km 轨迹图 引言 前两天在知乎上面找海外骑行.跑步软件Strava的时候,看到一个将运动轨迹从A App 导出,导入到B APP的工具 APP RunGap,恰巧之前给台湾.印度那边的测试同事处理他们的问题时,写过这样的一个工具,KML文件导出,然后在Mac下的 Google 地球上看轨迹是否偏差,是否存在坐标类型的转化错误等问题,能够比较快地定位问题. KML文件,读者有不知道的可以Google一下,它是一种专门存GPS 点数据的xml文件格式. 将

  • 使用Vue3+ts 开发ProTable源码教程示例

    目录 前台实现 实现效果 技术栈 使用方法 ProTable 设计思路 编码风格 css 小知识 表格操作 小结 后期功能扩展 后台实现 数据库 mysql 新建项目 RESTful 风格的 URL 定义 Sequelize controller model router.js API 文档 Apifox ts用到的一些 前台实现 实现效果 技术栈 vue3 + typescript + element-plus 使用方法 <template> <el-tabs type="b

  • 一看就懂的Android APP开发入门教程

    工作中有做过手机App项目,前端和android或ios程序员配合完成整个项目的开发,开发过程中与ios程序配合基本没什么问题,而android各种机子和rom的问题很多,这也让我产生了学习android和ios程序开发的兴趣.于是凌晨一点睡不着写了第一个android程序HelloAndroid,po出来分享给其他也想学习android开发的朋友,这么傻瓜的Android开发入门文章,有一点开发基础的应该都能看懂. 一.准备工作 主要以我自己的开发环境为例,下载安装JDK和Android SD

  • Android App开发中ViewPager组件的入门使用教程

    首先让大家有个全局的认识,直接上个项目,看看仅仅通过这几行代码,竟然就能完成如此强悍的功能.下篇再仔细讲讲为什么要这么写. 效果图: 实现了三个view间的相互滑动 第一个VIEW向第二个VIEW滑动: 第二个VIEW向第三个VIEW滑动: 一.新建项目,引入ViewPager控件 ViewPager.它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换. 1.在主布局文件里加入 <RelativeLayout xmlns:android="http://schem

  • Android app开发中的Fragment入门学习教程

    在Android3.0上开始引入了一个新概念叫Fragment.它有自己的布局文件,可以作为组件排布,也可以相互组合去实现不同的布局显示.使用Fragment可以重复利用代码,并且可以满足不同设备尺寸的需求.Fragment不能单独存在,只能存在于Activity中,而一个Activity可以拥有多个Fragment.很重要的一点是,Fragment可以和Activity中的其它组件一起使用,无需重写所有Activity的接口.所以使用Fragment就可以这样来完成上例中"主界面-详细界面&q

  • Android App开发中使用RecyclerView实现Gallery画廊的实例

    什么是RecyclerView         RecyclerView是Android 5.0 materials design中的组件之一,相应的还有CardView.Palette等.看名字我们就能看出一点端倪,没错,它主要的特点就是复用.我们知道,Listview中的Adapter中可以实现ViewHolder的复用.RecyclerView提供了一个耦合度更低的方式来复用ViewHolder,并且可以轻松的实现ListView.GridView以及瀑布流的效果. RecyclerVie

  • 浅谈Android app开发中Fragment的Transaction操作

    在Android中,对Fragment的操作都是通过FragmentTransaction来执行.而从Fragment的结果来看,FragmentTransaction中对Fragment的操作大致可以分为两类: 显示:add() replace() show() attach() 隐藏:remove() hide() detach() 对于每一组方法,虽然最后产生的效果类似,但方法背后带来的副作用以及对Fragment的生命周期的影响都不尽相同. add() vs. replace() 只有在

  • Win10下android studio开发环境配置图文教程

    一.安装Java JDK 从JDK下载地址下载并安装,注意选择是x86还是x64版本. 在安装期间系统会出现两次选择安装文件夹的提示,第一次是安装"jdk",第二次则是安装"jre". 安装成功如上图所示. 二.添加环境变量 计算机→属性→高级系统设置→高级→环境变量,新建环境变量,命名为JAVA_HOME,变量值填入你安装jdk的路径. 在系统变量里寻找 Path 变量,选择编辑,新建两个变量值%JAVA_HOME%\bin,%JAVA_HOME%\jre\bin

  • Android App开发的自动化测试框架UI Automator使用教程

    Android的自动化测试有很多框架,其中ui automator是google官方提供的黑盒UI相关的自动化测试工具,(GitHub主页:case使用java写,今天实践了一下官方文档中样例程序,其中还是有一些小问题需要总结一下的. 环境准备: 1.JDK(是的,你没看错,基础的android开发环境必备),以及对应的环境变量配置,不会的可以自己百度下下 2.Android Studio(IDE尊崇个人意愿) 3.android SDK以及配置 4.ANT(主要用于build我们的脚本,生成j

  • Android App开发中创建Fragment组件的教程

    你可以认为Fragment作为Activity的一个模块部分,有它自己的生命周期,获取它自己的事件,并且你可以在Activity运行的时候添加或者移除它(有点像你可以在不同的Activity中重用的一个"子Activity").这节课程讲述如何使用Support Library继承Fragment类,所以你的应用程序仍然是兼容运行的系统版本低于Android1.6的设备. 注意:如果你决定你的应用要求的最低的API级别是11或者更高,你不需要使用Support Library,反而能使

随机推荐