百度定位案例。(无地图版本)

        做的地图定位,用的是百度地图SDK,看了好多demo,官方的API也看了好几个版本。出的问题也各种查,也去百度地图API论坛咨询。为了以后再有需要的时候不这么麻烦,把这几天的东西大概做个总结。

首先是去http://lbsyun.baidu.com/apiconsole/key申请KEY,SHA1如果是eclipse在Window—Preferences—Android—Build。。包名就填自己的 包名就好。。Android Studio的SHA1自己百度,我也不知道。申请好KEY后,去相关下载里把自己需要用到的开发包选中进行下载。解压。然后就是新建工程,进行配置了。配置这里我就直接Ctrl+V 百度的了。百度官方配置链接  :http://lbsyun.baidu.com/index.php?title=androidsdk/guide/buildproject    拷贝到libs目录下文件比较新的版本:链接: http://pan.baidu.com/s/1skDdrPV 密码: ews2

配置环境

Eclipse工程配置方法

第一步:在工程里新建libs文件夹,将开发包里的baidumapapi_vX_X_X.jar拷贝到libs根目录下,将libBaiduMapSDK_vX_X_X.so拷贝到libs\armeabi目录下(官网demo里已有这两个文件,如果要集成到自己的工程里,就需要自己添加)(自己电脑里这几个文件去F:\BaiduMap相关\拷贝到libs目录下的文件这里找。)(或者去这里下载自己分享的:链接: http://pan.baidu.com/s/1skDdrPV 密码: ews2),拷贝完成后的工程目录如下图所示;

1.JPG

第二步:在工程属性->Java Build Path->Libraries中选择“Add External JARs”,选定baidumapapi_vX_X_X.jar,确定后返回。

通过以上两步操作后,您就可以正常使用百度地图SDK为您提供的全部功能了。

注意:由于adt插件升级,若您使用Eclipse adt 22的话,需要对开发环境进行相应的设置,方法如下:

1. 在Eclipse 中选中工程,右键选 Properties->Java Build Path->Order and Export 使 Android Private Libraries处于勾选状态;

2. Project -> clean-> clean all .

Android Studio工程配置方法

第一步:在工程app/libs目录下放入baidumapapi_vX_X_X.jar包,在src/main/目录下新建jniLibs目录,工程会自动加载src目录下的so动态库,放入libBaiduMapSDK_vX_X_X_X.so如下图所示,注意jar和so的前3位版本号必须一致,并且保证使用一次下载的文件夹中的两个文件,不能不同功能组件的jar或so交叉使用。

Androidstudio1.png

so的配置也可以参考demo给出的目录结构,如下图所示,在app工程路径下,新建libs,并在libs目录下放入对应不同CPU架构的so文件。这样工程并不会自动加载libs下的so,需在gradle编译时,通过加入代码: jniLibs.srcDir 'libs' 来说明so的路径为该libs路径。

Androidstudio2.png

第二步:工程配置还需要把jar包集成到自己的工程中,如图上图所示,放入libs目录下。对于每个jar文件,右键-选择Add As Library,导入到工程中。对应在build.gradle生成工程所依赖的jar文件说明,如图所示:

Androidstudio3.png

jar的配置也可参考eclipse方法,进行以下操作:

菜单栏选择 File —>Project Structure。

在弹出的Project Structure 对话框中, 选择module, 然后点击 Dependencies 选项卡.

点击绿色的加号选择File dependency. 然后选择要添加的jar包即可 完成上边的操作后在app目录下的build.gradle文件中,会有引入的类库,如上图所示。

Android studio工程配置详细请参考官方demo。

应用混淆

集成地图SDK的应用,在打包混淆的时候,需要注意与地图SDK相关的方法不可被混淆。混淆方法如下:

-keep class com.baidu.** {*;}
-keep class vi.com.** {*;}    
-dontwarn com.baidu.**

保证百度类不能被混淆,否则会出现网络不可用等运行时异常


说了 ,配置环境就直接粘贴的官方的。


然后是做没有地图版本的定位,开始这里接着官方文档,在Menifest清单文件中添加权限,设置service,key。

第一步:创建并配置工程(具体方法参见工程配置部分的介绍);

第二步:在AndroidManifest中添加开发密钥、所需权限等信息;

(1)在application中添加开发密钥

<application>  
    <meta-data  
        android:name="com.baidu.lbsapi.API_KEY"  
        android:value="开发者 key" />  
</application>

2)添加所需权限(这里是2016年3,4月份官方demo中的权限添加,和网页上的有点区别)

 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" >
    </uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
    </uses-permission>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >
    </uses-permission>
    <uses-permission android:name="android.permission.READ_LOGS" >
    </uses-permission>
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />

定位还需要在清单文件中添加一个service,因为定位SDK内部是一个SERVICE,有点绕,添加如下代码就行了:

<service
            android:name="com.baidu.location.f"
            android:enabled="true"
            android:process=":remote" >
            <intent-filter>
                <action android:name="com.baidu.location.service_v2.2" >
                </action>
            </intent-filter>
        </service>

这个好像一直就是这个,SDK版本怎么变添加的service这里也是这个,好像啊。


如果为了在多个类中使用,可以将定位的相关代码写在一个继承了Application的类中,大概步骤如下:


这里只是一个思路

动态注册一个广播,来监听定位结果。注册广播在重写的onreceive方法中,利用intent获取监听到的当前位置的字符串,然后设置在TextView中。进行控件的关联及按钮的点击事件的 监听。。在按钮的点击事件的监听中,开启Application。最后在写上一个进程结束后,销毁广播。

在开启的application中,首先介绍下这5个类:

1.BDLocation:封装了定位SDK的定位结果,BDLocationListener的onReceive方法中获取。通过该类用户可以获取error code,位置的坐标,精度半径等信息 

2.BDLocationListener: 获取定位结果,获取POI信息. 里面有2个onReceive方法

3.GeofenceClient:地理围栏SDK核心类 现在才发现在定位中用不到这个

4.LocationClient: 定位SDK的核心类

5.LocationClientOption:该类用来设置定位SDK的定位方式

 

在开启的application中,首先定义一个LocationClient类型对象,再重写的OnCreate()方法中,首先给LocationClient类型的对象初始化,在调用setAK()方法,设置AK,调用registerLocatonListener()(参数为BDLocationListenter类型的对象,这里就可以使用后面的新建的继承BDLocationListenter的类的对象)来注册监听函数,不然没有办法发起网络请求。

新建一个LocationClientOption对象根据需要来设置他的各种属性。设置好之后调用locationClientsetLocOption()(参数为刚新建的LocationClientOption类型的对象)方法来为其设置参数。

设置好相关参数后,启动SDK,发起定位,分别调用start()方法和requestLocation()方法。

新建一个类实现BDLocationListener接口,重写里面的2个方法,如果参数不为空,则通过广播将获取的位置发送出去供监听者接收。当用网络定位的时候,调用方法里参数名.getAddrStr()来获取位子描述的地理位置。

这个是发送广播:

public void sendBroadCast(String address) {

stopLocationClient();

 

Intent intent = new Intent(MainActivity.LOCATION_ACTION);

intent.putExtra("address", address);

sendBroadcast(intent);

// 发送广播,里面存有定位的结果

}

 

在广播中调用.stop()方法来停止定位SDK。

需要在Manifest清单文件中添加一个service和添加好多个权限。


具体代码如下

/**
 * BDLocation: 封装了定位SDK的定位结果,在BDLocationListener的onReceive方法中获取。通过该类用户可以获取error code,位置的坐标,精度半径等信息 
 * BDLocationListener: 获取定位结果,获取POI信息. 里面有2个onReceive方法
 * GeofenceClient:地理围栏SDK核心类
 * LocationClient: 定位SDK的核心类
 * LocationClientOption:该类用来设置定位SDK的定位方式
 *
 */

public class MyApplication extends Application {
private String AK = "0vm2PvFx8WLzhn3kPemOeA7KbwAPAz8S"; // 和应用证书和包名绑定绑定的密钥
private static MyApplication instance = null;

private LocationClient locationClient = null;
private MyBDLocationListener myBDLocationListener = new MyBDLocationListener();

@Override
public void onCreate() {
instance = this;
locationClient = new LocationClient(this);
locationClient.setAK(AK); // 设置AK,高版本SDK在Manifest中进行设置。
locationClient.registerLocationListener(myBDLocationListener);
// 注册监听函数,当没有注册监听函数时,无法发起网络请求。
super.onCreate();
}

public static MyApplication getInstance() {
return instance;
}

/**
* 设置相关参数
*/
private void setLocationClientOption() {
LocationClientOption locationClientOption = new LocationClientOption();
locationClientOption.setOpenGps(true); // 打开GPS
locationClientOption.setCoorType("bd09ll"); // 返回结果返回百度经纬度坐标系
// 这个属性一定要设置 不然找不到服务就无法定位。不过在高版本中是设置在Manifest中的
locationClientOption.setServiceName("com.baidu.location.service_v2.9");
locationClientOption.setScanSpan(3000);// 这个设置定位间隔,即3秒定位一次,不设置默认为定位1次
locationClientOption.setPoiExtraInfo(true); // 设置是否需要POI的电话地址等详细信息
locationClientOption.setAddrType("all"); // 设置是否要返回地址信息,默认为无地址信息。String 值为 all时,表示返回地址信息。
locationClientOption.setPoiNumber(10); // 设置POI个数
locationClientOption.disableCache(true); // 设置是否使用缓存定位

// setLocOption:设置参数
// 方法:public void setLocOption ( LocationClientOption )
// 配置定位SDK,参数为LocationClientOption类
locationClient.setLocOption(locationClientOption);
}

/**
* 发起定位
*/
public void requestLocationInfo() {
setLocationClientOption();

if (locationClient != null && !locationClient.isStarted()) {
locationClient.start(); // 启动定位SDK 这里其实可以把上面这几行代码封装在一个方法里,这样就可以多次方便的调用了。不过这里就自己看,就不改了
}

if (locationClient != null && locationClient.isStarted()) {
locationClient.requestLocation(); // 发起定位,异步获取当前位置
}
}

/**
* 发起离线定位
*/
public void requestLocationInfo2() {
setLocationClientOption();

if (locationClient != null && !locationClient.isStarted()) {
locationClient.start(); // 启动定位SDK
}

if (locationClient != null && locationClient.isStarted()) {
locationClient.requestOfflineLocation(); // 发起定位,异步获取当前位置
}
}


/**
* 监听函数,有更新位置的时候,格式化成字符串,输出到屏幕中 BDLocationListener:获取定位结果,获取POI信息。 2个方法:
* public void onReceiveLocation ( BDLocation location ); public void
* onReceivePoi(BDLocation poiLocation);

*   BDLocationListener在较高的版本中里面就一个ofReceive方法,这里是2个方法,一个是地理位置,一个是兴趣点

* poiLocation.getAddrStr():获取文字描述的地址(反地理编码)(网络定位)
*/
public class MyBDLocationListener implements BDLocationListener {
// 获取定位结果的接口。用户自己实现这个接口后,监听定位结果
@Override
public void onReceiveLocation(BDLocation location) {
// TODO Auto-generated method stub
if (location == null) {
sendBroadCast("定位失败!");
return;
}


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("\nlontitude : ");
sb.append(location.getLongitude());
sb.append("\nradius : ");
sb.append(location.getRadius());
sb.append("\n定位方法: ");
sb.append(location.getLocType());


if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位结果
sb.append("\nspeed : ");
sb.append(location.getSpeed());// 单位:公里每小时
sb.append("\nsatellite : ");
sb.append(location.getSatelliteNumber());
sb.append("\nheight : ");
sb.append(location.getAltitude());// 单位:米
sb.append("\naddr : ");
sb.append(location.getAddrStr());
sb.append("\ndescribe : ");
sb.append("gps定位成功");
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 网络定位结果
sb.append("\naddr : ");
sb.append(location.getAddrStr());
sb.append("\ndescribe : ");
sb.append("网络定位成功");
sendBroadCast(location.getAddrStr() + sb.toString());
Toast.makeText(getApplicationContext(), "在线定位",
Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 离线定位结果
sb.append("\ndescribe : ");
sb.append("离线定位成功,离线定位结果也是有效的");
geoPoint = new GeoPoint(latitudeOff, longitudeOff);
mkSearch.reverseGeocode(geoPoint);
Toast.makeText(getApplicationContext(), "离线定位",
Toast.LENGTH_SHORT).show();
} else if (location.getLocType() == BDLocation.TypeServerError) {
sb.append("\ndescribe : ");
sb.append("服务端网络定位失败,可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com,会有人追查原因");
} else if (location.getLocType() == BDLocation.TypeNetWorkException) {
sb.append("\ndescribe : ");
sb.append("网络不同导致定位失败,请检查网络是否通畅");
} else if (location.getLocType() == BDLocation.TypeCriteriaException) {
sb.append("\ndescribe : ");
sb.append("无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机");
}

MainActivity.LATITUDE = location.getLatitude();
MainActivity.LONGITUDE = location.getLongitude();
Log.i("BaiduLocationApiDem", sb.toString());
if (location.getAddrStr() != null) {
sendBroadCast(location.getAddrStr() + sb.toString());
} else {
sendBroadCast("未知地区");
}
}


// 获取POI信息的接口。用户自己实现这个接口后,监听poi的相关结果
@Override
public void onReceivePoi(BDLocation poi) {
// TODO Auto-generated method stub
if (poi == null) {
sendBroadCast("定位失败!");
return;
}
sendBroadCast(poi.getAddrStr());
}


}

/**
* 得到结果,发送广播

* @param address
*     结果,是一个字符串
*/
public void sendBroadCast(String address) {
stopLocationClient();


Intent intent = new Intent(MainActivity.LOCATION_ACTION);
intent.putExtra("address", address);
sendBroadcast(intent);
// 发送广播,里面存有定位的结果
}

/**
* 停止定位
*/
public void stopLocationClient() {
if (locationClient != null && locationClient.isStarted()) {
// 关闭定位SDK,调用stop之后,设置的参数LocationClientOption仍然保留
locationClient.stop();
}
}


然后再需要调用的类中调用方法,开启广播接受结果就可以了。以下是在主类中的代码:

public class MainActivity extends Activity implements OnClickListener {
private Button btnOnLine;
private Button btnOffLine;
private TextView tvHint;
private TextView tvLocation;
private TextView textView;

public static double LATITUDE = 0; // 这个就是保存纬度和经度
public static double LONGITUDE = 0;
 
private BroadcastReceiver broadcastReceiver;
public static String LOCATION_ACTION = "location_action";

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.test);

registerBroadCastReceiver();
init();
btnOnLine.setOnClickListener(this);
btnOffLine.setOnClickListener(this);
}

/**
* 动态的注册一个广播,来监听定位结果
*/
private void registerBroadCastReceiver() {
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String address = intent.getStringExtra("address");
if (address == null) {
tvLocation.setText("无位置信息");
}else {
tvLocation.setText(address);
}
textView.setText("纬度:" + LATITUDE + "\n经度:" + LONGITUDE);
}
};
IntentFilter intentFilter = new IntentFilter(LOCATION_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
}


// 控件的关联
private void init() {
btnOnLine = (Button) findViewById(R.id.test_btn_online);
btnOffLine = (Button) findViewById(R.id.test_btn_offline);
tvHint = (TextView) findViewById(R.id.test_tv_hint);
tvLocation = (TextView) findViewById(R.id.test_tv_location);
textView = (TextView) findViewById(R.id.test_tv_xinxi);
}


// 重写监听事件
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.test_btn_online:
tvHint.setVisibility(View.VISIBLE);
tvLocation.setText("正在定位......");
textView.setText(" ");
MyApplication.getInstance().requestLocationInfo();
break;
case R.id.test_btn_offline:
// if (tvHint.VISIBLE != View.VISIBLE) {
tvHint.setVisibility(View.VISIBLE);
// }
tvLocation.setText("正在定位......");
MyApplication.getInstance().requestLocationInfo2();
break;
default:
break;
}
}


// 进程结束后,销毁广播
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unregisterReceiver(broadcastReceiver);
}
}

不过这里我有个问题就是你要把Menifest清单文件中的Application改成上面那个你继承Application的类。如下:

 android:name="com.cmmr.location.test.MyApplication"

加上这个来引用你自己写的类

这个怎么在这里添加图片啊 不知道怎么搞了 ,反正就是下面那个Application 的图片



没有地图的版本大概就是这个样子吧,当然了 ,如果不想使用广播,且定位需求就在一个类的话,可以将上面MyApplication类中的广播去掉,剩下的大概就挑挑写在想要实现定位的类中,然后再监听返回结果的方法里处理结果,在合适的地方给地图Start和stop就可以了。其实到现在定位SDK的版本和以前改动不是太大,改动以我的理解大概是这些:KEY和service在menifist中配置,监听里改为一个方法,option中可以设置定位的模式。我的感觉改动就是这些。

源码(链接: http://pan.baidu.com/s/1nvlbyIX 密码: i4wb)这个源码中我贱嗖嗖的将定位结果如果文字信息多的话以跑马灯的形式显示。本来想把有地图的版本也在这里写的 ,想想算了 感觉还是分分类,那个就在重新写一个吧

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值