Source code analysis of gears Android WiFi/base station positioning

Source: Internet
Author: User

ArticleSource: http://www.limodev.cn/blog
Contact information of the author: Li xianjing <xianjimli at Hotmail dot com>

Broncho
A1 does not support the location of base stations and WiFi. In the old version of Android, networklocationprovider is available, which enables the location of base stations and WiFi,
Android 1.5 is removed after it is released. I was thinking about
Networklocationprovider is implemented in A1, but there is no time to study it. I know
The gears (http://code.google.com/p/gears/) is having similar functionality that was studied yesterday by GearsCodeTo see if it can be transplanted
Android.

1. DownloadSource code
SVN checkout http://gears.googlecode.com/svn/trunk/ gears-read-only

Find the source code in the gears/geolocation directory.

2. Pay attention to the location changes of base stations on the Android platform.

The Java class androidradiodataprovider is a subclass of phonestatelistener that monitors the status changes of Android phones. When the service status, signal strength, and base station changes, the following code is used to obtain the community information:

Radiodata = new radiodata ();
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;
}

Then, call the onupdateavailable function implemented in C code.

2. The native function onupdateavailable is implemented in radio_data_provider_android.cc.

Declare native functions

Jninativemethod androidradiodataprovider: native_methods _ [] = {
{"Onupdateavailable ",
"(L" gears_java_package "/androidradiodataprovider $ radiodata; j) V ",
Reinterpret_cast <void *> (androidradiodataprovider: onupdateavailable)
},
};

The JNI call seems to be able to only call static member functions. The object itself is passed in with a parameter, and then the object's member functions are called.

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 );
}
}

First, determine whether the information of the base station has changed. If the information of the base station has changed, notify the relevant listener.

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 deleting Ying observers.
Data_mutex _. Unlock ();

If (is_update_available ){
Policylisteners ();
}
}

In the following process, the positioning of the base station is the same as that of the Wi-Fi system. We will introduce it later. Next we will first look at the WiFi positioning.

3. Pay attention to the Wi-Fi changes on the Android platform.

The Java class androidwifidataprovider extends the broadcastreceiver class, which follows the WiFi scan results:

Intentfilter filter = new intentfilter ();
Filter. addaction (mwifimanager. scan_results_available_action );
Mcontext. registerreceiver (this, filter, null, Handler );

After receiving the Wi-Fi scan result, call the native function onupdateavailable and pass the Wi-Fi scan result.

Public void onreceive (context, 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. The native function onupdateavailable is implemented in 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 recommend y 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 deleting Ying observers.
Data_mutex _. Unlock ();

If (is_update_available ){
Is_first_scan_complete _ = true;
Policylisteners ();
}

# 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;
Policylisteners ();
}
# Endif
}

From the code above, we can see that the logic of wifi positioning is similar to that of base station positioning, but only the scanning result of wifi obtained by the former and the information of the base station obtained by the latter. The subsequent code is basically unified, and we will continue to look at it.

5. Notify the listener of the changes (WiFi/base station.

Both androidwifidataprovider and androidradiodataprovider inherit from devicedataproviderimplbase. The main function of devicedataproviderimplbase is to manage all 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. who is listening for changes (WiFi/Base Station)

Networklocationprovider is listening for changes (WiFi/base station ):

Radio_data_provider _ = radiodataprovider: Register (this );
Wifi_data_provider _ = wifidataprovider: Register (this );

When there is a change, the devicedataupdateavailable function is called:

// 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 ();
}

Devicedataupdateavailableimpl will be called at last, regardless of the Wi-Fi or base station changes:

Void networklocationprovider: devicedataupdateavailableimpl (){
Timestamp _ = getcurrenttimemillis ();

// Signal to the worker thread that new data is available.
Is_new_data_available _ = true;
Thread_icationication_event _. Signal ();
}

Here, only a signal is sent to notify another thread to process it.

7. Who is waiting for thread_icationication_event _

The thread function networklocationprovider: Run waits for thread_notification_event in a loop. When there is a change (WiFi/base station), it is ready to request the server to query the location.

Wait first:

If (remaining_time> 0 ){
Thread_icationication_event _. waitwithtimeout (
Static_cast <int> (remaining_time ));
} Else {
Thread_icationication_event _. Wait ();
}

Preparation request:

If (make_request ){
Makerequest ();
Remaining_time = 1;
}

Let's take a look at the implementation of makerequest:

First, find the location from the 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;
}

If not, make the actual request again.

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. Client protocol Packaging

The previous request _ Is A networklocationrequest instance. First, let's look at the implementation of makerequest:

First, package the parameters:

If (! Formrequestbody (host_name _, access_token, radio_data, wifi_data,
Request_address, address_language, latitude, longpolling,
Is_reverse_geocode _, & post_body _)){
Return false;
}

Thread for sending and receiving notifications

Thread_event _. Signal ();

8. threads responsible for sending and receiving

Void networklocationrequest: Run (){
While (true ){
Thread_event _. Wait ();
If (is_shutting_down _){
Break;
}
Makerequestimpl ();
}
}

Void networklocationrequest: makerequestimpl (){
Webcachedb: payloadinfo payload;

Send the packaged data to the server through an HTTP request

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 canceled. \ 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 "));
}
}

Parse Location Information

STD: string16 access_token;
Getlocationfromresponse (result, payload. status_code, response_body,
Timestamp _, URL _, is_reverse_geocode _,
& Position, & access_token );

The listener that notifies the location information.

Bool server_error =
! Result | (payload. status_code> = 500 & payload. status_code <600 );
Listener _-> locationresponseavailable (Position, server_error, access_token );
}
}

Someone may ask, which server is the request sent? The default URL is:

Static const char16 * kdefaloclocationproviderurl =
String16 (L "https://www.google.com/loc/json ");

Let's take a look at the following points:

1. The positioning process of WiFi and base station is as follows:

2. Each of networklocationprovider and networklocationrequest has a thread to process requests asynchronously.

3. The networklocationprovider here is different from the networklocationprovider in Android.
It is used for gears.
The networklocationprovider interface in Android must be packaged for use in map.

4. wi-Fi and base station positioning are irrelevant to the platform. As long as you can get the Wi-Fi scan result or the base station information and access Google's location server, whether you are an Android platform, windows Mobile platform is still a traditional feature phone, you can achieve WiFi and base station positioning.

Appendix: Principles of WiFi and base station positioning

Whether it is a Wi-Fi access point or a mobile network base station device, their locations are basically fixed. Devices (such as mobile phones) can find their IDs. The question is how to find the corresponding location through these IDs. The popular saying on the internet is that driving all the locations and connecting the locations of these devices with the GPS test locations.

reference:
gears: http://gears.googlecode.com/
Google map API: http://code.google.com/intl/zh-CN/apis/maps/documentation/reference.html
WiFi Positioning Technology: http://blog.csdn.net/NewMap/archive/2009/03/17/3999337.aspx

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.