1. 程式人生 > >Android模擬位置資訊

Android模擬位置資訊

Android手機設定——開發人員選擇中有一個“允許模仿位置”的選項,開發人員對開發的某些定位軟體(一般為地圖軟體)做測試的時候使用的,功能是模擬手機目前所處的位置(比如手機當前實際位置在中國,但測試軟體時要求測試條件為美國,就可以使用該功能進行測試軟體模擬定位)。

直接看程式碼:

package cn.vn.test;

import android.annotation.SuppressLint;

public class SetMockLocation extends Activity {
	private static final String TAG = "SetLocation";
	private LocationManager mLocationManager;
	private Context mContext;
	private String mMockProviderName = LocationManager.GPS_PROVIDER;
	private double mLongitude = 40.052462;
	private double mLatitude = 116.29064;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Log.d(TAG,"onCreate");
		mContext=this;
		mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
		enableTestProvider();
		setLocation();//設定模擬位置資訊,也可以建一個thread不斷設定虛擬位置資訊。
	}	
	@Override
	public void onStart() {
		super.onStart();
	}
	
	public void enableTestProvider(){
		ContentResolver res = mContext.getContentResolver();
		//獲取gps的狀態,false為關閉,true為開啟。
		boolean gps_enable = Settings.Secure.isLocationProviderEnabled(
	                      res, android.location.LocationManager.GPS_PROVIDER);
		if(gps_enable){
			//關閉gps
		    Settings.Secure.setLocationProviderEnabled(res,LocationManager.GPS_PROVIDER, false);
		}	
		//獲取“允許模擬地點”的狀態,0為不允許,1為允許。
		int mock_enable = Settings.Secure.getInt(
				res, Settings.Secure.ALLOW_MOCK_LOCATION, 0);  
		if(mock_enable == 0){
			try {
				//開啟 允許模擬地點
				Settings.Secure.putInt(res, Settings.Secure.ALLOW_MOCK_LOCATION, 1);  
			} catch 	(Exception e) {
				Log.e(TAG, "write error", e);
			}
		}
		mLocationManager.addTestProvider(mMockProviderName,
						 "requiresNetwork" == "", "requiresSatellite" == "",
						 "requiresCell" == "", "hasMonetaryCost" == "",
						 "supportsAltitude" == "", "supportsSpeed" == "",
						 "supportsBearing" == "supportsBearing",
						 Criteria.POWER_LOW,
						 Criteria.ACCURACY_FINE);
		mLocationManager.setTestProviderEnabled(mMockProviderName, true);
	    }
	@SuppressLint("NewApi")
	private void setLocation(){
		Log.d(TAG,"setLocation");
		Location loc = new Location(mMockProviderName);//這裡是模擬的gps位置資訊,當然也可以設定network位置資訊了。
		loc.setAccuracy(Criteria.ACCURACY_FINE);
		loc.setTime(System.currentTimeMillis());//設定當前時間
		loc.setLatitude(mLongitude);           //設定緯度
		loc.setLongitude(mLatitude);           //設定經度
		loc.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
		mLocationManager.setTestProviderLocation(mMockProviderName, loc); 
	}
	
	public void unenableTestProvider(){
		int mock_enable = Settings.Secure.getInt(
					   mContext.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0);  
		if(mock_enable == 0) return;
		try {
		    mLocationManager.clearTestProviderEnabled(mMockProviderName);
		    mLocationManager.removeTestProvider(mMockProviderName);
		} catch (Exception e) {
		    Log.e(TAG, "", e);
		}
		try {
			//關閉 允許模擬地點
			Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION, 0);  
		} catch (Exception e) {
		    Log.e(TAG, "write error", e);
		}
	    }
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		unenableTestProvider();
	}
		
}

以上的程式碼中關閉gps和開啟允許模擬位置會報錯:java.lang.SecurityException: Permission denial: writing to secure settings requires android.permission.WRITE_SECURE_SETTINGS。

配置檔案中加入許可權:

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

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

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

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

即使這樣依舊會報上面的錯誤,這是因為只有system app才可以有這個許可權。

這就要把上面的設定gps和模擬位置的程式碼刪掉。自己去設定中開啟模擬位置資訊。

這樣就可以設定想要的位置了。

別的一些軟體可能不顯示這個模擬位置,將獲取位置資訊改為僅裝置。這樣應該就可以了。

這些設定的模擬位置,我們可以通過平常獲取gps和network位置資訊獲取到。