您的位置:首页 > 移动开发 > 微信开发

Android百度地图(地位和POI附近搜索)-仿微信、QQ地理位置的分享

2015-06-06 09:49 836 查看
<pre>
因为到了新公司,比较忙加上又快6级考试,所以一个月没有更新博客。废话不多说,进入今天的主题。
要进行百度地图的开发首先要在百度地图官网进行密钥的申请,因为百度网站对于密钥的申请已经非常详细,我这里不再说明(详细介绍点击这里),申请下密钥后,在Androidmanifest中添加密钥、一些百度需要的权限以及远程服务的声明。
[/code]
<?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){
//在这里对附近所搜的位置进行处理
}
}
);
[/code]
最后监听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的效果图如下:
点击地图定位,进入下面的页面:
可以看到,已经完成了定位,此时图上有两个点,蓝色圆形标识手机当前的位置,而橘黄色的标识是位于屏幕中央,跟着滑动而滑动,下面是搜索附近的小区的结果。
可以看到当点击下方区域时相应的,程序是不会进行搜索和刷新,只有当手动在百度地图上滑动时,才会进行搜索和滑动。
然后点击发送,会将当前选定的位置的经纬度,位置名称和详细地址发送到指定的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;@Overridepublic 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 ZoomControlint 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() {@Overridepublic 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 {@Overridepublic void onGetPoiResult(PoiResult poiResult) {datas.addAll(poiResult.getAllPoi());preCheckedPosition = 0;isSearchFinished = true;refreshAdapter();}@Overridepublic void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {}}/*** 根据经纬度进行反地理编码*/private class MyGetGeoCoderResultListener implements OnGetGeoCoderResultListener {@Overridepublic void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {}@Overridepublic 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 {@Overridepublic void onMapStatusChangeStart(MapStatus mapStatus) {if (changeState) {datas.clear();refreshText.setVisibility(View.VISIBLE);listView.setVisibility(View.GONE);}}@Overridepublic void onMapStatusChange(MapStatus mapStatus) {}@Overridepublic 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);// 打开gpsoption.setCoorType("gcj02");option.setIsNeedAddress(true);option.setScanSpan(10000);mLocClient.setLocOption(option);mLocClient.start();}@Overrideprotected void onPause() {mMapView.onPause();if (mLocClient != null) {mLocClient.stop();}super.onPause();lastInfo = null;}@Overrideprotected void onDestroy() {if (mLocClient != null)mLocClient.stop();mMapView.onDestroy();unregisterReceiver(mBaiduReceiver);super.onDestroy();}/*** 监听函数,有新位置的时候,格式化成字符串,输出到屏幕中*/public class MyLocationListenner implements BDLocationListener {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic void onClick(View v) {finish();}});}/*** 点击相应的位置,移动到该位置*/private class MyItemClickListener implements AdapterView.OnItemClickListener {@Overridepublic 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 {@Overridepublic void onClick(View v) {if (currentLL != originalLL) {changeState = true;mBaiduMap.animateMapStatus(myselfU);}}}}
[/code]
</pre>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: