一.前言:
当前越来越多的安卓应用开始使用基于LBS的服务来完善用户体验。术语LBS(Location Based Service)可以称为基于位置信息的服务,使用百度地图或google地图进行开发的应用程序不可避免的要使用到定位功能。
首先说明一下,android系统其实自带了实现定位功能的API,主要使用AndroidFramework中的LocationManager类和Location类。
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 0,0,locationListener);
但是使用Android自带的API经常会遇到返回的location为null的情况,这是因为很多国内的手机在出厂的时候系统都被阉割过,导致在使用定位API的时候经常遇见错误。
因此一般建议使用百度定位API或者是Google地图API,百度地图在定位国内的地理位置时比较优秀,很多小的地理坐标都有明确标示而Google地图在世界范围内的位置坐标比较明确。
二.手机定位方式简介
1.GPS定位方式
最简单的手机定位方式当然是通过GPS模块(现在大部分的智能机应该都有了)。GPS方式准确度是最高的,但是它的缺点也非常明显:
(1),比较耗电;
(2),绝大部分用户默认不开启GPS模块;
(3),从GPS模块启动到获取第一次定位数据,可能需要比较长的时间;
(4),室内几乎无法使用。
这其中,缺点2,3都是比较致命的。需要指出的是,GPS走的是卫星通信的通道,在没有网络连接的情况下也能用。
2.Network定位方式
(1).基站定位
大致思路就是采集到手机上的基站ID号(cellid)和其它的一些信息(MNC,MCC,LAC等等),然后通过网络访问一些定位服务,获取并返回对应的经纬度坐标。基站定位的精确度不如GPS,但好处是能够在室内用,只要网络通畅就行。
(2).Wifi定位
和基站定位类似,这种方式是通过获取当前所用的wifi的一些信息,然后访问网络上的定位服务以获得经纬度坐标。
因为这两种方式都要借用网络进行定位,因此可以统称为网络定位方式。
三.使用百度API进行手机定位
3.1 开发前的准备
(1). 以locSDK*_3.1.jar为例。对用使用到liblocSDK3.so文件,这些都可以在百度云api的网站上下载。首先在libs文件夹下面建立armeabi文件夹,将liblocSDK3.so放到该文件夹下,将locSKD_*3.1.jar导入到项目中。
(2). 注意:红色警告
一定要将locSDK_3.1.jar放到libs文件夹下面,否则定位系统崩溃。(亲自遇见多次,慎重。)
(3). 百度定位是以服务的形式在后台开启,因此必须在manifest.xml文件中添加服务。
<service
android:enabled = "true"
android:name="com.baidu.location.f"
android:process=":remote"
>
</service>
(4).定位API需要开启很多权限
<uses-permission android:name="android.permission.INTERNET" />
<!-- 访问精确位置的权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 访问网络状态的权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 访问WIFI网络状态的权限 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 改变WIFI网络状态的权限 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- 读写存储卡的权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 读取电话状态的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
3.2 主要对象简介
(1).LocationClient类
定位需要的”句柄“类。
(2).LocationClientOption类
通过设置该类的对象间接完成对LocationClient对象的修改。
(3).自定义MyLocationListener继承BDLocationListener
该类主要有两个需要实现的回调函数,一般复写OnReceiveLoation(BDLocation location)方法。
3.3 Source Code
主界面显示当前位置的信息等参数。
package com.example.exadapter;
import java.util.ArrayList;
import java.util.List;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends Activity
{
@Override
protected void onStop()
{
// TODO Auto-generated method stub
mLocationClient.stop();
super.onStop();
}
//定位相关的变量
private LocationClient mLocationClient = null;
private BDLocation bdloca;
public MyLocationListener myLocListener = new MyLocationListener();
TextView locTV;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initView();
locListener();
}
/*
* 定位SDK监听函数
*
* */
public class MyLocationListener implements BDLocationListener
{
@Override
public void onReceiveLocation(BDLocation location) {
// TODO Auto-generated method stub
if(location == null)
{
return;
}
bdloca = location;
StringBuffer sb = new StringBuffer(256);
sb.append("time: ");
sb.append(location.getTime());
sb.append("\nerror code: ");
sb.append(location.getLocType());
sb.append("\nlatitude : ");
sb.append(location.getLatitude());
sb.append("\nlongitude : ");
sb.append(location.getLongitude());
sb.append("\nradius : ");
sb.append(location.getRadius());
if(location.getLocType() == BDLocation.TypeGpsLocation)
{
sb.append("\nspeed: ");
sb.append(location.getSpeed());
sb.append("\nsatellite: ");
sb.append(location.getSatelliteNumber());
}
else if(location.getLocType() == BDLocation.TypeNetWorkLocation)
{
sb.append("\naddr: ");
sb.append(location.getAddrStr());
}
sb.append("\nsdk version: ");
sb.append(mLocationClient.getVersion());
locTV.setText(sb.toString());
locTV.setTextSize(20);
locTV.setTextColor(Color.RED);
}
@Override
public void onReceivePoi(BDLocation arg0) {
// TODO Auto-generated method stub
}
}
private void locListener()
{
mLocationClient = new LocationClient(this);
LocationClientOption option = new LocationClientOption();
option.setAddrType("all");
option.setPoiExtraInfo(true);
option.setProdName("定位我当前的位置");
option.setPoiDistance(500);
option.setCoorType("bd0911");
option.setPoiNumber(3);
option.setPriority(LocationClientOption.NetWorkFirst);
option.setOpenGps(true);
option.setScanSpan(5000);
mLocationClient.setLocOption(option);
mLocationClient.registerLocationListener(myLocListener);
mLocationClient.start();
}
protected void initView()
{
locTV = (TextView) findViewById(R.id.locInfo);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
3.4.具体的各个参数的意义,可以查看百度官方的文档,都有详细的介绍。
四.App界面展示
下面的界面是一个ExpandableListView控件,用来做测试用的。
五.总结
手机定位是一个很实用的功能,现在基于LBS的手机APP越来越多,理解和掌握定位的实现具有很大的实际意义。