Android进阶笔记03:Android应用中实现查看"附近的人"的功能
1. 要实现" 附近的人" 这功能,然后就研究了下:
(1)首先要做的就是要获取到自己当前位置的经纬度(编程获取手机GPS定位模块的信息,进而获取自己当前位置的经纬度)
(2)然后就是上传自己的数据给服务器
(3)服务器经过计算然后把符合项目定义的最大距离的附近的人的数据传到前台
(4)前台通过数据来展示
其中最主要的其实就是经纬度的距离的计算:
源码下载地址: https://github.com/feicien/studydemo
手机端项目:NearByDemo
服务器端项目:NearbyServerDemo
2. 手机端代码讲解:
MainActivity是项目的入口Activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
boolean first = getSharedPreferences( "userinfo", Context.MODE_PRIVATE ).getBoolean( "first", false);
if (!first) {
Intent intent = new Intent( this, LoginActivity.class );
startActivity(intent);
}
....
}
(1) 查看附近的人,是需要使用用户信息的,因此在OnCreate方法中先判断用户是不是第一次打开应用,如果是第一次打开应用,跳转到LoginActivity,进行用户信息登记,之后便进入MainActivity。
(2)点击ActionBar上的附近的人,便会显示从服务器获取到的用户信息(目前服务器是把所有用户信息全部返回)
(3)请求网络使用的是Google在IO大会上才推出的Volley.
服务器端是使用Java web编写的。在这里不详细介绍了。计算距离的逻辑是从Android的提供的接口(Location.distanceBetween)中拔来的,应该是最精确的方法了:
下面这个是很精确的方法:
public static double computeDistance(double lat1, double lon1,
double lat2, double lon2) {
// Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
// using the "Inverse Formula" (section 4)
int MAXITERS = 20;
// Convert lat/long to radians
lat1 *= Math.PI / 180.0;
lat2 *= Math.PI / 180.0;
lon1 *= Math.PI / 180.0;
lon2 *= Math.PI / 180.0;
double a = 6378137.0; // WGS84 major axis
double b = 6356752.3142; // WGS84 semi-major axis
double f = (a - b) / a;
double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
double L = lon2 - lon1;
double A = 0.0;
double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
double cosU1 = Math.cos(U1);
double cosU2 = Math.cos(U2);
double sinU1 = Math.sin(U1);
double sinU2 = Math.sin(U2);
double cosU1cosU2 = cosU1 * cosU2;
double sinU1sinU2 = sinU1 * sinU2;
double sigma = 0.0;
double deltaSigma = 0.0;
double cosSqAlpha = 0.0;
double cos2SM = 0.0;
double cosSigma = 0.0;
double sinSigma = 0.0;
double cosLambda = 0.0;
double sinLambda = 0.0;
double lambda = L; // initial guess
for (int iter = 0; iter <</span> MAXITERS; iter++) {
double lambdaOrig = lambda;
cosLambda = Math.cos(lambda);
sinLambda = Math.sin(lambda);
double t1 = cosU2 * sinLambda;
double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
double sinSqSigma = t1 * t1 + t2 * t2; // (14)
sinSigma = Math.sqrt(sinSqSigma);
cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
sigma = Math.atan2(sinSigma, cosSigma); // (16)
double sinAlpha = (sinSigma == 0) ? 0.0 :
cosU1cosU2 * sinLambda / sinSigma; // (17)
cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
cos2SM = (cosSqAlpha == 0) ? 0.0 :
cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
A = 1 + (uSquared / 16384.0) * // (3)
(4096.0 + uSquared *
(-768 + uSquared * (320.0 - 175.0 * uSquared)));
double B = (uSquared / 1024.0) * // (4)
(256.0 + uSquared *
(-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
double C = (f / 16.0) *
cosSqAlpha *
(4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
double cos2SMSq = cos2SM * cos2SM;
deltaSigma = B * sinSigma * // (6)
(cos2SM + (B / 4.0) *
(cosSigma * (-1.0 + 2.0 * cos2SMSq) -
(B / 6.0) * cos2SM *
(-3.0 + 4.0 * sinSigma * sinSigma) *
(-3.0 + 4.0 * cos2SMSq)));
lambda = L +
(1.0 - C) * f * sinAlpha *
(sigma + C * sinSigma *
(cos2SM + C * cosSigma *
(-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
double delta = (lambda - lambdaOrig) / lambda;
if (Math.abs(delta) <</span> 1.0e-12) {
break;
}
}
return b * A * (sigma - deltaSigma);
}
还有一个简单方法,比上面精确度要差,如下:
public static double getDistance(double lat1,double longt1 , double lat2,double longt2) {
double PI = 3.14159265358979323; // 圆周率
double R = 6371229; // 地球的半径
double x, y, distance;
x = (longt2 - longt1) * PI * R * Math.cos(((lat1 + lat2) / 2) * PI / 180) / 180;
y = (lat2 - lat1) * PI * R / 180;
distance = Math.hypot(x, y);
return distance;
}
这里是把地球当成圆球来处理的:
System.out.println(getDistance(34.8082342, 113.6125439, 34.8002478, 113.659779));
System.out.println(computeDistance(34.8082342, 113.6125439, 34.8002478, 113.659779)); 4403.3428631300785
4412.121706417052
经过测试,对于4千米的2点,相差为10米左右,误差是可以接受的,因此推荐使用该方法。
3. 具体实例查看网友:
http://blog.csdn.net/lyhhj/article/details/49893723
Android进阶笔记03:Android应用中实现查看"附近的人"的功能的更多相关文章
- Android进阶笔记:Messenger源码详解
Messenger可以理解为一个是用于发送消息的一个类用法也很多,这里主要分析一下再跨进程的情况下Messenger的实现流程与源码分析.相信结合前面两篇关于aidl解析文章能够更好的对aidl有一个 ...
- Android进阶笔记:AIDL内部实现详解 (二)
接着上一篇分析的aidl的流程解析.知道了aidl主要就是利用Ibinder来实现跨进程通信的.既然是通过对Binder各种方法的封装,那也可以不使用aidl自己通过Binder来实现跨进程通讯.那么 ...
- 我的Android进阶之旅------>Android中查看应用签名信息
一.查看自己的证书签名信息 如上一篇文章<我的Android进阶之旅------>Android中制作和查看自定义的Debug版本Android签名证书>地址:http://blog ...
- 我的Android进阶之旅------> Android为TextView组件中显示的文本添加背景色
通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article ...
- 我的Android进阶之旅------> Android在TextView中显示图片方法
面试题:请说出Android SDK支持哪些方式显示富文本信息(不同颜色.大小.并包含图像的文本信息),并简要说明实现方法. 答案:Android SDK支持如下显示富文本信息的方式. 1.使用Tex ...
- 我的Android进阶之旅------>Android中AsyncTask源码分析
在我的<我的Android进阶之旅------>android异步加载图片显示,并且对图片进行缓存实例>文章中,先后使用了Handler和AsyncTask两种方式实现异步任务机制. ...
- 我的Android进阶之旅------> Android为TextView组件中显示的文本加入背景色
通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article ...
- 我的Android进阶之旅------>Android颜色值(#AARRGGBB)透明度百分比和十六进制对应关系以及计算方法
我的Android进阶之旅-->Android颜色值(RGB)所支持的四种常见形式 透明度百分比和十六进制对应关系表格 透明度 十六进制 100% FF 99% FC 98% FA 97% F7 ...
- 我的Android进阶之旅------>Android利用温度传感器实现带动画效果的电子温度计
要想实现带动画效果的电子温度计,需要以下几个知识点: 1.温度传感器相关知识. 2.ScaleAnimation动画相关知识,来进行水印刻度的缩放效果. 3.android:layout_weight ...
随机推荐
- 教你把UIView切成任意形状
有时候layer.cornerRadius并不能满足需求,自己实现drawRect又太麻烦,怎么办? 多的不说,直接上代码: - (void)dwMakeBottomRoundCornerWithRa ...
- 在线CSS圆角生成器
http://www.paibaidu.com/demo/CSSBorder/CSSBorder.html
- Hibernate中对象的三种状态以及Session类中saveOrUpdate方法与merge方法的区别
首先,用一张图说明一个对象,在Hibernate中,在调用了不同方法之后对象所处的不同状态 在Hibernate中,一个对象的状态可以被分为如图所示的三种 Transient:瞬时对象,该对象在数据库 ...
- SpringMVC+Json构建基于Restful风格的应用(转)
一.spring 版本:spring-framework-3.2.7.RELEASE 二.所需其它Jar包: 三.主要代码: web.xml <?xml version="1.0&qu ...
- 执行计划之CONCATENATION
CREATE TABLE T_CONCAT (ID NUMBER, NAME VARCHAR2(30), TYPE VARCHAR2(30)); INSERT INTO T_CONCAT SELECT ...
- 利用row_number over 函数删除重复记录
开窗函数 Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行 SQ ...
- 挖坑#3-----DP优化+CDQ分治+期望DP
1492: [NOI2007]货币兑换Cash 1176: [Balkan2007]Mokia 1452: [JSOI2009]Count 1563: [NOI2009]诗人小G tyvj1309 ...
- 查看Mysql执行计划
使用navicat查看mysql执行计划: 打开profile分析工具: 查看是否生效:show variable like ‘%profil%’; 查看进程:show processlist; 选择 ...
- Linux Shell编程(17)——嵌套循环
嵌套循环就是在一个循环中还有一个循环,内部循环在外部循环体中.在外部循环的每次执行过程中都会触发内部循环,直到内部循环执行结束.外部循环执行了多少次,内部循环就完成多少次.当然,不论是外部循环或内部循 ...
- 什么是系统,什么是算法 -- lemon OA 系统学习总结
一.对于模块划分的理解 对于一个大型(这里还只是一个中型系统)系统来说,代码的编写不是一日而就的,层次的明细也不是一眼就能看清楚的. 在这种情况下,需要想好,最好是由上而下地想好. 能够模块式地划分最 ...