1. 程式人生 > >Android模擬位置實現

Android模擬位置實現

今天,我們就使用Android自帶的模擬位置功能來實現。

準備工作:

1:設定-開發者選項-允許模擬位置 打鉤

2:我這裡使用了百度地圖,所以需要去申請一個地圖的key。傳送門申請key

3:定位方式修改成 僅限GPS

4:不是所有軟體的GPS都能被欺騙,比如QQ就不行,可能是QQ的定位方式經過處理吧,具體還需要檢驗,我只用微信作為測試,測試是成功的。

上程式碼

1:介面

Demo很簡單,就一個介面,介面上一個百度地圖,用來選擇位置,一個確認按鈕Button,一個顯示位置文字的TextView

佈局檔案activity_main.xml如下

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" >
<Button android:id="@+id/bt_Ok" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="確定" />
<TextView android:id="@+id/tv_location" android:layout_width="match_parent" android:layout_height="wrap_content" /> <RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.baidu.mapapi.map.MapView android:id="@+id/bmapView" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" /> </RelativeLayout> </LinearLayout>

2:程式碼
需要的介面:

[java] view plaincopy
LocationListener 模擬GPS介面
BDLocationListener 百度定位介面
OnMapClickListener 地圖點選介面
OnMarkerDragListener 地圖上拖動介面
OnGetGeoCoderResultListener 反地理資訊搜尋介面

變數定義:

    private String mMockProviderName = LocationManager.GPS_PROVIDER;;  
    private Button bt_Ok;  
    private LocationManager locationManager;  
    private double latitude = 31.3029742, longitude = 120.6097126;// 預設常州  
    private Thread thread;// 需要一個執行緒一直重新整理  
    private Boolean RUN = true;  
    private TextView tv_location;  

    boolean isFirstLoc = true;// 是否首次定位  
    // 定位相關  
    private LocationClient mLocClient;  
    private LocationMode mCurrentMode;// 定位模式  
    private BitmapDescriptor mCurrentMarker;// 定點陣圖標  
    private MapView mMapView;  
    private BaiduMap mBaiduMap;  

    // 初始化全域性 bitmap 資訊,不用時及時 recycle  
    private BitmapDescriptor bd = BitmapDescriptorFactory.fromResource(R.drawable.icon_gcoding);  
    private Marker mMarker;  
    private LatLng curLatlng;  
    private GeoCoder mSearch;  

關鍵程式碼:

@Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        iniView();  
        iniListner();  
        iniData();  
    }  

    /** 
     * iniView 介面初始化 
     *  
     */  
    private void iniView() {  
        bt_Ok = (Button) findViewById(R.id.bt_Ok);  
        tv_location = (TextView) findViewById(R.id.tv_location);  
        // 地圖初始化  
        mMapView = (MapView) findViewById(R.id.bmapView);  
        mBaiduMap = mMapView.getMap();  
        // 開啟定點陣圖層  
        mBaiduMap.setMyLocationEnabled(true);  
        // 定位初始化  
        mLocClient = new LocationClient(this);  
    }  

    /** 
     * iniListner 介面初始化 
     *  
     */  
    private void iniListner() {  
        bt_Ok.setOnClickListener(this);  
        mLocClient.registerLocationListener(this);  
        mBaiduMap.setOnMapClickListener(this);  
        mBaiduMap.setOnMarkerDragListener(this);  

        // 初始化搜尋模組,註冊事件監聽  
        mSearch = GeoCoder.newInstance();  
        mSearch.setOnGetGeoCodeResultListener(this);  
    }  

    /** 
     * iniData 資料初始化 
     *  
     */  
    private void iniData() {  
        inilocation();  
        iniMap();  
    }  

    /** 
     * iniMap 初始化地圖 
     *  
     */  
    private void iniMap() {  
        LocationClientOption option = new LocationClientOption();  
        option.setOpenGps(true);// 開啟gps  
        option.setCoorType("bd09ll"); // 設定座標型別  
        option.setScanSpan(1000);  
        mCurrentMode = LocationMode.NORMAL;  
        // 縮放  
        MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(14.0f);  
        mBaiduMap.setMapStatus(msu);  

        mBaiduMap.setMyLocationConfigeration(new MyLocationConfiguration(mCurrentMode, true,  
                mCurrentMarker));  
        mLocClient.setLocOption(option);  
        mLocClient.start();  
        initOverlay();  

        // 開啟執行緒,一直修改GPS座標  
        thread = new Thread(new Runnable() {  

            @Override  
            public void run() {  
                while (RUN) {  
                    try {  
                        Thread.sleep(500);  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    setLocation(longitude, latitude);  
                }  
            }  
        });  
        thread.start();  
    }  

    /** 
     * initOverlay 設定覆蓋物,這裡就是地圖上那個點 
     *  
     */  
    private void initOverlay() {  
        LatLng ll = new LatLng(latitude, longitude);  
        OverlayOptions oo = new MarkerOptions().position(ll).icon(bd).zIndex(9).draggable(true);  
        mMarker = (Marker) (mBaiduMap.addOverlay(oo));  
    }  

    /** 
     * inilocation 初始化 位置模擬 
     *  
     */  
    private void inilocation() {  
        locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);  
        locationManager.addTestProvider(mMockProviderName, false, true, false, false, true, true,  
                true, 0, 5);  
        locationManager.setTestProviderEnabled(mMockProviderName, true);  
        locationManager.requestLocationUpdates(mMockProviderName, 0, 0, this);  
    }  

    /** 
     * setLocation 設定GPS的位置 
     *  
     */  
    private void setLocation(double longitude, double latitude) {  
        Location location = new Location(mMockProviderName);  
        location.setTime(System.currentTimeMillis());  
        location.setLatitude(latitude);  
        location.setLongitude(longitude);  
        location.setAltitude(2.0f);  
        location.setAccuracy(3.0f);  
        locationManager.setTestProviderLocation(mMockProviderName, location);  
    }  

    @Override  
    public void onLocationChanged(Location location) {  
        double lat = location.getLatitude();  
        double lng = location.getLongitude();  
        Log.i("gps", String.format("location: x=%s y=%s", lat, lng));  
    }  

    @Override  
    public void onStatusChanged(String provider, int status, Bundle extras) {  
        // TODO Auto-generated method stub  

    }  

    @Override  
    public void onProviderEnabled(String provider) {  
        // TODO Auto-generated method stub  

    }  

    @Override  
    public void onProviderDisabled(String provider) {  
        // TODO Auto-generated method stub  

    }  

    @Override  
    protected void onPause() {  
        mMapView.onPause();  
        super.onPause();  
    }  

    @Override  
    protected void onResume() {  
        mMapView.onResume();  
        super.onResume();  
    }  

    @Override  
    public void onBackPressed() {  
        thisFinish();  
    }  

    @Override  
    protected void onDestroy() {  
        RUN = false;  
        thread = null;  

        // 退出時銷燬定位  
        mLocClient.stop();  
        // 關閉定點陣圖層  
        mBaiduMap.setMyLocationEnabled(false);  
        mMapView.onDestroy();  
        mMapView = null;  
        bd.recycle();  
        super.onDestroy();  
    }  

    private void thisFinish() {  
        AlertDialog.Builder build = new AlertDialog.Builder(this);  
        build.setTitle("提示");  
        build.setMessage("退出後,將不再提供定位服務,繼續退出嗎?");  
        build.setPositiveButton("確認", new DialogInterface.OnClickListener() {  

            @Override  
            public void onClick(DialogInterface dialog, int which) {  
                finish();  
            }  
        });  
        build.setNeutralButton("最小化", new DialogInterface.OnClickListener() {  

            @Override  
            public void onClick(DialogInterface dialog, int which) {  
                moveTaskToBack(true);  
            }  
        });  
        build.setNegativeButton("取消", new DialogInterface.OnClickListener() {  

            @Override  
            public void onClick(DialogInterface dialog, int which) {  

            }  
        });  
        build.show();  
    }  

    @Override  
    public void onClick(View v) {  
        int id = v.getId();  
        switch (id) {  
        case R.id.bt_Ok:  
            latitude = curLatlng.latitude;  
            longitude = curLatlng.longitude;  
            break;  
        }  
    }  

    /** 
     * 定位SDK監聽函式 
     */  
    @Override  
    public void onReceiveLocation(BDLocation location) {  
        // map view 銷燬後不在處理新接收的位置  
        if (location == null || mMapView == null) {  
            return;  
        }  

        if (isFirstLoc) {  
            isFirstLoc = false;  
            LatLng ll = new LatLng(location.getLatitude(), location.getLongitude());  
            setCurrentMapLatLng(ll);  
        }  
    }  

    @Override  
    public void onMapClick(LatLng arg0) {  
        setCurrentMapLatLng(arg0);  
    }  

    @Override  
    public boolean onMapPoiClick(MapPoi arg0) {  
        // TODO Auto-generated method stub  
        return false;  
    }  

    /** 
     * setCurrentMapLatLng 設定當前座標 
     */  
    private void setCurrentMapLatLng(LatLng arg0) {  
        curLatlng = arg0;  
        mMarker.setPosition(arg0);  

        // 設定地圖中心點為這是位置  
        LatLng ll = new LatLng(arg0.latitude, arg0.longitude);  
        MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);  
        mBaiduMap.animateMapStatus(u);  

        // 根據經緯度座標 找到實地資訊,會在介面onGetReverseGeoCodeResult中呈現結果  
        mSearch.reverseGeoCode(new ReverseGeoCodeOption().location(arg0));  
    }  

    /** 
     * onMarkerDrag 地圖上標記拖動結束 
     */  
    @Override  
    public void onMarkerDrag(Marker arg0) {  
        // TODO Auto-generated method stub  

    }  

    /** 
     * onMarkerDragEnd 地圖上標記拖動結束 
     */  
    @Override  
    public void onMarkerDragEnd(Marker marker) {  
        setCurrentMapLatLng(marker.getPosition());  
    }  

    /** 
     * onMarkerDragStart 地圖上標記拖動開始 
     */  
    @Override  
    public void onMarkerDragStart(Marker arg0) {  
        // TODO Auto-generated method stub  

    }  

    /** 
     * onGetGeoCodeResult 搜尋(根據實地資訊-->經緯座標) 
     */  
    @Override  
    public void onGetGeoCodeResult(GeoCodeResult arg0) {  
        // TODO Auto-generated method stub  

    }  

    /** 
     * onGetReverseGeoCodeResult 搜尋(根據座標-->實地資訊) 
     */  
    @Override  
    public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {  
        if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {  
            Toast.makeText(this, "抱歉,未能找到結果", Toast.LENGTH_LONG).show();  
            return;  
        }  

        tv_location.setText(String.format("偽造位置:%s", result.getAddress()));  
    }  

到底,就結束了,現在執行我們的程式,然後選擇一個地點,然後點選確認

接著,開啟微信,開啟附近的人,檢視結果,如果沒有修改定位,多嘗試幾次開啟附近,如果還不行,那就參考 準備工作 是否做好