Is it possible to somehow serialize/save Anchors, so that I can have a persistent offline trackability?
For example, I have a 3D scene to detect, which should be shareable and trackable for a long time. In order to do this, I think I need either a private cloud server for Anchors or offline anchor files so that they can be shared on multiple devices over a period of time.
Is it somehow possible with AR Core?
Thanks,
ARCore supports cloud anchors which meet what I think you are asking for, except for the 'long time' part.
At the moment they only fully support 1 day persistence - longer is apparently on the roadmap but at the time of writing there is no date (AFAIK).
There are 3rd party solutions which do offer this - take a look at 6D.ai for example: https://www.6d.ai/faq/ - this claims to support Persistence:
Persistence - objects stay in the world where you left them
Related
I'm trying to write an app for detecting "where you are" in a building use ARCore. I'd like to use previously learnt and then saved feature points to provide the initial sync position as well as then helping to continuously update position accurately. But this feature does not currently appear to be supported in ARCore.
Currently I'm using tracked images as a way to do an initial sync. It works, but not brilliantly - alignment is often a few degrees off and you have to approach the image pretty slowly and deliberately. And then once synced there is drift... Yes, loop closing works pretty well when it gets back to somewhere it recognises, but it needs to build up that map every time you start the session.
So, obvious solution: are there any plans for Google to implement "Area Learning" as it was back in Google Tango? It looks like Cloud Anchors might be some attempt to do this, but clearly that's all hosted on Google, and it strictly limited as to how long that data is stored. Currently that's just not a possible solution. OTOH, Apple's ARKit seems to now provide just what is needed:
https://developer.apple.com/documentation/arkit/saving_and_loading_world_data
Does this mean that Apple / ARKit is the only way to go for the app? Hope not...
You might want to check out persistent cloud anchors that is still in development.
From documentation:
Note: We’re currently developing persistent Cloud Anchors, which can
be resolved for much longer. Before making the feature broadly
available, we’re looking for more developers to help us explore and
test persistent Cloud Anchors in real world apps at scale. See here if
you’re interested.
We're looking to share AR experiences (ARWorldMap) over the web (not necessarily to devices nearby, I'm referring to data that can be stored to some server and then retrieved by another user).
Right now we're looking into ARWorldMap which is pretty awesome, but I think it only works on the same device AND with devices nearby. We want to be able to delete these constraints (and therefore save the experience over the web on some server) so that everyone else can automatically see 3D things with their devices (not necessarily at the same time) exactly where they were places.
Do you know if it's possible to send the archived data (ARWorldMap) to some server in some kind of format so that another user can later retrieve that data and load the AR experience on their device?
The ARWorldMap contains the feature points in the enviroment around the user. For example, the exact position and size of a table but including all the other points found by the camera. You can visualize those with the debugOptions.
It does not make sense to share those to a user that is not in the same room.
What you want to do is share the interactions between the users, eg when an object was placed or rotated.
This is something you would need to implement yourself anyway since ARWorldMap only contains anchors and features.
I can recommend Inside Swift Shot from last years WWDC as a starting point.
Yep technically it’s possible as according to docs here. You will have to use the nsssecure coding protocol, might have to extend if you aren’t using a swift backend though. It’s still possible as the arkit anchors are defined by a mix of point maps, rotational data , and image algos. Just implement portions of codable to JSON and voila it’s viable for most backends. Of course this is easier said then done.
I'm still in the very early stages of a game, and I am saving information using a KeyChain wrapper class someone made. I wanted to ask for some advice early on, since I have time to change my approach.
My game has the potential to persist a fair amount of data about the player and what they've done, such as:
how much gold the player has
what items they've acquired (you can get about 50 items)
what skills, spells, and abilities they've chosen for their character
what experience level they are, max health, stats, etc
The reason I decided to store this in KeyChain was that I was told it's encrypted and much more difficult to tamper with. I felt there were other solutions such as the ones below, but I wrote some potential reasons why that might not be good:
Make everything web-based, and stored in a database somewhere on my server - I want my game to be playable offline
Use a local database (FMDB, let's say) - I could use a tool to edit the values directly, and give myself more health, etc.
Use Core Data - Never used this before, not sure if this is the same ease of tampering as #3?
GameCenter - Never used this before, so not sure what the lift is
NSPreferences - Preferences are more easily tampered with (i've used a tool to change the values pretty quickly)
So I am not sure if i'm completely wrong above, but let's say there is some degree of truth there and KeyChain is a good approach. The problem is now what if I want to then somehow allow the player to pick up a new device and pick up where they left off? How on earth would I serialize all that data I'm saving in keychain? I don't mind creating a giant JSON document of the values, and sending it along somewhere (where? to GameCenter?)
Any advice / pointers in the right direction would be good, especially now since i'm in the early stages and can make changes to step back.
Thanks so much everyone appreciate your time!
A few thoughts based on lessons learned (usually, "the hard way") that may (or may not) be helpful. :)
I see three requirements in your post: offline play (requiring local storage), data security (which is a massive topic in and of itself) and synchronization.
Playable offline:
Thus you need some sort of local storage. Keychain, Core Data, SQL, NSPreferences are all options. I don't know the limitations of the Keychain, so not really sure how suitable it is for continuous read/write of large chunks of data.
Data security:
They keychain protects your secrets when you're not logged in, and partitions them between apps. https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/02concepts/concepts.html and http://evgenii.com/blog/sharing-keychain-in-ios/ give more details. That should prevent other tools from modifying other app's content on non-jailbroken devices.
Core Data, SQL, et al will be inside your app's container, which makes it harder for other tools to access on non-jailbroken devices. There's a good description here: https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
NSPreferences doesn't offer any security that I'm aware of. Plus, if they jailbreak the device, they basically have root access on a linux machine and can probably do anything they want.
In today's security world, the mantra is generally, "assume breach." As in, assume if they want in bad enough, they're going to find a way in. Thus you need to think about other layers of defense: partitioning your secrets so compromised secrets have limited value, encryption at rest and encryption in transit. Obfuscating the data before you write it/transmit is therefore another layer of defense (although they may still edit it and you'll have to handle potential garbage values).
You can chase security pretty far down the rabbit hole; you'll have to decide where the cost outweighs the benefit, and/or what risks you intend to defend against.
Synchronization across devices:
Thus you need a syncing solution. the iCloud Keychain syncs between devices, so if the keychain meets your storage needs, this probably will meet your sync needs, too. Again, I'm not sure if there are size or frequency-of-update constraints. I haven't used this, but this SO answer gives more info: https://stackoverflow.com/a/32606371/1641444. Based on Apple's docs (https://support.apple.com/en-us/HT204085) it looks like the user does have to enable syncing for this to work.
Otherwise, Apple provides GameCenter and CloudKit. Or you could explore 3rd party options. I've used GameCenter and CloudKit to sync data across devices. CloudKit wins over GameCenter, IMO, no contest.
With GameCenter, you gain multiplayer matchmaking and channels to share data between users. But, you have to adhere specifically to its structure which is IMO both extremely frustrating to work with and limited in functionality. Check the GameCenter and GKTurnBasedMatch tags here on SO for a taste of the problems.
CloudKit is a lower-level solution. It allows you to store a wide variety of data objects in iCloud and "subscribe" to change notifications. All data is contained within a container for the app, and has a "private" (user-specific) section and a public (shared by all users of the app) section. After watching the introductory WWDC videos on CloudKit, I was successfully sync'ing user settings between devices AND different users on different devices in no time. However, if you want some of the multiplayer features of GameCenter, you'll have to build the data model/subscriptions yourself. Since you support offline play, you'd need to save your data to a local storage solution and periodically upload it to iCloud for sync.
Conclusion (aka TL;DR)
So, my opinion is: none of the tools individually meet all three of your requirements, and you'll end up rolling your own solution for at least 1 req, regardless of which option you go for. In my multiplayer game, I'm trusting in Apple's filesystem (containers) to provide sufficient data security, I'm using a local storage option within the app's container, and I'm periodically writing NSData objects to cloudKit for synchronization across devices. I hit my frustration limit with GameCenter and pulled it from my app.
Star for a good question!!
I'm doing something similar with this. Right now, I'm using UserDefaults for primary storage. When I need to transfer data, I can save it to iCloudKit, or I could export it as a plist or json to use with AlamoFire, email, etc.
As for actually storing the data, I saw you mentioned CoreData.. that is kind of overkill! Look at NSCoder and NSKeyedArchiver.
Personally, I make my own save/load functions that manipulate dictionaries, then toss them into a UserDefaults key.
An example hierarchy of how I store dicts in UserDefaults (there are many ways to go about this)
Key:
Items->Equipment->Weapons->WeaponName
Value:
{ dictionary of data like AP, Cost, etc }
This to me is easier than using NSCoder, and certainly easier than CoreData!! The goal is to turn everything into a dictionary, which you can then easily put into UserDefaults, which allows you to easily create plists or save to the cloud.
With the above key system, you basically just do for loops to find what you need, parsing out each section.. so a function to display all equipment, you just load the entire UserDefaults.standard.dictionaryRepresentation, then search for keys that only have 'Items->Equipment' and so on.
Hope this helps!
I have some functions from my game I could share if you need more tips.
UPDATE:
If you are making this an online game, I would focus on learning the essentials of persistence and cloud usage first, then port it to a more secure platform that uses encryption.
Your best bet will be to create your own servers and transfer data that way. That will give you exactly what you want, when you want it, and with the security that you want.
If you want to use GameCenter, I would use GC as an in-between layer of something custom you created, so that way you can filter out the cheaters' scores / have more flexibility.
I am developing iOS 5 app which I want to communicate with server providing information about the nearby places for a given location: places locations and annotations. I want to use MapKit to populate my map with this information.
I didn't find any straightforward information regarding the following questions:
Does MapKit has tiles functionality (Google Maps way) out-of-the-box and do I need to work on it additionally, if not?
What is the best practice of retrieving places information (markers positions and annotations) from server?
Is it possible to cache this information so an user can see the nearby places of "his city" in offline mode?
Actually questions 2 and 3 are interrelated: they both address the problem of not retrieving an information (locations + annotations) that is already on map multiple times.
Hopefully I am not overlooking something obvious here.
Thanks!
Update 1: (Regarding places, not maps) More specifically I am interested in, how should I create a "hand-crafted" logical tiles for regions containing the places I fetch from the server, so they would not require refetching themselves when user scrolls the map? I know I can dive into implementing this functionality myself. For example, should I write the places just fetched to a local storage using Core Data immediately after fetching them or organize some queue? Or how could I know when I need to perform a request about the specific region on server and when I just fetch local data that is already on the device? I just want to know, are there any recommended approaches, best practices? Hopefully, I wrote it clear here.
Update 2: I am wondering about best practices here (links, example) not to start creating all this (points 2+3) from scratch. Are there any frameworks incapsulating this or good tutorials?
#Stanislaw - We have implemented the functionality you describe in an app called PreventConnect for one of our clients. The client already had some data stored out in a Google Fusion table. We extended their existing solution by adding another Google Fusion table which stores the geocoordinates for a number of locations. All this being said, to answer your questions...
1) The map portion itself is pretty out of the box, the tiles and what not, but you'll need to do some coding to get zoom extents, pin drops, annotations, and things like that working the way you expect them to work.
2) We found the Google Fusion solution to be quite effective. If you don't want to use Google Fusion there are other cloud database providers like StackMob, database.com, and many others. Google is free and they have an iOS SDK that makes communicating with Google Fusion pretty simple.
3) Absolutely! We cache much of the data in a Core Data store locally on the device. This greatly improves performance and responsiveness.
Time to write a solid answer to this my question (I could have it written a year ago but somehow I lost it from my mind).
Does MapKit has tiles functionality (Google Maps way) out-of-the-box and do I need to work on it additionally, if not?
The answer is yes: MapKit does have it. The keywords here are overlays (MKOverlay, MKOverlayView and others). See my another answer.
See also:
WWDC 2010 Session: Customizing Maps with Overlays,
Apple-WWDC10-TileMap.
What is the best practice of retrieving places information (markers positions and annotations) from server?
Actually since then I didn't learn a lot about "best practices" - unfortunately, nobody told me about them :( - that is why I will describe "my practices".
First of all, there are two strategies of populating a MapKit map with places:
The first strategy is about populating your map with the places by demand: imagine you want to display and see all places nearby (for example, no more than 1km from current user location) - this approach assumes that you ask your server only the places for the box you are being interested in. It means something like: "if I am in Berlin (and I expect 200 places for Berlin), why should I ever fetch the places from Russia, Japan, ... (10000+ places)".
This approach leads to relying on "tiles" functionality that question N1 address: Google maps and Apple maps are usually drawn using 'tiles' so for your "Berlin" portion of map you rely on corresponding "Berlin" tiles that are drawn by MKMapView - you use their dimensions, to ask your server only the places within the "Berlin" box (see my linked answer and the demo app there).
Initially this was the approach I've used and my implementation worked perfectly but later I was pushed to use second approach (see below) because the problem of clustering appeared.
The second strategy is to fetch all the places at once (yeah, all this 10000+ or more) and use Core Data to fetch the places needed for the visible portions of map your are interested in.
Second approach means, that during the first run you send your server a request to fetch all places (I have about 2000 in my app). Important here is that you restrict the fields you fetch to only geo-ones that you really need for your map: id, latitude, longitude.
This 'fetch-all' fetch has a significant impact on my app's first start time (On "the oldest" iPhone 4, I have near 700ms for the whole Fetch + Parse-JSON-into-Core-Data process, and extensive benchmarks show me that it is Core Data and its inserts is a bottleneck) but then you have all the essential geo-info about your places on your device.
Note, that whatever strategy you use, you should do a process of fetching these geo-points efficiently:
Imagine Core Data entity Place which has the following fields structure (preudo-Objective-C code):
// Unique identificator
NSNumber *id,
// Geo info
NSNumber *latitude,
NSNumber *longitude,
// The rest "heavy" info
NSString *name,
NSString *shortDescription,
NSString *detailedDescription, etc
Fetching places efficiently means that you ask only your place records geo-data from your server to make the process of this mirroring as fast as possible.
See also this hot topic: Improve process of mirroring server database to a client database via JSON?.
The clustering problem is out of scope of this question but is still very relevant and affects the whole algorithm you use for the whole proces - the only note I will leave here is that all the current existing clustering solutions will require you to use second strategy - you must have all the places prepared before you run into the clustering algorithms that will organize your places on a map - it means that if you decide to use clustering you must use strategy #2.
Relevant links on clustering:
WWDC 2011 Session: Visualizing Information Geographically with MapKit,
How To Efficiently Display Large Amounts of Data on iOS Maps,
kingpin - Open-source clustering solution: performant and easy-to-use.
Is it possible to cache this information so an user can see the nearby places of "his city" in offline mode?
Yes, both strategies do this: the first one caches the places you see on your map - if you observed Berlin's portion of map you will have Berlin part cached...
When using the second strategy: you will have all essential geo-information about your places cached and ready to be drawn on a map in offline mode (assuming that MapKit cached the map images of regions you browse in offline mode).
I have a Rails 3 app that I'm looking to create in-house analytics for. The items I need to track are impressions (and unique impressions), clicks that come from those impressions, and conversions that come from those clicks. And these are all user-specific so each user can see how many impressions, clicks, and conversions they've received.
What is the best way to go about this? Should I create a separate rails app and call it with pixels? Or should I include all the analytics code in the same app?
Also, are there any analytics platforms already out there that I can customize to meet my needs?
Thanks!
Tim
Before you start re-inventing the wheel, Google Analytics provide a developer API (via OAuth, among other choices) that may provide you with the ability to do what you need (provide each user with a view of their own data).
http://code.google.com/apis/analytics/docs/gdata/home.html
Building your own, while it may seem like an initially basic thing to do, could have serious performance implications further down the line, and Google provide a very detailed view of the the data.
If you really want to write your own, I would strongly urge you not to hit the database for each request you want to track. Keep the data in Redis, or one of the alternatives and periodically persist it to the database via a background task.
If, however, you don't want to put your data into the clutches of our Google Overlord :) then you might indeed consider rolling your own. I have twice before - and I'm doing it again right now: better this time, of course!
If your traffic is not very high and you're running on any decent server platform then adding a tracking system is not going to tax your Rails app noticeably (I know that depends on what 'decent server platform' means but this stuff is pretty cheap these days). Writing to a database is typically very fast - you'd have to have shedloads of clicks to not want to do this straightaway. You can probably bypass most if not all of your before_filters and so on to get a lightning response. One app that runs 2.3.9 uses Metal to do this, for example.
In my new tracking system I have an STI table that goes with models derived from an Activity model; in here you can record both impressions and clicks. Impressions are recorded as the page is built and clicks are recorded using AJAX.
I'm not going to bother with fancy graphs and so on - I'm happy with raw numbers - but these could be added, of course.
At the moment my system is just in the usual app/ folder but I'll probably move it to an engine so I can re-use it more easily.
Hope that helps!
BTW I use Google Analytics as well for a range of sites and it's OK - I just like to do this bit myself.
Depending on how you are going to associate Google Analytics data with a specific user then you might need to double-check the privacy implications. Google doesn't allow their data to be associated with any identifying information about the users being tracked.
If there is a problem then you could try out Piwik as it's open source and you can do what you like with it. It's written in PHP, not Ruby so that might be an issue. As #d11wtq mentions, tracking systems can have performance issues if not built in the right way so you'd be better off starting from something that's already proven to work if possible.