Location, motion, and activity recording framework for iOS

Overview

LocoKit

A Machine Learning based location recording and activity detection framework for iOS.

Location and Motion Recording

  • Combined, simplified Core Location and Core Motion recording
  • Filtered, smoothed, and simplified location and motion data
  • Near real time stationary / moving state detection
  • Automatic energy use management, enabling all day recording
  • Automatic stopping and restarting of recording, to avoid wasteful battery use

Activity Type Detection

  • Machine Learning based activity type detection
  • Improved detection of Core Motion activity types (stationary, walking, running, cycling, automotive)
  • Distinguish between specific transport types (car, train, bus, motorcycle, airplane, boat)

Record High Level Visits and Paths

  • Optionally produce high level Path and Visit timeline items, to represent the recording session at human level. Similar to Core Location's CLVisit, but with much higher accuracy, much more detail, and with the addition of Paths (ie the trips between Visits).
  • Optionally persist your recorded samples and timeline items to a local SQL based store, for retention between sessions.

More information about timeline items can be found here

Supporting the Project

LocoKit is an LGPL licensed open source project. Its ongoing development is made possible thanks to the support of its backers on Patreon.

If you have an app that uses LocoKit and is a revenue generating product, please consider sponsoring LocoKit development, to ensure the project that your product relies on stays healthy and actively maintained.

Thanks so much for your support!

Installation

pod 'LocoKit'
pod 'LocoKit/LocalStore' # optional

Note: Include the optional LocoKit/LocalStore subspec if you would like to retain your samples and timeline items in the SQL persistent store.

High Level Recording

Record TimelineItems (Paths and Visits)

// retain a timeline manager
self.timeline = TimelineManager()

// start recording, and producing timeline items 
self.timeline.startRecording()

// observe timeline item updates
when(timeline, does: .updatedTimelineItem) { _ in
    let currentItem = timeline.currentItem

    // duration of the current Path or Visit
    print("item.duration: \(currentItem.duration)")

    // activity type of the current Path (eg walking, cycling, car)
    if let path = currentItem as? Path {
        print("path.activityType: \(path.activityType)")
    }

    // examine each of the LocomotionSamples within the Path or Visit
    for sample in currentItem.samples {
        print("sample: \(sample)")
    }
}

Low Level Recording

Record LocomotionSamples (CLLocations combined with Core Motion data)

// the recording manager singleton
let loco = LocomotionManager.highlander
// decide which Core Motion features to include
loco.recordPedometerEvents = true
loco.recordAccelerometerEvents = true
loco.recordCoreMotionActivityTypeEvents = true
// decide whether to use "sleep mode" to allow for all day recording 
loco.useLowPowerSleepModeWhileStationary = true

Note: The above settings are all on by default. The above snippets are unnecessary, and just here to show you some of the available options.

// start recording 
loco.startRecording()
// watch for updated LocomotionSamples
when(loco, does: .locomotionSampleUpdated) { _ in

    // the raw CLLocation
    print(loco.rawLocation)

    // a more usable, de-noised CLLocation
    print(loco.filteredLocation)

    // a smoothed, simplified, combined location and motion sample
    print(loco.locomotionSample())
}

Fetching TimelineItems / Samples

If you wanted to get all timeline items between the start of today and now, you might do this:

let date = Date() // some specific day
let items = store.items(
        where: "deleted = 0 AND endDate > ? AND startDate < ? ORDER BY endDate",
        arguments: [date.startOfDay, date.endOfDay])

You can also construct more complex queries, like for fetching all timeline items that overlap a certain geographic region. Or all samples of a specific activity type (eg all "car" samples). Or all timeline items that contain samples over a certain speed (eg paths containing fast driving).

Detect Activity Types

Note that if you are using a TimelineManager, activity type classifying is already handled for you by the manager, on both the sample and timeline item levels. You should only need to directly interact with clasifiers if you are either not using a TimelineManager, or are wanting to do low level processing at the sample level.

// fetch a geographically relevant classifier
let classifier = ActivityTypeClassifier(coordinate: location.coordinate)

// classify a locomotion sample
let results = classifier.classify(sample)

// get the best match activity type
let bestMatch = results.first

// print the best match type's name ("walking", "car", etc)
print(bestMatch.name)

Note: The above code snippets use SwiftNotes to make the event observing code easier to read. If you're not using SwiftNotes, your observers should be written something like this:

let noteCenter = NotificationCenter.default
let queue = OperationQueue.main 

// watch for updates
noteCenter.addObserver(forName: .locomotionSampleUpdated, object: loco, queue: queue) { _ in
    // do stuff
}

Background Location Monitoring

If you want the app to be relaunched after the user force quits, enable significant location change monitoring.

More details and requirements here

Examples and Screenshots

Documentation

Try the LocoKit Demo App

  1. Download or clone this repository
  2. pod install
  3. In Xcode, change the Demo App project's "Team" to match your Apple Developer Account
  4. In Xcode, change the Demo App project's "Bundle Identifier" to something unique
  5. Build and run!
  6. Go for a walk, cycle, drive, etc, and see the results :)

Try Arc App on the App Store

  • To see the SDK in action in a live, production app, install Arc App from the App Store, our free life logging app based on LocoKit
Comments
  • High battery usage consumption while stationary

    High battery usage consumption while stationary

    A handful of Arc App users are reporting mysteriously high battery usage. Sometimes 10 or 20 times more than expected.

    For the more extreme cases the users are seeing their batteries draining in a matter of hours. Normally Arc App and LocoKit can record entire days on a single battery charge, so for these particular users, something very wrong is happening.

    My current best guess of the cause, based on user screenshots, is that for these users LocoKit is cycling between sleep and wake every few minutes, while stationary, instead of staying in sleep state until the user leaves their current location.

    My hunch is the affected devices are producing a magical rare mix of low accuracy location data and slowly drifting location data, which could be somehow getting through LocoKitCore's filtering. Basically some poisonous combination of inaccurate location data while stationary that's slipping through the cracks and messing up sleep mode.

    The problem is this never happens on any of my test devices, and is extremely difficult to properly debug remotely. So I need your help!

    Are you experiencing this bug? Are you an iOS developer?

    If so, I could really do with your help!

    The best way to help is to install the LocoKit Demo App from this repo, and run it on the affected device in the affected location, and look for patterns.

    The "LM" tab will hopefully be the most informative. Look for:

    • Patterns in "Requesting accuracy" vs "Receiving accuracy"
    • The number of locations in the "Latest sample"
    • Incorrect changes in "Moving state"
    • Drifting current location dots on the map
    • A pattern of alternating short visits and short paths in the "TM" view while stationary

    Note: You won't need an API key. I don't believe this bug is related to the ML classifiers at all.

    Thanks for your help!

    bug Arc App help needed 
    opened by sobri909 50
  • Example for persistent store

    Example for persistent store

    Hey, I'm having some trouble figuring out how to get the persistent store set up.

    It seems like things might be working in localstorage, there is some level of persistence on the device in my simulator (e.g. when I print out Items, this persists from one session to the next). But I'm not seeing those show up in a database anywhere. I didn't see a ton of specifics on this in terms of what type of database to use and how to set it up. Any help would be much appreciated!

    Here's my file where I'm initializing everything (also, fair warning, I come from a node.js background, so swift in general is all a bit new to me 😄)

    Thank you in advance!

    //
    //  AppDelegate.swift
    //  Joy
    //
    //  Created by Danny on 10/4/17.
    //  Copyright © 2017 Joy. All rights reserved.
    //
    
    import UIKit
    import LocoKit
    import SwiftNotes
    
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        
        var timeline: TimelineManager = PersistentTimelineManager()
        var store: PersistentTimelineStore = PersistentTimelineStore()
        
        var window: UIWindow?
        
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
            LocoKitService.apiKey = "<REDACTED>"
            
            self.store = PersistentTimelineStore()
            store.dbUrl = URL(string: "<REDACTED>")!
    
            // the CoreLocation / CoreMotion recording singleton
            let loco = LocomotionManager.highlander
            
            // this is independent of the user's setting, and will show a blue bar if user has denied "always"
            loco.locationManager.allowsBackgroundLocationUpdates = true
            
            // retain a timeline manager
            self.timeline = PersistentTimelineManager()
            
            // restore the active timeline items from local db
            if let timeline = timeline as? PersistentTimelineManager {
                timeline.bootstrapActiveItems()
                print("bootstrapActiveItems ran....")
                
                // start recording, and producing timeline items
                self.timeline.startRecording()
            }
            
            // observe new timeline items
            when(timeline, does: .newTimelineItem) { _ in
                if let currentItem = self.timeline.currentItem {
                    print(".newTimelineItem (\(String(describing: type(of: currentItem))))")
                }
                onMain {
                    let items = self.itemsToShow
                    print(items, "<<<<")
                }
            }
            
            // observe timeline item updates
            when(timeline, does: .updatedTimelineItem) { _ in
                onMain {
                    let items = self.itemsToShow
                }
            }
            
            // observe timeline items finalised after post processing
            when(timeline, does: .finalisedTimelineItem) { note in
                if let item = note.userInfo?["timelineItem"] as? TimelineItem {
                    print(".finalisedTimelineItem (\(String(describing: type(of: item))))")
                }
            }
            
            when(timeline, does: .mergedTimelineItems) { note in
                if let description = note.userInfo?["merge"] as? String {
                    print(".mergedItems (\(description))")
                }
            }
            
            // observe incoming location / locomotion updates
            when(loco, does: .locomotionSampleUpdated) { _ in
                self.locomotionSampleUpdated()
            }
            
            // observe changes in the recording state (recording / sleeping)
            when(loco, does: .recordingStateChanged) { _ in
                // don't log every type of state change, because it gets noisy
                if loco.recordingState == .recording || loco.recordingState == .off {
                    print(".recordingStateChanged (\(loco.recordingState))")
                }
            }
            
            // observe changes in the moving state (moving / stationary)
            when(loco, does: .movingStateChanged) { _ in
                print(".movingStateChanged (\(loco.movingState))")
            }
            
            when(loco, does: .startedSleepMode) { _ in
                print(".startedSleepMode")
            }
            
            when(loco, does: .stoppedSleepMode) { _ in
                print(".stoppedSleepMode")
            }
            
            when(.debugInfo) { note in
                if let info = note.userInfo?["info"] as? String {
                    print(".debug (\(info))")
                } else {
                    print(".debug (nil)")
                }
            }
            
            return true
        }
        
        var itemsToShow: [TimelineItem] {
            if timeline is PersistentTimelineManager { return persistentItemsToShow }
            
            guard let currentItem = timeline.currentItem else { return [] }
            
            // collect the linked list of timeline items
            var items: [TimelineItem] = [currentItem]
            var workingItem = currentItem
            while let previous = workingItem.previousItem {
                items.append(previous)
                workingItem = previous
            }
            
            return items
        }
        
        var persistentItemsToShow: [TimelineItem] {
            guard let timeline = timeline as? PersistentTimelineManager else { return [] }
            
            // make sure the db is fresh
            timeline.store.save()
            
            // fetch all items in the past 24 hours
            let boundary = Date(timeIntervalSinceNow: -60 * 60 * 24)
            return timeline.store.items(where: "deleted = 0 AND endDate > ? ORDER BY endDate DESC", arguments: [boundary])
        }
        
        func locomotionSampleUpdated() {
            let loco = LocomotionManager.highlander
            
            // don't bother updating the UI when we're not in the foreground
            guard UIApplication.shared.applicationState == .active else {
                return
            }
            
            // get the latest sample and update the results views
            let sample = loco.locomotionSample()
        }
    
        func showLoggedInView() {
            // initilize vc right away, otherwise flashes on launch
            let vc = UINavigationController(rootViewController: SummaryViewController())
            show(vc)
        }
    
        func showLoggedOutView() {
            let vc = OnboardingNavigationController(rootViewController: WelcomeViewController())
            show(vc)
        }
    
        private func show(_ vc: UIViewController) {
            window = UIWindow(frame: UIScreen.main.bounds)
            window?.rootViewController = vc
            window?.makeKeyAndVisible()
            window?.tintColor = .joyPurple
        }
    
        func applicationDidBecomeActive(_ application: UIApplication) {
            application.applicationIconBadgeNumber = 0
        }
    
    }
    
    question 
    opened by dannyfreed 23
  • LocoKit doesn't build on Xcode 9.3

    LocoKit doesn't build on Xcode 9.3

    I have many "Swift Compiler Error" in my project after installing it with CocoaPods (57).

    I can't even build the LocoKit Demo App because it also gives me all of these errors.

    This is the error I get when adding it to my project.

    • 'collations' is inaccessible due to 'private' protection level (and many others of the same type)

    These are the errors I get trying to build the LocoKit Demo app (20):

    • Type 'ComplexArray' does not conform to protocol 'RangeReplaceableCollection'
    • Ambiguous use of 'count'
    • Type 'ValueArraySlice' does not conform to protocol 'Collection'

    What am I doing wrong?

    opened by antoniogermano 9
  • Throttle network requests for the same location.

    Throttle network requests for the same location.

    I've played a little with SDK (latest version, master branch). I'm testing it on my project which has NetworkLogger. (I use it to inspect network request, log specific info)
    What I've found strange that my application using SDK executes tones of API requests for the same coordinates. I tried to change my location just by walking at the office. So I don't have significant location changes, just stationary. Also I use default accuracy options (30 meters). It might be better to add some throttling mechanism in order to reduce number of network requests for the same location.

    Image with debugger Link for screenshot

    iOS version: 11.4.1 Device: iPhone 6+ Xcode: 9.4.1 GPS/Wifi/CoreMotion is Enabled.

    opened by EugeneEl 7
  • why notice “Unable to find a pod with name, author, summary, or description matching `ArcKit`” when I pod search ArcKit

    why notice “Unable to find a pod with name, author, summary, or description matching `ArcKit`” when I pod search ArcKit

    hello,i clone code About ‘ArcKit’ ,but couldn't run ,tips can‘t find ’ArcKit‘ ,try ’pod install‘ tips ’Unable to find a specification for ArcKit (= 5.0.0.pre)‘. how i can fix it, thx谢谢!!

    opened by ouzs 7
  • LocoKit won't build on Apple Silicon Macs

    LocoKit won't build on Apple Silicon Macs

    Thank you for an awesome library, @sobri909!

    I recently moved to using an M1 Mac as my daily driver - and, unfortunately, LocoKitCore.framework is not a happy camper. While building to device works, simulator build fails due to either a missing ARM64 version of the iOS 10 SDK or to Swift 5.1/5.3 incompatibilities - the error message is not particularly clear on that.

    Attempts to build an app with LocoKit end up with the following error:

    <unknown>:0: error: unable to load standard library for target 'arm64-apple-ios10.0'
    [redacted]:10:8: error: failed to build module 'LocoKitCore' from its module interface; the compiler that produced it, 'Apple Swift version 5.1.3 effective-4.2 (swiftlang-1100.0.282.1 clang-1100.0.33.15)', may have used features that aren't supported by this compiler, 'Apple Swift version 5.3.1 effective-4.2 (swiftlang-1200.0.41 clang-1200.0.32.8)'
    import LocoKitCore
    

    Any chance you could rebuild the LocoKitCore.framework with the most recent Swift compiler and/or target a newer standard library? Happy to help out with debugging this if you don't have access to an Apple Silicon Mac!

    opened by bogo 6
  • Can't build develop

    Can't build develop

    Hello,

    I've just added the develop branch as pod dependency using

    pod 'LocoKit', :git => 'https://github.com/sobri909/LocoKit.git', :branch => 'develop'
      pod 'LocoKit/Timelines', :git => 'https://github.com/sobri909/LocoKit.git', :branch => 'develop'
      pod 'LocoKitCore', :git => 'https://github.com/sobri909/LocoKit.git', :branch => 'develop'
    

    When building, I get this error in LocoMotionManager.swift: image

    It seems to be due to the fact that LocoKitCore framework hasn't been committed to the repo since a long time? Is it possible to build it from source?

    bug 
    opened by corradio 6
  • Xcode 10.2 Can't Build

    Xcode 10.2 Can't Build

    My podfile is as below:

    pod 'LocoKit', :git => 'https://github.com/sobri909/LocoKit.git', :branch => 'develop'
    pod 'LocoKitCore', :git => 'https://github.com/sobri909/LocoKit.git', :branch => 'develop'
    pod 'LocoKit/Timelines', :git => 'https://github.com/sobri909/LocoKit.git', :branch => 'develop'
    

    And I got error: ../Pods/LocoKit/LocoKit/Timelines/ActivityTypes/ActivityTypesCache.swift:10:8: Module compiled with Swift 4.2 cannot be imported by the Swift 5.0 compiler: ../Pods/LocoKitCore/LocoKitCore.framework/Modules/LocoKitCore.swiftmodule/arm.swiftmodule

    ../Pods/LocoKit/LocoKit/Timelines/ActivityTypes/ActivityTypesCache.swift:10:8: Module compiled with Swift 4.2 cannot be imported by the Swift 5.0 compiler: ../Pods/LocoKitCore/LocoKitCore.framework/Modules/LocoKitCore.swiftmodule/arm64.swiftmodule

    My project's swift language is 4.2, and pod is also 4.2. I already try this https://stackoverflow.com/a/46739102/5957749 but still not work at all......

    opened by Faydee1220 6
  • [Question] iOS 12

    [Question] iOS 12

    👋 Hey Matt, anything else we should be cautious of when updating to Swift 4.2? Saw this thread https://github.com/sobri909/LocoKit/issues/20 and was successfully able to migrate to Swift 4.2.

    iOS 12 Unfortunately with our existing build on the latest released version of LocoKit, we're experiencing weird/inaccurate location data on iOS 12. I saw this comment, looks like you were/are experiencing similar issues https://github.com/sobri909/LocoKit/issues/29#issuecomment-423201624

    I'm seeing much higher rates of background fails in iOS 12 (in Arc's analytics, and on my test devices). And much higher rates of nonsense location data, with some devices "sleepwalking" on almost a daily basis, several kilometres away from where they really are.

    Are you still seeing issues with LocoKit on iOS 12? Did Apple end up fixing some of their issues with the patch release? Anything I can potentially help with? (don't know how much time I have)

    For what it's worth, I'm also experiencing quite a few crashes in the background on TimelineStore.save(). The app crashes after some time in the background. Anything potentially wrong with my setup or are you noticing the same thing? Any help is much appreciated, thanks.

    0  libswiftCore.dylib             0x10143e480 _stdlib_destroyTLS + 207848
    1  libswiftCore.dylib             0x101493f2c swift_unexpectedError + 280
    2  LocoKit                        0x101064b10 TimelineStore.save() (TimelineStore.swift:325)
    3  LocoKit                        0x101066858 closure #1 in TimelineStore.process(changes:) (TimelineStore.swift:348)
    4  LocoKit                        0x100ff2a68 thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
    5  libdispatch.dylib              0x1db5c36c8 _dispatch_call_block_and_release + 24
    6  libdispatch.dylib              0x1db5c4484 _dispatch_client_callout + 16
    7  libdispatch.dylib              0x1db56bc18 _dispatch_lane_serial_drain$VARIANT$mp + 592
    8  libdispatch.dylib              0x1db56c760 _dispatch_lane_invoke$VARIANT$mp + 432
    9  libdispatch.dylib              0x1db574f00 _dispatch_workloop_worker_thread + 600
    10 libsystem_pthread.dylib        0x1db7a60f0 _pthread_wqthread + 312
    11 libsystem_pthread.dylib        0x1db7a8d00 start_wqthread + 4
    
    bug 
    opened by joediv 6
  • More activity types, and open sourcing the ML classifiers

    More activity types, and open sourcing the ML classifiers

    It's too early to start on this one yet, but implementation ideas have been popping up in my head all week, so I might as well get them written down.

    Misc random thoughts

    1. Ditch the coords pseudo counts for transport types that are coordinate bound (eg car, bus, train, and any future road/track/etc bound types).

    2. Only include types in the transport classifier that have non zero sample/coord counts for the D2 region, to avoid over stuffing the classifiers with possible types.

    3. Look at ditching some model features, due to possibly being a negative influence. coreMotionActivityType is the most likely candidate for ditching, due to being wrong more often than right. Next would be courseVariance, due to being essentially meaningless for all types except stationary, since the introduction of the Kalmans.

    4. Try letting zero step Hz back in for walking. There's certainly enough data for the models now, and phones are newer and smarter, so there's less risk of false zeroes, and more data to cope gracefully with those cases now too.

    5. Look at deepening / broadening the composite classifiers tree. Could consider clustering all "steps" based types in a subtree (walking, running, cycling, horse riding, maybe skateboarding, others). Consider clustering the road bound types (car, bus, tram?). And there's the open question of whether a third depth would make sense in some cases, for when there's too many types to be sensibly clustered in a single classifier.

    • Need to flesh out the storage model for user custom types. And for custom types that have the potential to being upgraded to shared types. Things like naming specific train lines, naming specific roads, etc. These might initially come in as custom user types, but there needs to be a privacy conscious, opt-in path to upgrading these to shared types, if it makes sense to do so.

    I'll come back to this and add more thoughts over the next week or two. There's a bunch more details that have already crossed my mind, but I'm not remembering them right now...

    enhancement 
    opened by sobri909 6
  • ArcKit doesn't build in XCode 8.3

    ArcKit doesn't build in XCode 8.3

    I did a pod install for ArcKit which was successful, but when I build, I get the error:

    “Swift Language Version” (SWIFT_VERSION) is required to be configured correctly for targets which use Swift. Use the [Edit > Convert > To Current Swift Syntax…] menu to choose a Swift version or use the Build Settings editor to configure the build setting directly.

    I did this to upgrade to Swift 3.0, but it still fails to build. I also changed the build target to be iOS 10.3 instead of iOS 11, but still doesn't build. Is there anyway to fix this?

    Thanks.

    opened by gadgetman4u 6
  • Question for Histogram.probabilityFor

    Question for Histogram.probabilityFor

    I just curious why use max of bins as divisor instead of sum of bins?

    LocoKit/Timelines/ActivityTypes/Histogram.swift

    
        public func probabilityFor(_ value: Double) -> Double {
            guard let max = bins.max() else {
                return 0
            }
           
            // shouldn't be possible. but... 
            guard !binWidth.isNaN else {
                return 0
            }
            
            // single bin histograms result in binary 0 or 1 scores
            if bins.count == 1 {
                return value == range.min ? 1 : 0
            }
            
            let bin: Int
            if value == range.max {
                bin = bins.count - 1
            } else {
                let binDouble = floor((value - range.min) / binWidth)
                
                if binDouble > Double(bins.count - 1) {
                    return 0
                }
                
                guard !binDouble.isNaN && binDouble > Double(Int.min) && binDouble < Double(Int.max) else {
                    return 0
                }
                
                bin = binWidth > 0 ? Int(binDouble) : 0
            }
            
            guard bin >= 0 && bin < bins.count else {
                return 0
            }
            
            return (Double(bins[bin]) / Double(max)).clamped(min: 0, max: 1)
        }
    
    opened by pipi32167 2
  • Xcode 13 / Swift 5.5 compatible LocoKitCore

    Xcode 13 / Swift 5.5 compatible LocoKitCore

    Current CocoaPods published version is 7.0 (although I see 7.1 tagged here in github).

    With Xcode 13 / Swift 5.5 am getting:

    error: module compiled with Swift 5.1.3 cannot be imported by the Swift 5.5.1 compiler

    Will you be providing a compatible update for the binary LocoKitCore ?

    Thanks

    opened by mwoollard 4
  • Deleting TimelineItems

    Deleting TimelineItems

    Hi @sobri909, Please help me on deleting TimelineItems from db. I'm trying with tappedClear() function to delete items. but I'm not able to track that how many items are already delete from db, because immediate boolean in save() function is false.

     var dataSet: TimelineSegment?
    
     var itemsToShow: [TimelineItem] {
            return dataSet?.timelineItems ?? []
      }
        
      func tappedClear() {
            // TODO: flush the timeline data
            self.itemsToShow.forEach {
                $0.delete()
            }
            store.keepDeletedObjectsFor = TimeInterval(timerCount)
            store.hardDeleteSoftDeletedObjects()
        }
        
      public func save(_ object: TimelineObject, immediate: Bool) {
            mutex.sync {
                if let item = object as? TimelineItem {
                    itemsToSave.insert(item)
                } else if let sample = object as? PersistentSample {
                    samplesToSave.insert(sample)
                }
            }
            if immediate { save() }
        }
    
    opened by avinashamanjha251 5
  • Getting Only stationary activityType from most recent TimelineItem

    Getting Only stationary activityType from most recent TimelineItem

    Hi Matt, I'm trying to fetch most recent "TimelineItem" and I'm getting it... but every time I'm getting activityType either stationary or nil. Please help me on this. Thanks in advance.

    if let mostRecentItem = self.store.mostRecentItem { printDebug("=========================================") printDebug("item (mostRecentItem)") printDebug("item modeMovingActivityType (String(describing: mostRecentItem.modeMovingActivityType))") printDebug("item activityType (String(describing: mostRecentItem.activityType))") printDebug("item modeActivityType (String(describing: mostRecentItem.modeActivityType))") printDebug("item startDate (String(describing: mostRecentItem.startDate))") printDebug("item endDate (String(describing: mostRecentItem.endDate))") printDebug("item duration (mostRecentItem.duration)") printDebug("item stepCount (String(describing: mostRecentItem.stepCount))") }

    opened by avinashamanjha251 3
  • LocoKit SPM resolve warning

    LocoKit SPM resolve warning

    FYI: while building the latest ArcMini, Xcode spit out the following warning:

    found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target
        .../DerivedData/Arc_Mini-dlenhigbcoeldyfxldburkutnfjk/SourcePackages/checkouts/LocoKit/LocoKit/Timelines/ActivityTypes/CoordinateBins.fbs
    

    Not sure if this is a LocoKit or ArcMini issue.

    opened by BrianBatchelder 2
Releases(4.0.0)
  • 4.0.0(Nov 27, 2017)

    Added

    • Added a low power Sleep Mode. Read the useLowPowerSleepModeWhileStationary API docs for more details.
    • Added ability to disable dynamic desiredAccuracy adjustments. Read the
      dynamicallyAdjustDesiredAccuracy API docs for more details.
    • Added LocomotionManager settings for configuring which (if any) Core Motion features to make use of whilst recording.

    Removed

    • startCoreLocation() has been renamed to startRecording() and now starts both Core Location and Core Motion recording (depending on your LocomotionManager settings). Additionally, stopCoreLocation() has been renamed to stopRecording(), and startCoreMotion() and stopCoreMotion() have been removed.
    • recordingCoreLocation and recordingCoreMotion have been removed, and replaced by recordingState.
    • The locomotionSampleUpdated notification no longer includes a userInfo dict.
    Source code(tar.gz)
    Source code(zip)
  • 3.0.0(Nov 23, 2017)

    Added

    • Open sourced LocomotionManager and LocomotionSample.

    Changed

    • Moved apiKey from LocomotionManager to ArcKitService. Note that this is a breaking change - you will need up update your code to set the API key in the new location.
    • Split the SDK into two separate frameworks. The ArcKit framework now contains only the open source portions, while the new ArcKitCore contains the binary framework. (Over time I will be open sourcing more code by migrating it from the binary framework to the source framework.)
    Source code(tar.gz)
    Source code(zip)
Allows you to use custom maps in iphone applications and attempts to mimics some of the behaviour of the MapKit framework

NAMapKit Lets you drop pins or custom annotations onto a standard UIImage or a tiled NATiledImageView. Includes callouts, multi-colored pins, animatio

Neil Ang 263 Jun 29, 2022
Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL

Mapbox GL Native A C++ library that powers customizable vector maps in native applications on multiple platforms by taking stylesheets that conform to

Mapbox 4.2k Jan 9, 2023
A spatial analysis library written in Swift for native iOS, macOS, tvOS, watchOS, and Linux applications, ported from Turf.js.

Turf for Swift ?? ?? ?? ?? ⌚️ A spatial analysis library written in Swift for native iOS, macOS, tvOS, watchOS, and Linux applications, ported from Tu

Mapbox 187 Dec 19, 2022
A Swift wrapper for forward and reverse geocoding of OpenStreetMap data

Nominatim NominatimKit is a Swift wrapper for forward and reverse geocoding of OpenStreetMap data. Why? Geocoding location data on iOS requires the us

Josef Moser 53 Feb 5, 2022
MSFlightMapView allows you to easily add and animate geodesic flights to Google map

MSFlightMapView Demo Requirements iOS 10.0+ Xcode 9.0+ Installation Just add the MSFlightMapView folder to your project. or use CocoaPods: pod 'MSFlig

Muhammad Abdul Subhan 48 Aug 13, 2022
Demo in SwiftUI of Apple Map, Google Map, and Mapbox map

SNMapServices SNMapServices is a serices for iOS written in SwiftUI. It provides Map capability by subclassing Mapbox, Google map and Apple map. This

Softnoesis 3 Dec 16, 2022
Google Directions API helper for iOS, written in Swift

PXGoogleDirections Google Directions API SDK for iOS, entirely written in Swift. ?? Features Supports all features from the Google Directions API as o

Romain L 268 Aug 18, 2022
JDSwiftMap is an IOS Native MapKit Library. You can easily make a highly customized HeatMap.

JDSwiftMap is an IOS Native MapKit Library. You can easily make a highly customized HeatMap. Installation Cocoapods pod 'JDSWiftHeatMap' Usage JDSwi

郭介騵 135 Dec 26, 2022
Recording Indicator Utility lets you turn off the orange microphone recording indicator light for live events and screencasts.

Recording Indicator Utility Recording Indicator Utility lets you turn off the orange microphone recording indicator light, making it ideal for profess

Tyshawn Cormier 121 Jan 1, 2023
Simple library to detect motion type (walking, running, automotive) and count users steps. This library will make motion detection much more easily.

SOMotionDetector Simple library to detect motion for iOS by arturdev . Based on location updates and acceleration. ###Requierments iOS > 6.0 Compatibl

Artur  Mkrtchyan 1.1k Nov 25, 2022
A Location Manager for easily implementing location services & geofencing in iOS. Ready for iOS 11.

A Location Manager for easily implementing location services & geofencing in iOS, written in Objective-C. Ready for iOS 11. Features Get current/conti

Benzamin Basher 108 Jul 9, 2022
🛰 CoreLocation Made Easy - Efficient & Easy Location Tracker, IP Location, Gecoder, Geofence, Autocomplete, Beacon Ranging, Broadcaster and Visits Monitoring

Location Manager Made Easy SwiftLocation is a lightweight Swift Library that provides an easy way to work with location-related functionalities. No mo

Daniele Margutti 3.2k Dec 30, 2022
🛰 CoreLocation Made Easy - Efficient & Easy Location Tracker, IP Location, Gecoder, Geofence, Autocomplete, Beacon Ranging, Broadcaster and Visits Monitoring

Location Manager Made Easy SwiftLocation is a lightweight Swift Library that provides an easy way to work with location-related functionalities. No mo

Daniele Margutti 3.2k Dec 30, 2022
OutRun is an iOS app for recording and viewing your outdoor workouts

OutRun is an iOS app for recording and viewing your outdoor workouts. Despite the name it supports not just running, but also walking, hiking, cycling and skating.

Tim Fraedrich 195 Dec 28, 2022
AudiosPlugin is a Godot iOS Audio Plugin that resolves the audio recording issue in iOS for Godot Engine.

This plugin solves the Godot game engine audio recording and playback issue in iOS devices. Please open the Audios Plugin XCode Project and compile the project. You can also use the libaudios_plugin.a binary in your project.

null 3 Dec 22, 2022
In-app screen recording using ReplayKit in iOS. Written in Swift 5 on Xcode 12.3

In-App-ScreenRecording-iOS In-app screen recording using ReplayKit in iOS. Written in Swift 5 on Xcode 12.3 Features: Recording application screen onl

Ahmed Abdelkarim 4 Dec 23, 2022
RadialMenu is a custom control for providing a touch context menu (like iMessage recording in iOS 8) built with Swift & POP

RadialMenu Looking for help? For $150/hr I'll help with your RadialMenu problems including integrating it into your project. Email [email protected] t

Brad Jasper 297 Nov 27, 2022
RadialMenu is a custom control for providing a touch context menu (like iMessage recording in iOS 8) built with Swift & POP

RadialMenu Looking for help? For $150/hr I'll help with your RadialMenu problems including integrating it into your project. Email [email protected] t

Brad Jasper 297 Nov 27, 2022
FDSoundActivatedRecorder - Start recording when the user speaks

FDSoundActivatedRecorder Start recording when the user speaks. All you have to do is tell us when to start listening. Then we wait for an audible nois

William Entriken 271 Nov 3, 2022
Alter SDK is a cross-platform SDK consisting of a real-time 3D avatar system, facial motion capture, and an Avatar Designer component built from scratch for web3 interoperability and the open metaverse.

Alter SDK is a cross-platform SDK consisting of a real-time 3D avatar system, facial motion capture, and an Avatar Designer component built from scratch for web3 interoperability and the open metaverse.

Alter 45 Nov 29, 2022