How to sync registered users in database with iPhone contacts - objective-c

Imagine an iphone app that automatically registers users on the first start according to their phone identity (e.g. phone number*) on a server database.
Afterwards, users should see which of their friends already use the app, i.e. which of their contacts are registered on the DB.
An obvious solution would be to always send a select-request to the DB containing all of the users contacts, everytime the user refreshs his or her friend list. As a result, the user retrieves the list of their registered contacts (friends).
Is there any better way to realize this synchronization between the user management on the server and the contacts in the user's address book. Sending multiple select-requests (each user for every refresh) with dozens of phone numbers might not be performant at all.
Example:
WhatsApp is actually a good example for this scenario. You can add new contacts to your address book and WhatsApp automatically refreshs your WhatsApp friend list according to your phone book. I really like this idea because the user don't need to create an account manually.
*I know about the problems of using phone numbers in AppStore apps, so this question really focusses on the architectural problem.
EDIT
this comment (Whatsapp contacts syncronization) describes the mentioned simple approach. but is this really the smartest way?

Related

How does one create database tables (MSSQL) to handle notifications to users and system notifications to all users?

I would like to create a notification system for a web application I'm working on. I'm having trouble designing a database that is laid out in a "correct" format. This is what I would like to accomplish:
Have different notification types, such as Office, User, Client, Vendors, and System. User, Client, and Vendors are different "classes" of users that can login to different portals on the site. They would each have notifications just to their login. Office and System would be notifications for a whole entire office, so every user would see it (like meeting notices) while system would be for every user in all systems (like website shutting down for maintenance).
I want a notification button that displays the number of unread notifications. A user can click on the notification to mark it as read to remove it from the list.
The user can go to a separate "all notifications screen" to see all the notifications they ever got and search them.
I have a single table like this:
*Table: Notifications
notification_id int primary key
entity_type varchar
entity_id int
title varchar
message varchar
created datetime
didRead bit
readDate datetime
The entity type is Office, User, Client, Vendors, or System. The id is the corresponding entity id. Since each user for users, client, and vendors are in a different table, it is possible for a separate user, client, and vendor to all have the same id like 4444 etc. The entity type lets me know what table to look into to use the id for.
This works well if the notification is for a user. One record for the one notification for the user. The user reads it and it is marked.
The problem is with system and office notifications. Once I create a single record for a system notification, I can show it to the user by doing a SQL for the their notifications OR system notifications OR office notifications. However, I have NO way of determining if that user read the system or office notification. Since the entity id in the case of system is null or in office it is the office id, if I mark it as read, it will be read for everyone in the office. Only the first person to see it gets alerted.
I could make it so every system notification creates an individual notification for a user, but lets say I have 8 million users. Doesn't that mean for every system notification that I have to create 8 million records? I may be wrong (as in maybe it is no big deal for SQL Server), but something tells me that is bad and will bloat the database fast. Especially since I can see office notifications take off.
I was thinking of making a notification read table containing entity id, entity type, and notification id, but then aren't I just moving the same issue to a different table? Also wouldn't a join to this table now need three items being the entity id, entity type, and notification id? I would assume that would kill performance once the table grew.
Main Question: How can I design the table so I am able to read/unread any notification that comes to any user, including their individual notifications and system/office wide notifications? I want system and office notifications to hit a broad range of users, while user, client, and vendor notifications only hit a specific user while allowing all cases to be readable/unreadable.
I use Microsoft SQL server if that makes a difference.
Edit:
Tried adding an image (crappy paint skills) to show what I was asking for.

API for "People" contact data

I'm working on a Win8 metro signup flow and would like to be able to seamlessly pull, using the user-provided phone #, a photo and display name from the built-in "People" app. I'm having trouble finding documentation/code outside of ContactPicker (which isn't what I need).
Couple questions:
Is there an API to pull contact data that would be present in the "People" app?
If so, is there a way to configure capabilities to avoid interrupting the user with a modal "Ok for app xyz to access your address book"?
Thanks.
Confirmed that there is no API to pull contacts programmatically.
You can't pull contacts without permission, it's a security feature. You CAN interrogate the contact data users pick via the Contact Picker though.
You therefore have to ask the user to pick contacts relevant to your task, call the single / multiple contact picker then once picked, you can interrogate the contacts as much as you want. They have phone numbers, emails, locations all the data you might want hanging off those.
As far as I can tell, there's no way to maintain a persistent link to them though, so store that data while you can.

iTunes connect will not let me add myself as a user

I am working on an app in iTunes connect for a client, under their iTunes connect account. I want to add myself as a user so that I can get email notifications of updates in app status. When I try to add myself as a user I get the following message:
The email address you entered already belongs to an iTunes Connect account. To continue, enter a different email address
I am using this email address on my own company's iTunes connect account, but not on my client's account. How can I add myself as a user?
#sarnold Turning your comment into an answer because it worked for me.
Two Separate Websites
Apparently for historical and organizational reasons, Apple operates their developer and app store business in a bifurcated manner.
developer.apple.com
The web site for all the technical resources, including documentation, WWDC videos and such.
itunesconnect.apple.com
This completely separate web site handles the business end:
Contracts, banking, payments.
Uploading your finished app.
Defining your In-App Purchase products.
Problem: Different Handling Of Accounts
The developer.apple.com site is slick in that a programmer can have a single Apple ID used to join multiple developer accounts. She may work for three different companies, and be assigned a role on each of those companies’ Developer accounts all on the same Apple ID. When she logs in to the Developer site, she is presented with a popup menu asking which of the three companies’ Developer accounts she wants to access during this work session. Nice.
The problem: in iTunesConnect, not so nice. In iTunesConnect, the "admin" person cannot assign existing Apple IDs as members with a role. Very strange. The admin is forced to create a new ID for each person being adding to the team. That means the person joining must have multiple email address. If an admin tries to add you to their iTunesConnect with an email address already used on some other company's iTunesAccount, an error message reports that email address / Apple ID is already in use. Obviously the programming team running the iTunesConnect site could use some help from the Developer site's team. ☹
Workaround: Email Address Trick
The workaround cited by sarnold involves a feature of email addresses. The spec for email servers has a feature where you can extend your email address. You can add a suffix to the first part of your email name by appending a "+" PLUS SIGN. From what I could figure out, the email software first looks for the extended name. If no such name is found, it drops the extension and looks again. If found, the shorter version of the email address is actually used.
So if the programmer Susan wants to use her email address susan#example.com for a second or third iTunesAccount, she tells her client's admin person at Acme Corporation to use something like this as her email address: susan+acme.com#example.com. Apple will still create a needless extra Apple ID for Susan, but at least Susan does not have to bother with creating and accessing extra email accounts. The emails sent by Apple will arrive at her susan#example.com address.
Susan double-checked this would work before talking to the admin person. She sent herself an email to susan+acme.com#example.com to make sure it arrived at the susan#example.com account.
Effectively, the email servers are not fooled by the extended email address, but iTunesConnect is fooled into creating an new Apple ID using an old email account.
Basically, you can't invite other iOS devs to review your efforts seems to be the result of this policy.
I had (and have) the exact same problem... what makes me kinda like FlavorScape's suggestion ;)
What I did is something similar to sarnold's comment: I used an alternative email address (_#gmail.com instead of _#googlemail.com) and this actually created a new AppleID with this email address.
It works fine, but it would be so much better to just connect my actual Developer account to my client's.
The way it's like at the moment, I can not even access the developer resources and (most importantly) the provisioning center with the new Apple ID, so my client has to do create new provisioning profiles and stuff, which is pretty frustrating and complicated.
Additionally, it is a pain to let him test the Apps on his own devices, because of the developer certificate is installed on my Mac, not his, and I am therefore the only one (or better, my Mac is the only computer) that can install new provisioning profiles on his devices.
Is there a better way to connect the accounts and solve these problems?
Cheers,
Nils
Apple now will allow the same email address to be invited to multiple itunes connect accounts and no longer allows new emails to be added with the +. Just a word of warning to others who were doing this the original post is now out of date with Apples new policy it seems.
#knl: The problem in the original question is specifically with iTunes Connect. If you want to be able to manage the Provisioning center -- to make profiles etc -- ask your client to add you to that account. Here are the steps:
Go to "Member Center"
Select the "People" tab
Click on invitations
Select "Invite person"
in the next screen they can select your role including "Member" (limited access) and "Admin" (full access)
From apple documentation:
You can only create test user accounts using an iTunes Connect
accounts with the Admin or Technical role assigned to it. Test users
do not have access to iTunes Connect, but will be able to test in-app
purchases in a development environment on a registered test device.
Link here

Design for getting Twitter friends list for large user base and managing rate limiting

Assume there's a mobile app and a server.
I have question about rate limiting and hoping someone can give some advice on a design as I'm banging my head on how to navigate around rate limit. There must be something I"m missing because the 150 unauthenticated rate limit per IP per hour is extremely low.
Imagine the scenario I want to build is the following (simplified into a trivial example for this discusion). Assume user is signed into Twitter for this entire discussion to remove discussion about oAuth.
Mobile talks to our service to show users twitter friends list. Every time the mobile app is loaded, it will show the entire friends list, and highlighting the new friends that were added within the last 2 days.
That's it. But the trick is that I want to ensure that the friends list is always up to date in the client, which means our server has to have the most recent up to date friends list.
Periodically, I want my server to automatically scan the Twitter friends list for every user of my app to see if new friends have been added.
Our initial design was getting our server to do all the work with this flow:
New User signs in on client, gives access token to server
Server makes call to Twitter REST APIs to get initial friends lists
Server stores the Twitter Friends IDs and shows responds to the client with that list.
Periodically (e.g. every 48 hours), server checks Twitter REST APIs for friends list for each user and compares it to our cached Twitter friends list we have for them to see who is new and to highlight in the mobile app.
The good thing about this is that all the interaction with twitter to get friends list, compare and peridiocally refresh is on the server. Mobile client just makes a single call to my server and gets friends list.
The problem with this design is that it will work for a single user, but since the rate limit is 150 per hour on un-authenticated calls, I will hit my limit as soon as 151 users user my service (which has a fixed IP).
The only solution I can see is to have the client do the work for each user, then send me the friends list which my server caches. This takes care of Step #2 above. However, for Step #4, I'd have to build something into the client to auto refresh twitter friends and send back to the server.
This is super clumsy to have the client involved at all in this Twitter friends list operation.
At first I thought I was crazy and the public unauthenticated APIs like getting friends lists wouldn't be subject to rate limiting. However, according to their docs, it is.
Am I missing something obvious or is the only way to solve this is to put heavy logic into the client?
With whitelisting gone for those that aren't grandfathered or Twitter business partners, I don't think you have any alternative but to have your mobile app do the Twitter API calls from the handset.
Having the handset call Twitter isn't a bad thing by any means. Pretty much every Twitter client in the world does it. One benefit will be that the user will be authenticated to Twitter, and thus her full 350 calls per hour will be available to you. Keep in mind, however, that you should minimize your calls since the user may have other Twitter-aware applications installed on her handset eating into your call allotment, and vice versa.
Now to the solution. The way I would implement your use case would be to first fetch the complete list of friends for your user by calling the friends/ids method.
http://api.twitter.com/1/friends/ids.json?screen_name=yourUsersName
The above call will return the most recent 5,000 friend IDs, in order followed, for #yourUsersName. If you want to fetch more friend IDs than the first 5,000, you'll need to specify the cursor parameter to initiate paging.
Next, I would check the latest list of friends we just fetched against the list on the handset, syncing them by removing any IDs that are no longer present, while adding any that are new.
If we only need the friend IDs, then we're done at a cost of one API call per 5,000 friend IDs. If, however, we need to get user info for these new friends as well, then I would call users/lookup and pass in the list of all new users that we discovered while syncing friend IDs. You can request up to 100 user objects at a time.
http://api.twitter.com/1/users/lookup.json?user_id=123123,5235235,456243,4534563
You user must be authenticated in order to make the above request, but the call can fetch any Twitter user profiles you wish -- not just those that are friends of the authenticated user.
So, let's say for example that a user has 2,500 friends and has never used your app before. In that case, she would burn one call to fetch all of the friend IDs, and 25 calls for her friends' information. That's not too bad to get the app populated with data.
Subsequent calls should be more streamlined with probably only two calls burned (one for the IDs, and one to get the new friends).
Finally, once the data has been updated on the handset, the deltas for the IDs and user data can be gathered up and pushed to your server.
It may even be possible that your server application won't even have to interface with Twitter at all, and that should alleviate the 150 user limit you are encountering.
Some final notes:
Be sure to note in your app's privacy policy that you sync your user's friend list with your server.
I recommend specifying JSON as the return format for all Twitter API calls. It is a much more lightweight document format than XML, and you will typically transfer only about 1/3 to 1/2 as much data over the wire.
Pick a Twitter framework appropriate for your mobile device and your programming language. Twitter access is a commodity these days, and there's little to no reason to reinvent how to access the Twitter API.
I answered a similar question about an approach for efficiently fetching followers here.
Since you are making request on behalf of users you should make those requests be authenticated as those users. Then requests will count against each users own pool of 350 requests/hour.

How to obtain the phone number when reading facebook contacts

I thought it was impossible to read phone numbers of contacts using facebook APIs, but "Facebook for HTC Sense" android application is syncing all that information to my local agenda.
Somebody knows how are they implementing this feature?
Is it for people you already have in your contacts? It's possible they are just cross-referencing other pieces of information (like email) against your local contact info.
Because phone number isn't a field in the graph nor is it one in the corresponding FQL table.
The fql fields are "cell" and "other_phone" but they are not available unless your app is whitelisted like obviously their iphone/android apps are. You can request those fields but they will return back null values, confirming those are the fields (requesting fields that don't exist throws errors).