Gears Android WIFI/基站定位源代码分析
来源:互联网 发布:高仪和科勒哪个好 知乎 编辑:程序博客网 时间:2024/05/16 17:09
文章出处:http://www.limodev.cn/blog
作者联系方式:李先静 <xianjimli at hotmail dot com>
作者联系方式:李先静 <xianjimli at hotmail dot com>
Broncho A1还不支持基站和WIFI定位,Android的老版本里是有NetworkLocationProvider的,它实现了基站和WIFI定位,但从 android 1.5之后就被移除了。本来想在broncho A1里自己实现NetworkLocationProvider的,但一直没有时间去研究。我知道 gears(http://code.google.com/p/gears/)是有提供类似的功能,昨天研究了一下Gears的代码,看能不能移植到 android中来。
1.下载源代码
[url]svn checkout http://gears.googlecode.com/svn/trunk/ gears-read-only[/url]
定位相关的源代码在gears/geolocation目录中。
2.关注android平台中的基站位置变化。
JAVA类AndroidRadioDataProvider是 PhoneStateListener的子类,用来监听Android电话的状态变化。当服务状态、信号强度和基站变化时,就会用下面代码获取小区信息:
然后调用用C代码实现的onUpdateAvailable函数。
2.Native函数onUpdateAvailable是在 radio_data_provider_android.cc里实现的。
声明Native函数
JNI调用好像只能调用静态成员函数,把对象本身用一个参数传进来,然后再调用对象的成员函数。
先判断基站信息有没有变化,如果有变化则通知相关的监听者。
接下来的过程,基站定位和WIFI定位是一样的,后面我们再来介绍。下面我们先看 WIFI定位。
3.关注android平台中的WIFI变化。
JAVA类AndroidWifiDataProvider扩展了 BroadcastReceiver类,它关注WIFI扫描结果:
当收到WIFI扫描结果后,调用Native函数 onUpdateAvailable,并把WIFI的扫描结果传递过去。
4.Native函数onUpdateAvailable是在 wifi_data_provider_android.cc里实现的。
从以上代码可以看出,WIFI定位和基站定位的逻辑差不多,只是前者获取的WIFI的扫描结果,而后者获取的基站信息。后面代码的基本上就统一起来了,接下来我们继续看。
5.把变化(WIFI/基站)通知给相应的监听者。
6.谁在监听变化(WIFI/基站)
NetworkLocationProvider在监听变化(WIFI/基站):
当有变化时,会调用函数DeviceDataUpdateAvailable:
无论是WIFI还是基站变化,最后都会调用 DeviceDataUpdateAvailableImpl:
这里面只是发了一个signal,通知另外一个线程去处理。
7.谁在等待thread_notification_event_
线程函数NetworkLocationProvider::Run在一个循环中等待 thread_notification_event,当有变化(WIFI/基站)时,就准备请求服务器查询位置。
先等待:
准备请求:
再来看MakeRequest的实现:
先从cache中查找位置:
如果找不到,再做实际的请求
7.客户端协议包装
前面的request_是NetworkLocationRequest实例,先看 MakeRequest的实现:
先对参数进行打包:
通知负责收发的线程
8.负责收发的线程
把打包好的数据通过HTTP请求,发送给服务器
解析出位置信息
通知位置信息的监听者。
有人会问,请求是发哪个服务器的?当然是google了,缺省的URL是:
回过头来,我们再总结一下:
1.WIFI和基站定位过程如下:
2.NetworkLocationProvider和 NetworkLocationRequest各有一个线程来异步处理请求。
3.这里的NetworkLocationProvider与android中的 NetworkLocationProvider并不是同一个东西,这里是给gears用的,要在android的google map中使用,还得包装成android中的NetworkLocationProvider的接口。
4.WIFI和基站定位与平台无关,只要你能拿到WIFI扫描结果或基站信息,而且能访问google的定位服务器,不管你是Android平台,Windows Mobile平台还是传统的feature phone,你都可以实现WIFI和基站定位。
附: WIFI和基站定位原理
无论是WIFI的接入点,还是移动网络的基站设备,它们的位置基本上都是固定的。设备端(如手机)可以找到它们的ID,现在的问题就是如何通过这些ID找到对应的位置。网上的流行的说法是开车把所有每个位置都跑一遍,把这些设备的位置与 GPS测试的位置关联起来。
参考资料:
Gears:[url] http://gears.googlecode.com/[/url]
Google 地图 API:[url] http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html[/url]
wifi定位技术:[url] http://blog.csdn.net/NewMap/archive/2009/03/17/3999337.aspx
[/url]
1.下载源代码
[url]svn checkout http://gears.googlecode.com/svn/trunk/ gears-read-only[/url]
定位相关的源代码在gears/geolocation目录中。
2.关注android平台中的基站位置变化。
JAVA类AndroidRadioDataProvider是 PhoneStateListener的子类,用来监听Android电话的状态变化。当服务状态、信号强度和基站变化时,就会用下面代码获取小区信息:
- RadioData radioData = new RadioData();
- GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation;
- // Extract the cell id, LAC, and signal strength.
- radioData.cellId = gsmCellLocation.getCid();
- radioData.locationAreaCode = gsmCellLocation.getLac();
- radioData.signalStrength = signalStrength;
- // Extract the home MCC and home MNC.
- String operator = telephonyManager.getSimOperator();
- radioData.setMobileCodes(operator, true);
- if (serviceState != null) {
- // Extract the carrier name.
- radioData.carrierName = serviceState.getOperatorAlphaLong();
- // Extract the MCC and MNC.
- operator = serviceState.getOperatorNumeric();
- radioData.setMobileCodes(operator, false);
- }
- // Finally get the radio type.
- int type = telephonyManager.getNetworkType();
- if (type == TelephonyManager.NETWORK_TYPE_UMTS) {
- radioData.radioType = RADIO_TYPE_WCDMA;
- } else if (type == TelephonyManager.NETWORK_TYPE_GPRS
- || type == TelephonyManager.NETWORK_TYPE_EDGE) {
- radioData.radioType = RADIO_TYPE_GSM;
- }
RadioData radioData = new RadioData(); GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation; // Extract the cell id, LAC, and signal strength. radioData.cellId = gsmCellLocation.getCid(); radioData.locationAreaCode = gsmCellLocation.getLac(); radioData.signalStrength = signalStrength; // Extract the home MCC and home MNC. String operator = telephonyManager.getSimOperator(); radioData.setMobileCodes(operator, true); if (serviceState != null) { // Extract the carrier name. radioData.carrierName = serviceState.getOperatorAlphaLong(); // Extract the MCC and MNC. operator = serviceState.getOperatorNumeric(); radioData.setMobileCodes(operator, false); } // Finally get the radio type. int type = telephonyManager.getNetworkType(); if (type == TelephonyManager.NETWORK_TYPE_UMTS) { radioData.radioType = RADIO_TYPE_WCDMA; } else if (type == TelephonyManager.NETWORK_TYPE_GPRS || type == TelephonyManager.NETWORK_TYPE_EDGE) { radioData.radioType = RADIO_TYPE_GSM; }
然后调用用C代码实现的onUpdateAvailable函数。
2.Native函数onUpdateAvailable是在 radio_data_provider_android.cc里实现的。
声明Native函数
- JNINativeMethod AndroidRadioDataProvider::native_methods_[] = {
- {"onUpdateAvailable",
- "(L" GEARS_JAVA_PACKAGE "/AndroidRadioDataProvider$RadioData;J)V",
- reinterpret_cast<void*>(AndroidRadioDataProvider::OnUpdateAvailable)
- },
- };
JNINativeMethod AndroidRadioDataProvider::native_methods_[] = { {"onUpdateAvailable", "(L" GEARS_JAVA_PACKAGE "/AndroidRadioDataProvider$RadioData;J)V", reinterpret_cast<void*>(AndroidRadioDataProvider::OnUpdateAvailable) },};
JNI调用好像只能调用静态成员函数,把对象本身用一个参数传进来,然后再调用对象的成员函数。
- void AndroidRadioDataProvider::OnUpdateAvailable(JNIEnv* env,
- jclass cls,
- jobject radio_data,
- jlong self) {
- assert(radio_data);
- assert(self);
- AndroidRadioDataProvider *self_ptr =
- reinterpret_cast<AndroidRadioDataProvider*>(self);
- RadioData new_radio_data;
- if (InitFromJavaRadioData(env, radio_data, &new_radio_data)) {
- self_ptr->NewRadioDataAvailable(&new_radio_data);
- }
- }
void AndroidRadioDataProvider::OnUpdateAvailable(JNIEnv* env, jclass cls, jobject radio_data, jlong self) { assert(radio_data); assert(self); AndroidRadioDataProvider *self_ptr = reinterpret_cast<AndroidRadioDataProvider*>(self); RadioData new_radio_data; if (InitFromJavaRadioData(env, radio_data, &new_radio_data)) { self_ptr->NewRadioDataAvailable(&new_radio_data); }}
先判断基站信息有没有变化,如果有变化则通知相关的监听者。
- void AndroidRadioDataProvider::NewRadioDataAvailable(
- RadioData* new_radio_data) {
- bool is_update_available = false;
- data_mutex_.Lock();
- if (new_radio_data && !radio_data_.Matches(*new_radio_data)) {
- radio_data_ = *new_radio_data;
- is_update_available = true;
- }
- // Avoid holding the mutex locked while notifying observers.
- data_mutex_.Unlock();
- if (is_update_available) {
- NotifyListeners();
- }
- }
void AndroidRadioDataProvider::NewRadioDataAvailable( RadioData* new_radio_data) { bool is_update_available = false; data_mutex_.Lock(); if (new_radio_data && !radio_data_.Matches(*new_radio_data)) { radio_data_ = *new_radio_data; is_update_available = true; } // Avoid holding the mutex locked while notifying observers. data_mutex_.Unlock(); if (is_update_available) { NotifyListeners(); }}
接下来的过程,基站定位和WIFI定位是一样的,后面我们再来介绍。下面我们先看 WIFI定位。
3.关注android平台中的WIFI变化。
JAVA类AndroidWifiDataProvider扩展了 BroadcastReceiver类,它关注WIFI扫描结果:
- IntentFilter filter = new IntentFilter();
- filter.addAction(mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
- mContext.registerReceiver(this, filter, null, handler);
IntentFilter filter = new IntentFilter(); filter.addAction(mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION); mContext.registerReceiver(this, filter, null, handler);
当收到WIFI扫描结果后,调用Native函数 onUpdateAvailable,并把WIFI的扫描结果传递过去。
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(
- mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
- if (Config.LOGV) {
- Log.v(TAG, "Wifi scan resulst available");
- }
- onUpdateAvailable(mWifiManager.getScanResults(), mNativeObject);
- }
- }
public void onReceive(Context context, Intent intent) { if (intent.getAction().equals( mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { if (Config.LOGV) { Log.v(TAG, "Wifi scan resulst available"); } onUpdateAvailable(mWifiManager.getScanResults(), mNativeObject); } }
4.Native函数onUpdateAvailable是在 wifi_data_provider_android.cc里实现的。
- JNINativeMethod AndroidWifiDataProvider::native_methods_[] = {
- {"onUpdateAvailable",
- "(Ljava/util/List;J)V",
- reinterpret_cast<void*>(AndroidWifiDataProvider::OnUpdateAvailable)
- },
- };
- void AndroidWifiDataProvider::OnUpdateAvailable(JNIEnv* /* env */,
- jclass /* cls */,
- jobject wifi_data,
- jlong self) {
- assert(self);
- AndroidWifiDataProvider *self_ptr =
- reinterpret_cast<AndroidWifiDataProvider*>(self);
- WifiData new_wifi_data;
- if (wifi_data) {
- InitFromJava(wifi_data, &new_wifi_data);
- }
- // We notify regardless of whether new_wifi_data is empty
- // or not. The arbitrator will decide what to do with an empty
- // WifiData object.
- self_ptr->NewWifiDataAvailable(&new_wifi_data);
- }
- void AndroidWifiDataProvider::NewWifiDataAvailable(WifiData* new_wifi_data) {
- assert(supported_);
- assert(new_wifi_data);
- bool is_update_available = false;
- data_mutex_.Lock();
- is_update_available = wifi_data_.DiffersSignificantly(*new_wifi_data);
- wifi_data_ = *new_wifi_data;
- // Avoid holding the mutex locked while notifying observers.
- data_mutex_.Unlock();
- if (is_update_available) {
- is_first_scan_complete_ = true;
- NotifyListeners();
- }
- #if USING_CCTESTS
- // This is needed for running the WiFi test on the emulator.
- // See wifi_data_provider_android.h for details.
- if (!first_callback_made_ && wifi_data_.access_point_data.empty()) {
- first_callback_made_ = true;
- NotifyListeners();
- }
- #endif
- }
JNINativeMethod AndroidWifiDataProvider::native_methods_[] = { {"onUpdateAvailable", "(Ljava/util/List;J)V", reinterpret_cast<void*>(AndroidWifiDataProvider::OnUpdateAvailable) },}; void AndroidWifiDataProvider::OnUpdateAvailable(JNIEnv* /* env */, jclass /* cls */, jobject wifi_data, jlong self) { assert(self); AndroidWifiDataProvider *self_ptr = reinterpret_cast<AndroidWifiDataProvider*>(self); WifiData new_wifi_data; if (wifi_data) { InitFromJava(wifi_data, &new_wifi_data); } // We notify regardless of whether new_wifi_data is empty // or not. The arbitrator will decide what to do with an empty // WifiData object. self_ptr->NewWifiDataAvailable(&new_wifi_data);} void AndroidWifiDataProvider::NewWifiDataAvailable(WifiData* new_wifi_data) { assert(supported_); assert(new_wifi_data); bool is_update_available = false; data_mutex_.Lock(); is_update_available = wifi_data_.DiffersSignificantly(*new_wifi_data); wifi_data_ = *new_wifi_data; // Avoid holding the mutex locked while notifying observers. data_mutex_.Unlock(); if (is_update_available) { is_first_scan_complete_ = true; NotifyListeners(); } #if USING_CCTESTS // This is needed for running the WiFi test on the emulator. // See wifi_data_provider_android.h for details. if (!first_callback_made_ && wifi_data_.access_point_data.empty()) { first_callback_made_ = true; NotifyListeners(); }#endif}
从以上代码可以看出,WIFI定位和基站定位的逻辑差不多,只是前者获取的WIFI的扫描结果,而后者获取的基站信息。后面代码的基本上就统一起来了,接下来我们继续看。
5.把变化(WIFI/基站)通知给相应的监听者。
- AndroidWifiDataProvider和AndroidRadioDataProvider都是继承了DeviceDataProviderImplBase,DeviceDataProviderImplBase的主要功能就是管理所有Listeners。
- static DeviceDataProvider *Register(ListenerInterface *listener) {
- MutexLock mutex(&instance_mutex_);
- if (!instance_) {
- instance_ = new DeviceDataProvider();
- }
- assert(instance_);
- instance_->Ref();
- instance_->AddListener(listener);
- return instance_;
- }
- static bool Unregister(ListenerInterface *listener) {
- MutexLock mutex(&instance_mutex_);
- if (!instance_->RemoveListener(listener)) {
- return false;
- }
- if (instance_->Unref()) {
- delete instance_;
- instance_ = NULL;
- }
- return true;
- }
AndroidWifiDataProvider和AndroidRadioDataProvider都是继承了DeviceDataProviderImplBase,DeviceDataProviderImplBase的主要功能就是管理所有Listeners。 static DeviceDataProvider *Register(ListenerInterface *listener) { MutexLock mutex(&instance_mutex_); if (!instance_) { instance_ = new DeviceDataProvider(); } assert(instance_); instance_->Ref(); instance_->AddListener(listener); return instance_; } static bool Unregister(ListenerInterface *listener) { MutexLock mutex(&instance_mutex_); if (!instance_->RemoveListener(listener)) { return false; } if (instance_->Unref()) { delete instance_; instance_ = NULL; } return true; }
6.谁在监听变化(WIFI/基站)
NetworkLocationProvider在监听变化(WIFI/基站):
- radio_data_provider_ = RadioDataProvider::Register(this);
- wifi_data_provider_ = WifiDataProvider::Register(this);
radio_data_provider_ = RadioDataProvider::Register(this); wifi_data_provider_ = WifiDataProvider::Register(this);
当有变化时,会调用函数DeviceDataUpdateAvailable:
- // DeviceDataProviderInterface::ListenerInterface implementation.
- void NetworkLocationProvider::DeviceDataUpdateAvailable(
- RadioDataProvider *provider) {
- MutexLock lock(&data_mutex_);
- assert(provider == radio_data_provider_);
- is_radio_data_complete_ = radio_data_provider_->GetData(&radio_data_);
- DeviceDataUpdateAvailableImpl();
- }
- void NetworkLocationProvider::DeviceDataUpdateAvailable(
- WifiDataProvider *provider) {
- assert(provider == wifi_data_provider_);
- MutexLock lock(&data_mutex_);
- is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_);
- DeviceDataUpdateAvailableImpl();
- }
// DeviceDataProviderInterface::ListenerInterface implementation.void NetworkLocationProvider::DeviceDataUpdateAvailable( RadioDataProvider *provider) { MutexLock lock(&data_mutex_); assert(provider == radio_data_provider_); is_radio_data_complete_ = radio_data_provider_->GetData(&radio_data_); DeviceDataUpdateAvailableImpl();} void NetworkLocationProvider::DeviceDataUpdateAvailable( WifiDataProvider *provider) { assert(provider == wifi_data_provider_); MutexLock lock(&data_mutex_); is_wifi_data_complete_ = wifi_data_provider_->GetData(&wifi_data_); DeviceDataUpdateAvailableImpl();}
无论是WIFI还是基站变化,最后都会调用 DeviceDataUpdateAvailableImpl:
- void NetworkLocationProvider::DeviceDataUpdateAvailableImpl() {
- timestamp_ = GetCurrentTimeMillis();
- // Signal to the worker thread that new data is available.
- is_new_data_available_ = true;
- thread_notification_event_.Signal();
- }
void NetworkLocationProvider::DeviceDataUpdateAvailableImpl() { timestamp_ = GetCurrentTimeMillis(); // Signal to the worker thread that new data is available. is_new_data_available_ = true; thread_notification_event_.Signal();}
这里面只是发了一个signal,通知另外一个线程去处理。
7.谁在等待thread_notification_event_
线程函数NetworkLocationProvider::Run在一个循环中等待 thread_notification_event,当有变化(WIFI/基站)时,就准备请求服务器查询位置。
先等待:
- if (remaining_time > 0) {
- thread_notification_event_.WaitWithTimeout(
- static_cast<int>(remaining_time));
- } else {
- thread_notification_event_.Wait();
- }
if (remaining_time > 0) { thread_notification_event_.WaitWithTimeout( static_cast<int>(remaining_time)); } else { thread_notification_event_.Wait(); }
准备请求:
- if (make_request) {
- MakeRequest();
- remaining_time = 1;
- }
if (make_request) { MakeRequest(); remaining_time = 1; }
再来看MakeRequest的实现:
先从cache中查找位置:
- const Position *cached_position =
- position_cache_->FindPosition(radio_data_, wifi_data_);
- data_mutex_.Unlock();
- if (cached_position) {
- assert(cached_position->IsGoodFix());
- // Record the position and update its timestamp.
- position_mutex_.Lock();
- position_ = *cached_position;
- position_.timestamp = timestamp_;
- position_mutex_.Unlock();
- // Let listeners know that we now have a position available.
- UpdateListeners();
- return true;
- }
const Position *cached_position = position_cache_->FindPosition(radio_data_, wifi_data_); data_mutex_.Unlock(); if (cached_position) { assert(cached_position->IsGoodFix()); // Record the position and update its timestamp. position_mutex_.Lock(); position_ = *cached_position; position_.timestamp = timestamp_; position_mutex_.Unlock(); // Let listeners know that we now have a position available. UpdateListeners(); return true; }
如果找不到,再做实际的请求
- return request_->MakeRequest(access_token,
- radio_data_,
- wifi_data_,
- request_address_,
- address_language_,
- kBadLatLng, // We don't have a position to pass
- kBadLatLng, // to the server.
- timestamp_);
return request_->MakeRequest(access_token, radio_data_, wifi_data_, request_address_, address_language_, kBadLatLng, // We don't have a position to pass kBadLatLng, // to the server. timestamp_);
7.客户端协议包装
前面的request_是NetworkLocationRequest实例,先看 MakeRequest的实现:
先对参数进行打包:
- if (!FormRequestBody(host_name_, access_token, radio_data, wifi_data,
- request_address, address_language, latitude, longitude,
- is_reverse_geocode_, &post_body_)) {
- return false;
- }
if (!FormRequestBody(host_name_, access_token, radio_data, wifi_data, request_address, address_language, latitude, longitude, is_reverse_geocode_, &post_body_)) { return false; }
通知负责收发的线程
- thread_event_.Signal();
thread_event_.Signal();
8.负责收发的线程
- void NetworkLocationRequest::Run() {
- while (true) {
- thread_event_.Wait();
- if (is_shutting_down_) {
- break;
- }
- MakeRequestImpl();
- }
- }
- void NetworkLocationRequest::MakeRequestImpl() {
- WebCacheDB::PayloadInfo payload;
void NetworkLocationRequest::Run() { while (true) { thread_event_.Wait(); if (is_shutting_down_) { break; } MakeRequestImpl(); }} void NetworkLocationRequest::MakeRequestImpl() { WebCacheDB::PayloadInfo payload;
把打包好的数据通过HTTP请求,发送给服务器
- scoped_refptr<BlobInterface> payload_data;
- bool result = HttpPost(url_.c_str(),
- false, // Not capturing, so follow redirects
- NULL, // reason_header_value
- HttpConstants::kMimeApplicationJson, // Content-Type
- NULL, // mod_since_date
- NULL, // required_cookie
- true, // disable_browser_cookies
- post_body_.get(),
- &payload,
- &payload_data,
- NULL, // was_redirected
- NULL, // full_redirect_url
- NULL); // error_message
- MutexLock lock(&is_processing_response_mutex_);
- // is_aborted_ may be true even if HttpPost succeeded.
- if (is_aborted_) {
- LOG(("NetworkLocationRequest::Run() : HttpPost request was cancelled.\n"));
- return;
- }
- if (listener_) {
- Position position;
- std::string response_body;
- if (result) {
- // If HttpPost succeeded, payload_data is guaranteed to be non-NULL.
- assert(payload_data.get());
- if (!payload_data->Length() ||
- !BlobToString(payload_data.get(), &response_body)) {
- LOG(("NetworkLocationRequest::Run() : Failed to get response body.\n"));
- }
- }
scoped_refptr<BlobInterface> payload_data; bool result = HttpPost(url_.c_str(), false, // Not capturing, so follow redirects NULL, // reason_header_value HttpConstants::kMimeApplicationJson, // Content-Type NULL, // mod_since_date NULL, // required_cookie true, // disable_browser_cookies post_body_.get(), &payload, &payload_data, NULL, // was_redirected NULL, // full_redirect_url NULL); // error_message MutexLock lock(&is_processing_response_mutex_); // is_aborted_ may be true even if HttpPost succeeded. if (is_aborted_) { LOG(("NetworkLocationRequest::Run() : HttpPost request was cancelled.\n")); return; } if (listener_) { Position position; std::string response_body; if (result) { // If HttpPost succeeded, payload_data is guaranteed to be non-NULL. assert(payload_data.get()); if (!payload_data->Length() || !BlobToString(payload_data.get(), &response_body)) { LOG(("NetworkLocationRequest::Run() : Failed to get response body.\n")); } }
解析出位置信息
- std::string16 access_token;
- GetLocationFromResponse(result, payload.status_code, response_body,
- timestamp_, url_, is_reverse_geocode_,
- &position, &access_token);
std::string16 access_token; GetLocationFromResponse(result, payload.status_code, response_body, timestamp_, url_, is_reverse_geocode_, &position, &access_token);
通知位置信息的监听者。
- bool server_error =
- !result || (payload.status_code >= 500 && payload.status_code < 600);
- listener_->LocationResponseAvailable(position, server_error, access_token);
- }
- }
bool server_error = !result || (payload.status_code >= 500 && payload.status_code < 600); listener_->LocationResponseAvailable(position, server_error, access_token); }}
有人会问,请求是发哪个服务器的?当然是google了,缺省的URL是:
- static const char16 *kDefaultLocationProviderUrl =
- STRING16(L"https://www.google.com/loc/json");
static const char16 *kDefaultLocationProviderUrl = STRING16(L"https://www.google.com/loc/json");
回过头来,我们再总结一下:
1.WIFI和基站定位过程如下:
2.NetworkLocationProvider和 NetworkLocationRequest各有一个线程来异步处理请求。
3.这里的NetworkLocationProvider与android中的 NetworkLocationProvider并不是同一个东西,这里是给gears用的,要在android的google map中使用,还得包装成android中的NetworkLocationProvider的接口。
4.WIFI和基站定位与平台无关,只要你能拿到WIFI扫描结果或基站信息,而且能访问google的定位服务器,不管你是Android平台,Windows Mobile平台还是传统的feature phone,你都可以实现WIFI和基站定位。
附: WIFI和基站定位原理
无论是WIFI的接入点,还是移动网络的基站设备,它们的位置基本上都是固定的。设备端(如手机)可以找到它们的ID,现在的问题就是如何通过这些ID找到对应的位置。网上的流行的说法是开车把所有每个位置都跑一遍,把这些设备的位置与 GPS测试的位置关联起来。
参考资料:
Gears:[url] http://gears.googlecode.com/[/url]
Google 地图 API:[url] http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html[/url]
wifi定位技术:[url] http://blog.csdn.net/NewMap/archive/2009/03/17/3999337.aspx
[/url]
zhua
- Gears Android WIFI/基站定位源代码分析
- Gears Android WIFI/基站定位源代码分析
- android 基站定位 wifi定位
- Android基站定位源代码
- Android基站定位源代码
- Android 基站定位源代码
- Android 基站定位源代码
- Android基站定位源代码
- Android基站定位源代码
- Android基站定位源代码
- android 使用基站 wifi定位
- android gps wifi 基站定位
- android基站和wifi定位
- android WIFI定位和基站定位实现
- android WIFI定位和基站定位实现
- android gps wifi 基站 定位集合
- android gps ,wifi ,基站定位集合
- Android里实现基站和WIFI定位
- Enterprise Architect 7.5快捷键大全
- SQL Server连接中的四个最常见错误:
- 操纵JsonObject的方法
- linux中强大且常用命令:find、grep
- 高通推新一代芯片平台可简化智能手机开发
- Gears Android WIFI/基站定位源代码分析
- oracle min(date), max(date)
- 基于json-lib.jar包 创建JSONObject的四个常用方法
- SNMP PDU Format总结
- Things you need to remember to become a successful developer
- java实现缩略图、水印
- GIS之家:OGC
- WinMerge比对java文件设置
- 回答问题的智慧