简单基站定位程序

来源:互联网 发布:基本的医学常识知乎 编辑:程序博客网 时间:2024/04/30 14:43

在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;    }


原创粉丝点击