<pre>
因为到了新公司,比较忙加上又快6级考试,所以一个月没有更新博客。废话不多说,进入今天的主题。
要进行百度地图的开发首先要在百度地图官网进行密钥的申请,因为百度网站对于密钥的申请已经非常详细,我这里不再说明(详细介绍点击这里),申请下密钥后,在Androidmanifest中添加密钥、一些百度需要的权限以及远程服务的声明。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.application">
<!--百度地图需要的权限-->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light.NoActionBar">
<!--这里输入百度密钥-->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="这里输入你自己申请的密钥" />
<!--百度的远程服务-->
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" />
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".BaiduMapActivity" />
</application>
</manifest>
这样就完成了前期的准备工作,现在进入正式开发阶段。
首先通过LocationClient对用户现在的位置进行定位,需要设置此类的一些基本属性以及监听的事件(当探测到用户的位置时,调用此方法),下面是核心代码
mLocClient = new LocationClient(this);
mLocClient.registerLocationListener(myListener);
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true);// 打开gps
option.setCoorType("gcj02");//设置坐标类型
option.setIsNeedAddress(true);//设置是否需要位置信息,默认为无地址
option.setScanSpan(10000);//设置扫描间隔,单位为毫秒
mLocClient.setLocOption(option);
mLocClient.start();//开始定位
定位到当前的位置后,开始搜索附近的兴趣点POI(Point of Interest)的搜索,这里使用到得类为PoiSearch,这个类支持城市所搜、范围所搜和附近所搜,而我们需要的是附近搜索SearchNearby(PoiNearbySearchOption option)这个方法。核心代码:
mPoiSearch = PoiSearch.newInstance();//实例化对象
//设置搜索的关键字、经纬度以及所搜的范围
mPoiSearch.searchNearby(new PoiNearbySearchOption().keyword("小区").location(llA).radius(1000));
mPoiSearch.setOnGetPoiSearchResultListener(new OnGetPoiSearchResultListener{
@Override
public void onGetPoiResult(PoiResult poiResult){
//在这里对附近所搜的位置进行处理
}
}
);
最后监听BaiduMap状态的变化,取得手机屏幕中心的经纬度,然后使用GeoCoder进行反地理编码,得到该经纬度的位置信息。核心代码:
mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
@Override
public void onMapStatusChangeStart(MapStatus mapStatus) {
//手势操作地图,设置地图状态等操作导致地图状态开始改变。
}
@Override
public void onMapStatusChange(MapStatus mapStatus) {
//地图状态变化中
}
@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
//地图状态改变结束
mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(mapStatus.target));//对定位的经纬度进行反编码
}
});
mSearch.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
//地理编码查询结果回调函数
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
//反地理编码查询结果回调函数
}
});
Demo的效果图如下:
![](https://img-blog.csdn.net/20150607165723483)
点击地图定位,进入下面的页面:
可以看到,已经完成了定位,此时图上有两个点,蓝色圆形标识手机当前的位置,而橘黄色的标识是位于屏幕中央,跟着滑动而滑动,下面是搜索附近的小区的结果。
![](https://img-blog.csdn.net/20150607165602253)
可以看到当点击下方区域时相应的,程序是不会进行搜索和刷新,只有当手动在百度地图上滑动时,才会进行搜索和滑动。
然后点击发送,会将当前选定的位置的经纬度,位置名称和详细地址发送到指定的Activity进行使用。
显示到MainActivity中,然后点击此信息,会在百度地图中标识出该位置。而此时是不能进行主动选取的。
这就大概实现了QQ和微信的位置共享的功能。
其中最主要的BaiduMapActivity的代码如下,剩下的代码太多就不贴出来了,感兴趣的朋友可以下载研究
点击这里下载
package com.application;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ZoomControls;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMapOptions;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationConfiguration.LocationMode;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.poi.OnGetPoiSearchResultListener;
import com.baidu.mapapi.search.poi.PoiDetailResult;
import com.baidu.mapapi.search.poi.PoiNearbySearchOption;
import com.baidu.mapapi.search.poi.PoiResult;
import com.baidu.mapapi.search.poi.PoiSearch;
import com.baidu.mapapi.utils.CoordinateConverter;
import java.util.ArrayList;
import java.util.List;
public class BaiduMapActivity extends Activity {
public final static String LATITUDE = "latitude";
public final static String LONGITUDE = "longitude";
public final static String ADDRESS = "address";
public final static String NAME = "name";
private ImageView original;
private BaiduMapAdatper adatper;
private LatLng originalLL, currentLL;//初始化时的经纬度和地图滑动时屏幕中央的经纬度
static MapView mMapView = null;
private GeoCoder mSearch = null;
private LocationClient mLocClient;// 定位相关
public MyLocationListenner myListener = new MyLocationListenner();
private LinearLayout sendButton = null;
private PoiSearch mPoiSearch;
private List<PoiInfo> datas;
private PoiInfo lastInfo = null;
public static BaiduMapActivity instance = null;
private ProgressDialog progressDialog;
private BaiduMap mBaiduMap;
private MapStatusUpdate myselfU;
private ListView listView;
private boolean changeState = true;//当滑动地图时再进行附近搜索
private int preCheckedPosition = 0;//点击的前一个位置
private TextView refreshText;
/**
* 构造广播监听类,监听 SDK key 验证以及网络异常广播
*/
public class BaiduSDKReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String s = intent.getAction();
String st1 = "Network error";
if (s.equals(SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR)) {
String st2 = "key validation error!Please on AndroidManifest.xml file check the key set";
Toast.makeText(instance, st2, Toast.LENGTH_SHORT).show();
} else if (s.equals(SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR)) {
Toast.makeText(instance, st1, Toast.LENGTH_SHORT).show();
}
}
}
private BaiduSDKReceiver mBaiduReceiver;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SDKInitializer.initialize(getApplicationContext());
instance = this;
setContentView(R.layout.activity_baidumap);
setTitle();
init();
}
private void init() {
original = (ImageView) findViewById(R.id.bmap_local_myself);
listView = (ListView) findViewById(R.id.bmap_listview);
mMapView = (MapView) findViewById(R.id.bmap_View);
mSearch = GeoCoder.newInstance();
sendButton = (LinearLayout) findViewById(R.id.right_title_layout);
refreshText = (TextView) findViewById(R.id.bmap_refresh);
ImageView centerIcon = (ImageView) findViewById(R.id.bmap_center_icon);
datas = new ArrayList<PoiInfo>();
adatper = new BaiduMapAdatper(BaiduMapActivity.this,
datas, R.layout.adapter_baidumap_item);
listView.setAdapter(adatper);
Intent intent = getIntent();
double latitude = intent.getDoubleExtra(LATITUDE, 0);
LocationMode mCurrentMode = LocationMode.NORMAL;
mBaiduMap = mMapView.getMap();
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(15.0f);
mBaiduMap.setMapStatus(msu);
mPoiSearch = PoiSearch.newInstance();
mMapView.setLongClickable(true);
// 隐藏百度logo ZoomControl
int count = mMapView.getChildCount();
for (int i = 0; i < count; i++) {
View child = mMapView.getChildAt(i);
if (child instanceof ImageView || child instanceof ZoomControls) {
child.setVisibility(View.INVISIBLE);
}
}
// 隐藏比例尺
mMapView.showScaleControl(false);
if (latitude == 0) {
mMapView = new MapView(this, new BaiduMapOptions());
mBaiduMap.setMyLocationConfigeration(new MyLocationConfiguration(
mCurrentMode, true, null));
mBaiduMap.setMyLocationEnabled(true);
showMapWithLocationClient();
setOnclick();
} else {
double longtitude = intent.getDoubleExtra(LONGITUDE, 0);
String address = intent.getStringExtra(ADDRESS);
LatLng p = new LatLng(latitude, longtitude);
mMapView = new MapView(this,
new BaiduMapOptions().mapStatus(new MapStatus.Builder()
.target(p).build()));
listView.setVisibility(View.GONE);
refreshText.setVisibility(View.GONE);
original.setVisibility(View.GONE);
centerIcon.setVisibility(View.GONE);
showMap(latitude, longtitude, address.split("|")[1]);
}
// 注册 SDK 广播监听者
IntentFilter iFilter = new IntentFilter();
iFilter.addAction(SDKInitializer.SDK_BROADTCAST_ACTION_STRING_PERMISSION_CHECK_ERROR);
iFilter.addAction(SDKInitializer.SDK_BROADCAST_ACTION_STRING_NETWORK_ERROR);
mBaiduReceiver = new BaiduSDKReceiver();
registerReceiver(mBaiduReceiver, iFilter);
}
/**
* 设置点击事件
*/
private void setOnclick() {
mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener() {
@Override
public void onTouch(MotionEvent motionEvent) {
changeState = true;
}
});
original.setOnClickListener(new MyOnClickListener());
listView.setOnItemClickListener(new MyItemClickListener());
mPoiSearch.setOnGetPoiSearchResultListener(new MyGetPoiSearchResult());
mBaiduMap.setOnMapStatusChangeListener(new MyMapStatusChangeListener());
mSearch.setOnGetGeoCodeResultListener(new MyGetGeoCoderResultListener());
}
private boolean isSearchFinished;
private boolean isGeoCoderFinished;
private void refreshAdapter() {
if (isSearchFinished && isGeoCoderFinished) {
adatper.notifyDataSetChanged();
refreshText.setVisibility(View.GONE);
listView.setVisibility(View.VISIBLE);
isSearchFinished = false;
isGeoCoderFinished = false;
}
}
/**
* 根据关键字查找附近的位置信息
*/
private class MyGetPoiSearchResult implements OnGetPoiSearchResultListener {
@Override
public void onGetPoiResult(PoiResult poiResult) {
datas.addAll(poiResult.getAllPoi());
preCheckedPosition = 0;
isSearchFinished = true;
refreshAdapter();
}
@Override
public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
}
}
/**
* 根据经纬度进行反地理编码
*/
private class MyGetGeoCoderResultListener implements OnGetGeoCoderResultListener {
@Override
public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
return;
}
lastInfo.address = result.getAddress();
lastInfo.location = result.getLocation();
lastInfo.name = "[位置]";
datas.add(lastInfo);
preCheckedPosition = 0;
adatper.setSelection(0);
isGeoCoderFinished = true;
refreshAdapter();
}
}
/**
* 监听位置发生了变化
*/
private class MyMapStatusChangeListener implements BaiduMap.OnMapStatusChangeListener {
@Override
public void onMapStatusChangeStart(MapStatus mapStatus) {
if (changeState) {
datas.clear();
refreshText.setVisibility(View.VISIBLE);
listView.setVisibility(View.GONE);
}
}
@Override
public void onMapStatusChange(MapStatus mapStatus) {
}
@Override
public void onMapStatusChangeFinish(MapStatus mapStatus) {
if (changeState) {
boolean isFirstLoad = true;
if (isFirstLoad) {
originalLL = mapStatus.target;
}
currentLL = mapStatus.target;
// 反Geo搜索
mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(currentLL));
mPoiSearch.searchNearby(new PoiNearbySearchOption().keyword("小区")
.location(currentLL).radius(1000));
}
}
}
/**
* 查看别人发过来,或者已经发送出去的位置信息
*
* @param latitude 维度
* @param longtitude 经度
* @param address 详细地址信息
*/
private void showMap(double latitude, double longtitude, String address) {
sendButton.setVisibility(View.GONE);
LatLng llA = new LatLng(latitude, longtitude);
OverlayOptions ooA = new MarkerOptions().position(llA).icon(BitmapDescriptorFactory
.fromResource(R.drawable.icon_yourself_lication))
.zIndex(4).draggable(true);
mBaiduMap.addOverlay(ooA);
MapStatusUpdate u = MapStatusUpdateFactory.newLatLngZoom(llA, 17.0f);
mBaiduMap.animateMapStatus(u);
}
/**
* 显示当前的位置信息
*/
private void showMapWithLocationClient() {
String str1 = "正在刷新";
progressDialog = new ProgressDialog(this);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.setMessage(str1);
progressDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface arg0) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
finish();
}
});
progressDialog.show();
mLocClient = new LocationClient(this);
mLocClient.registerLocationListener(myListener);
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true);// 打开gps
option.setCoorType("gcj02");
option.setIsNeedAddress(true);
option.setScanSpan(10000);
mLocClient.setLocOption(option);
mLocClient.start();
}
@Override
protected void onPause() {
mMapView.onPause();
if (mLocClient != null) {
mLocClient.stop();
}
super.onPause();
lastInfo = null;
}
@Override
protected void onDestroy() {
if (mLocClient != null)
mLocClient.stop();
mMapView.onDestroy();
unregisterReceiver(mBaiduReceiver);
super.onDestroy();
}
/**
* 监听函数,有新位置的时候,格式化成字符串,输出到屏幕中
*/
public class MyLocationListenner implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
if (location == null) {
return;
}
sendButton.setEnabled(true);
if (progressDialog != null) {
progressDialog.dismiss();
}
if (lastInfo != null) {
return;
}
lastInfo = new PoiInfo();
mBaiduMap.clear();
LatLng llA = new LatLng(location.getLatitude(), location.getLongitude());
lastInfo.location = llA;
lastInfo.address = location.getAddrStr();
lastInfo.name = "[位置]";
LatLng ll = new LatLng(location.getLatitude() - 0.0002, location.getLongitude());
CoordinateConverter converter = new CoordinateConverter();//坐标转换工具类
converter.coord(ll);//设置源坐标数据
converter.from(CoordinateConverter.CoordType.COMMON);//设置源坐标类型
LatLng convertLatLng = converter.convert();
OverlayOptions myselfOOA = new MarkerOptions().position(convertLatLng).icon(BitmapDescriptorFactory
.fromResource(R.drawable.icon_yourself_lication))
.zIndex(4).draggable(true);
mBaiduMap.addOverlay(myselfOOA);
myselfU = MapStatusUpdateFactory.newLatLngZoom(convertLatLng, 17.0f);
mBaiduMap.animateMapStatus(myselfU);
}
}
private void showRightWithText(String str,
View.OnClickListener clickListener) {
TextView rightText = (TextView) findViewById(R.id.right_title_text);
rightText.setVisibility(View.VISIBLE);
rightText.setText(str);
//设置点击区域
LinearLayout rightClickRange = (LinearLayout) findViewById(R.id.right_title_layout);
rightClickRange.setOnClickListener(clickListener);
}
protected void showLeftWithImage(int resId,
View.OnClickListener clickListener) {
ImageView leftImage = (ImageView) findViewById(R.id.left_title_image);
leftImage.setVisibility(View.VISIBLE);
leftImage.setImageResource(resId);
//设置点击区域
LinearLayout leftClickRange = (LinearLayout) findViewById(R.id.left_title_layout);
leftClickRange.setOnClickListener(clickListener);
}
private void setTitle() {
TextView title = (TextView) findViewById(R.id.center_title);
title.setText("位置信息");
showRightWithText("发送", new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = BaiduMapActivity.this.getIntent();
intent.putExtra(LATITUDE, lastInfo.location.latitude);
intent.putExtra(LONGITUDE, lastInfo.location.longitude);
intent.putExtra(ADDRESS, lastInfo.address);
intent.putExtra(NAME, lastInfo.name);
BaiduMapActivity.this.setResult(RESULT_OK, intent);
finish();
}
});
showLeftWithImage(R.drawable.btn_back, new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
/**
* 点击相应的位置,移动到该位置
*/
private class MyItemClickListener implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (preCheckedPosition != position) {
adatper.setSelection(position);
View view1 = listView.getChildAt(preCheckedPosition - listView.getFirstVisiblePosition());
ImageView checked = null;
if (view1 != null) {
checked = (ImageView) view1.findViewById(R.id.adapter_baidumap_location_checked);
checked.setVisibility(View.GONE);
}
preCheckedPosition = position;
changeState = false;
PoiInfo info = datas.get(position);
LatLng llA = info.location;
MapStatusUpdate u = MapStatusUpdateFactory.newLatLngZoom(llA, 17.0f);
mBaiduMap.animateMapStatus(u);
lastInfo = info;
checked = (ImageView) view.findViewById(R.id.adapter_baidumap_location_checked);
checked.setVisibility(View.VISIBLE);
}
}
}
private class MyOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
if (currentLL != originalLL) {
changeState = true;
mBaiduMap.animateMapStatus(myselfU);
}
}
}
}
</pre>