2014年5月12日星期一

Android 关于百度地图Android SDK几处修正使用说明(非官方)

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
Android 关于百度地图Android SDK几处修正使用说明(非官方)  阅读原文»

Android 关于百度地图Android SDK几处修正使用说明(非官方)

本篇主要是因为最近在学习使用百度地图,发现了一些问题,跟大伙分享一下。

1、根据android sdk开发指南中"Hello World"的例子,构建一个基础的地图页面,如果大家完全按照示例代码中所写的那样,是不会执行成功的,会有以下问题的错误提示"java.lang.RuntimeException: Unable to instantiate activity ComponentInfo"

这个问题出现的原因是

在第二步,配置Activity部分,android:name的值为.MapDemo,而在第四步,创建地图Activity处,创建的Activity继承类名写的却是MyMapActivity。如果你想让在AndroidManifest.xml中配置Activity时的.MapDemo为起始的Activity,除了要在<Activity></Activity>之间加上以下这段代码之外

  <intent-filter>      <actionandroid:name="android.intent.action.MAIN"/>      <categoryandroid:name="android.intent.category.LAUNCHER"/>  </intent-filter>  

还要把android:name的.MapDemo改成你当前项目的"包名+MyMapActivity"或者直接写"MyMapActivity",这样再执行就会构建出一个基础的百度地图。

这个问题其实也是一个Android开发的基础问题,也算是对我这个Android半吊子一个知识点的巩固。下面针对这个问题的出现回顾以下知识点:

(1)AndroidManifest.xml作为项目的布局文件,时时刻刻把握整个项目命脉,项目启动时,要设置启动项,权限不够时,要加相应的权限设置。

(2)在AndroidManifest.xml中配置的Activity如何与src中的.java文件联系在一起呢?就是依靠配置的该Activity中的android:name的值要完全与.java文件中的类名一致。

(3)而"后台"的.java文件又是如何与"前台"的res/layout中的activity布局文件联系在一起的呢(请允许我用前后台这样的非专业术语来说,因为自己主做web开发,这样说感觉比较形象)?就是通过.java文件中,继承Activity类的新类的OnCreate方法中

  setContentView(R.layout.activity_main)  

这样的一条语句搞定的,这里的activity_main即是布局文件的名字而已。

由以上的几条我们会发现Android开发中,主要的两个东西都是靠名称去匹配的,所以我们在开发中一定要在这方面多多注意,至于是不是其他的东西也是依赖名称去匹配,就需要我们去不断在开发中发现。

2、说的第二个问题是关于坐标的,在百度地图给出的源码中,我们会发现类似这样的语句

  GeoPoint point =new GeoPoint((int)(39.915* 1E6),(int)(116.404* 1E6));  

翻译一下就是创建一个GeoPoint类型的纬度为39.915度,经度为116.404度的坐标点,为什么要*1E6,是为了把传入的经度,纬度转换成微度,就是在原基础上乘以10的-6次幂。至于GeoPoint中到底是什么样,那都是百度封装好的,所以我也懒着去关心了,大家知道跟坐标点有关就行了。

不过这里容易出现一个小问题,就是我们习惯性的会认为写坐标点的时候是这种格式"经度,纬度",而这个方法的构造函数完全是相反的。当然,这不算什么,但是问题就出在,在百度地图官方给出的"拾取坐标系统"工具(链接:http://api.map.baidu.com/lbsapi/getpoint/index.html,这个东东还是很实用的,如果我们做地图开发没有它,那就没戏啦,它主要就是坐标-地址的查询工具)中,使用的坐标点形式就是"经度,纬度",有点把我们带偏的感觉。所以容易搞错,这块要注意一下,否则坐标都在十万八千里之外了。

PS:经度(longitude),纬度(latitude)

3、关于定位SDK的,这个问题真心的很坑人。下午耗了几个小时,真不爽。

虽然标题说的是android sdk,

在百度地图官方定位SDK处可谓是非常详细,把如何构建基础定位功能的步骤已经详细给我们列出,但这里有个小瑕疵我不得不说,达到了令人发指的地步。

先来简单回顾一下百度地图官方给出的东东

在V4.1版本的第3点,功能类的使用,3.1.1初始化LocationClient类 小节

  public LocationClient mLocationClient = null;  public BDLocationListener myListener = new MyLocationListener();  publicvoid onCreate() {      mLocationClient = new LocationClient(getApplicationContext());     //声明LocationClient类      mLocationClient.registerLocationListener( myListener );    //注册监听函数  }  

3.1.3设置定位参数 小节

  LocationClientOption option = new LocationClientOption();  option.setLocationMode(LocationMode.Hight_Accuracy);//设置定位模式  option.setCoorType("bd09ll");//返回的定位结果是百度经纬度,默认值gcj02  option.setScanType(5000);//设置发起定位请求的间隔时间为5000ms  option.setIsNeedAddress(true);//返回的定位结果包含地址信息  option.setNeedDeviceDirect(true);//返回的定位结果包含手机机头的方向  mLocClient.setLocOption(option);  

对了这处的第4行setScanType方法请改写成setScanSpan。之所以写错可能是先前版本的成员方法名,在这个版本中已经不再存在。

3.1.4发起定位请求 小节

  if (mLocClient != null && mLocClient.isStarted())    mLocClient.requestLocation();  else   Log.d("LocSDK3", "locClient is null or not started");  

乍一看条理非常的清晰,先声明类,绑定方法,如果有特殊要求,再加个option的设置,最后验证对象是否为空,不为空就执行最终的请求定位,多完美啊!~

但是如果我们就这样执行了,那么就会发现log中一直出现"locClient is null or not started"这句话,我试了N多遍,都有了想吐血的冲动(请原谅我的吐槽),最后通过对定位sdk的sample一行一行去找才发现了问题(之所以一行一行的找,是因为把项目导入本地工程之后,各种红,运行不了),原因就在于,在对LocationClient类实例调用requestLocation()方法之前,一定要调用一下start()方法,像这样:

  mLocationClient.start();  

哦~~那是什么?对的,开发指南中并没有写出来。应该是一个使LocationClient实例启动的方法,所以后面if条件句中的isStarted()我们也就明白是怎么回事了。

4、接着说一下如何成功在本地运行Android SDK给出的"BaiduMap_AndroidSDK_v2.4.1_Sample"示例,这是官方的一个Demo,为我们展示了在Android SDK下的各个功能模块。

如果大家细心读了百度地图的使用规则,就知道如果我们想使用百度地图API,就必须申请对应的KEY,而申请KEY的关键,我总结的话就是在安全码上,下面只说Android SDK安全码组成:数字签名+;+包名

其实这部分百度地图申请KEY的《查看详细配置方法》里已经详细说明。我只是想说这里的包名,要写成我们下载下来的示例包名:baidumapsdk.demo。

这块可能对大多数朋友来说顺理成章,我之所以说一下是因为第一次申请KEY,而且是先创建了一个本地项目,又没有直接去运行Sample,所以当时就有点懵,误把针对自己项目的KEY当成可以在Sample上使用的KEY。

这块大家没遇到这个问题就从脑子里抹去吧。

随着一步步的探索,慢慢的就能跟随自己的想法来使用百度地图去设计一些小功能了,之后也遇到了一些问题,不过感觉解决的都很快,这里就不一一详述了,都是些小问题。如果大家遇到其他Android SDK上的问题比较头大,我们可以交流一下。

另外,这几天通过对百度地图API的学习,也看到了差距,自己还是要不断的去学习,提升自己,向度娘看齐。

本文出自 "给我一根儿烟" 博客,请务必保留此出处http://zhouhongyu1989.blog.51cto.com/2931598/1409723

分享至 一键收藏,随时查看,分享好友!
海量数据解决思路之Hash算法  阅读原文»

海量数据解决思路之Hash算法

本文将粗略讲述一下Hash算法的概念特性,里边会结合分布式系统负载均衡实例对Hash的一致性做深入探讨。另外,探讨一下Hash算法在海量数据处理方案中的通用性。最后,从源代码出发,具体分析一下Hash算法在MapReduce框架的中的应用。

二、Hash算法

Hash可以通过散列函数将任意长度的输入变成固定长度的输出,也可以将不同的输入映射成为相同的相同的输出,而且这些输出范围也是可控制的,所以起到了很好的压缩映射和等价映射功能。这些特性被应用到了信息安全领域中加密算法,其中等价映射这一特性在海量数据解决方案中起到相当大的作用,特别是在整个MapReduce框架中,下面章节会对这二方面详细说。话说,Hash为什么会有这种压缩映射和等价映射功能,主要是因为Hash函数在实现上都使用到了取模。下面看看几种常用的Hash函数:

・直接取余法:f(x):= x mod maxM ; maxM一般是不太接近 2^t 的一个质数。
・乘法取整法:f(x):=trunc((x/maxX)*maxlongit) mod maxM,主要用于实数。
・平方取中法:f(x):=(x*x div 1000 ) mod 1000000); 平方后取中间的,每位包含信息比较多。

三、Hash算法在海量数据处理方案中的应用

单机处理海量数据的大体主流思想是和MapReduce框架一样,都是采取分而治之的方法,将海量数据切分为若干小份来进行处理,并且在处理的过程中要兼顾内存的使用情况和处理并发量情况。而更加仔细的处理流程大体上分为几步(对大多数情况都使用,其中少部分情况要根据你自己的实际情况和其他解决方法做比较采用最符合实际的方法):

  • 第一步:分而治之。

采用Hash取模进行等价映射。采用这种方法可以将巨大的文件进行等价分割(注意:符合一定规律的数据要被分割到同一个小文件)变成若干个小文件再进行处理。这个方法针对数据量巨大,内存受到限制时十分有效。

  • 第二步:利用hashMap在内存中进行统计。

我们通过Hash映射将大文件分割为小文件后,就可以采用HashMap这样的存储结构来对小文件中的关注项进行频率统计。具体的做法是将要进行统计的Item作为HashMap的key,此Item出现的次数作为value。

  • 第三步:在上一步进行统计完毕之后根据场景需求往往需要对存储在HashMap中的数据根据出现的次数来进行排序。其中排序我们可以采用堆排序、快速排序、归并排序等方法。

现在我们来看看具体的例子:

【例子1】海量日志数据,提取出某日访问百度次数最多的那个IP

思路:当看到这样的业务场景,我们脑子里应该立马会想到这些海量网关日志数据量有多大?这些IP有多少中组合情况,最大情况下占多少存储空间?解决这样的问题前我们最重要的先要知道数据的规模,这样才能从大体上制定解决方案。所以现在假设这些这些网关日志量有3T。下面大体按照我们上面的步骤来对解决此场景进行分析:

(1)首先,从这些海量数据中过滤出指定一天访问百度的用户IP,并逐个写到一个大文件中。

(2)采用"分而治之"的思想用Hash映射将大文件进行分割降低数据规模。按照IP地址的Hash(IP)%1024值,把海量IP日志分别存储到1024个小文件中,其中Hash函数得出值为分割后小文件的编号。

3)逐个读小文件,对于每一个小文件构建一个IP为key,出现次数为value的HashMap。对于怎么利用HashMap记录IP出现的次数这个比较简单,因为我们可以通过程序读小文件将IP放到HashMap中key的之后可以先判断此IP是否已经存在如果不存在直接放进去,其出现次数记录为1,如果此IP已经存储则过得其对应的value值也就是出现的次数然后加1就ok。最后,按照IP出现的次数采用排序算法对HashMap中的数据进行排序,同时记录当前出现次数最多的那个IP地址;

(4)走到这步,我们可以得到1024个小文件中出现次数最多的IP了,再采用常规的排序算法找出总体上出现次数最多的IP就ok了。

这个我们需要特别地明确知道一下几点内容:

第一:我们通过Hash函数:Hash(IP)%1024将大文件映射分割为了1024个小文件,那么这1024个小文件的大小是否均匀?另外,我们采用HashMap来进行IP频率的统计,内存消耗是否合适?

  • 首先是第一个问题,被分割的小文件的大小的均匀程度是取决于我们使用怎么样的Hash函数,对本场景而言就是:Hash(IP)%1024。设计良好的Hash函数可以减少冲突,使数据均匀的分割到1024个小文件中。但是尽管数据映射到了另外一些不同的位置,但数据还是原来的数据,只是代替和表示这些原始数据的形式发生了变化而已。

  • 另外,看看第二个问题:用HashMap统计IP出现频率的内存使用情况。

要想知道HashMap在统计IP出现的频率,那么我们必须对IP组合的情况有所了解。32Bit的IP最多可以有2^32种的组合方式,也就是说去所有IP最多占4G存储空间。在此场景中,我们已经根据IP的hash值将大文件分割出了1024个小文件,也就是说这4G的IP已经被分散到了1024个文件中。那么在Hash函数设计合理最perfect的情况下针对每个小文件的HashMap占的内存大小最多为4G/1024+存储IP对应的次数所占的空间,所以内存绝对够用。

第二:Hash取模是一种等价映射,换句话说通过映射分割之后相同的元素只会分到同一个小文件中去的。就本场景而言,相同的IP通过Hash函数后只会被分割到这1024个小文件中的其中一个文件。

【例子2】给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?

思路:还是老一套,先Hash映射降低数据规模,然后统计排序。

具体做法:

(1)分析现有数据的规模。

按照每个url64字节来算,每个文件有50亿个url,那么每个文件大小为5G*64=320G。320G远远超出内存限定的4G,所以不能将其全部加载到内存中来进行处理,需要采用分而治之的方法进行处理。

(2)Hash映射分割文件。逐行读取文件a,采用hash函数:Hash(url)%1000将url分割到1000个小文件中,文件即为f1_1,f1_2,f1_3,...,f1_1000。那么理想情况下每个小文件的大小大约为300m左右。再以相同的方法对大文件b进行相同的操作再得到1000个小文件,记为:f2_1,f2_2,f2_3,...,f2_1000。

经过一番折腾后我们将大文件进行了分割并且将相同url都分割到了这2组小文件中下标相同的两个文件中,其实我们可以将这2组文件看成一个整体:f1_1&f2_1,f1_2&,f2_2,f1_3&f2_3,...,f1_1000&f2_1000。那么我们就可以将问题转化成为求这1000对小文件中相同的url就可以了。接下来,求每对小文件中的相同url,首先将每对对小文件中较小的那个的url放到HashSet结构中,然后遍历对应这对小文件中的另一个文件,看其是否存才刚刚构建的HashSet中,如果存在说明是一样的url,将这url直接存到结果文件就ok了。

【例子3】有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序。

【例子4】有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。

像例子3和例子4这些场景都可以用我们的一贯老招数解决:先Hash映射降低数据规模,然后统计加载到内存,最后排序。具体做法可以参考上面2个例子。

四、Hash算法在MapReduce框架中的应用

Hash算法在分布式计算框架MapReduce中起着核心作用。先来看看下面整个mapreduce的运行流程,首先是原始数据经过切片进入到map函数中,经?p>阅读更多内容

没有评论:

发表评论

声明

转载有价值的IT博客,版权属原作者所有

标签

博客归档