Android模擬位置實現
阿新 • • 發佈:2019-02-02
今天,我們就使用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()));
}
到底,就結束了,現在執行我們的程式,然後選擇一個地點,然後點選確認
接著,開啟微信,開啟附近的人,檢視結果,如果沒有修改定位,多嘗試幾次開啟附近,如果還不行,那就參考 準備工作 是否做好