先提示一點,不能使用用模擬器研究Android的基站定位:基站資訊是來自電訊廠商的,模擬器只能類比網路延遲(-netdelay)、網速(-netspeed)、以及一些電話相關的操作,gsm <call|accept|busy|cancel|data|hold|list|voice|status>。還不能類比訊號。
一段基於Rexsee( www.rexsee.com)的基本樣本demo,其中cid 和 lac 為經緯度。
01 function query(){
02 var loction = eval('('+rexseeCellLocation.getLastKnownLocation()+')');
03 var type = location.type.toLowerCase();
04 var mcc = parseInt(location.operator.substring(0,3));
05 var mnc = (type=='gsm')?parseInt(location.operator.substring(3)):location.systemId;
06 var cid= (type=='gsm')?location.cid:location.baseStationId;
07 var lac= (type=='gsm')?location.lac:location.networkId;
08 var postData="{\version\":\"1.1.0\",\"host\":\maps.google.com\",\"access_token\";\"2:k7j3G6LaL6u_lafw:4iXOeOpTh1glSXe\",\"home_mobile_country_code\":"+mcc+",\"home_mobile_network_code\":"+mnc+",\"address_language\";\"zh_CN\",\"radio_type\";\""+type+"\",\"request_address\":true,\"cell_towers\":[{\"cell_id\":+cid+",\"location_area_code\":+lac+",\"mobile_aountry_code\":"+mcc+",\"mobile_network_code\":"+mnc+",\"timing_advance\":5555}]}";
09
10 alert(rexseeAjax.syncSubmit('http://www.google.com/loc/json',postData,'utf-8'));
11 }
返回的結果是:
需要注意幾個問題:
1. 如果直接用alert(rexseeCellLocation.getLastKnownLocation()); 這個方法得到的經緯度會是兩個非常大的數字 所以需要通過ajax提交到"http://www.google.com/loc/json" 把所需要的經緯度返回來;
2. 開始監聽,一旦位置發生變化,會觸發事件onCellLocationChanged。所以,要在 onCellLocationChanged中寫代碼,調用你的query函數。而不是直接使用onclick測試。
Rexsee擴充函數介紹
【函數】 boolean isEnabled()
【說明】 是否正在監聽基站定位的變化。
【返回】 true或false。
【參數】 無
【樣本】
view sourceprint?1 alert(rexseeCellLocation.isEnabled());
【函數】 boolean enable()
【說明】 開始監聽,一旦位置發生變化,會觸發事件onCellLocationChanged。
【返回】 true或false。
【參數】 無
【樣本】
view sourceprint?1 alert(rexseeCellLocation.enable());
【函數】 boolean disable()
【說明】 停止監聽。
【返回】 true或false。
【參數】 無
【樣本】
view sourceprint?1 alert(rexseeCellLocation.disable());
【函數】 JsonObject getLastKnownLocation()
【說明】 讀取基站定位元據,注意,CDMA網路和GSM網路的定位元據格式是不同的。
【返回】 JSON對象,使用eval('('+json+')')轉換為JavaScript對象。
【參數】 無
【樣本】
view sourceprint?1 alert(rexseeCellLocation.getLastKnownLocation());
rexseeCellLocation.java源碼如下:
001 /*
002 * Copyright (C) 2011 The Rexsee Open Source Project
003 *
004 * Licensed under the Rexsee License, Version 1.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.rexsee.com/CN/legal/license.html
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package rexsee.location;
018
019 import rexsee.core.browser.JavascriptInterface;
020 import rexsee.core.browser.RexseeBrowser;
021 import android.content.Context;
022 import android.telephony.CellLocation;
023 import android.telephony.PhoneStateListener;
024 import android.telephony.TelephonyManager;
025 import android.telephony.cdma.CdmaCellLocation;
026 import android.telephony.gsm.GsmCellLocation;
027
028 public class RexseeCellLocation implements JavascriptInterface {
029
030 private static final String INTERFACE_NAME = "CellLocation";
031 @Override
032 public String getInterfaceName() {
033 return mBrowser.application.resources.prefix + INTERFACE_NAME;
034 }
035 @Override
036 public JavascriptInterface getInheritInterface(RexseeBrowser childBrowser) {
037 return this;
038 }
039 @Override
040 public JavascriptInterface getNewInterface(RexseeBrowser childBrowser) {
041 return new RexseeCellLocation(childBrowser);
042 }
043
044 public static final String EVENT_ONCELLLOCATIONCHANGED = "onCellLocationChanged";
045
046 public final Context mContext;
047 private final RexseeBrowser mBrowser;
048 private final int mPhoneType;
049 private PhoneStateListener mListener = null;
050 private CellLocation mLocation = null;
051
052 public RexseeCellLocation(RexseeBrowser browser) {
053 mContext = browser.getContext();
054 mBrowser = browser;
055 browser.eventList.add(EVENT_ONCELLLOCATIONCHANGED);
056 TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
057 mPhoneType = tm.getPhoneType();
058 }
059
060 //JavaScript Interface
061 public boolean isEnabled() {
062 return mListener != null;
063 }
064 public boolean enable() {
065 try {
066 TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
067 mListener = new PhoneStateListener() {
068 @Override
069 public void onCellLocationChanged(CellLocation location) {
070 mLocation = location;
071 mBrowser.eventList.run(EVENT_ONCELLLOCATIONCHANGED);
072 }
073 };
074 tm.listen(mListener, PhoneStateListener.LISTEN_CELL_LOCATION);
075 return true;
076 } catch (Exception e) {
077 mBrowser.exception(getInterfaceName(), e);
078 return false;
079 }
080 }
081 public boolean disable() {
082 if (mListener == null) return true;
083 try {
084 TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
085 tm.listen(mListener, PhoneStateListener.LISTEN_NONE);
086 mListener = null;
087 return true;
088 } catch (Exception e) {
089 mBrowser.exception(getInterfaceName(), e);
090 return false;
091 }
092 }
093 public String getLastKnownLocation() {
094 if (mLocation == null) return "{}";
095 TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
096 String rtn = "";
097 rtn += "\"operator\":\"" + tm.getNetworkOperator() + "\"";
098 rtn += ",\"operatorName\":\"" + tm.getNetworkOperatorName() + "\"";
099 if (mPhoneType == TelephonyManager.PHONE_TYPE_GSM) {
100 GsmCellLocation gsm = (GsmCellLocation) mLocation;
101 rtn += ",\"type\":\"GSM\"";
102 rtn += ",\"cid\":" + gsm.getCid();
103 rtn += ",\"lac\":" + gsm.getLac();
104 } else if (mPhoneType == TelephonyManager.PHONE_TYPE_CDMA) {
105 CdmaCellLocation cdma = (CdmaCellLocation) mLocation;
106 rtn += ",\"type\":\"CDMA\"";
107 rtn += ",\"baseStationId\":" + cdma.getBaseStationId();
108 rtn += ",\"baseStationLatitude\":" + cdma.getBaseStationLatitude();
109 rtn += ",\"baseStationLongitude\":" + cdma.getBaseStationLongitude();
110 rtn += ",\"networkId\":" + cdma.getNetworkId();
111 rtn += ",\"systemId\":" + cdma.getSystemId();
112 }
113 return "{" + rtn + "}";
114 }
115
116 }
僅對Rexsee的源碼和函數事件做了整理,相關的demo或源碼解析可以在Rexsee社區瞭解,目前Rexsee已提供了近2000個擴充,覆蓋Android原生功能超過90%,且全部開放: http://www.rexsee.com/
摘自 yejiang