android里面的原生的Location、LocationManager已经无法实现定位,原因是google关闭了API的定位服务器(http://www.google.com/loc/jsonogle.com/loc/json)。
由于应用涉及到国外和国内不同用户,而全球范围内除了google,还没发现有做的比较好的。
于是有这样的思路,在国内采用百度地图定位,国外则根据基站信息和IP来记录,延后做定位处理,或者根据sim卡信息获取ISOCode,获取国家代码,能确定来自哪个国家。
下载百度定位API,如果编译不过的,需要重新导入locSDK_3.3.jar,clear->rebuild就可以了。
百度定位代码:
public class MainActivity extends Activity
{
private Button cityButton = null;
private String loc = null; // 保存定位信息
public LocationClient mLocationClient = null;
public BDLocationListener myListener = new MyLocationListener();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLocationClient = new LocationClient(getApplicationContext()); // 声明LocationClient类
mLocationClient.registerLocationListener(myListener); // 注册监听函数
cityButton = (Button) super.findViewById(R.id.cityButton);
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true);// 打开GPS
option.setAddrType("all");// 返回的定位结果包含地址信息
option.setCoorType("bd09ll");// 返回的定位结果是百度经纬度,默认值gcj02
option.setScanSpan(3000);// 设置发起定位请求的间隔时间为3000ms
option.disableCache(false);// 禁止启用缓存定位
option.setPriority(LocationClientOption.NetWorkFirst);// 网络定位优先
mLocationClient.setLocOption(option);// 使用设置
mLocationClient.start();// 开启定位SDK
mLocationClient.requestLocation();// 开始请求位置
}
@Override
public void onDestroy()
{
stopListener();//停止监听
super.onDestroy();
}
public class MyLocationListener implements BDLocationListener
{
@Override
public void onReceiveLocation(BDLocation location)
{
if (location != null)
{
StringBuffer sb = new StringBuffer(128);// 接受服务返回的缓冲区
//sb.append(location.getCity());// 获得城市
sb.append(location.getAddrStr());
loc = sb.toString().trim();
MainActivity.this.cityButton.setText(loc);
} else
{
MainActivity.this.cityButton.setText("无法定位");
return;
}
}
@Override
public void onReceivePoi(BDLocation arg0)
{
// TODO Auto-generated method stub
}
}
/**
* 停止,减少资源消耗
*/
public void stopListener()
{
if (mLocationClient != null && mLocationClient.isStarted())
{
mLocationClient.stop();// 关闭定位SDK
mLocationClient = null;
}
}
}
获取硬件信息代码:
public class HardwareInfo {
Context m_Context;
String phoneNumberString; //手机号
String isoCodeString; //ISO标准的国家码,即国际长途区号
String operatorString; //网络运营商的名字
String imei;
String software_version; //软件版本
String device; //机型
String system_version; //android系统版本号
String networking; //联网方式,wifi/3G/2G
SCell sCell; //基站信息
String ipAddress_net; //IP地址-外网
String ipAddress_lan; //IP地址-内网
public HardwareInfo(Context context) {
m_Context = context;
}
public void GetAllInfo() throws Exception {
TelephonyManager tm = (TelephonyManager)m_Context.getSystemService(Context.TELEPHONY_SERVICE);
phoneNumberString = tm.getLine1Number();
isoCodeString = tm.getNetworkCountryIso();
operatorString = tm.getSimOperatorName();
imei =((TelephonyManager)m_Context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
PackageManager pm = m_Context.getPackageManager();
try {
PackageInfo packInfo = pm.getPackageInfo(m_Context.getPackageName(), 0);
software_version = packInfo.versionName;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
device=android.os.Build.MODEL; // 手机型号
system_version=android.os.Build.VERSION.RELEASE;
//获取网络连接管理者
ConnectivityManager connectionManager = (ConnectivityManager)m_Context.getSystemService(Context.CONNECTIVITY_SERVICE);
//获取网络的状态信息,有下面三种方式
NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();
networking = networkInfo.getTypeName();
sCell = getCellInfo();
ipAddress_net = GetNetIp("http://iframe.ip138.com/ic.asp");
ipAddress_lan = getLocalIpAddress();
}
private SCell getCellInfo() throws Exception {
SCell cell = new SCell();
/** 调用API获取基站信息 */
TelephonyManager mTelNet = (TelephonyManager) m_Context.getSystemService(Context.TELEPHONY_SERVICE);
GsmCellLocation location = (GsmCellLocation) mTelNet.getCellLocation();
if (location == null)
throw new Exception("获取基站信息失败");
String operator = mTelNet.getNetworkOperator();
int mcc = Integer.parseInt(operator.substring(0, 3));
int mnc = Integer.parseInt(operator.substring(3));
int cid = location.getCid();
int lac = location.getLac();
/** 将获得的数据放到结构体中 */
cell.MCC = mcc;
cell.MNC = mnc;
cell.LAC = lac;
cell.CID = cid;
return cell;
}
//获取本地IP
public static String getLocalIpAddress() {
try {
for (Enumeration en = NetworkInterface
.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration enumIpAddr = intf
.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()
&& !inetAddress.isLinkLocalAddress()) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (SocketException ex) {
Log.e("WifiPreference IpAddress", ex.toString());
}
return null;
}
//获取外网IP
String GetNetIp(String ipaddr) {
URL infoUrl = null;
InputStream inStream = null;
try {
infoUrl = new URL(ipaddr);
URLConnection connection = infoUrl.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) connection;
int responseCode = httpConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
inStream = httpConnection.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(inStream, "utf-8"));
StringBuilder strber = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
strber.append(line + "\n");
inStream.close();
//从反馈的结果中提取出IP地址
int start = strber.indexOf("[");
int end = strber.indexOf("]", start + 1);
line = strber.substring(start + 1, end);
return line;
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
/** 基站信息结构体 */
public class SCell{
public int MCC; //MCC,Mobile Country Code,移动国家代码(中国的为460);
public int MNC; //MNC,Mobile Network Code,移动网络号码(中国移动为00,中国联通为01);
public int LAC; //LAC,Location Area Code,位置区域码;
public int CID; //CID,Cell Identity,基站编号,是个16位的数据(范围是0到65535)。
public String getCell() {
String myLoc = "" + MCC +":" + MNC + ":" + LAC + ":" + CID;
return myLoc;
}
}
把需要的信息通过POST方式发送给后台Web服务器记录,我的服务器采用Django+mySql。
public class Send2Web {
public static void Send2Sina_Single(HardwareInfo hardwareInfo, BDLocation location) {
List nameValuePairs = new ArrayList();
nameValuePairs.add(new BasicNameValuePair("test_date", location.getTime()));
nameValuePairs.add(new BasicNameValuePair("software_version", hardwareInfo.software_version));
nameValuePairs.add(new BasicNameValuePair("device", hardwareInfo.device));
nameValuePairs.add(new BasicNameValuePair("system_version", hardwareInfo.system_version));
nameValuePairs.add(new BasicNameValuePair("imei", hardwareInfo.imei));
nameValuePairs.add(new BasicNameValuePair("isocode", hardwareInfo.isoCodeString));
nameValuePairs.add(new BasicNameValuePair("location", location.getCity()));
nameValuePairs.add(new BasicNameValuePair("latitude", ""+location.getLatitude()));
nameValuePairs.add(new BasicNameValuePair("longitude", ""+location.getLongitude()));
nameValuePairs.add(new BasicNameValuePair("cgi", hardwareInfo.sCell.getCell()));
nameValuePairs.add(new BasicNameValuePair("ip_address", hardwareInfo.ipAddress_net));
nameValuePairs.add(new BasicNameValuePair("networking", hardwareInfo.networking));
nameValuePairs.add(new BasicNameValuePair("operators", hardwareInfo.operatorString));
int returncode =httpPostData("http://yourweb.sinaapp.com/", nameValuePairs);
Log.i("http_post_return", "code:"+returncode);
}
// 1. 使用POST方式时,传递参数必须使用NameValuePair数组
// 2. 使用GET方式时,通过URL传递参数,注意写法
// 3. 通过setEntity方法来发送HTTP请求
// 4. 通过DefaultHttpClient 的 execute方法来获取HttpResponse
// 5. 通过getEntity()从Response中获取内容
public static int httpPostData(String urlString,List nameValuePairs){
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(urlString);
try{
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
HttpResponse response = httpclient.execute(httppost);
int statusCode = response.getStatusLine().getStatusCode();
return statusCode;
}catch(Exception e){
e.printStackTrace();
}
return 0;
}
}