(1)Android GPS:需要GPS硬件支持,直接和卫星交互来获取当前经纬度,这种方式需要手机支持GPS模块(现在大部分的智能机应该都有了)。通过GPS方式准确度是最高的,但是它的缺点也非常明显:1,比较耗电;2,绝大部分用户默认不开启GPS模块;3,从GPS模块启动到获取第一次定位数据,可能需要比较长的时间;4,室内几乎无法使用。这其中,缺点2,3都是比较致命的。需要指出的是,GPS走的是卫星通信的通道,在没有网络连接的情况下也能用。
要实用Adnroid平台的GPS设备,首先需要添加上权限,所以需要添加如下权限:
uses-permission android:name= android.permission.ACCESS_FINE_LOCATION
首先判断GPS模块是否存在或者是开启:
private
void openGPSSettings() {
LocationManager alm = (LocationManager)
this
.getSystemService(Context.LOCATION_SERVICE);
if
(alm
.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) {
Toast.makeText(
this
, GPS模块正常 ,Toast.LENGTH_SHORT)
.show();
return
;
}
Toast.makeText(
this
, 请开启GPS! ,Toast.LENGTH_SHORT).show();
Intent intent = newIntent(Settings.ACTION_SECURITY_SETTINGS);
startActivityForResult(intent,
0
);
//此为设置完成后返回到获取界面
}
如果开启正常,则会直接进入到显示页面,如果开启不正常,则会进行到GPS设置页面:
private
void getLocation()
{
// 获取位置管理服务
LocationManager locationManager;
String serviceName = Context.LOCATION_SERVICE;
locationManager = (LocationManager)
this
.getSystemService(serviceName);
// 查找到服务信息
Criteria criteria =
new
Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
// 高精度
criteria.setAltitudeRequired(
false
);
criteria.setBearingRequired(
false
);
criteria.setCostAllowed(
true
);
criteria.setPowerRequirement(Criteria.POWER_LOW);
// 低功耗
String provider =locationManager.getBestProvider(criteria,
true
);
// 获取GPS信息
Location location =locationManager.getLastKnownLocation(provider);
// 通过GPS获取位置
updateToNewLocation(location);
// 设置监听*器,自动更新的最小时间为间隔N秒(1秒为1*1000,这样写主要为了方便)或最小位移变化超过N米
locationManager.requestLocationUpdates(provider,
100
*
1000
,
500
,
locationListener);
}
private
void updateToNewLocation(Location location) {
TextView tv1;
tv1 = (TextView)
this
.findViewById(R.id.tv1);
if
(location !=
null
) {
double
latitude = location.getLatitude();
double
longitude=location.getLongitude();
tv1.setText( 维度: + latitude+ \n经度 +longitude);
}
else
{
tv1.setText( 无法获取地理信息 );
}
}
(2)Android 基站定位:Android 基站定位只要明白了基站/WIFI定位的原理,自己实现基站/WIFI定位其实不难。基站定位一般有几种,第一种是利用手机附近的三个基站进行三角定位,由于每个基站的位置是固定的,利用电磁波在这三个基站间中转所需要时间来算出手机所在的坐标;第二种则是利用获取最近的基站的信息,其中包括基站 id,location area code、mobile country code、mobile network code和信号强度,将这些数据发送到google的定位web服务里,就能拿到当前所在的位置信息,误差一般在几十米到几百米之内。其中信号强度这个数据很重要,
http://www.jb51.net/article/34522.htm
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
< uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class Test extends Activity {
Context context=this;
LinearLayout mainView=null;
Button button=null;
TextView tv=null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTitle("基站+联网+google数据库定位");
mainView=new LinearLayout(this);
mainView.setOrientation(LinearLayout.VERTICAL);
button=new Button(this);
button.setText("定位测试");
button.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
(new HttpThread(context)).start();
}
});
mainView.addView(button,new LinearLayout.LayoutParams(-2,-2));
tv=new TextView(this);
tv.setText("Hello!\n");
mainView.addView(tv);
setContentView(mainView);
}
class HttpThread extends Thread{
TelephonyManager tm=null;
GsmCellLocation gcl=null;
int cid=0;
int lac=0;
int mcc = 0;
int mnc =0;
StringBuffer sb=null;
Handler handler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
tv.append(sb.toString());
break;
}
super.handleMessage(msg);
}
};
HttpThread(Context context){
tm=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
gcl=(GsmCellLocation) tm.getCellLocation();
cid=gcl.getCid();
lac=gcl.getLac();
mcc = Integer.valueOf(tm.getNetworkOperator().substring(0,3));
mnc = Integer.valueOf(tm.getNetworkOperator().substring(3,5));
sb=new StringBuffer();
sb.append("cid:"+cid + "\n");
sb.append("lac:"+lac + "\n");
sb.append("mcc:"+mcc + "\n");
sb.append("mnc:"+mnc + "\n");
}
public void run(){
try {
JSONObject jObject = new JSONObject();
jObject.put("version", "1.1.0");
jObject.put("host", "maps.google.com");
jObject.put("request_address", true);
if (mcc == 460) {
jObject.put("address_language", "zh_CN");
} else {
jObject.put("address_language", "en_US");
}
JSONArray jArray = new JSONArray();
JSONObject jData = new JSONObject();
jData.put("cell_id", cid);
jData.put("location_area_code", lac);
jData.put("mobile_country_code", mcc);
jData.put("mobile_network_code", mnc);
jArray.put(jData);
jObject.put("cell_towers", jArray);
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://www.google.com/loc/json");
StringEntity se = new StringEntity(jObject.toString());
post.setEntity(se);
HttpResponse resp = client.execute(post);
BufferedReader br = null;
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
sb.append("联网成功\n");
br = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));
}else{
sb.append("联网获取数据失败!\n");
}
String result = br.readLine();
while (result != null) {
sb.append(result);
result = br.readLine();
}
}catch(Exception ex){
sb.append(ex.getMessage());
}
Message msg=new Message();
msg.what=1;
handler.sendMessage(msg);
}
}
}
(3)Android Wifi定位:根据一个固定的WifiMAC地址,通过收集到的该Wifi热点的位置,然后访问网络上的定位服务以获得经纬度坐标。因为它和基站定位其实都需要使用网络,所以在Android也统称为Network方式。
public
class WiFiInfoManager
implements
Serializable {
private
static
final
long
serialVersionUID= -4582739827003032383L;
private
Context context;
public
WiFiInfoManager(Context context) {
super
();
this
.context = context;
}
public
WifiInfo getWifiInfo() {
WifiManager manager = (WifiManager)context
.getSystemService(Context.WIFI_SERVICE);
WifiInfo info =
new
WifiInfo();
info.mac =manager.getConnectionInfo().getBSSID();
Log.i( TAG , WIFI MACis: + info.mac);
return
info;
}
public
class
WifiInfo {
public
String mac;
public
WifiInfo() {
super
();
}
}
}
上面是取到WIFI的mac地址的方法,下面是把地址发送给google服务器,代码如下
public
staticLocation getWIFILocation(WifiInfo wifi) {
if
(wifi ==
null
) {
Log.i( TAG , wifiis
null
. );
return
null
;
}
DefaultHttpClient client = newDefaultHttpClient();
HttpPost post =
new
HttpPost( http:
//www.google.com/loc/json );
JSONObject holder =
new
JSONObject();
try
{
holder.put( version ,
1.1
.
0
);
holder.put( host , maps.google.com );
JSONObject data;
JSONArray array =
new
JSONArray();
if
(wifi.mac !=
null
wifi.mac.trim().length()
0
) {
data =
new
JSONObject();
data.put( mac_address , wifi.mac);
data.put( signal_strength ,
8
);
data.put( age ,
0
);
array.put(data);
}
holder.put( wifi_towers ,array);
Log.i( TAG , request json: + holder.toString());
StringEntity se = newStringEntity(holder.toString());
post.setEntity(se);
HttpResponse resp =client.execute(post);
int
state =resp.getStatusLine().getStatusCode();
if
(state == HttpStatus.SC_OK) {
HttpEntity entity =resp.getEntity();
if
(entity !=
null
) {
BufferedReader br = newBufferedReader(
newInputStreamReader(entity.getContent()));
StringBuffer sb = newStringBuffer();
String resute = ;
while
((resute =br.readLine()) !=
null
) {
sb.append(resute);
}
br.close();
Log.i( TAG , response json: + sb.toString());
data = newJSONObject(sb.toString());
data = (JSONObject)data.get( location );
Location loc = newLocation(
android.location.LocationManager.NETWORK_PROVIDER);
loc.setLatitude((Double)data.get( latitude ));
loc.setLongitude((Double)data.get( longitude ));
loc.setAccuracy(Float.parseFloat(data.get( accuracy )
.toString()));
loc.setTime(System.currentTimeMillis());
return
loc;
}
else
{
return
null
;
}
}
else
{
Log.v( TAG , state + );
return
null
;
}
}
catch
(Exception e) {
Log.e( TAG ,e.getMessage());
return
null
;
}
}
(3.1)而WIFI定位与基站定位的结合,笔者也在网上找到一个很好的文章,笔者对此就不做任何解释,直接给出网址 http://www.jb51.net/article/52673.htm
众所周知的,在OPhone和大部分国产的Android定制机里不支持最简单实用的基站和WIFI定位,只能使用速度慢而耗电的GPS定位,但OPhone和华为/中兴生产的一些Android定制机却占据了一定的市场,因此导致了很多使用了定位技术的Andorid应用挺尴尬的。
不过其实只要明白了基站/WIFI定位的原理,自己实现基站/WIFI定位其实不难。基站定位一般有几种,第一种是利用手机附近的三个基站进行三角定位,由于每个基站的位置是固定的,利用电磁波在这三个基站间中转所需要时间来算出手机所在的坐标;第二种则是利用获取最近的基站的信息,其中包括基站id,location area code、mobile country code、mobile network code和信号强度,将这些数据发送到google的定位web服务里,就能拿到当前所在的位置信息,误差一般在几十米到几百米之内。其中信号强度这个数据很重要,网上很多所谓的手动通过基站和WIFI信息定位的方法误差大都是因为没使用信号强度而导致误差过大。高德也自己做了一个基站库,具体可以google搜索一下。
现在在一些大中型城市里,WIFI已经普及,有私人或企业的WIFI,亦有中国电信的WIFI,通过WIFI信息进行定位,并不需要真正连接上指定的WIFI路由器,只需要探测到有WIFI存在即可,因此当手机使用的不是GSM制式(因为google的基站库里并没在保存太多的CDMA基站)的时候,也可以使用WIFI进行定位,原理也和基站定位一样,必须要拿到WIFI路由器的SSID和信号强度。
由于有些用户默认是将WIFI关闭的,通过API开启WIFI硬件并进行搜索附近的WIFI路由器需要一段时间,怎样才能将手机基站定位和WIFI定位完美结合起来呢,Android提供了一种很好的机制,就是Handler和Looper,Handler和Looper一般用于跨线程传递数据,但当在单线程里使用时,就变成了一个先进先出的消息泵。利用这个消息泵进行调度,就可以将基站定位和WIFI定位完美结合。以下是相关的代码:
CellInfoManager.javaimport
java.lang.reflect.Method;
import
java.util.Iterator;
import
java.util.List;
import
org.json.JSONArray;
import
org.json.JSONException;
import
org.json.JSONObject;
import
android.content.Context;
import
android.telephony.CellLocation;
import
android.telephony.NeighboringCellInfo;
import
android.telephony.PhoneStateListener;
import
android.telephony.TelephonyManager;
import
android.telephony.gsm.GsmCellLocation;
import
android.util.Log;
public
class
CellInfoManager {
private
int
asu;
private
int
bid;
private
int
cid;
private
boolean
isCdma;
private
boolean
isGsm;
private
int
lac;
private
int
lat;
private
final
PhoneStateListener listener;
private
int
lng;
private
int
mcc;
private
int
mnc;
private
int
nid;
private
int
sid;
private
TelephonyManager tel;
private
boolean
valid;
private
Context context;
public
CellInfoManager(Context paramContext) {
this
.listener =
new
CellInfoListener(
this
);
tel = (TelephonyManager) paramContext.getSystemService(Context.TELEPHONY_SERVICE);
this
.tel.listen(
this
.listener, PhoneStateListener.LISTEN_CELL_LOCATION | PhoneStateListener.LISTEN_SIGNAL_STRENGTH);
context = paramContext;
}
public
static
int
dBm(
int
i) {
int
j;
if
(i >=
0
&& i <=
31
)
j = i *
2
+ -
113
;
else
j =
0
;
return
j;
}
public
int
asu() {
return
this
.asu;
}
public
int
bid() {
if
(!
this
.valid)
update();
return
this
.bid;
}
public
JSONObject cdmaInfo() {
if
(!isCdma()) {
return
null
;
}
JSONObject jsonObject =
new
JSONObject();
try
{
jsonObject.put(
"bid"
, bid());
jsonObject.put(
"sid"
, sid());
jsonObject.put(
"nid"
, nid());
jsonObject.put(
"lat"
, lat());
jsonObject.put(
"lng"
, lng());
}
catch
(JSONException ex) {
jsonObject =
null
;
Log.e(
"CellInfoManager"
, ex.getMessage());
}
return
jsonObject;
}
public
JSONArray cellTowers() {
JSONArray jsonarray =
new
JSONArray();
int
lat;
int
mcc;
int
mnc;
int
aryCell[] = dumpCells();
lat = lac();
mcc = mcc();
mnc = mnc();
if
(aryCell ==
null
|| aryCell.length <
2
) {
aryCell =
new
int
[
2
];
aryCell[
0
] = cid;
aryCell[
1
] = -
60
;
}
for
(
int
i =
0
; i < aryCell.length; i +=
2
) {
try
{
int
j2 = dBm(i +
1
);
JSONObject jsonobject =
new
JSONObject();
jsonobject.put(
"cell_id"
, aryCell[i]);
jsonobject.put(
"location_area_code"
, lat);
jsonobject.put(
"mobile_country_code"
, mcc);
jsonobject.put(
"mobile_network_code"
, mnc);
jsonobject.put(
"signal_strength"
, j2);
jsonobject.put(
"age"
,
0
);
jsonarray.put(jsonobject);
}
catch
(Exception ex) {
ex.printStackTrace();
Log.e(
"CellInfoManager"
, ex.getMessage());
}
}
if
(isCdma())
jsonarray =
new
JSONArray();
return
jsonarray;
}
public
int
cid() {
if
(!
this
.valid)
update();
return
this
.cid;
}
public
int
[] dumpCells() {
int
[] aryCells;
if
(cid() ==
0
) {
aryCells =
new
int
[
0
];
return
aryCells;
}
List<NeighboringCellInfo> lsCellInfo =
this
.tel.getNeighboringCellInfo();
if
(lsCellInfo ==
null
|| lsCellInfo.size() ==
0
) {
aryCells =
new
int
[
1
];
int
i = cid();
aryCells[
0
] = i;
return
aryCells;
}
int
[] arrayOfInt1 =
new
int
[lsCellInfo.size() *
2
+
2
];
int
j =
0
+
1
;
int
k = cid();
arrayOfInt1[
0
] = k;
int
m = j +
1
;
int
n = asu();
arrayOfInt1[j] = n;
Iterator<NeighboringCellInfo> iter = lsCellInfo.iterator();
while
(
true
) {
if
(!iter.hasNext()) {
break
;
}
NeighboringCellInfo localNeighboringCellInfo = (NeighboringCellInfo) iter.next();
int
i2 = localNeighboringCellInfo.getCid();
if
((i2 <=
0
) || (i2 ==
65535
))
continue
;
int
i3 = m +
1
;
arrayOfInt1[m] = i2;
m = i3 +
1
;
int
i4 = localNeighboringCellInfo.getRssi();
arrayOfInt1[i3] = i4;
}
int
[] arrayOfInt2 =
new
int
[m];
System.arraycopy(arrayOfInt1,
0
, arrayOfInt2,
0
, m);
aryCells = arrayOfInt2;
return
aryCells;
}
public
JSONObject gsmInfo() {
if
(!isGsm()) {
return
null
;
}
JSONObject localObject =
null
;
while
(
true
) {
try
{
JSONObject localJSONObject1 =
new
JSONObject();
String str1 =
this
.tel.getNetworkOperatorName();
localJSONObject1.put(
"operator"
, str1);
String str2 =
this
.tel.getNetworkOperator();
if
((str2.length() ==
5
) || (str2.length() ==
6
)) {
String str3 = str2.substring(
0
,
3
);
String str4 = str2.substring(
3
, str2.length());
localJSONObject1.put(
"mcc"
, str3);
localJSONObject1.put(
"mnc"
, str4);
}
localJSONObject1.put(
"lac"
, lac());
int
[] arrayOfInt = dumpCells();
JSONArray localJSONArray1 =
new
JSONArray();
int
k =
0
;
int
m = arrayOfInt.length /
2
;
while
(
true
) {
if
(k >= m) {
localJSONObject1.put(
"cells"
, localJSONArray1);
localObject = localJSONObject1;
break
;
}
int
n = k *
2
;
int
i1 = arrayOfInt[n];
int
i2 = k *
2
+
1
;
int
i3 = arrayOfInt[i2];
JSONObject localJSONObject7 =
new
JSONObject();
localJSONObject7.put(
"cid"
, i1);
localJSONObject7.put(
"asu"
, i3);
localJSONArray1.put(localJSONObject7);
k +=
1
;
}
}
catch
(JSONException localJSONException) {
localObject =
null
;
}
}
}
public
boolean
isCdma() {
if
(!
this
.valid)
update();
return
this
.isCdma;
}
public
boolean
isGsm() {
if
(!
this
.valid)
update();
return
this
.isGsm;
}
public
int
lac() {
if
(!
this
.valid)
update();
return
this
.lac;
}
public
int
lat() {
if
(!
this
.valid)
update();
return
this
.lat;
}
public
int
lng() {
if
(!
this
.valid)
update();
return
this
.lng;
}
public
int
mcc() {
if
(!
this
.valid)
update();
return
this
.mcc;
}
public
int
mnc() {
if
(!
this
.valid)
update();
return
this
.mnc;
}
public
int
nid() {
if
(!
this
.valid)
update();
return
this
.nid;
}
public
float
score() {
float
f1 = 0f;
int
[] aryCells =
null
;
int
i =
0
;
float
f2 = 0f;
if
(isCdma()) {
f2 =
1065353216
;
return
f2;
}
if
(isGsm()) {
f1 =
0
.0F;
aryCells = dumpCells();
int
j = aryCells.length;
if
(i >= j)
f2 = f1;
}
if
(i <=
0
) {
return
1065353216
;
}
int
m = aryCells[i];
for
(i =
0
; i < m; i++) {
if
((m <
0
) || (m >
31
))
f1 +=
0
.5F;
else
f1 +=
1
.0F;
}
f2 = f1;
return
f2;
}
public
int
sid() {
if
(!
this
.valid)
update();
return
this
.sid;
}
public
void
update() {
this
.isGsm =
false
;
this
.isCdma =
false
;
this
.cid =
0
;
this
.lac =
0
;
this
.mcc =
0
;
this
.mnc =
0
;
CellLocation cellLocation =
this
.tel.getCellLocation();
int
nPhoneType =
this
.tel.getPhoneType();
if
(nPhoneType ==
1
&& cellLocation
instanceof
GsmCellLocation) {
this
.isGsm =
true
;
GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation;
int
nGSMCID = gsmCellLocation.getCid();
if
(nGSMCID >
0
) {
if
(nGSMCID !=
65535
) {
this
.cid = nGSMCID;
this
.lac = gsmCellLocation.getLac();
}
}
}
try
{
String strNetworkOperator =
this
.tel.getNetworkOperator();
int
nNetworkOperatorLength = strNetworkOperator.length();
if
(nNetworkOperatorLength !=
5
) {
if
(nNetworkOperatorLength !=
6
)
;
}
else
{
this
.mcc = Integer.parseInt(strNetworkOperator.substring(
0
,
3
));
this
.mnc = Integer.parseInt(strNetworkOperator.substring(
3
, nNetworkOperatorLength));
}
if
(
this
.tel.getPhoneType() ==
2
) {
this
.valid =
true
;
Class<?> clsCellLocation = cellLocation.getClass();
Class<?>[] aryClass =
new
Class[
0
];
Method localMethod1 = clsCellLocation.getMethod(
"getBaseStationId"
, aryClass);
Method localMethod2 = clsCellLocation.getMethod(
"getSystemId"
, aryClass);
Method localMethod3 = clsCellLocation.getMethod(
"getNetworkId"
, aryClass);
Object[] aryDummy =
new
Object[
0
];
this
.bid = ((Integer) localMethod1.invoke(cellLocation, aryDummy)).intValue();
this
.sid = ((Integer) localMethod2.invoke(cellLocation, aryDummy)).intValue();
this
.nid = ((Integer) localMethod3.invoke(cellLocation, aryDummy)).intValue();
Method localMethod7 = clsCellLocation.getMethod(
"getBaseStationLatitude"
, aryClass);
Method localMethod8 = clsCellLocation.getMethod(
"getBaseStationLongitude"
, aryClass);
this
.lat = ((Integer) localMethod7.invoke(cellLocation, aryDummy)).intValue();
this
.lng = ((Integer) localMethod8.invoke(cellLocation, aryDummy)).intValue();
this
.isCdma =
true
;
}
}
catch
(Exception ex) {
Log.e(
"CellInfoManager"
, ex.getMessage());
}
}
class
CellInfoListener
extends
PhoneStateListener {
CellInfoListener(CellInfoManager manager) {
}
public
void
onCellLocationChanged(CellLocation paramCellLocation) {
CellInfoManager.
this
.valid =
false
;
}
public
void
onSignalStrengthChanged(
int
paramInt) {
CellInfoManager.
this
.asu = paramInt;
}
}
}
WifiInfoManager.java
import
java.util.ArrayList;
import
java.util.Iterator;
import
java.util.List;
import
org.json.JSONArray;
import
org.json.JSONObject;
import
android.content.Context;
import
android.net.wifi.ScanResult;
import
android.net.wifi.WifiManager;
import
android.util.Log;
public
class
WifiInfoManager {
private
WifiManager wifiManager;
public
WifiInfoManager(Context paramContext) {
this
.wifiManager = (WifiManager) paramContext.getSystemService(Context.WIFI_SERVICE);
}
public
List<WifiInfo> dump() {
if
(!
this
.wifiManager.isWifiEnabled()) {
return
new
ArrayList<WifiInfo>();
}
android.net.wifi.WifiInfo wifiConnection =
this
.wifiManager.getConnectionInfo();
WifiInfo currentWIFI =
null
;
if
(wifiConnection !=
null
) {
String s = wifiConnection.getBSSID();
int
i = wifiConnection.getRssi();
String s1 = wifiConnection.getSSID();
currentWIFI =
new
WifiInfo(s, i, s1);
}
ArrayList<WifiInfo> lsAllWIFI =
new
ArrayList<WifiInfo>();
if
(currentWIFI !=
null
) {
lsAllWIFI.add(currentWIFI);
}
List<ScanResult> lsScanResult =
this
.wifiManager.getScanResults();
for
(ScanResult result : lsScanResult) {
WifiInfo scanWIFI =
new
WifiInfo(result);
if
(!scanWIFI.equals(currentWIFI))
lsAllWIFI.add(scanWIFI);
}
return
lsAllWIFI;
}
public
boolean
isWifiEnabled() {
return
this
.wifiManager.isWifiEnabled();
}
public
JSONArray wifiInfo() {
JSONArray jsonArray =
new
JSONArray();
for
(WifiInfo wifi : dump()) {
JSONObject localJSONObject = wifi.info();
jsonArray.put(localJSONObject);
}
return
jsonArray;
}
public
WifiManager wifiManager() {
return
this
.wifiManager;
}
public
JSONArray wifiTowers() {
JSONArray jsonArray =
new
JSONArray();
try
{
Iterator<WifiInfo> localObject = dump().iterator();
while
(
true
) {
if
(!(localObject).hasNext()) {
return
jsonArray;
}
jsonArray.put(localObject.next().wifi_tower());
}
}
catch
(Exception localException) {
Log.e(
"location"
, localException.getMessage());
}
return
jsonArray;
}
public
class
WifiInfo
implements
Comparable<WifiInfo> {
public
int
compareTo(WifiInfo wifiinfo) {
int
i = wifiinfo.dBm;
int
j = dBm;
return
i - j;
}
public
boolean
equals(Object obj) {
boolean
flag =
false
;
if
(obj ==
this
) {
flag =
true
;
return
flag;
}
else
{
if
(obj
instanceof
WifiInfo) {
WifiInfo wifiinfo = (WifiInfo) obj;
int
i = wifiinfo.dBm;
int
j = dBm;
if
(i == j) {
String s = wifiinfo.bssid;
String s1 = bssid;
if
(s.equals(s1)) {
flag =
true
;
return
flag;
}
}
flag =
false
;
}
else
{
flag =
false
;
}
}
return
flag;
}
public
int
hashCode() {
int
i = dBm;
int
j = bssid.hashCode();
return
i ^ j;
}
public
JSONObject info() {
JSONObject jsonobject =
new
JSONObject();
try
{
String s = bssid;
jsonobject.put(
"mac"
, s);
String s1 = ssid;
jsonobject.put(
"ssid"
, s1);
int
i = dBm;
jsonobject.put(
"dbm"
, i);
}
catch
(Exception ex) {
}
return
jsonobject;
}
public
JSONObject wifi_tower() {
JSONObject jsonobject =
new
JSONObject();
try
{
String s = bssid;
jsonobject.put(
"mac_address"
, s);
int
i = dBm;
jsonobject.put(
"signal_strength"
, i);
String s1 = ssid;
jsonobject.put(
"ssid"
, s1);
jsonobject.put(
"age"
,
0
);
}
catch
(Exception ex) {
}
return
jsonobject;
}
public
final
String bssid;
public
final
int
dBm;
public
final
String ssid;
public
WifiInfo(ScanResult scanresult) {
String s = scanresult.BSSID;
bssid = s;
int
i = scanresult.level;
dBm = i;
String s1 = scanresult.SSID;
ssid = s1;
}
public
WifiInfo(String s,
int
i, String s1) {
bssid = s;
dBm = i;
ssid = s1;
}
}
}
CellLocationManager.java
import
java.util.ArrayList;
import
java.util.Iterator;
import
java.util.List;
import
org.apache.http.HttpEntity;
import
org.apache.http.HttpResponse;
import
org.apache.http.client.methods.HttpPost;
import
org.apache.http.entity.StringEntity;
import
org.apache.http.impl.client.DefaultHttpClient;
import
org.apache.http.util.EntityUtils;
import
org.json.JSONArray;
import
org.json.JSONObject;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.net.ConnectivityManager;
import
android.net.NetworkInfo;
import
android.net.wifi.WifiManager;
import
android.os.Handler;
import
android.os.Message;
import
android.telephony.CellLocation;
import
android.util.Log;
import
android.widget.Toast;
import
com.google.android.photostream.UserTask;
public
abstract
class
CellLocationManager {
public
static
int
CHECK_INTERVAL =
15000
;
public
static
boolean
ENABLE_WIFI =
true
;
private
static
boolean
IS_DEBUG =
false
;
private
static
final
int
STATE_COLLECTING =
2
;
private
static
final
int
STATE_IDLE =
0
;
private
static
final
int
STATE_READY =
1
;
private
static
final
int
STATE_SENDING =
3
;
private
static
final
int
MESSAGE_INITIALIZE =
1
;
private
static
final
int
MESSAGE_COLLECTING_CELL =
2
;
private
static
final
int
MESSAGE_COLLECTING_WIFI =
5
;
private
static
final
int
MESSAGE_BEFORE_FINISH =
10
;
private
int
accuracy;
private
int
bid;
private
CellInfoManager cellInfoManager;
private
Context context;
private
boolean
disableWifiAfterScan;
private
int
[] aryGsmCells;
private
double
latitude;
private
double
longitude;
private
MyLooper looper;
private
boolean
paused;
private
final
BroadcastReceiver receiver;
private
long
startScanTimestamp;
private
int
state;
private
Task task;
private
long
timestamp;
private
boolean
waiting4WifiEnable;
private
WifiInfoManager wifiManager;
public
CellLocationManager(Context context, CellInfoManager cellinfomanager, WifiInfoManager wifiinfomanager) {
receiver =
new
CellLocationManagerBroadcastReceiver();
this
.context = context.getApplicationContext();
cellInfoManager = cellinfomanager;
wifiManager = wifiinfomanager;
}
private
void
debug(Object paramObject) {
if
(IS_DEBUG) {
System.out.println(paramObject);
String str = String.valueOf(paramObject);
Toast.makeText(
this
.context, str, Toast.LENGTH_SHORT).show();
}
}
public
int
accuracy() {
return
this
.accuracy;
}
public
double
latitude() {
return
this
.latitude;
}
public
double
longitude() {
return
this
.longitude;
}
public
abstract
void
onLocationChanged();
public
void
pause() {
if
(state >
0
&& !paused) {
looper.removeMessages(MESSAGE_BEFORE_FINISH);
paused =
true
;
}
}
public
void
requestUpdate() {
if
(state != STATE_READY) {
return
;
}
boolean
bStartScanSuccessful =
false
;
CellLocation.requestLocationUpdate();
state = STATE_COLLECTING;
looper.sendEmptyMessage(MESSAGE_INITIALIZE);
if
(wifiManager.wifiManager().isWifiEnabled()) {
bStartScanSuccessful = wifiManager.wifiManager().startScan();
waiting4WifiEnable =
false
;
}
else
{
startScanTimestamp = System.currentTimeMillis();
if
(!ENABLE_WIFI || !wifiManager.wifiManager().setWifiEnabled(
true
)) {
int
nDelay =
0
;
if
(!bStartScanSuccessful)
nDelay =
8000
;
looper.sendEmptyMessageDelayed(MESSAGE_COLLECTING_WIFI, nDelay);
debug(
"CELL UPDATE"
);
}
else
{
waiting4WifiEnable =
true
;
}
}
}
public
void
resume() {
if
(state >
0
&& paused) {
paused =
false
;
looper.removeMessages(MESSAGE_BEFORE_FINISH);
looper.sendEmptyMessage(MESSAGE_BEFORE_FINISH);
}
}
public
void
start() {
if
(state <= STATE_IDLE) {
Log.i(
"CellLocationManager"
,
"Starting..."
);
context.registerReceiver(receiver,
new
IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
context.registerReceiver(receiver,
new
IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION));
looper =
new
MyLooper();
state = STATE_READY;
paused =
false
;
waiting4WifiEnable =
false
;
disableWifiAfterScan =
false
;
debug(
"CELL LOCATION START"
);
requestUpdate();
}
}
public
void
stop() {
if
(state > STATE_IDLE) {
context.unregisterReceiver(receiver);
debug(
"CELL LOCATION STOP"
);
looper =
null
;
state = STATE_IDLE;
if
(disableWifiAfterScan) {
disableWifiAfterScan =
false
;
wifiManager.wifiManager().setWifiEnabled(
false
);
}
}
}
public
long
timestamp() {
return
this
.timestamp;
}
protected
boolean
isConnectedWithInternet() {
ConnectivityManager conManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = conManager.getActiveNetworkInfo();
if
(networkInfo !=
null
) {
return
networkInfo.isAvailable();
}
return
false
;
}
private
class
MyLooper
extends
Handler {
private
float
fCellScore;
private
JSONArray objCellTowersJson;
public
void
handleMessage(Message paramMessage) {
if
(CellLocationManager.
this
.looper !=
this
)
return
;
boolean
flag =
true
;
switch
(paramMessage.what) {
default
:
break
;
case
MESSAGE_INITIALIZE:
this
.objCellTowersJson =
null
;
this
.fCellScore =
1
.401298E-045F;
case
MESSAGE_COLLECTING_CELL:
if
(CellLocationManager.
this
.state != CellLocationManager.STATE_COLLECTING)
break
;
JSONArray objCellTowers = CellLocationManager.
this
.cellInfoManager.cellTowers();
float
fCellScore = CellLocationManager.
this
.cellInfoManager.score();
if
(objCellTowers !=
null
) {
float
fCurrentCellScore =
this
.fCellScore;
if
(fCellScore > fCurrentCellScore) {
this
.objCellTowersJson = objCellTowers;
this
.fCellScore = fCellScore;
}
}
this
.sendEmptyMessageDelayed(MESSAGE_COLLECTING_CELL, 600L);
break
;
case
MESSAGE_COLLECTING_WIFI:
if
(CellLocationManager.
this
.state != CellLocationManager.STATE_COLLECTING)
break
;
this
.removeMessages(MESSAGE_COLLECTING_CELL);
this
.removeMessages(MESSAGE_BEFORE_FINISH);
// if (CellLocationManager.this.disableWifiAfterScan && CellLocationManager.this.wifiManager.wifiManager().setWifiEnabled(true))
// CellLocationManager.this.disableWifiAfterScan = false;
CellLocationManager.
this
.state = CellLocationManager.STATE_SENDING;
if
(CellLocationManager.
this
.task !=
null
)
CellLocationManager.
this
.task.cancel(
true
);
int
[] aryCell =
null
;
if
(CellLocationManager.
this
.cellInfoManager.isGsm())
aryCell = CellLocationManager.
this
.cellInfoManager.dumpCells();
int
nBid = CellLocationManager.
this
.cellInfoManager.bid();
CellLocationManager.
this
.task =
new
CellLocationManager.Task(aryCell, nBid);
JSONArray[] aryJsonArray =
new
JSONArray[
2
];
aryJsonArray[
0
] =
this
.objCellTowersJson;
aryJsonArray[
1
] = CellLocationManager.
this
.wifiManager.wifiTowers();
if
(
this
.objCellTowersJson !=
null
)
Log.i(
"CellTownerJSON"
,
this
.objCellTowersJson.toString());
if
(aryJsonArray[
1
] !=
null
)
Log.i(
"WIFITownerJSON"
, aryJsonArray[
1
].toString());
CellLocationManager.
this
.debug(
"Post json"
);
CellLocationManager.
this
.task.execute(aryJsonArray);
break
;
case
MESSAGE_BEFORE_FINISH:
if
(CellLocationManager.
this
.state != CellLocationManager.STATE_READY || CellLocationManager.
this
.paused)
break
;
// L7
if
(CellLocationManager.
this
.disableWifiAfterScan && CellLocationManager.
this
.wifiManager.wifiManager().setWifiEnabled(
false
))
CellLocationManager.
this
.disableWifiAfterScan =
false
;
if
(!CellLocationManager.
this
.cellInfoManager.isGsm()) {
// L9
if
(CellLocationManager.
this
.bid == CellLocationManager.
this
.cellInfoManager.bid()) {
flag =
true
;
}
else
{
flag =
false
;
}
// L14
if
(flag) {
requestUpdate();
}
else
{
this
.sendEmptyMessageDelayed(
10
, CellLocationManager.CHECK_INTERVAL);
}
}
else
{
// L8
if
(CellLocationManager.
this
.aryGsmCells ==
null
|| CellLocationManager.
this
.aryGsmCells.length ==
0
) {
// L10
flag =
true
;
}
else
{
int
[] aryCells = CellLocationManager.
this
.cellInfoManager.dumpCells();
if
(aryCells !=
null
&& aryCells.length !=
0
) {
// L13
int
nFirstCellId = CellLocationManager.
this
.aryGsmCells[
0
];
if
(nFirstCellId == aryCells[
0
]) {
// L16
int
cellLength = CellLocationManager.
this
.aryGsmCells.length /
2
;
List<Integer> arraylist =
new
ArrayList<Integer>(cellLength);
List<Integer> arraylist1 =
new
ArrayList<Integer>(aryCells.length /
2
);
int
nIndex =
0
;
int
nGSMCellLength = CellLocationManager.
this
.aryGsmCells.length;
while
(nIndex < nGSMCellLength) {
// goto L18
arraylist.add(CellLocationManager.
this
.aryGsmCells[nIndex]);
nIndex +=
2
;
}
// goto L17
nIndex =
0
;
while
(nIndex < aryCells.length) {
// goto L20
arraylist1.add(aryCells[nIndex]);
nIndex +=
2
;
}
// goto L19
int
nCounter =
0
;
for
(Iterator<Integer> iterator = arraylist.iterator(); iterator.hasNext();) {
// goto L22
if
(arraylist1.contains(iterator.next()))
nCounter++;
}
// goto L21
int
k4 = arraylist.size() - nCounter;
int
l4 = arraylist1.size() - nCounter;
if
(k4 + l4 > nCounter)
flag =
true
;
else
flag =
false
;
if
(flag) {
StringBuilder stringbuilder =
new
StringBuilder(k4).append(
" + "
);
stringbuilder.append(l4).append(
" > "
);
stringbuilder.append(nCounter);
CellLocationManager.
this
.debug(stringbuilder.toString());
}
break
;
}
else
{
// L15
flag =
true
;
CellLocationManager.
this
.debug(
"PRIMARY CELL CHANGED"
);
// goto L14
if
(flag) {
requestUpdate();
}
else
{
this
.sendEmptyMessageDelayed(MESSAGE_BEFORE_FINISH, CellLocationManager.CHECK_INTERVAL);
}
}
}
else
{
// L12
flag =
true
;
// goto L14
if
(flag) {
requestUpdate();
}
else
{
this
.sendEmptyMessageDelayed(MESSAGE_BEFORE_FINISH,CellLocationManager.CHECK_INTERVAL);
}
}
}
}
}
}
}
class
Task
extends
UserTask<JSONArray, Void, Void> {
int
accuracy;
int
bid;
int
[] cells;
double
lat;
double
lng;
long
time;
public
Task(
int
[] aryCell,
int
bid) {
this
.time = System.currentTimeMillis();
this
.cells = aryCell;
this
.bid = bid;
}
public
Void doInBackground(JSONArray[] paramArrayOfJSONArray) {
try
{
JSONObject jsonObject =
new
JSONObject();
jsonObject.put(
"version"
,
"1.1.0"
);
jsonObject.put(
"host"
,
"maps.google.com"
);
jsonObject.put(
"address_language"
,
"zh_CN"
);
jsonObject.put(
"request_address"
,
true
);
jsonObject.put(
"radio_type"
,
"gsm"
);
jsonObject.put(
"carrier"
,
"HTC"
);
JSONArray cellJson = paramArrayOfJSONArray[
0
];
jsonObject.put(
"cell_towers"
, cellJson);
JSONArray wifiJson = paramArrayOfJSONArray[
1
];
jsonObject.put(
"wifi_towers"
, wifiJson);
DefaultHttpClient localDefaultHttpClient =
new
DefaultHttpClient();
String strJson = jsonObject.toString();
StringEntity objJsonEntity =
new
StringEntity(strJson);
localHttpPost.setEntity(objJsonEntity);
HttpResponse objResponse = localDefaultHttpClient.execute(localHttpPost);
int
nStateCode = objResponse.getStatusLine().getStatusCode();
HttpEntity httpEntity = objResponse.getEntity();
byte
[] arrayOfByte =
null
;
if
(nStateCode /
100
==
2
)
arrayOfByte = EntityUtils.toByteArray(httpEntity);
httpEntity.consumeContent();
String strResponse =
new
String(arrayOfByte,
"UTF-8"
);
jsonObject =
new
JSONObject(strResponse);
this
.lat = jsonObject.getJSONObject(
"location"
).getDouble(
"latitude"
);
this
.lng = jsonObject.getJSONObject(
"location"
).getDouble(
"longitude"
);
this
.accuracy = jsonObject.getJSONObject(
"location"
).getInt(
"accuracy"
);;
}
catch
(Exception localException) {
return
null
;
}
return
null
;
}
public
void
onPostExecute(Void paramVoid) {
if
(CellLocationManager.
this
.state != CellLocationManager.STATE_SENDING || CellLocationManager.
this
.task !=
this
)
return
;
if
((
this
.lat !=
0
.0D) && (
this
.lng !=
0
.0D)) {
CellLocationManager.
this
.timestamp =
this
.time;
CellLocationManager.
this
.latitude =
this
.lat;
CellLocationManager.
this
.longitude =
this
.lng;
CellLocationManager.
this
.accuracy =
this
.accuracy;
CellLocationManager.
this
.aryGsmCells =
this
.cells;
CellLocationManager.
this
.bid =
this
.bid;
StringBuilder sb =
new
StringBuilder(
"CELL LOCATION DONE: ("
);
sb.append(
this
.lat).append(
","
).append(
this
.lng).append(
")"
);
CellLocationManager.
this
.debug(sb.toString());
CellLocationManager.
this
.state = STATE_READY;
CellLocationManager.
this
.looper.sendEmptyMessageDelayed(MESSAGE_BEFORE_FINISH, CellLocationManager.CHECK_INTERVAL);
CellLocationManager.
this
.onLocationChanged();
}
else
{
CellLocationManager.
this
.task =
null
;
CellLocationManager.
this
.state = CellLocationManager.STATE_READY;
CellLocationManager.
this
.looper.sendEmptyMessageDelayed(MESSAGE_BEFORE_FINISH, 5000L);
}
}
}
private
class
CellLocationManagerBroadcastReceiver
extends
BroadcastReceiver {
@Override
public
void
onReceive(Context arg0, Intent intent) {
// access$0 state
// 1 debug
// access$2 loop
// 3 startScanTimestamp
// 4 disableWifiAfterScan
// 5 wifimanager
if
(CellLocationManager.
this
.state != CellLocationManager.STATE_COLLECTING)
return
;
String s = intent.getAction();
if
(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(s)) {
// goto _L4; else goto _L3
// _L3:
CellLocationManager.
this
.debug(
"WIFI SCAN COMPLETE"
);
CellLocationManager.
this
.looper.removeMessages(MESSAGE_COLLECTING_WIFI);
long
lInterval = System.currentTimeMillis() - CellLocationManager.
this
.startScanTimestamp;
if
(lInterval > 4000L)
CellLocationManager.
this
.looper.sendEmptyMessageDelayed(MESSAGE_COLLECTING_WIFI, 4000L);
else
CellLocationManager.
this
.looper.sendEmptyMessage(MESSAGE_COLLECTING_WIFI);
}
else
{
// _L4:
if
(!CellLocationManager.
this
.waiting4WifiEnable)
return
;
String s1 = intent.getAction();
if
(!WifiManager.WIFI_STATE_CHANGED_ACTION.equals(s1))
return
;
int
wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
4
);
// _L5:
if
(wifiState == WifiManager.WIFI_STATE_ENABLING) {
boolean
flag2 = CellLocationManager.
this
.wifiManager.wifiManager().startScan();
// _L8:
CellLocationManager.
this
.disableWifiAfterScan =
true
;
CellLocationManager.
this
.paused =
false
;
// int i = flag2 ? 1 : 0;
// int nDelay = i != 0 ? 8000 : 0;
// CellLocationManager.this.looper.sendEmptyMessageDelayed(MESSAGE_COLLECTING_WIFI, nDelay);
CellLocationManager.
this
.debug(
"WIFI ENABLED"
);
}
}
}
}
}
CellInfoManager cellManager =
new
CellInfoManager(
this
);
WifiInfoManager wifiManager =
new
WifiInfoManager(
this
);
CellLocationManager locationManager =
new
CellLocationManager(
this
, cellManager, wifiManager) {
@Override
public
void
onLocationChanged() {
txtAutoNaviInfo.setText(
this
.latitude() +
"-"
+
this
.longitude());
this
.stop();
}
};
locationManager.start();
public
void
register(LocationManager locationManager,
boolean
gps, Context context) {
if
(DEBUG) Log.d(TAG,
"Registering this location listener: "
+
this
.toString());
long
updateMinTime = SLOW_LOCATION_UPDATE_MIN_TIME;
long
updateMinDistance = SLOW_LOCATION_UPDATE_MIN_DISTANCE;
if
(gps) {
updateMinTime = LOCATION_UPDATE_MIN_TIME;
updateMinDistance = LOCATION_UPDATE_MIN_DISTANCE;
}
List<String> providers = locationManager.getProviders(
true
);
int
providersCount = providers.size();
if
(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
setChanged();
notifyObservers(
null
);
}
for
(
int
i =
0
; i < providersCount; i++) {
String providerName = providers.get(i);
if
(locationManager.isProviderEnabled(providerName)) {
updateLocation(locationManager.getLastKnownLocation(providerName));
}
// Only register with GPS if we've explicitly allowed it.
if
(gps || !LocationManager.GPS_PROVIDER.equals(providerName)) {
locationManager.requestLocationUpdates(providerName, updateMinTime,
updateMinDistance,
this
);
}
}
if
(cellLocationManager ==
null
) {
CellInfoManager cellManager =
new
CellInfoManager(context);
WifiInfoManager wifiManager =
new
WifiInfoManager(context);
cellLocationManager =
new
CellLocationManager(context, cellManager, wifiManager) {
@Override
public
void
onLocationChanged() {
if
((latitude() ==
0
.0D) || (longitude() ==
0
.0D))
return
;
Location result =
new
Location(
"CellLocationManager"
);
result.setLatitude(latitude());
result.setLongitude(longitude());
result.setAccuracy(accuracy());
onBestLocationChanged(result);
this
.stop();
}
};
}
//cellLocationManager.stop();
cellLocationManager.start();
// LocationController controller = LocationController.requestLocationUpdates("", updateMinTime,updateMinDistance, this, context);
// controller.requestCurrentLocation();
}
4. AGPS定位
AGPS(AssistedGPS:辅助全球卫星定位系统)是结合GSM或GPRS与传统卫星定位,利用基地台代送辅助卫星信息,以缩减GPS芯片获取卫星信号的延迟时间,受遮盖的室内也能借基地台讯号弥补,减轻GPS芯片对卫星的依赖度。和纯GPS、基地台三角定位比较,AGPS能提供范围更广、更省电、速度更快的定位服务,理想误差范围在10公尺以内,日本和美国都已经成熟运用AGPS于LBS服务(Location Based Service,基于位置的服务)。AGPS技术是一种结合了网络基站信息和GPS信息对移动台进行定位的技术,可以在GSM/GPRS、WCDMA和CDMA2000网络中使进行用。该技术需要在手机内增加GPS接收机模块,并改造手机的天线,同时要在移动网络上加建位置服务器、差分GPS基准站等设备。AGPS解决方案的优势主要体现在其定位精度上,在室外等空旷地区,其精度在正常的GPS工作环境下,可以达到10米左右,堪称目前定位精度最高的一种定位技术。该技术的另一优点为:首次捕获GPS信号的时间一般仅需几秒,不像GPS的首次捕获时间可能要2~3分钟