项目实战:android 地图定位两个用户之间的距离

来源:互联网 发布:编程序软件 编辑:程序博客网 时间:2024/05/19 09:51

本篇是地图定位功能,实现了两个用户之间相差距离的计算和展示。

思路如下:

1,首先用百度地图,进行注册创建应用。

2,在A用户发表信息的时候,获取到A用户的地理位置。//这里可以展示也可以不展示

3,当B用户看到A用户信息的时候,获取到B用户的位置,查询出A用户的位置,相减就可以得出相差距离。

第三步具体思路:

1,判断A用户的地理位置是否为空,因为如果不为空的话就显示,那么A查看信息时会显示距离自己0米 / / 注意这里一定要是地理位置,获取错了会报空指针

2,获取当前用户位置信息和发表用户位置的对象BDLocation,获取到经度和纬度转换成LatLng。

3,根据百度地图里的DistanceUtil.getDistance(la_start, la_end)获得起始和终点距离,将距离转换成int类型//默认是double也可以

4,判断<1000米的时候,显示为米,//如果不判断数据很大的时候,我们的用户估计会崩溃掉

5,else这里显示的是公里,为了降低误差,这里用(count +500)%1000 +"公里"

代码如下:

1,登录百度map API 创建应用。下载文件。将libs目录下文件全部复制到工程目录的libs目录下

2,所以的清单文件配置权限

<!-- 百度定位 -->    <!-- 这个权限用于进行网络定位 -->    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >    </uses-permission>    <!-- 这个权限用于访问GPS定位 -->    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >    </uses-permission>    <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >    </uses-permission>    <!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >    </uses-permission>    <!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->    <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" />    <!-- SD卡读取权限,用户写入离线定位数据 -->    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >    </uses-permission>    <!-- 允许应用读取低级别的系统日志文件 -->    <uses-permission android:name="android.permission.READ_LOGS" >    </uses-permission>

<meta-data            android:name="com.baidu.lbsapi.API_KEY"            android:value="开发者key" />
 <!-- 百度定位 -->        <service            android:name="com.baidu.location.f"            android:enabled="true"            android:process=":remote" >        </service>

2,初始化地图建议在Appliction全局里

package com.xdl.utils;import java.util.ArrayList;import java.util.List;import android.app.Application;import android.util.Log;import com.baidu.location.BDLocation;import com.baidu.location.BDLocationListener;import com.baidu.location.LocationClient;import com.baidu.location.LocationClientOption;import com.baidu.location.BDNotifyListener;//假如用到位置提醒功能,需要import该类//如果使用地理围栏功能,需要import如下类import com.baidu.location.BDGeofence;import com.baidu.location.BDLocationStatusCodes;import com.baidu.location.GeofenceClient;import com.baidu.location.GeofenceClient.OnAddBDGeofencesResultListener;import com.baidu.location.GeofenceClient.OnRemoveBDGeofencesResultListener;import com.baidu.location.LocationClientOption.LocationMode;import com.baidu.mapapi.SDKInitializer;import com.xdl.bean.Driay;/** * 本类是大型数据的传递所用 * 继承后,在清单的Application加入本类引用,name="" * 数据携带有两种方法, * 1,getAppliton可以获取到但是在没有Activity的页面是无法获取到的 * 2,模式思想,在全局定义一个本类对象的变量。在onCreate方法中返回该对象 * 因为onCreate方法会在程序没有启动起来的时候就会开始运行 * 3,实现get和set方法。 * @author Administrator * *获取定位: *1,导入包和在清单文件注册好。 *2.先加载百度SDKInitializer.initialize(getApplicationContext()); //必须有这个,否则空指针 *3.实现内部类BDLocationListener方法 *4.注册 */public class MyAppliction extends Application {//创建本类对象public static MyAppliction myAppliction;//做准备工作public List<Driay> driay;//百度定位public LocationClient mLocationClient = null;public BDLocationListener myListener = null;//定义集合将内容添加进去,判断当集合数据的长度小于等于10的时候,一旦大于就重置数据,重置是从0下标移除public List<BDLocation> location = new ArrayList<BDLocation>();//声明@Overridepublic void onCreate() {myAppliction = this;//返回对象引用initBaiDumap();RegisterMap();super.onCreate();}private void RegisterMap() { mLocationClient = new LocationClient(getApplicationContext());//声明LocationClient类 LocationClientOption option = new LocationClientOption(); option.setLocationMode(LocationMode.Hight_Accuracy);//设置定位模式 option.setCoorType("bd09ll");//返回的定位结果是百度经纬度,默认值gcj02 option.setScanSpan(5000);//设置发起定位请求的间隔时间为5000ms option.setIsNeedAddress(true);//返回的定位结果包含地址信息 option.setOpenGps(true);//GPS开启 mLocationClient.setLocOption(option); myListener = new BDLocationListener() {@Overridepublic void onReceiveLocation(BDLocation arg0) {if (location.size()==10) {//判断长度等于10location.clear();//重置}location.add(arg0);}};mLocationClient.registerLocationListener( myListener );//注册监听mLocationClient.start();//启动}private void initBaiDumap() {//注意该方法要再setContentView方法之前实现         <span style="white-space:pre"></span> SDKInitializer.initialize(getApplicationContext()); //必须有这个,否则空指针}public void setLocation(List<BDLocation> location) {this.location = location;}public List<BDLocation> getLocation() {return location;}public List<Driay> getDriay() {return driay;}public void setDriay(List<Driay> driay) {this.driay = driay;}}

3,添加数据的时候,我们需要获取到定位的数据

package com.xdl.activity;import java.io.IOException;import java.util.ArrayList;import java.util.List;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.util.EntityUtils;import org.json.JSONException;import org.json.JSONObject;import android.graphics.Color;import android.graphics.Shader;import android.graphics.drawable.shapes.Shape;import android.os.AsyncTask;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.EditText;import android.widget.GridView;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import cn.bmob.v3.BmobUser;import cn.bmob.v3.listener.SaveListener;import com.baidu.location.BDLocation;import com.xdl.adapter.CreateDirayAdapter;import com.xdl.base.BaseActivity;import com.xdl.bean.Driay;import com.xdl.bean.User;import com.xdl.bmob.R;import com.xdl.utils.MyAppliction;public class CreateDirayActivity extends BaseActivity implements OnItemClickListener, OnClickListener {private ImageView save;//保存private TextView tvLocation;//地图// 切换图标逻辑private int[] ivFromGridViewDatas = { R.drawable.icon_pencil,R.drawable.icon_selected };private boolean flag = false;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.act_creatediray);initview();initDatas();initviewOper();}private void initviewOper() {adapter = new CreateDirayAdapter(datas, this);// 添加到适配器中save.setOnClickListener(this);}private void initview() {save = (ImageView) findViewById(R.id.item_creatediray_save);tvLocation = (TextView) findViewById(R.id.item_creatediray_tvlocation);}// -------------------------------------------------------@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.item_creatediray_save://保存final Driay driay =new Driay();//地理位置------------------------------------------------------------List<BDLocation> loca = MyAppliction.myAppliction.getLocation();//driay.setLocation(loca.get(0));//这样也可以的。获取是当前有点误差driay.setLocation(loca.get(loca.size()-1));//精确一些driay.save(this, new SaveListener() {@Overridepublic void onSuccess() {List<Driay> list = MyAppliction.myAppliction.getDriay();if (list==null) {list = new ArrayList<Driay>();list.add(0, driay);//添加到数据里。0是数据库里0位置跟地图没有关系MyAppliction.myAppliction.setDriay(list);CreateDirayActivity.this.finish();}else{list.add(0, driay);MyAppliction.myAppliction.setDriay(list);CreateDirayActivity.this.finish();}toast("保存成功");}@Overridepublic void onFailure(int arg0, String arg1) {}});break;}}// ------------------------------------------------------------}

4,xlistview里fragment代码如下。上拉,下拉刷新

package com.xdl.fragment;import java.util.ArrayList;import java.util.List;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.ImageView;import android.widget.TextView;import cn.bmob.v3.BmobQuery;import cn.bmob.v3.BmobUser;import cn.bmob.v3.listener.FindListener;import com.xdl.activity.CreateDirayActivity;import com.xdl.activity.HomeActivity;import com.xdl.adapter.XlistViewBaseAdapter;import com.xdl.base.BaseFragment;import com.xdl.bean.Driay;import com.xdl.bean.User;import com.xdl.bmob.R;import com.xdl.utils.MyAppliction;import com.xdl.xlistview.XListView;import com.xdl.xlistview.XListView.IXListViewListener;public class InterDirayFragment extends BaseFragment implements OnClickListener, IXListViewListener {private HomeActivity act;private XListView xlistview;//数据private ImageView ivDriay;private TextView tvDriay;//private List<Driay> datas;private XlistViewBaseAdapter xvbAdapter;private int count = 0;//记录下拉次数@Overridepublic void onAttach(Activity activity) {act = (HomeActivity) activity;super.onAttach(activity);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// TODO Auto-generated method stubreturn inflater.inflate(R.layout.fragment_interdiray, null);}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {initview();initDatas();initviewOper();super.onActivityCreated(savedInstanceState);}private void initDatas() {datas = MyAppliction.myAppliction.getDriay();xvbAdapter = new XlistViewBaseAdapter(act, datas);//将数据添加进适配器里***************************************}private void initviewOper() {if (datas != null) {xlistview.setVisibility(View.VISIBLE);tvDriay.setVisibility(View.INVISIBLE);xlistview.setAdapter(xvbAdapter);}else{xlistview.setVisibility(View.INVISIBLE);tvDriay.setVisibility(View.VISIBLE);}//如果点击图片+号。或者中间的创建日记提示,需要跳往另外一个Activity中让用户写日记ivDriay.setOnClickListener(this);tvDriay.setOnClickListener(this);//xlistview的监听方法,实现上拉刷新xlistview.setXListViewListener(this);//开启xlistview的下拉刷新xlistview.setPullLoadEnable(true);}private void initview() {ivDriay = (ImageView) findviewById(R.id.fragment_interdiray_addicon);tvDriay = (TextView) findviewById(R.id.fragment_interdiray_text);xlistview = (XListView) findviewById(R.id.fragment_interdiray_xlistview);}@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();}// --------------------------------------------------------------------------@Overridepublic void onClick(View v) {switch (v.getId()) {//因为都是跳往的同一个所以我们可以省略breakcase R.id.fragment_interdiray_addicon:case R.id.fragment_interdiray_text:startActivity(new Intent(act,CreateDirayActivity.class));break;}}//-----------------------------------------------------------------------//********************************************************************/** * 上拉刷新,要重新从服务器获取数据。并且显示 */@Overridepublic void onRefresh() {BmobQuery<Driay> query = new BmobQuery<Driay>();//重新请求数据//query.addWhereEqualTo("Driay", BmobUser.getCurrentUser(act, User.class).getUsername());query.setLimit(10);query.order("-createdAt");query.findObjects(act, new FindListener<Driay>() {@Overridepublic void onSuccess(List<Driay> arg0) {//重新将数据填充到适配器xvbAdapter = new XlistViewBaseAdapter(act, arg0);//这里的arg0是新查的数据xlistview.setAdapter(xvbAdapter);toast(act, "更新完毕");//关闭刷新xlistview.stopRefresh();}@Overridepublic void onError(int arg0, String arg1) {}});}/** * 加载更多要从服务器获取数据,显示,需要注意的是每次查询的数据条数记录。得保持在用户上一次查询到的记录处。 * 实现方法,需要先开启xlisview的下拉刷新 * 1.在全局定义一个变量记录用户下拉的次数 * 2.分页查询条件为setlimet(10+5*count);//基础显示为10条,加上每次加载5条数据 * 3.需要注意的是我们下拉加载更多后需要更新数据的长度,这次添加长度不能用适配器显示, * 因为用适配器显示的话,会重新加载,用户又得从第一条数据开始看。解决办法,在适配器里定义一个 * 方法传入参数List集合。用里面的数据集合加上传入的 * 4.我们这里更新了数据,但是需要通知一下全局的数据发生了变化所以要通知Appliction。方法set它的集合即可。 * 5.当数据发生变化时,我们需要更新数据的长度,有一个方法叫notifyDataSetChanged() * 6.当加载完数据,要关闭下拉刷新 */@Overridepublic void onLoadMore() {count++;BmobQuery<Driay> query = new BmobQuery<Driay>();query.setLimit(10+5*count);//每次查询5条query.order("-createdAt");//倒叙query.findObjects(act, new FindListener<Driay>() {@Overridepublic void onSuccess(List<Driay> arg0) {//显示数据要添加到adapter显示,不能用setadapter重新设置xvbAdapter.butoomUdapter(arg0);//通知全局数据发生变化MyAppliction.myAppliction.setDriay(arg0);//更新适配器长度xvbAdapter.notifyDataSetChanged();//关闭xlistview.stopLoadMore();}@Overridepublic void onError(int arg0, String arg1) {// TODO Auto-generated method stub}});}//*********************************************************************}

5,BasAdapter适配器里

package com.xdl.adapter;import java.util.List;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import com.baidu.location.BDLocation;import com.baidu.location.LocationClientOption.LocationMode;import com.baidu.mapapi.model.LatLng;import com.baidu.mapapi.utils.DistanceUtil;import com.xdl.activity.HomeActivity;import com.xdl.activity.SplashActivity;import com.xdl.bean.Driay;import com.xdl.bmob.R;import com.xdl.utils.MyAppliction;public class XlistViewBaseAdapter extends BaseAdapter {/** * 1,数据 * 2,适配器 */private HomeActivity act;private List<Driay> datas;public XlistViewBaseAdapter(HomeActivity act, List<Driay> datas) {super();this.act = act;this.datas = datas;}@Overridepublic int getCount() {//if (datas.size()==0) //可以删除//return 0;//elsereturn datas.size();}@Overridepublic Object getItem(int position) {// TODO Auto-generated method stubreturn datas.get(position);}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {if (convertView == null) {convertView = act.getLayoutInflater().inflate(R.layout.item_xlistview, null);}TextView location = (TextView) ViewHolder.get(convertView,R.id.item_xlistview_location);weather.setText(datas.get(position).getWeather());//获取位置显示。先判断位置不为空的情况下在显示if (datas.get(position).getLocation()!=null ) {location.setText(obtainLocation(position));//自定义方法求位置}return convertView;}//获取地理位置。方法公共//地理位置相差多少米,应该有起始位置和终点位置public CharSequence obtainLocation(int position) {//当前位置BDLocation dangQianLocation = MyAppliction.myAppliction.getLocation().get(MyAppliction.myAppliction.getLocation().size()-1);Log.i("zzz", "当前的经度:"+dangQianLocation.getLatitude());//发表信息的位置BDLocation faBiaoLocation = datas.get(position).getLocation();Log.i("zzz", "发表信息的经度:"+faBiaoLocation.getLatitude());//当前经度和纬度转换成位置LatLng la_end = new LatLng(dangQianLocation.getLatitude(), dangQianLocation.getLongitude());//发表信息的经度和纬度转换成位置LatLng la_start = new LatLng(faBiaoLocation.getLatitude(), faBiaoLocation.getLongitude());//求出位置相差多少米int distanse = (int) DistanceUtil.getDistance(la_start, la_end);//转换成公里if (distanse < 1000) {return distanse+"米"; //距离误差大小为500米以内}else{return (distanse+500)%1000+"公里";}}//这里是下拉刷新更新数据的方法public void butoomUdapter(List<Driay> lists){//datas.addAll(lists);//这样添加是错误。添加的是所有的数据datas = lists;}}
javaBean

package com.xdl.bean;import com.baidu.location.BDLocation;import cn.bmob.v3.BmobObject;/** * 这是查询的时候所用的 * @author Administrator * */public class Driay extends BmobObject{private  BDLocation location;//网络日记发表的经纬度,在有了地图后在调用private String installionid;public int getId() {return id;}public void setId(int id) {this.id = id;}public BDLocation getLocation() {return location;}public void setLocation(BDLocation location) {this.location = location;}@Overridepublic String toString() {return "Driay [id=" + id + ", fromusername=" + fromusername + ", text="+ text + ", color=" + color + ", weather=" + weather+ ", weather_img=" + weather_img + ", tcolor=" + tcolor+ ", location=" + location + ", installionid=" + installionid+ "]";}}
















0 0