Android方位指向功能的实现

实现功能:
根据当前位置和目的位置的经纬度,将方向指针指向目的地。

如图:

使用到的技术点主要有指北针,定位,方位角计算。

1.指北针

Android方向感应器取的数组中第0项即为方向(值得范围是 0 ~ 359 其中0=North, 90=East, 180=South, 270=West)

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
//注册方向感应器
mSensorManager.registerListener(mListener, mSensor,
SensorManager.SENSOR_DELAY_GAME);
//方向感应传感器监听事件,取到第0项方向值,并传递给自定义View展示
private final SensorEventListener mListener = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {
mValues = event.values;
if (mView != null) {
mView.setValues(mValues);
mView.invalidate();
}
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};

2.定位

采用基站定位,速度快,缺点是必须移动网络可用

取得基站信息

private JSONObject doApn() throws Exception {
JSONObject holder = new JSONObject();
holder.put("version", "1.1.0");
holder.put("host", "maps.google.com");
holder.put("address_language", "zh_CN");
holder.put("request_address", true);

TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
GsmCellLocation gcl = (GsmCellLocation) tm.getCellLocation();
int cid = gcl.getCid();
int lac = gcl.getLac();
int mcc = Integer.valueOf(tm.getNetworkOperator().substring(0,
3));
int mnc = Integer.valueOf(tm.getNetworkOperator().substring(3,
5));

JSONArray array = new JSONArray();
JSONObject data = new JSONObject();
data.put("cell_id", cid);
data.put("location_area_code", lac);
data.put("mobile_country_code", mcc);
data.put("mobile_network_code", mnc);
array.put(data);
holder.put("cell_towers", array);

return holder;
}

提交基站信息到google的服务器,获取经纬度数据

public HttpResponse execute(JSONObject params) throws Exception {
HttpClient httpClient = new DefaultHttpClient();

HttpConnectionParams.setConnectionTimeout(httpClient.getParams(),
20 * 1000);
HttpConnectionParams.setSoTimeout(httpClient.getParams(), 20 * 1000);

HttpPost post = new HttpPost("http://74.125.71.147/loc/json");
// 设置代理
if (postType == DO_APN) {
// 获取当前正在使用的APN接入点
Uri uri = Uri.parse("content://telephony/carriers/preferapn");
Cursor mCursor = context.getContentResolver().query(uri, null,
null, null, null);
if (mCursor != null) {
if(mCursor.moveToFirst()) {
String proxyStr = mCursor.getString(mCursor
.getColumnIndex("proxy"));
if (proxyStr != null && proxyStr.trim().length() > 0) {
HttpHost proxy = new HttpHost(proxyStr, 80);
httpClient.getParams().setParameter(
ConnRouteParams.DEFAULT_PROXY, proxy);
}
}
}
}

StringEntity se = new StringEntity(params.toString());
post.setEntity(se);
HttpResponse response = httpClient.execute(post);
return response;
}

3.方位角的计算

根据两点的经纬度计算方位角

// 计算方位角,正北向为0度,以顺时针方向递增
private double computeAzimuth(double lat1, double lon1, double lat2,
double lon2) {
double result = 0.0;

int ilat1 = (int) (0.50 + lat1 * 360000.0);
int ilat2 = (int) (0.50 + lat2 * 360000.0);
int ilon1 = (int) (0.50 + lon1 * 360000.0);
int ilon2 = (int) (0.50 + lon2 * 360000.0);

lat1 = Math.toRadians(lat1);
lon1 = Math.toRadians(lon1);
lat2 = Math.toRadians(lat2);
lon2 = Math.toRadians(lon2);

if ((ilat1 == ilat2) && (ilon1 == ilon2)) {
return result;
} else if (ilon1 == ilon2) {
if (ilat1 > ilat2)
result = 180.0;
} else {
double c = Math
.acos(Math.sin(lat2) * Math.sin(lat1) + Math.cos(lat2)
* Math.cos(lat1) * Math.cos((lon2 - lon1)));
double A = Math.asin(Math.cos(lat2) * Math.sin((lon2 - lon1))
/ Math.sin(c));
result = Math.toDegrees(A);
if ((ilat2 > ilat1) && (ilon2 > ilon1)) {
} else if ((ilat2 < ilat1) && (ilon2 < ilon1)) {
result = 180.0 - result;
} else if ((ilat2 < ilat1) && (ilon2 > ilon1)) {
result = 180.0 - result;
} else if ((ilat2 > ilat1) && (ilon2 < ilon1)) {
result += 360.0;
}
}
return result;
}

方位角计算的公式参考此文:http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115

4.画方向指针和旋转

代码直接拷贝自API DEMO,在旋转方位做了一点修改

构建方向指针

public SampleView(Context context) {
super(context);
mPath.moveTo(0, -25);
mPath.lineTo(-10, 30);
mPath.lineTo(0, 25);
mPath.lineTo(10, 30);
mPath.close();
}

旋转canvas,并画方向指针

protected void onDraw(Canvas canvas) {
Paint paint = mPaint;

canvas.drawColor(Color.WHITE);

paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);

canvas.translate(getWidth() / 2, getHeight() / 2);
if (mValues != null) {
canvas.rotate(-mValues[0] + (float) directionAngle);
}
canvas.drawPath(mPath, mPaint);

}

项目下载:方位指向

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>