最近做的一个功能中涉及到了网络定位,当前采取的方案是利用谷歌提供的Google Maps Geolocation API实现,其中需要我们提供用户当前的基站列表+wifi列表。然后问题就来了,最后发现在6.0的手机上–不开启GPS的时候wifi列表为空。尼玛,吓得我立马打开demo查看代码:
public WifiManager mWifiManager;
//描述任何Wifi连接状态
private WifiInfo mWifiInfo;
private List<ScanResult> mScanResult;
private final int SCAN = 1;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case SCAN :
Log.e("ConnectActivity","scan -----------");
mWifiManager.startScan();
mScanResult = mWifiManager.getScanResults();
listView.setAdapter(new MyAdapter(ConnectActivity.this,mScanResult));
mWifiInfo = mWifiManager.getConnectionInfo();
textView2.setText("当前网络情况:"+mWifiInfo.getBSSID()+"\n"+mWifiInfo.getMacAddress()+
"\n"+mWifiInfo.getSSID()+"\n"+mWifiInfo.getFrequency()+"\n"+mWifiInfo.getIpAddress());
mHandler.sendEmptyMessageDelayed(SCAN, 2000);
break;
}
}
};
查看mWifiManager.getScanResults();这句代码,你会发现
IWifiManager mService;
//其他代码
/**
* Return the results of the latest access point scan.
* @return the list of access points found in the most recent scan. An app must hold
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get valid results.
*/
public List<ScanResult> getScanResults() {
try {
return
mService.getScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
return null;
}
}
这时候你需要看底层源码具体的实现了,它的实现在:
android / platform / frameworks / opt / net / wifi / lollipop-dev / . / service / java / com / android / server / wifi / WifiServiceImpl.java
/**
* Return the results of the most recent access point scan, in the form of
* a list of {@link ScanResult} objects.
* @return the list of results
*/
public List<ScanResult> getScanResults(String callingPackage) {
enforceAccessPermission();
int userId = UserHandle.getCallingUserId();
int uid = Binder.getCallingUid();
boolean canReadPeerMacAddresses = checkPeersMacAddress();
boolean isActiveNetworkScorer =
NetworkScorerAppManager.isCallerActiveScorer(mContext, uid);
boolean hasInteractUsersFull = checkInteractAcrossUsersFull();
long ident = Binder.clearCallingIdentity();
try {
if (!canReadPeerMacAddresses && !isActiveNetworkScorer
&& !isLocationEnabled(callingPackage)) {
return new ArrayList<ScanResult>();
}
if (!canReadPeerMacAddresses && !isActiveNetworkScorer
&& !checkCallerCanAccessScanResults(callingPackage, uid)) {
return new ArrayList<ScanResult>();
}
if (mAppOps.noteOp(AppOpsManager.OP_WIFI_SCAN, uid, callingPackage)
!= AppOpsManager.MODE_ALLOWED) {
return new ArrayList<ScanResult>();
}
if (!isCurrentProfile(userId) && !hasInteractUsersFull) {
return new ArrayList<ScanResult>();
}
return mWifiStateMachine.syncGetScanResultsList();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
这里重点查看:
if (!canReadPeerMacAddresses && !isActiveNetworkScorer
&& !isLocationEnabled(callingPackage)) {
return new ArrayList<ScanResult>();
}
也就是说谷歌要求我们在定位的时候同时开启GPS的开关,当然这个有可能是谷歌考虑到自己的接口可以通过wifi列表定位,所以要求开发者要让用户有这个知情权吧。