Slide 1

Slide 1 text

ਫௗܟຬ lҐஔ৘ใΛਖ਼֬ʹτϥοΩϯά͢Δٕज़z @mizutory /

Slide 2

Slide 2 text

ࣗݾ঺հ 4POZ&SJDTTPOͰܞଳి࿩ͷ։ൃΛ9QFSJB9
 ·Ͱ΍͍ͬͯ·ͨ͠ɻ
 %FWJDF%SJWFS #PPU$PEF .FNPSZ.BOBHFS (PMESVTI$PNQVUJOHגࣜձࣾΛ࢝ΊΔ Ґஔ৘ใΛ࢖ͬͨ"OESPJEJ04ΞϓϦΛ։ൃͯ͠དྷ·ͨ͠ɻ

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Ґஔ৘ใͷऔಘ Ϛοϓ΁ͷඳը Ґஔ৘ใͷϑΟϧλϦϯά όοςϦʔফඅʹ͍ͭͯ

Slide 5

Slide 5 text

Ґஔ৘ใͷऔಘ

Slide 6

Slide 6 text

Ґஔ৘ใτϥοΩϯάͷͨΊͷΞʔΩςΫνϟ .BJO"DUJWJUZ -PDBUJPO4FSWJDF TUBSU CJOE PO4FSWJDF$POOFDUFE

Slide 7

Slide 7 text

-PDBUJPO.BOBHFS LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); Integer gpsFreqInMillis = 1000; Integer gpsFreqInDistance = 5; // in meters locationManager.addGpsStatusListener(this); locationManager.requestLocationUpdates(gpsFreqInMillis, gpsFreqInDistance, criteria, this, null); LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); Integer gpsFreqInMillis = 1000; Integer gpsFreqInDistance = 5; // in meters locationManager.addGpsStatusListener(this); locationManager.requestLocationUpdates(gpsFreqInMillis, gpsFreqInDistance, criteria, this, null); LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); Integer gpsFreqInMillis = 1000; Integer gpsFreqInDistance = 5; // in meters locationManager.addGpsStatusListener(this); locationManager.requestLocationUpdates(gpsFreqInMillis, gpsFreqInDistance, criteria, this, null); LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); Integer gpsFreqInMillis = 1000; Integer gpsFreqInDistance = 5; // in meters locationManager.addGpsStatusListener(this); locationManager.requestLocationUpdates(gpsFreqInMillis, gpsFreqInDistance, criteria, this, null);

Slide 8

Slide 8 text

$SJUFSJBͷ࡞੒ Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH);

Slide 9

Slide 9 text

Ґஔ৘ใऔಘ࣌ͷίʔϧόοΫPO-PDBUJPO$IBOHFE ͜͜Ͱ-PDBUJPOΦϒδΣΫτΛऔಘͯ͠ɺ-PDBM#SPBEDBTU.BOBHFSΛ࢖ͬ ͯαʔϏεͷ֎ʹ௨஌͢Δɻ public void onLocationChanged(final Location newLocation) { if(isLogging){ //locationList.add(newLocation); filterAndAddLocation(newLocation); } Intent intent = new Intent("LocationUpdated"); intent.putExtra("location", newLocation); LocalBroadcastManager.getInstance(this.getApplication()).sendBroadcast(intent); }

Slide 10

Slide 10 text

Ϛοϓ΁ͷඳը

Slide 11

Slide 11 text

.BQ"1*,FZͷऔಘ

Slide 12

Slide 12 text

HSBEMF

Slide 13

Slide 13 text

.BQ7JFX

Slide 14

Slide 14 text

mapView = (MapView) this.findViewById(R.id.map); mapView.onCreate(savedInstanceState); mapView.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap googleMap) { map = googleMap; map.getUiSettings().setZoomControlsEnabled(false); map.setMyLocationEnabled(false); map.getUiSettings().setCompassEnabled(true); map.getUiSettings().setMyLocationButtonEnabled(true); w ζʔϜίϯτϩʔϧΛඇදࣔʹ͢Δɻ w ࣗ෼ͷҐஔΛࣔ͢ΠϯσΟέʔλʔΛඇදࣔʹ͢Δɻ ޙͰࣗ෼Ͱඳ͘ʣ w ίϯύεͷػೳΛΦϯʹ͢Δ w ݱࡏ஍ʹඈͿϘλϯΛදࣔʹ͢Δ

Slide 15

Slide 15 text

Ϛοϓ্΁ͷඳը -PDBUJPO4FSWJDF .BJO"DUJWJUZ -PDBUJPO

Slide 16

Slide 16 text

Ϛοϓ্΁ͷඳը NBQBEE$JSDMF

Slide 17

Slide 17 text

Ϛοϓ্΁ͷඳը NBQBEE.BSLFS [PPNͯ͠΋ಉ͡େ͖͞

Slide 18

Slide 18 text

Ϛοϓ্΁ͷඳը NBQBEE1PMZMJOF

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

ϑΟϧλϦϯά

Slide 21

Slide 21 text

औಘ࣌ࠁͰϑΟϧλʔ͢Δ

Slide 22

Slide 22 text

Ґஔ৘ใऔಘλΠϛϯάʹӨڹΛ༩͑Δ΋ͷ • GPSӴ੕ͷҐஔ ʢ಄্ʹͨ͘͞Μ͋Δ͔Ͳ͏͔ʣ • Ӵ੕ͱAndroidػͱͷؒͷো֐෺ʢϏϧɺथ໦ɺӢͳ Ͳʣ • ܞଳి࿩ج஍ہͷҐஔ ʢۙ͘ʹͨ͘͞Μ͋Δ͔ʣ • ܞଳి࿩ج஍ہͱAndroidػͱͷؒͷো֐෺ͷঢ়گ ݹ͍Ґஔ৘ใ Ωϟογϡ͞ΕͨҐஔ৘ใ

Slide 23

Slide 23 text

Ґஔ৘ใͷݹ͞Λଌఆͯ͠ϑΟϧλʔ͢Δ private long getLocationAge(Location newLocation){ long locationAge; if(android.os.Build.VERSION.SDK_INT >= 17) { long currentTimeInMilli = (long)(SystemClock.elapsedRealtimeNanos() / 1000000); long locationTimeInMilli = (long)(newLocation.getElapsedRealtimeNanos() / 1000000 locationAge = currentTimeInMilli - locationTimeInMilli; }else{ locationAge = System.currentTimeMillis() - newLocation.getTime(); } return locationAge; } long age = getLocationAge(location); if(age > 5 * 1000){ //more than 5 seconds Log.d(TAG, "Location is old"); oldLocationList.add(location); return false; }

Slide 24

Slide 24 text

ਫฏํ޲ͷਫ਼౓ͰϑΟϧλʔ͢Δ

Slide 25

Slide 25 text

ਫฏํ޲ͷਫ਼౓͕औΕͳ͍έʔεΛ஄͘ if(location.getAccuracy() <= 0){ Log.d(TAG, "Latitidue and longitude values are invalid."); noAccuracyLocationList.add(location); return false; }

Slide 26

Slide 26 text

ਫฏํ޲ͷਫ਼౓ͰϑΟϧλʔ͢Δ float horizontalAccuracy = location.getAccuracy(); if(horizontalAccuracy > 10){ //10meter filter Log.d(TAG, "Accuracy is too low."); inaccurateLocationList.add(location); return false; }

Slide 27

Slide 27 text

ϑΟϧλʔͨ͠ྫ

Slide 28

Slide 28 text

HFU"DDVSBDZ ͷਫ਼౓͸

Slide 29

Slide 29 text

,BMNBO'JMUFSͰϑΟϧλʔ͢Δ /* Kalman Filter */ float Qvalue; long locationTimeInMillis = (long)(location.getElapsedRealtimeNanos() / 1000000); long elapsedTimeInMillis = locationTimeInMillis - runStartTimeInMillis; if(currentSpeed == 0.0f){ Qvalue = 3.0f; //3 meters per second }else{ Qvalue = currentSpeed; // meters per second } kalmanFilter.Process(location.getLatitude(), location.getLongitude(), location.getAccuracy(), elapsedTimeInMillis, Qvalue double predictedLat = kalmanFilter.get_lat(); double predictedLng = kalmanFilter.get_lng(); Location predictedLocation = new Location("");//provider name is unecessary predictedLocation.setLatitude(predictedLat);//your coords of course predictedLocation.setLongitude(predictedLng); float predictedDeltaInMeters = predictedLocation.distanceTo(location); if(predictedDeltaInMeters > 60){ Log.d(TAG, "Kalman Filter detects mal GPS, we should probably remove this from track"); kalmanFilter.consecutiveRejectCount += 1; if(kalmanFilter.consecutiveRejectCount > 3){ kalmanFilter = new KalmanLatLong(3); //reset Kalman Filter if it rejects more than 3 times in raw. } kalmanNGLocationList.add(location); return false; }else{ kalmanFilter.consecutiveRejectCount = 0; }

Slide 30

Slide 30 text

,BMNBO'JMUFSͰϑΟϧλʔ͢Δ

Slide 31

Slide 31 text

,BMNBO'JMUFSͰϑΟϧλʔ͢Δ

Slide 32

Slide 32 text

RunKeeper

Slide 33

Slide 33 text

Nike+

Slide 34

Slide 34 text

Nike+

Slide 35

Slide 35 text

όοςϦʔ

Slide 36

Slide 36 text

時間(秒) 距離(m) GPS個数 バッテリー
 (スタート時) バッテリー
 (ゴール) 消費量 42km走った 場合 5時間走った 場合 Nexus6 Low Battery (every 5m) 1968 5710.0 790 16% 12% 4% 29.6% 36.6% Nexus6p Mid Battery (every 1m) 1785 5738.8 1349 50% 48% 2% 14.7% 20.1% Nexus6 Low Battery (every 5m) 1497 4583.8 581 22% 20% 2% 18.4% 24% Nexus6p High Battery (every 5m) 1684 5036.0 675 98% 95% 3% 25.1% 32% ෼ɺLNͰͷফඅྔ

Slide 37

Slide 37 text

όοςϦʔ࢒ྔͷऔಘ private BroadcastReceiver batteryInfoReceiver = new BroadcastReceiver(){ @Override public void onReceive(Context ctxt, Intent intent) { int batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); float batteryLevelScaled = batteryLevel / (float)scale; batteryLevelArray.add(Integer.valueOf(batteryLevel)); batteryLevelScaledArray.add(Float.valueOf(batteryLevelScaled)); batteryScale = scale; } };

Slide 38

Slide 38 text

όοςϦʔ࢒ྔʹΑͬͯ$SJUFSJBΛม͑Δ .JOJNVN%JTUBODFͱ.JOJNVN5JNF͸ม͑ͯ΋(14νοϓ͕ফඅ͢ΔΤωϧΪʔ͸ಉ ͡ɻҐஔ৘ใΛड͚औ͔ͬͯΒͷॲཧʹΤωϧΪʔΛ࢖͍ͬͯΔ৔߹ʢαʔόʔ΁ͷૹ৴ͳͲʣ ͸ɺ.JOJNVN%JTUBODFͱ.JOJNVN5JNFͷ஋Λେ͖͘͢Δɻ όοςϦʔ࢒ྔΛҙࣝͨ͠ઃܭ LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria(); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_HIGH); criteria.setAltitudeRequired(false); criteria.setSpeedRequired(true); criteria.setCostAllowed(true); criteria.setBearingRequired(false); //API level 9 and up criteria.setHorizontalAccuracy(Criteria.ACCURACY_HIGH); criteria.setVerticalAccuracy(Criteria.ACCURACY_HIGH); Integer gpsFreqInMillis = 1000; Integer gpsFreqInDistance = 5; // in meters locationManager.addGpsStatusListener(this); locationManager.requestLocationUpdates(gpsFreqInMillis, gpsFreqInDistance, criteria, this, null);

Slide 39

Slide 39 text

時間 (秒) 距離(m) GPS個数 バッテリー
 (スタート時) バッテリー
 (ゴール) 消費量 42km走った 場合 5時間走った 場合 Nexus6p Mid Battery (every 1m, 1sec) 1785 5738.8 1349 50% 48% 2% 14.7% 20.1% Nexus6p High Battery (every 5m, 1sec) 1684 5036.0 675 98% 95% 3% 25.1% 32% .JOJNVN%JTUBODFͱ.JOJNVN5JNF͸ม͑ͨ৔߹ͷόοςϦʔফඅྔ

Slide 40

Slide 40 text

଱ٱੑʹ͍ͭͯ ʔʼଓ͖͸࠙਌ձͰʂ

Slide 41

Slide 41 text

Blog medium.com/@mizutory/ github.com/mizutori/AndroidLocationStarterKit Code [email protected] @mizutory Twitter www.goldrushcomputing.com