简单基站定位程序

在Android操作系统下,基站定位其实很简单,先说一下实现流程:

调用SDK中的API(TelephonyManager)获得MCC、MNC、LAC、CID等信息,然后通过google的API获得所在位置的经纬度,最后再通过google map的API获得实际的地理位置。(google真牛!)

有同学会问:MNC、MCC、LAC、CID都是些什么东西?google又怎么通过这些东西就获得经纬度了呢?

我们一起来学习一下:

MCC,Mobile Country Code,移动国家代码(中国的为460);

MNC,Mobile Network Code,移动网络号码(中国移动为00,中国联通为01);

LAC,Location Area Code,位置区域码;

CID,Cell Identity,基站编号,是个16位的数据(范围是0到65535)。

了解了这几个名词的意思,相信有些朋友已经知道后面的事了:google存储了这些信息,直接查询就能得到经纬度了。(至于google怎么得到移动、联通的基站信息,这就不得而知了,反正google免费提供接口,直接调用就是)

package com.android.demo;

 
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
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.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
 
public class DemoActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        /** 为按钮绑定事件 */
        Button btnGetLocation = (Button) findViewById(R.id.button1);
        btnGetLocation.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                onBtnClick();
            }
        });
    }
     
    /** 基站信息结构体 */
    public class SCell{
        public int MCC;
        public int MNC;
        public int LAC;
        public int CID;
    }
     
    /** 经纬度信息结构体 */
    public class SItude{
        public String latitude;
        public String longitude;
    }
     
    /** 按钮点击回调函数 */
    private void onBtnClick() {
        /** 弹出一个等待状态的框 */
        ProgressDialog mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setMessage("正在获取中...");
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mProgressDialog.show();
 
        try {
            /** 获取基站数据 */
            SCell cell = getCellInfo();
 
            /** 根据基站数据获取经纬度 */
            SItude itude = getItude(cell);
 
            /** 获取地理位置 */
            String location = getLocation(itude);
 
            /** 显示结果 */
            showResult(cell, location);
 
            /** 关闭对话框 */
            mProgressDialog.dismiss();
        } catch (Exception e) {
            /** 关闭对话框 */
            mProgressDialog.dismiss();
            /** 显示错误 */
            TextView cellText = (TextView) findViewById(R.id.cellText);
            cellText.setText(e.getMessage());
            Log.e("Error", e.getMessage());
        }
    }
     
    /**
     * 获取基站信息
     * 
     * @throws Exception
     */
    private SCell getCellInfo() throws Exception {
        SCell cell = new SCell();
 
        /** 调用API获取基站信息 */
        TelephonyManager mTelNet = (TelephonyManager) 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;
    }
     
    /**
     * 获取经纬度
     * 
     * @throws Exception
     */
    private SItude getItude(SCell cell) throws Exception {
        SItude itude = new SItude();
 
        /** 采用Android默认的HttpClient */
        HttpClient client = new DefaultHttpClient();
        /** 采用POST方法 */
        HttpPost post = new HttpPost("http://www.google.com/loc/json");
        try {
            /** 构造POST的JSON数据 */
            JSONObject holder = new JSONObject();
            holder.put("version", "1.1.0");
            holder.put("host", "maps.google.com");
            holder.put("address_language", "zh_CN");
            holder.put("request_address", true);
            holder.put("radio_type", "gsm");
            holder.put("carrier", "HTC");
 
            JSONObject tower = new JSONObject();
            tower.put("mobile_country_code", cell.MCC);
            tower.put("mobile_network_code", cell.MNC);
            tower.put("cell_id", cell.CID);
            tower.put("location_area_code", cell.LAC);
 
            JSONArray towerarray = new JSONArray();
            towerarray.put(tower);
            holder.put("cell_towers", towerarray);
 
            StringEntity query = new StringEntity(holder.toString());
            post.setEntity(query);
 
            /** 发出POST数据并获取返回数据 */
            HttpResponse response = client.execute(post);
            HttpEntity entity = response.getEntity();
            BufferedReader buffReader = new BufferedReader(new InputStreamReader(entity.getContent()));
            StringBuffer strBuff = new StringBuffer();
            String result = null;
            while ((result = buffReader.readLine()) != null) {
                strBuff.append(result);
            }
 
            /** 解析返回的JSON数据获得经纬度 */
            JSONObject json = new JSONObject(strBuff.toString());
            JSONObject subjosn = new JSONObject(json.getString("location"));
 
            itude.latitude = subjosn.getString("latitude");
            itude.longitude = subjosn.getString("longitude");
             
            Log.i("Itude", itude.latitude + itude.longitude);
             
        } catch (Exception e) {
            Log.e(e.getMessage(), e.toString());
            throw new Exception("获取经纬度出现错误:"+e.getMessage());
        } finally{
            post.abort();
            client = null;
        }
         
        return itude;
    }
     
    /**
     * 获取地理位置
     * 
     * @throws Exception
     */
    private String getLocation(SItude itude) throws Exception {
        String resultString = "";
 
        /** 这里采用get方法,直接将参数加到URL上 */
        String urlString = String.format("http://maps.google.cn/maps/geo?key=abcdefg&q=%s,%s", itude.latitude, itude.longitude);
        Log.i("URL", urlString);
 
        /** 新建HttpClient */
        HttpClient client = new DefaultHttpClient();
        /** 采用GET方法 */
        HttpGet get = new HttpGet(urlString);
        try {
            /** 发起GET请求并获得返回数据 */
            HttpResponse response = client.execute(get);
            HttpEntity entity = response.getEntity();
            BufferedReader buffReader = new BufferedReader(new InputStreamReader(entity.getContent()));
            StringBuffer strBuff = new StringBuffer();
            String result = null;
            while ((result = buffReader.readLine()) != null) {
                strBuff.append(result);
            }
            resultString = strBuff.toString();
 
            /** 解析JSON数据,获得物理地址 */
            if (resultString != null && resultString.length() > 0) {
                JSONObject jsonobject = new JSONObject(resultString);
                JSONArray jsonArray = new JSONArray(jsonobject.get("Placemark").toString());
                resultString = "";
                for (int i = 0; i < jsonArray.length(); i++) {
                    resultString = jsonArray.getJSONObject(i).getString("address");
                }
            }
        } catch (Exception e) {
            throw new Exception("获取物理位置出现错误:" + e.getMessage());
        } finally {
            get.abort();
            client = null;
        }
 
        return resultString;
    }
     
    /** 显示结果 */
    private void showResult(SCell cell, String location) {
        TextView cellText = (TextView) findViewById(R.id.cellText);
        cellText.setText(String.format("基站信息:mcc:%d, mnc:%d, lac:%d, cid:%d",
                cell.MCC, cell.MNC, cell.LAC, cell.CID));
 
        TextView locationText = (TextView) findViewById(R.id.lacationText);
        locationText.setText("物理位置:" + location);
    }
}



打开AndroidManifest.xml配置文件,在里面添加相应的配置信息:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

<uses-permission android:name="android.permission.INTERNET"></uses-permission>


可能有的同学还是出现错误,没有成功:

█ 提示“www.google.com…”什么的错误

请确认你的手机能访问互联网,调用google的API是必须联网的。

█ 提示获取不到基站信息

你确定你是在手机上测试的吗?模拟器可不行哦。或者你的手机使用的CMDA网络?这个例子只支持GSM网络…

█ 获取不到经纬度

很有可能你中奖了,你所在的基站还没纳入google的数据库…(话说我之前也遇到过,怎么查就是查不出经纬度来,返回数据为空)

█ 获取到的地理地址不正确

这个可能程序出错了,可能google出错了?

其实google map API返回的数据中还包含了很多其他信息,我们可以用来开发一些更有趣的功能,如制作我们专属的地图软件、足迹记录软件等,充分发挥你的创造力:)

这个程序基本实现了基站定位功能,但还有很多问题,如:点击了按钮后界面会卡住(访问网络时阻塞了进程)、未对异常进一步处理、不兼容CMDA网络等。

另外这个程序的精度也不够,获得的位置实际上是基站的物理位置,与人所在的位置还有一定差距。在城市里面,一般采用密集型的小功率基站,精度一般在几百米范围内,而在郊区常为大功率基站,密度很小,精度一般在几千米以上。



关于google 基站信息API的官方说明---->google api


通过基站的基本信息,通过Google Gears获取对应的GPS经纬度。

private Location callGear(ArrayList cellID) {
        if (cellID == null) return null;
        DefaultHttpClient client = new DefaultHttpClient();
        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");
            holder.put("home_mobile_country_code", cellID.get(0).mobileCountryCode);
            holder.put("home_mobile_network_code", cellID.get(0).mobileNetworkCode);
            holder.put("radio_type", cellID.get(0).radioType);
            holder.put("request_address", true);
            if ("460".equals(cellID.get(0).mobileCountryCode))
                holder.put("address_language", "zh_CN");
            else
                holder.put("address_language", "en_US");
            JSONObject data,current_data;
            JSONArray array = new JSONArray();
            current_data = new JSONObject();
            current_data.put("cell_id", cellID.get(0).cellId);
            current_data.put("location_area_code", cellID.get(0).locationAreaCode);
            current_data.put("mobile_country_code", cellID.get(0).mobileCountryCode);
            current_data.put("mobile_network_code", cellID.get(0).mobileNetworkCode);
            current_data.put("age", 0);
            array.put(current_data);
            if (cellID.size() > 2) {
                for (int i = 1; i < cellID.size(); i++) {
                    data = new JSONObject();
                    data.put("cell_id", cellID.get(i).cellId);
                    data.put("location_area_code", cellID.get(i).locationAreaCode);
                    data.put("mobile_country_code", cellID.get(i).mobileCountryCode);
                    data.put("mobile_network_code", cellID.get(i).mobileNetworkCode);
                    data.put("age", 0);
                    array.put(data);
                }
            }
            holder.put("cell_towers", array);
            StringEntity se = new StringEntity(holder.toString());
            Log.e("Location send", holder.toString());
            post.setEntity(se);
            HttpResponse resp = client.execute(post);
            HttpEntity entity = resp.getEntity();
 
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(entity.getContent()));
            StringBuffer sb = new StringBuffer();
            String result = br.readLine();
            while (result != null) {
                Log.e("Locaiton receive", result);
                sb.append(result);
                result = br.readLine();
            }
            if(sb.length()              return null;
            data = new JSONObject(sb.toString());
            data = (JSONObject) data.get("location");
 
            Location loc = new 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(GetUTCTime());
            return loc;
        } catch (JSONException e) {
            return null;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


通过Google Map API根据GPS经纬度获取当前位置。

private String getLocation(Location itude) throws Exception {
        String resultString = "";
 
        /** 这里采用get方法,直接将参数加到URL上 */
        String urlString = String.format("http://maps.google.cn/maps/geo?key=abcdefg&q=%s,%s", itude.getLatitude(), itude.getLongitude());
        Log.i("URL", urlString);
 
        /** 新建HttpClient */
        HttpClient client = new DefaultHttpClient();
        /** 采用GET方法 */
        HttpGet get = new HttpGet(urlString);
        try {
            /** 发起GET请求并获得返回数据 */
            HttpResponse response = client.execute(get);
            HttpEntity entity = response.getEntity();
            BufferedReader buffReader = new BufferedReader(new InputStreamReader(entity.getContent()));
            StringBuffer strBuff = new StringBuffer();
            String result = null;
            while ((result = buffReader.readLine()) != null) {
                strBuff.append(result);
            }
            resultString = strBuff.toString();
 
            /** 解析JSON数据,获得物理地址 */
            if (resultString != null && resultString.length() > 0) {
                JSONObject jsonobject = new JSONObject(resultString);
                JSONArray jsonArray = new JSONArray(jsonobject.get("Placemark").toString());
                resultString = "";
                for (int i = 0; i < jsonArray.length(); i++) {
                    resultString = jsonArray.getJSONObject(i).getString("address");
                }
            }
        } catch (Exception e) {
            throw new Exception("获取物理位置出现错误:" + e.getMessage());
        } finally {
            get.abort();
            client = null;
        }
 
        return resultString;
    }


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值