Android进阶笔记03:Android应用中实现查看“附近的人”的功能

1. 要实现" 附近的人" 这功能,然后就研究了下:

(1)首先要做的就是要获取到自己当前位置的经纬度

(2)然后就是上传自己的数据给服务器

(3)服务器经过计算然后把符合项目定义的最大距离的附近的人的数据传到前台

(4)前台通过数据来展示

其中最主要的其实就是经纬度的距离的计算:

源码下载地址: https://github.com/feicien/studydemo
手机端项目:NearByDemo
服务器端项目:NearbyServerDemo

2. 手机端代码讲解:
MainActivity是项目的入口Activity:

1 @Override
2 protected void onCreate(Bundle savedInstanceState) {
3       boolean first = getSharedPreferences( "userinfo", Context.MODE_PRIVATE ).getBoolean( "first", false);
4       if (!first) {
5                 Intent intent = new Intent( this, LoginActivity.class );
6                 startActivity(intent);
7       }
8           ....
9      }

(1) 查看附近的人,是需要使用用户信息的,因此在OnCreate方法中先判断用户是不是第一次打开应用,如果是第一次打开应用,跳转到LoginActivity,进行用户信息登记,之后便进入MainActivity。

(2)点击ActionBar上的附近的人,便会显示从服务器获取到的用户信息(目前服务器是把所有用户信息全部返回)

(3)请求网络使用的是Google在IO大会上才推出的Volley.

服务器端是使用Java web编写的。在这里不详细介绍了。计算距离的逻辑是从Android的提供的接口(Location.distanceBetween)中拔来的,应该是最精确的方法了:

下面这个是很精确的方法:

 1 public static double computeDistance(double lat1, double lon1,
 2   double lat2, double lon2) {
 3   // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
 4   // using the "Inverse Formula" (section 4)
 5   int MAXITERS = 20;
 6   // Convert lat/long to radians
 7   lat1 *= Math.PI / 180.0;
 8   lat2 *= Math.PI / 180.0;
 9   lon1 *= Math.PI / 180.0;
10   lon2 *= Math.PI / 180.0;
11   double a = 6378137.0; // WGS84 major axis
12   double b = 6356752.3142; // WGS84 semi-major axis
13   double f = (a - b) / a;
14   double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
15   double L = lon2 - lon1;
16   double A = 0.0;
17   double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
18   double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
19   double cosU1 = Math.cos(U1);
20   double cosU2 = Math.cos(U2);
21   double sinU1 = Math.sin(U1);
22   double sinU2 = Math.sin(U2);
23   double cosU1cosU2 = cosU1 * cosU2;
24   double sinU1sinU2 = sinU1 * sinU2;
25   double sigma = 0.0;
26   double deltaSigma = 0.0;
27   double cosSqAlpha = 0.0;
28   double cos2SM = 0.0;
29   double cosSigma = 0.0;
30   double sinSigma = 0.0;
31   double cosLambda = 0.0;
32   double sinLambda = 0.0;
33   double lambda = L; // initial guess
34   for (int iter = 0; iter <</span> MAXITERS; iter++) {
35       double lambdaOrig = lambda;
36       cosLambda = Math.cos(lambda);
37       sinLambda = Math.sin(lambda);
38       double t1 = cosU2 * sinLambda;
39       double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
40       double sinSqSigma = t1 * t1 + t2 * t2; // (14)
41       sinSigma = Math.sqrt(sinSqSigma);
42       cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
43       sigma = Math.atan2(sinSigma, cosSigma); // (16)
44       double sinAlpha = (sinSigma == 0) ? 0.0 :
45           cosU1cosU2 * sinLambda / sinSigma; // (17)
46       cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
47       cos2SM = (cosSqAlpha == 0) ? 0.0 :
48           cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
49       double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
50       A = 1 + (uSquared / 16384.0) * // (3)
51           (4096.0 + uSquared *
52            (-768 + uSquared * (320.0 - 175.0 * uSquared)));
53       double B = (uSquared / 1024.0) * // (4)
54           (256.0 + uSquared *
55            (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
56       double C = (f / 16.0) *
57           cosSqAlpha *
58           (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
59       double cos2SMSq = cos2SM * cos2SM;
60       deltaSigma = B * sinSigma * // (6)
61           (cos2SM + (B / 4.0) *
62            (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
63             (B / 6.0) * cos2SM *
64             (-3.0 + 4.0 * sinSigma * sinSigma) *
65             (-3.0 + 4.0 * cos2SMSq)));
66       lambda = L +
67           (1.0 - C) * f * sinAlpha *
68           (sigma + C * sinSigma *
69            (cos2SM + C * cosSigma *
70             (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
71       double delta = (lambda - lambdaOrig) / lambda;
72       if (Math.abs(delta) <</span> 1.0e-12) {
73           break;
74       }
75   }
76   return  b * A * (sigma - deltaSigma);
77 }

还有一个简单方法,比上面精确度要差,如下:

1 public static double getDistance(double lat1,double longt1 , double lat2,double longt2) {
2                   double PI = 3.14159265358979323; // 圆周率
3                   double R = 6371229; // 地球的半径
4                   double x, y, distance;
5                   x = (longt2 - longt1) * PI * R * Math.cos(((lat1 + lat2) / 2) * PI / 180) / 180;
6                   y = (lat2 - lat1) * PI * R / 180;
7                   distance = Math.hypot(x, y);
8                   return distance;
9     }
时间: 2024-10-25 14:42:53

Android进阶笔记03:Android应用中实现查看“附近的人”的功能的相关文章

Android学习笔记_78_ Android开发中使用软引用和弱引用防止内存溢出

在<Effective Java 2nd Edition>中,第6条"消除过期的对象引用"提到,虽然Java有 垃圾回收机制,但是只要是自己管理的内存,就应该警惕内存泄露的问题,例如的对象池.缓存中的过期对象都有可能引发内存泄露的问题.书中还提到可以用 WeakHashMap来作为缓存的容器可以有效解决这一问题.之前也确实遇到过类似问题,但是没有接触过"弱引用"相关的问题,于是查阅了一些资料. <Java 理论与实践: 用弱引用堵住内存泄漏>

九、Android学习笔记_ Android开发中使用软引用和弱引用防止内存溢出

在<Effective Java 2nd Edition>中,第6条"消除过期的对象引用"提到,虽然Java有 垃圾回收机制,但是只要是自己管理的内存,就应该警惕内存泄露的问题,例如的对象池.缓存中的过期对象都有可能引发内存泄露的问题.书中还提到可以用 WeakHashMap来作为缓存的容器可以有效解决这一问题.之前也确实遇到过类似问题,但是没有接触过"弱引用"相关的问题,于是查阅了一些资料. <Java 理论与实践: 用弱引用堵住内存泄漏>

我的Android进阶之旅------&gt; Android在TextView中显示图片方法

面试题:请说出Android SDK支持哪些方式显示富文本信息(不同颜色.大小.并包含图像的文本信息),并简要说明实现方法. 答案:Android SDK支持如下显示富文本信息的方式. 1.使用TextView组件可以显示富文本信息.在TextView组件中可以使用富文本标签来显示富文本信息,这种标签类似于HTML标签,但比HTML标签简单,支持有限的几种显示富文本的方式.如<font>标签用于设置字体和颜色,<b>用于设置粗体.包含这些标签的文本不能直接作为TextView.se

我的Android进阶之旅------&gt; Android为TextView组件中显示的文本添加背景色

通过上一篇文章 我的Android进阶之旅------> Android在TextView中显示图片方法 (地址:http://blog.csdn.net/ouyang_peng/article/details/46916963) 我们学会了在TextView中显示图片的方法,现在我们来学习如何为TextView组件中显示的文本添加背景色.要求完成的样子如图所示: 首先来学习使用BackgroundColorSpan对象设置文字背景色,代码如下: TextView textView=(TextV

Android学习笔记之mainfest文件中android属性

Android学习笔记之mainfest文件中android属性 - Impossible is nothing - 博客频道 - CSDN.NET 以前的零散笔记, 共享一下, 有错误的地方还请指正. android:allowTaskReparenting 是否允许activity更换从属的任务,比如从短信息任务 切换到浏览器任务.---------------------------------------------------------------------------------

我的Android进阶之旅------&gt;Android疯狂连连看游戏的实现之实现游戏逻辑(五)

在上一篇<我的Android进阶之旅------>Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)>中提到的两个类: GameConf:负责管理游戏的初始化设置信息. GameService:负责游戏的逻辑实现. 其中GameConf的代码如下:cn\oyp\link\utils\GameConf.java package cn.oyp.link.utils; import android.content.Context; /** * 保存游戏配置的对象

Android学习笔记一 Android的构成

一个Android程序是由多个Activity松散构成通过Intnet对象相互调用每个Activity相对独立. R文件:自动生成,存储着程序集所包含的资源文件. src:包含程序中所有的Activity类文件. 新添加的Activity必须在AndroidManifest.xml中进行注册. values:该文件夹下的元素会在R文件中生成资源ID. Android学习笔记一 Android的构成

我的Android进阶之旅------&gt;Android利用Sensor(传感器)实现水平仪功能的小例

这里介绍的水平仪,指的是比较传统的气泡水平仪,在一个透明圆盘内充满液体,液体中留有一个气泡,当一端翘起时,该气泡就会浮向翘起的一端. 利用方向传感器返回的第一个参数,实现了一个指南针小应用. 我的Android进阶之旅------>Android利用Sensor(传感器)实现指南针功能 (地址:http://blog.csdn.net/ouyang_peng/article/details/8801204) 接下来,我们利用返回的第二.三个参数实现该水平仪.因为第二个参数,反映底部翘起的角度(当

Android学习笔记_79_ Android 使用 搜索框

1.在资源文件夹下创建xml文件夹,并创建一个searchable.xml: <?xml version="1.0" encoding="utf-8"?> <searchable xmlns:android="http://schemas.android.com/apk/res/android" android:label="@string/sms_search" android:hint="@st