实现功能:
根据当前位置和目的位置的经纬度,将方向指针指向目的地。
如图:
使用到的技术点主要有指北针,定位,方位角计算。
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);
}
项目下载:方位指向
