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

<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的效果图如下:
 
 
 
 
	点击地图定位,进入下面的页面:

	可以看到,已经完成了定位,此时图上有两个点,蓝色圆形标识手机当前的位置,而橘黄色的标识是位于屏幕中央,跟着滑动而滑动,下面是搜索附近的小区的结果。
	
	可以看到当点击下方区域时相应的,程序是不会进行搜索和刷新,只有当手动在百度地图上滑动时,才会进行搜索和滑动。

	然后点击发送,会将当前选定的位置的经纬度,位置名称和详细地址发送到指定的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>
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值