ฉันจะจำลองตำแหน่งของฉันบนอุปกรณ์จริง (Nexus One) ได้อย่างไร ฉันรู้ว่าคุณสามารถทำได้ด้วยตัวจำลองในแผงควบคุมตัวจำลอง แต่สิ่งนี้ไม่ได้ผลสำหรับอุปกรณ์ทางกายภาพ
ฉันจะจำลองตำแหน่งของฉันบนอุปกรณ์จริง (Nexus One) ได้อย่างไร ฉันรู้ว่าคุณสามารถทำได้ด้วยตัวจำลองในแผงควบคุมตัวจำลอง แต่สิ่งนี้ไม่ได้ผลสำหรับอุปกรณ์ทางกายภาพ
คำตอบ:
ดูเหมือนวิธีเดียวที่จะทำคือการใช้ผู้ให้บริการสถานที่จำลอง
คุณต้องเปิดใช้งานสถานที่จำลองในแผงการพัฒนาในการตั้งค่าและเพิ่มของคุณ
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
กับรายการของคุณ
ตอนนี้คุณสามารถเข้าไปในรหัสของคุณและสร้างผู้ให้บริการตำแหน่งจำลองของคุณเองและตั้งค่าตำแหน่งของผู้ให้บริการนี้
หากคุณใช้โทรศัพท์นี้เฉพาะในห้องปฏิบัติการพัฒนามีโอกาสที่คุณจะสามารถประสานชิป GPS และฟีดพอร์ตอนุกรมโดยตรงด้วยลำดับ NMEA จากอุปกรณ์อื่น
ฉันหวังว่าฉันจะมีสายเคเบิลของฉันมีประโยชน์ ฉันรู้ว่าคุณสามารถ telnet เพื่อจำลองเพื่อเปลี่ยนตำแหน่ง
$ telnet localhost 5554
Android Console: type 'help' for a list of commands
OK
geo fix -82.411629 28.054553
OK
ฉันจำไม่ได้ว่าคุณสามารถ telnet ไปยังอุปกรณ์ของคุณ แต่ฉันคิดว่าคุณทำได้ ฉันหวังว่านี่จะช่วยได้.
คุณจะต้องใช้ adb (สะพานแก้จุดบกพร่อง Android) สำหรับสิ่งนี้ (CLI)
คุณสามารถใช้สิทธิ์บริการตำแหน่งเพื่อจำลองตำแหน่ง ...
"android.permission.ACCESS_MOCK_LOCATION"
และในจาวาโค้ดของคุณ
// Set location by setting the latitude, longitude and may be the altitude...
String[] MockLoc = str.split(",");
Location location = new Location(mocLocationProvider);
Double lat = Double.valueOf(MockLoc[0]);
location.setLatitude(lat);
Double longi = Double.valueOf(MockLoc[1]);
location.setLongitude(longi);
Double alti = Double.valueOf(MockLoc[2]);
location.setAltitude(alti);
ฉันประสบความสำเร็จกับรหัสต่อไปนี้ แม้ว่ามันจะให้ฉันล็อคเดียวด้วยเหตุผลบางอย่าง (แม้ว่าฉันได้ลองคู่ LatLng ที่แตกต่างกัน) มันทำงานได้สำหรับฉัน mLocationManager
เป็นสิ่งLocationManager
ที่เกี่ยวกับLocationListener
:
private void getMockLocation()
{
mLocationManager.removeTestProvider(LocationManager.GPS_PROVIDER);
mLocationManager.addTestProvider
(
LocationManager.GPS_PROVIDER,
"requiresNetwork" == "",
"requiresSatellite" == "",
"requiresCell" == "",
"hasMonetaryCost" == "",
"supportsAltitude" == "",
"supportsSpeed" == "",
"supportsBearing" == "",
android.location.Criteria.POWER_LOW,
android.location.Criteria.ACCURACY_FINE
);
Location newLocation = new Location(LocationManager.GPS_PROVIDER);
newLocation.setLatitude (/* TODO: Set Some Lat */);
newLocation.setLongitude(/* TODO: Set Some Lng */);
newLocation.setAccuracy(500);
mLocationManager.setTestProviderEnabled
(
LocationManager.GPS_PROVIDER,
true
);
mLocationManager.setTestProviderStatus
(
LocationManager.GPS_PROVIDER,
LocationProvider.AVAILABLE,
null,
System.currentTimeMillis()
);
mLocationManager.setTestProviderLocation
(
LocationManager.GPS_PROVIDER,
newLocation
);
}
setTestProviderStatus
จะใช้ที่นี่เพื่อแจ้งเตือน / โพสต์ไปยัง / กำหนดเวลาเหตุการณ์ด้วย LocationManager ที่ผู้ให้บริการ GPS พบการแก้ไข "ตอนนี้" เพื่อให้การประมวลผลของเหตุการณ์ดังกล่าวสามารถเกิดขึ้นได้
mLocationManager
คืออะไรLocationManager
ซึ่งขึ้นอยู่กับ LocationListener"? ฉันจะทำสิ่งนี้ได้อย่างไร ขอบคุณ ..
LocationManager
บริการและLocationListener
: blog.doityourselfandroid.com/2010/12/25/...
สิ่งที่ Dr1Ku โพสต์ทำงานได้ ใช้รหัสวันนี้ แต่ต้องการเพิ่ม locs เพิ่มเติม ดังนั้นนี่คือการปรับปรุงบางอย่าง:
ทางเลือก: แทนที่จะใช้สตริง LocationManager.GPS_PROVIDER คุณอาจต้องการกำหนด constat PROVIDER_NAME ของคุณเองและใช้มัน เมื่อลงทะเบียนเพื่ออัปเดตตำแหน่งให้เลือกผู้ให้บริการผ่านเกณฑ์แทนการระบุโดยตรงเป็นสตริง
ครั้งแรก: แทนที่จะเรียก removeTestProvider ก่อนอื่นให้ตรวจสอบว่ามีผู้ให้บริการที่จะลบหรือไม่ (เพื่อหลีกเลี่ยง IllegalArgumentException):
if (mLocationManager.getProvider(PROVIDER_NAME) != null) {
mLocationManager.removeTestProvider(PROVIDER_NAME);
}
ที่สอง: ในการเผยแพร่มากกว่าหนึ่งที่ตั้งคุณต้องตั้งเวลาสำหรับที่ตั้ง:
newLocation.setTime(System.currentTimeMillis());
...
mLocationManager.setTestProviderLocation(PROVIDER_NAME, newLocation);
นอกจากนี้ยังมีการทดสอบ google ที่ใช้ MockLocationProviders: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/1.5_r4/android/location/LocationManagerProximityTest.java
ตัวอย่างการทำงานที่ดีอีกตัวอย่างสามารถดูได้ที่: http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/
อีกบทความที่ดีคือ: http://ballardhack.wordpress.com/2010/09/23/location-gps-and-automated-testing-on-android/#comment-1358 นอกจากนี้คุณยังจะพบรหัสบางอย่างที่ใช้งานได้จริงสำหรับ ฉันในโปรแกรมจำลอง
Mock Provider
GPS ปกติจะไม่ทำงานฉันไม่สามารถแก้ไขได้ (ฉันกำลังทดสอบอุปกรณ์โดยตรง) นี่อาจไม่เป็นเช่นนั้นเนื่องจากมีเหตุการณ์มากมายเกิดขึ้นใน Android ตั้งแต่นั้นมา
มีแอพที่มีอยู่ใน Android Market ที่ให้คุณระบุ "ตำแหน่งจำลอง" สำหรับอุปกรณ์ของคุณ
ฉันค้นหาhttps://market.android.comและพบแอปที่ชื่อว่า "My Fake Location" ที่เหมาะกับฉัน
ผู้ให้บริการ GPS จำลองที่กล่าวถึงโดย Paul ด้านบน (ที่http://www.cowlumbus.nl/forum/MockGpsProvider.zip ) เป็นอีกตัวอย่างหนึ่งที่มีซอร์สโค้ด - แม้ว่าฉันจะไม่สามารถติดตั้ง APK ที่ให้มาได้ (กล่าวว่าล้มเหลว [INSTALL_FAILED_OLDER_SDK] และอาจต้องการคอมไพล์ใหม่)
ในการใช้ตำแหน่งจำลอง GPS คุณต้องเปิดใช้งานในการตั้งค่าอุปกรณ์ของคุณ ไปที่การตั้งค่า -> แอปพลิเคชัน -> การพัฒนาและทำเครื่องหมาย "อนุญาตสถานที่จำลอง"
จากนั้นคุณสามารถใช้แอพที่อธิบายไว้ข้างต้นเพื่อตั้งค่าพิกัด GPS และ Google maps และแอพอื่น ๆ จะใช้ตำแหน่งจำลอง GPS ที่คุณระบุ
สิ่งนี้ใช้ได้สำหรับฉัน (Android Studio):
ปิดใช้งานการติดตาม GPS และ WiFi บนโทรศัพท์ บน Android 5.1.1 และด้านล่างเลือก "เปิดใช้งานตำแหน่งจำลอง" ในตัวเลือกของนักพัฒนา
ทำสำเนารายการของคุณในไดเรกทอรี src / debug เพิ่มรายการต่อไปนี้ (นอกแท็ก "แอปพลิเคชัน"):
Android ใช้สิทธิ์: name = "android.permission.ACCESS_MOCK_LOCATION"
ตั้งค่าส่วนแผนที่เรียกว่า "แผนที่" รวมรหัสต่อไปนี้ใน onCreate ():
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
ll = new MyLocationListener();
if (lm.getProvider("Test") == null) {
lm.addTestProvider("Test", false, false, false, false, false, false, false, 0, 1);
}
lm.setTestProviderEnabled("Test", true);
lm.requestLocationUpdates("Test", 0, 0, ll);
map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng l) {
Location loc = new Location("Test");
loc.setLatitude(l.latitude);
loc.setLongitude(l.longitude);
loc.setAltitude(0);
loc.setAccuracy(10f);
loc.setElapsedRealtimeNanos(System.nanoTime());
loc.setTime(System.currentTimeMillis());
lm.setTestProviderLocation("Test", loc);
}
};
โปรดทราบว่าคุณอาจต้องเพิ่ม "minSdkVersion" ในโมดูลไฟล์ gradle ของคุณชั่วคราวเป็น 17 เพื่อใช้วิธีการ "setElapsedRealtimeNanos"
รวมรหัสต่อไปนี้ไว้ในคลาสกิจกรรมหลัก:
private class MyLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
// do whatever you want, scroll the map, etc.
}
}
เรียกใช้แอปของคุณด้วย AS ใน Android 6.0 ขึ้นไปคุณจะได้รับข้อยกเว้นด้านความปลอดภัย ตอนนี้ไปที่ตัวเลือกของนักพัฒนาในการตั้งค่าและเลือก "เลือกแอปจำลองตำแหน่ง" เลือกแอพของคุณจากรายการ
ตอนนี้เมื่อคุณแตะบนแผนที่ onLocationChanged () จะเริ่มต้นด้วยพิกัดของการแตะของคุณ
ฉันเพิ่งรู้เรื่องนี้ดังนั้นตอนนี้ฉันไม่ต้องเดินไปรอบ ๆ บริเวณใกล้เคียงด้วยโทรศัพท์ในมือ
ฉันได้สร้างตัวจัดการแบบง่ายจำลองตำแหน่งการเคลื่อนที่จากตำแหน่งเริ่มต้น
เริ่มในการติดต่อกลับของคุณ:
private final GoogleApiClient.ConnectionCallbacks mConnectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
if (BuildConfig.USE_MOCK_LOCATION) {
LocationServices.FusedLocationApi.setMockMode(mGoogleApiClient, true);
new MockLocationMovingHandler(mGoogleApiClient).start(48.873399, 2.342911);
}
}
@Override
public void onConnectionSuspended(int i) {
}
};
ชั้นจัดการ:
private static class MockLocationMovingHandler extends Handler {
private final static int SET_MOCK_LOCATION = 0x000001;
private final static double STEP_LATITUDE = -0.00005;
private final static double STEP_LONGITUDE = 0.00002;
private final static long FREQUENCY_MS = 1000;
private GoogleApiClient mGoogleApiClient;
private double mLatitude;
private double mLongitude;
public MockLocationMovingHandler(final GoogleApiClient googleApiClient) {
super(Looper.getMainLooper());
mGoogleApiClient = googleApiClient;
}
public void start(final double initLatitude, final double initLongitude) {
if (hasMessages(SET_MOCK_LOCATION)) {
removeMessages(SET_MOCK_LOCATION);
}
mLatitude = initLatitude;
mLongitude = initLongitude;
sendEmptyMessage(SET_MOCK_LOCATION);
}
public void stop() {
if (hasMessages(SET_MOCK_LOCATION)) {
removeMessages(SET_MOCK_LOCATION);
}
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
case SET_MOCK_LOCATION:
Location location = new Location("network");
location.setLatitude(mLatitude);
location.setLongitude(mLongitude);
location.setTime(System.currentTimeMillis());
location.setAccuracy(3.0f);
location.setElapsedRealtimeNanos(System.nanoTime());
LocationServices.FusedLocationApi.setMockLocation(mGoogleApiClient, location);
mLatitude += STEP_LATITUDE;
mLongitude += STEP_LONGITUDE;
sendEmptyMessageDelayed(SET_MOCK_LOCATION, FREQUENCY_MS);
break;
}
}
}
หวังว่ามันจะช่วย ..
วิธีแก้ปัญหาที่กล่าวถึงโดย icyerasor และจัดหาโดย Pedro ที่ http://pedroassuncao.com/blog/2009/11/12/android-location-provider-mock/ ทำงานได้ดีมากสำหรับฉัน อย่างไรก็ตามมันไม่ได้ให้การสนับสนุนสำหรับการเริ่มต้นการหยุดและการรีสตาร์ทผู้ให้บริการ GPS จำลองอย่างถูกต้อง
ฉันได้เปลี่ยนรหัสของเขาเล็กน้อยและเขียนคลาสใหม่เป็น AsyncTask แทนเธรด สิ่งนี้ช่วยให้เราสามารถสื่อสารกับ UI Thread ดังนั้นเราจึงสามารถเริ่มต้นใหม่ผู้ให้บริการ ณ จุดที่เราอยู่เมื่อเราหยุดมัน สิ่งนี้มีประโยชน์เมื่อการวางแนวหน้าจอเปลี่ยนไป
รหัสพร้อมกับโครงการตัวอย่างสำหรับ Eclipse สามารถพบได้ใน GitHub: https://github.com/paulhoux/Android-MockProviderGPS
เครดิตทั้งหมดควรไปที่ Pedro เพื่อทำงานอย่างหนัก
เพิ่มในรายการของคุณ
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"
tools:ignore="MockLocation,ProtectedPermissions" />
ฟังก์ชันตำแหน่งจำลอง
void setMockLocation() {
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
locationManager.addTestProvider(LocationManager.GPS_PROVIDER, false, false,
false, false, true, true, true, 0, 5);
locationManager.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true);
Location mockLocation = new Location(LocationManager.GPS_PROVIDER);
mockLocation.setLatitude(-33.852); // Sydney
mockLocation.setLongitude(151.211);
mockLocation.setAltitude(10);
mockLocation.setAccuracy(5);
mockLocation.setTime(System.currentTimeMillis());
mockLocation.setElapsedRealtimeNanos(System.nanoTime());
locationManager.setTestProviderLocation(LocationManager.GPS_PROVIDER, mockLocation);
}
คุณจะต้องเปิดใช้งานตำแหน่งจำลองในการตั้งค่าผู้พัฒนาอุปกรณ์ของคุณ หากยังไม่พร้อมใช้งานให้ตั้ง "แอปพลิเคชันตำแหน่งจำลอง" เป็นแอปพลิเคชันของคุณเมื่อมีการใช้งานด้านบน
แอพ GPS ปลอมจาก google play ช่วยฉันได้ เพียงให้แน่ใจว่าคุณอ่านเส้นทางทั้งหมดในคำอธิบายแอพ คุณต้องปิดการใช้งานบริการระบุตำแหน่งอื่น ๆ รวมถึงเริ่มแอพหลังจากเปิดใช้งาน "Fake GPS" ทำงานได้ดีสำหรับสิ่งที่ฉันต้องการ
นี่คือลิงค์ไปยังแอปใน GooglePlay: Fake GPS
บทช่วยสอนของ Google สำหรับการทำสิ่งนี้สามารถพบได้ที่นี่มีตัวอย่างโค้ดและอธิบายกระบวนการ
http://developer.android.com/training/location/location-testing.html#SendMockLocations
ติดตั้งแอพปลอม GPS https://play.google.com/store/apps/details?id=com.incorporateapps.fakegps.fre&hl=th
ตัวเลือกของนักพัฒนา -> เลือกแอปจำลองตำแหน่ง (หมายถึงแอพปลอมที่ตั้ง)
แอพ GPS ปลอม :
แท็บสองครั้งบนแผนที่เพื่อเพิ่ม -> คลิกปุ่มเล่น -> แสดงขนมปัง "หยุดตำแหน่งปลอม"
ในที่สุดตรวจสอบกับแอพ google map
ฉันเขียนแอพที่ใช้งาน WebServer (REST-Like) บนโทรศัพท์ Android ของคุณเพื่อให้คุณสามารถตั้งตำแหน่ง GPS จากระยะไกลได้ เว็บไซต์จัดทำแผนที่ซึ่งคุณสามารถคลิกเพื่อกำหนดตำแหน่งใหม่หรือใช้ปุ่ม "wasd" เพื่อเลื่อนไปในทิศทางใดก็ได้ แอปเป็นวิธีแก้ปัญหาอย่างรวดเร็วดังนั้นจึงแทบไม่มี UI หรือเอกสาร แต่การนำไปใช้งานนั้นเป็นไปอย่างรวดเร็วและคุณสามารถค้นหาทุกอย่างในชั้นเรียน (เพียงสี่)
ที่เก็บโครงการ: https://github.com/juliusmh/RemoteGeoFix
หากอุปกรณ์ของคุณเสียบเข้ากับคอมพิวเตอร์และพยายามเปลี่ยนสาย GPS ผ่านทางตัวควบคุม Emulator อุปกรณ์นั้นจะไม่ทำงาน
นี่คือการควบคุมอีมูเลเตอร์ด้วยเหตุผล
เพียงตั้งค่าเพื่ออัปเดตคุณในการเปลี่ยน GPS
lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
ll = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
onGPSLocationChanged(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {
bigInfo.setText("Changed "+ status);
}
public void onProviderEnabled(String provider) {
bigInfo.setText("Enabled "+ provider);
}
public void onProviderDisabled(String provider) {
bigInfo.setText("Disabled "+ provider);
}
};
เมื่อ GPS ได้รับการปรับปรุงให้เขียนวิธีการต่อไปนี้เพื่อทำสิ่งที่คุณต้องการ
public void onGPSLocationChanged(Location location){
if(location != null){
double pLong = location.getLongitude();
double pLat = location.getLatitude();
textLat.setText(Double.toString(pLat));
textLong.setText(Double.toString(pLong));
if(autoSave){
saveGPS();
}
}
}
อย่าลืมที่จะนำเหล่านี้ในที่ประจักษ์
android.permission.ACCESS_FINE_LOCATION
android.permission.ACCESS_MOCK_LOCATION
ฉันสงสัยว่าคุณต้องการการตั้งค่าตำแหน่งจำลองอย่างละเอียดหรือไม่ ในกรณีของฉันเมื่อฉันได้รับตำแหน่งแก้ไขฉันถูกเรียกใช้ฟังก์ชันเพื่อทำบางสิ่งบางอย่างกับตำแหน่งใหม่นั้น ในเวลาสร้างสถานที่จำลอง และเรียกใช้ฟังก์ชั่นด้วยตำแหน่งนั้นแทน รู้มาตลอดว่าในระยะสั้นขณะที่ GPS จะเกิดขึ้นกับตำแหน่งปัจจุบันจริง ซึ่งก็โอเค หากคุณมีเวลาอัปเดตตั้งไว้อย่างเพียงพอ
อาจไม่ใช่วิธี 'โปรแกรมเมอร์' แต่ถ้าคุณต้องการประหยัดเวลาและหาวิธีแก้ปัญหาในการทำงานลองใช้แอปหนึ่งในแอปที่อุทิศให้กับสถานที่จำลองใน Google Play:
ใช้ประโยชน์จากเครื่องมือจำลองตำแหน่งแบบโต้ตอบที่สะดวกและฟรีสำหรับโทรศัพท์และแท็บเล็ต Android (ชื่อ CATLES) มันสร้างตำแหน่ง GPS ในระดับระบบ (แม้ในแอพ Google Maps หรือ Facebook) และทำงานได้ทั้งบนอุปกรณ์จริงและอุปกรณ์เสมือน:
ใช้สิทธิ์นี้ในไฟล์ Manifest
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION">
android studio จะแนะนำว่า "ควรจะขอตำแหน่งจำลองในไฟล์ทดสอบหรือดีบักเฉพาะรายการ (โดยทั่วไปคือ src / debug / AndroidManifest.xml)" เพียงปิดการใช้งานการตรวจสอบ
ตอนนี้ให้แน่ใจว่าคุณได้ตรวจสอบ " อนุญาตสถานที่จำลอง " ในการตั้งค่านักพัฒนาของโทรศัพท์ของคุณ
ใช้ LocationManager
locationManager.addTestProvider(mocLocationProvider, false, false,
false, false, true, true, true, 0, 5);
locationManager.setTestProviderEnabled(mocLocationProvider, true);
ตอนนี้ตั้งค่าตำแหน่งทุกที่ที่คุณต้องการ
Location mockLocation = new Location(mocLocationProvider);
mockLocation.setLatitude(lat);
mockLocation.setLongitude(lng);
mockLocation.setAltitude(alt);
mockLocation.setTime(System.currentTimeMillis());
locationManager.setTestProviderLocation( mocLocationProvider, mockLocation);
การแก้ปัญหาดังกล่าวข้างต้นไม่ได้ทำงานสำหรับฉันเพราะฉันถูกทดสอบบนอุปกรณ์ Android กับรุ่นล่าสุดบริการของ Google Play ซึ่งใช้FusedLocationProviderClient หลังจากตั้งค่าการอนุญาตตำแหน่งจำลองในรายการแอพและแอปเป็นแอปจำลองตำแหน่งที่ระบุในการตั้งค่านักพัฒนาซอฟต์แวร์ (ตามที่ระบุไว้ในคำตอบก่อนหน้า) จากนั้นฉันเพิ่มรหัส Kotlin ด้านล่างซึ่งจำลองตำแหน่งเรียบร้อยแล้ว
locationProvider = FusedLocationProviderClient(context)
locationProvider.setMockMode(true)
val loc = Location(providerName)
val mockLocation = Location(providerName) // a string
mockLocation.latitude = latitude // double
mockLocation.longitude = longitude
mockLocation.altitude = loc.altitude
mockLocation.time = System.currentTimeMillis()
mockLocation.accuracy = 1f
mockLocation.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mockLocation.bearingAccuracyDegrees = 0.1f
mockLocation.verticalAccuracyMeters = 0.1f
mockLocation.speedAccuracyMetersPerSecond = 0.01f
}
// locationManager.setTestProviderLocation(providerName, mockLocation)
locationProvider.setMockLocation(mockLocation)