標籤:
1. 要實現" 附近的人" 這功能,然後就研究了下:
(1)首先要做的就是要擷取到自己當前位置的經緯度
(2)然後就是上傳自己的資料給伺服器
(3)伺服器經過計算然後把符合項目定義的最大距離的附近的人的資料傳到前台
(4)前台通過資料來展示
其中最主要的其實就是經緯度的距離的計算:
源碼: https://github.com/feicien/studydemo
手機端項目:NearByDemo
伺服器端項目:NearbyServerDemo
2. 手機端代碼講解:
MainActivity是項目的入口Activity:
1 @Override2 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 axis12 double b = 6356752.3142; // WGS84 semi-major axis13 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 guess34 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; // defn50 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 }
Android進階筆記03:Android應用中實現查看“附近的人”的功能