android GPS定位
第一步:APIKey获取
如果你要嵌入googlemap在你自己的app里面,就必须要apikey,当然,如果你不嵌入goolemap,只是要获得经纬度,可以不用获得apikey的。
1.apikey介绍
对于开发者来说,apikey一般分两类,debugkey和releasekey(如果你只用debugkey,生成出来的apk在其他手机上也能正常显示googlemap)。debugkey是和我们~/.android/debug.keystore对应的(后面会讲到),这也就是说,你下载和拷贝别人的工程到你电脑上,你是不能加载上googlemap的,常见的情况就是只显示很多格子。(~/.android/debug.keystore文件不是在工程里面)当然,这也是导致你把你自己的工程(可以加载地图)拷贝到其它人电脑上,他那边也是显示不出来地图的。-----------解决办法就是自己去重新申请apikey,替换掉就行了。
还有一种就是releasekey,我们开发产品是要所有人都能使用的,我们不可能为每个手机都去申请apikey。所以当我们要发布给别个手机使用的时候,需要在去重新申请一个apikey,然后用和这个新apikey相关联的签名文件(xxxx.keystore)签名,然后就可以发布出去了。
注意:当你拷贝别人工程的时候,你有两种方式来显示googlemap,一种是你拷贝别人工程在eclipse运行该工程来显示googlemap,另一种是你可以直接运行别人工程里面的apk(xxx_project/bin/xxx.apk--------如果有的话),你会发现我们在eclipse运行工程并不能显示googlemap,但是我们直接运行apk文件却能显示googlemap。后面通过讲解签名原理就明白了。你只要知道,xxx_project/bin/xxx.apk文件是别人的debug.keystore签名过的。
2.获取apikey
•找到或创建keystore证书文件;
做开发的话,如果是linux,证书文件就是~/.android/debug.keystore。
如果要发布了,需要重新创建证书文件keytool-genkey-aliasandroid.keystore-validity20000-keystoreandroid.keystore
•生成MD5认证指纹;
开发者使用keytool-list-keystore~/.android/debug.keystore
发布就使用keytool-list-keystoreandroid.keystore
格式大概是97:A8:A9:45:01:2C:4A:66:83:DE:F1:08:90:A8:38:55(这个key不能用,我改过数据了)
•生成GoogleMapAPIKey。
http://code.google.com/intl/zh-CN/android/maps-api-signup.html
上面这个连接是生成apikey的网站,它要求输入上面的认证指纹97:A8:A9:45:01:2C:4A:66:83:DE:F1:08:90:A8:38:55
从第二步我们可以看出生成apikey的流程:证书------>>>认证指纹--------->>>apikey
所以这就解释了,为什么你下载别人的工程显示不了地图,因为他的apikey是由他电脑上的证书文件(~/.android/debug.keystore)生成的,而这个文件是不会在工程里面的。而我们发布的apk文件为什么所有手机都能用呢,那是因为我们在打包的时候要选择签名文件,而这个签名文件就是我们的证书文件android.keystore。并不是说需要把该证书文件拷贝到apk里面,而是用该证书文件来签名,签名具体要做的就是用该证书文件里面的私钥签名,并把该证书文件里面的公钥和私钥的签名结果放在apk里面,记住不是把私钥放在apk里面,那样就不安全了。下面是证书文件的简单介绍。
android.keystore简单介绍
这个文件相当于一个密钥管理库,里面保存了多对公钥和私钥,还有其它一些信息。
当我们选择一个签名文件的时候,会让我们选择alias文件,其实可以出现多个,eclipse会读取证书文件(android.keystore)里面的所有公私钥对显示成一个列表,如下所示
alias其实就是你的私钥,开始我也不知道私钥到底存到哪儿去了,做了一些测试之后,我估计就是保存在了我们的证书文件里面,并且可以保存多组公私钥。当我们选择一个alia时,也就选择了一对公私钥准备签名。
如果我们用命令行来签名可以看得更明白些,到底android签名做了写什么:
这里我用yan私钥签名HelloGoogleMaps.apk并生成signed.apksig
这里只是在META-INF文件夹下面添加了两项(adding操作),其它都是签名操作(signing操作---其实就是用私钥加密的过程),但是网上的资料说是会添加四项,我这边可能有地方没对,当我查看eclipse签名出来的另一个apk文件,有三项。
所以不管怎样,至少有一点是明确的,apk里面的META-INF文件夹是签名文件签名结果的,到底有哪些内容呢?下面是网上的解释。
CERT.SF:生成每个文件相对的密钥
MANIFEST.MF:数字签名信息
xxx.SF:这是JAR文件的签名文件,占位符xxx标识了签名者
xxx.DSA:对输出文件的签名和公钥
里面有一项很重要,就是xxx.DSA文件,这里面保存了公钥,我们知道签名的原理就是用私钥加密(signing操作),用公钥解密。
所以当我们安装apk的时候,android系统应该会用xxx.DSA文件里面的公钥解密私钥加密(signing操作)的信息----------也就是META-INF文件夹下的签名信息,如果解密成功,则验证通过,不然就不能安装。
上面这个扯的有点远了。好了,回到我们GoogleMap上来。
第二步:加入MapView。
既然现在我们获得了apikey,现在就可以用它了。
环境:
首先要支持googlemap的add-on,创建模拟器的时候,选择googlemap创建。------------这一步可能会遇到很多问题,确实比较麻烦
常见的就是缺少一个库。
权限:
<uses-permissionandroid:name="android.permission.INTERNET"/>
<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permissionandroid:name="android.permission.ACCESS_COARSE_UPDATES"/>
MapView控件
<com.google.android.maps.MapView
android:id="@+id/geoMap"android:clickable="true"
android:layout_width="fill_parent"android:layout_height="fill_parent"
android:apiKey="0Vk_Sg_P9567z06o6eTbzFrwJwErAMqS2bZOI0w"/>-----------------(这个aipKey也不能用,我改过了)
继承MapActivity
任何要嵌入googlemap的活动必须要继承MapActivity。不能简单的继续Activity就行了。
如果不出什么问题,基本可以看到googlemap可以在你的app里面显示了。
下面我讲一点定位方面的知识。
定位知识
首先googlemap定位有两个方案:wifi和GPS
1.wifi定位:
由于GPS无法完成室内定位,所以google借助wifi来实现室内定位。
wifi定位原理和基站地位差不多,都是google通过手机搜集wifi热点或基站ID信息来达到定位的。大致原理应该是:
当我们使用GPS的时候,google会收集周边的wifi热点上传到google服务器建立一个数据库。这里要注意,我们不一定是要连接到该wifi热点,只要手机能搜索到该热点就行了。我想该热点应该有个全球唯一标识--有两种猜测
一个是无线路由器的Mac地址---------------------------------这个是全球唯一的。
google可以这样做,就是收集当前这个wifi热点无线路由器的Mac地址和你当前GPS位置到服务器,但是有个问题,这个无线路由器不一定一直保持在那个位置,比如,如果你搬家了,或者坏了。那么这个wifi热点就不准确了。但是我们可以想象出现这种情况的概率真的很低,你想想你家的无线路由器从买回来到现在你动过它几次???即使搬家了(和该路由器换地方了---足够远),你也很快会将该信息上传到google服务器的。只要你用GPS就行了。而且即使你不使用GPS上传,说不定周围某个使用GPS的人从你家经过,就已经将你的wifi热点上传到google服务器了。
当然还有一种就是你无线路由器接入网络的那个网口有个地址(-------------只是猜测有个地址。不一定有。),当你使用GPS的时候,它把这个上传到服务器建立数据库。这样即使你搬家也没有影响,因为他不靠你的wifi路由器定位,而是你路由器即将出入的那个网口找到你。当然前提也是那个网口已经在google数据库里面了。
不管怎样:
从这里,我们能得出一下信息:
1.wifi定位并不是通过很高深的技术实现的。仅仅收集信息,上传信息,查询数据库,然而,google做的不是普通人能做的,在海量数据的前提下,普通人就不能玩得转了。
2.信息是我们自己上传的,当我们在打开googlemapapp的时候,他弹出框让我们勾选wifi定位。
当我们勾选wifi定位的时候,他会给我警告,是否允许google收集你的地理位置。你只要点击agree,你的收集就会在你不知情的情况下上传地理信息到google服务器,来帮助google完善数据库。
如果你不同意,当然就不能使用wifi定位,也就是不能实现室内定位,但是室外还是可以定位的,毕竟GPS技术可不是靠收集信息实现的。这也就是为什么是你点击UseGPSsatellites的时候不会弹出上面的警告框。
2.GPS定位
这个知识就很多了,不详细讲了,大致是至少用3颗卫星来找到你的,你和每一颗卫星形成一个空间球体,然后这3个空间球的焦点就是你。所以卫星数不能少于3,不然是找不到你的。
总结:
我们开发googlemap要注意几点
1.如果发现不能获取经纬度,一般是因为你在室内做的测试,这个一开始也困扰了我很久。其实代码是没有问题的,主要是在室内不能获得GPS信号。
2.当不能获得GPS数据的时候,我们一般会给位置初始化一个值,假设是(0.0,0.0),结果发现地图变成蓝色的了,很多人会认为地图加载不了,其实地图已经显示出来了,蓝色是因为(0.0,0.0)这个地方是海洋,如果你的zoomLeve级别很大,那么你是看不到陆地位置,即使你在那里不缩小地图的情况下滑动一天地图也很难从海里滑到陆地。但是如果你把地图缩小,滑动了一会儿就看到陆地了。地图就正常了。---------------------------------从这点也看出:google牛逼earth很大。
3.即使你勾选了wifi定位,也很难获得地理位置,这是因为你的wifi地址没在google数据库里面,多用几次GPS就好了,我也不知道到底什么时候google数据库会更新,不过等着吧。。会更新的。
4.我们做GoogleMap开发的时候,记得经常清除你调式App的data。因为里面包含了google地图的缓存数据。有时候其实是不能获取GPS的,但是打开程序发现还是有数据,不是因为它能获得GPS,而是因为他读取的缓存。
5.这点比较有意思,就是当你发现你的app不能加载googlemap的时候,你可以看看你手机的状态栏里面的wifi图标和手机信号图标是否是绿色,如果不是绿色而是灰色,表示你当前不能连接上google的服务(比如,gmail,gtalk,googlemap等)。那么googlemap肯定也加载不上了,要知道,googlemap会去服务器上下载地图的。所以呢,等着信号图标变成灰色的时候在试试吧。
6.最后,发布的时候记得重新申请APIkey,具体原因上面已经解释了。