I am able to programmatically insert an entry into the Android call log with a number, date, duration & type BUT I cannot figure out how to also include a photo, label and name?
The entry I'm adding is for an existing Contact with the exact same number. I've noticed on a Motorola device the name & pic appears if the number matches an existing Contact but on my HTC Incredible something is missing?
I do the following.. (didn't know what to even try for the photo)
ContentValues values = new ContentValues();
values.put(CallLog.Calls.NUMBER, number);
values.put(CallLog.Calls.CACHED_NAME, name);
values.put(CallLog.Calls.CACHED_NUMBER_LABEL, label);
values.put(CallLog.Calls.DATE, date);
values.put(CallLog.Calls.DURATION, duration);
values.put(CallLog.Calls.TYPE, myCallType);
context.getContentResolver().insert(CallLog.Calls.CONTENT_URI, values);
You cannot insert photos into the call log itself; those are stored in the Contact that is linked to the call log entry. See ContactsContract.Data for more information about how to do that.
As far as the HTC device not updating the call log with an existing photo, it could be tied to the way that HTC Sense caches call log entries; I have seen similar issues that only appear on Sense devices.
Call log entries are typically stored in the calls table in the Contacts app database (/data/data/com.android.providers.contacts/databases/contacts2.db). For some reason, it appears that HTC Sense does not update existing call log entries if contact data changes, but other ROMs do.
For example, if I use an HTC EVO LTE with stock Sense 5.0 to place a call to someone I have saved as "Jenny Smith", an entry is created in the calls table, which includes a name field -- where it stores Jenny Smith. If I update her contact information to "Jenny Jones" and place a new call to her, a new entry is stored in the calls table with the name Jenny Jones, but the previous entry is not changed. The actual Call History screen shows all of the calls as Jenny Jones, but the database itself has old name.
Other devices I have tested (including an Nexus 5) update previous entries in the calls table when the Call Log is viewed. Your Motorola device likely behaves like the Nexus 5, refreshing the data as needed.
I am not a database wizard, but have a reasonable amount of familiarity with them. From a database structure perspective, it seems odd to me that any contact-specific information is stored in that calls table (it contains a raw_contacts_id field that is linked to the same field in the contacts table of that database where all of the actual contact information is stored), but that's how it is implemented.
The only reasonable way of doing it (that works for me anyway) is to add a contact directly to the handset and then add your call log pointing at that contact, afterwards you can then remove the contact from the handset. The only issue with this is if your app gets killed before removing the contact so you would have to implement some sort of clean up on next app launch. It's all very messy for what should be a simple task.
Related
I have to solve this situation: in my Spring + JPA web application I have a jsp similar to an excel work sheet.
So I have a certain number of cells and each cell is saved in a DB table with additional information: I have a row for each cell.
id | value | column | row | ...
I use this structure because number of columns in my jsp table is dynamic.
At the moment, when I save cells I truncate the current set of rows in DB table and re-insert all the new rows. This is the fastest way I found to update a large set of rows.
But now I have a concurrency problem: the jsp page can be used by different users at the same time and this can cause overwriting problems on other users savings.
I need to implement some kind of lock in my web app. I found there are mainly two types of lock: optimistic vs pessimistic.
Can you suggest me a common approach to solve this situation? Where do I need to implement the lock, at data access level or at service level?
NOTE to be more clear: table values are shared among users, but can be updated by anyone among authorized users.
The solution would probably depend on the behavior requirements.
How about the following scenario: users A and B started to change some values, then user A pressed Save button and saved data, after that user B did the same. User B got an error message saying something like "the data has been updated, please reload the page". He reloads the page and lose all changes he did :( Only after that he is able to save his changes, but he has to do it once again.
Other possible scenario: users A and B accessing the page, but only the user who was the first will be able to save his work, other users will see message saying something like "someone else is editing the page, try again later".
For the first scenario you can implement the following: each line of the table (in database) has a last-update-timestamp which is updated to current time each time this row is changed.
Now, let's imagine user A get row with timestamp 1 when opened the page, user B was a little bit slower and got the same row with timestamp 2. But, he did his changes faster and pressed Save button first. Now, the row is saved in DB with timestamp let's say 5. User A is trying to save his changes, but the timestamp of his data is 1, which is different from 5 currently in DB. That means someone changed that data already and he should see error message I mentioned above.
Second scenario is a little bit harder to implement. I think the best way to do this is to open transaction to DB which
reads the row(s) we want;
put some flag like "locked" to true for all of them;
if some row is locked already, fails (or return available rows, depending on what you need). But, probably should fail;
returns rows to jsp page;
Now, if other user requested the same rows, transaction will fail and he will not be able to start changing data.
User A should put these locked flags back to false when he saves the data.
Important thing: these locks should have timeout to prevent situation when user opened the page and closed it without saving (or browser crash, or something else). You may also want to implement some kind of lock reackquire for the same user - when user opened the page for the first time, then closed it without saving data and opened once again - he should be able to edit the data. This can be done by identifying user somehow - login, cookie, and so on.
I am using parse.com cloud storage, to implement level sharing/downloading and rating for built in level editor for my game, so players are allowed to built and test their own created levels, latter on they can share it with different players, that`s how I upload it to the parse.com cloud storage:
ParseObject testObject = new ParseObject("Levels");
testObject.put("file", new ParseFile(name + ".lvl", levelString.getBytes()));
testObject.put("author", authorName);
testObject.put("email", authorEmail);
testObject.saveInBackground();
It works fine, but I wanted to let players also rate downloaded levels (lets say 1-5 stars) it could be simple, by creating new two fields called rating and ratings count, so every time someone will vote, I would add it to ratings count and would ++ ratings count.
Problem is, how to prevent player from rating particular level multiple times? Thanks.
I have thought about this for a project of mine. In the end you will need two data points.
You need to track the counts per rank on the object (Level in your case)
You need to track UserLevelRating, at minimum a reference to the user, reference to the target (Level), and the rating given (if you will let people change ratings)
Depending on how you want to implement it, to prevent rating something twice, or to allow people to change the rating they have given something, you would do a query for the current user and the Level. If a record is returned they have already voted, so prevent them from voting again.
You could add some cloud code using before-safe or after-save logic to handle other things, such as changing the vote and updating the counts on the target (Level).
Here's a sample of the logic I would use for a simple single vote system without changing votes:
Test for existence of UserLevelRating record, if it exists prevent voting
Saving vote, include User=current user, Level=selected level, Rating=stars given
Cloud code, in after-save of UserLevelRating, looks at Level property, loads the level, calls increment on the property for the rating (e.g. if Rating=3, increment("Stars3") would be called)
Anytime you load a Level object you would have counts for each rating, and could produce the average.
I have an application which uses the Calendar Provider for adding, editing and removing events. I have an interface of a calendar, which shows which days have events attached. Adding events works Perfectly. For adding an event I hardcoded the calendarID with the number 3, so calID = 3.
long calID=3;
values.put(Events.DESCRIPTION, description);
values.put(Events.CALENDAR_ID, calID);
values.put(Events.EVENT_TIMEZONE, "Europe/London");
Uri uri = cr.insert(Events.CONTENT_URI, values);
This works perfectly. the View i've programmed shows the events. I open the Calendar application which comes included on my phone (Xperia J) and I can see that the event is there.
I tried to delete events with the following code:
ContentResolver cr = mContext.getContentResolver();
ContentValues values = new ContentValues();
Uri deleteUri = null;
deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = mContext.getContentResolver().delete(deleteUri, null, null);
This code was DIRECTLY copied from developer.android.com website.
This doesn't Delete! I debugged the code and the value of 'rows' is equal to 1, so effectivelly the row should have been deleted.
However I get back to my app, and the event still exists there. Interesting thing: I've checked the Calendar Application that comes in my phone, and the event doesn't exist there. So it has been deleted (?). I thought that maybe i am not refreshing my app, so i closed it, reinstalled it, and it never deletes. I debug again the code for deletion, and once again the 'rows' value is equal to one, to the very same event! So, 'rows' is always returning 1 EVERY TIME i want to the delete it. So the row was deleted, but it was not deleted.
What is happening here? Is it because when I added the event, I hardcoded the calendarID?
As you noticed, deleting an event doesn't really remove the row from the DB until the event is synced to the server.
It's quite logical, otherwise the calendar sync adapter would not be able to retrieve event data to send a DELETE request to the server. That's why there is a DELETED column in the event table, which you must check when querying events:
http://developer.android.com/reference/android/provider/CalendarContract.SyncColumns.html#DELETED
By the way if you query Instances instead of Events (which does expansion of recurring events), deleted events are removed automatically from the result.
SOLVED. Basically the problem is that the event seemed to be locally removed on the phone, but was not yet synced with my Google Account. After syncing, the events were both removed from my phone and my Google Account associated to the phone.
This is another proof how annoying can be programming on Android, specially when special attention is not given to little details like these. I lost 2 days just to find out this basic issue...
There are two versions of delete: as an application and as a sync adapter. An application delete sets the deleted column to 1. This flag that tells the sync adapter that the row was deleted and that this deletion should be propagated to the server. A sync adapter delete removes the event from the database along with all its associated data.
I am developing an Android app which needs to know when a contact is added/updated/deleted.
So I read several posts for it. I understand that we can get notified through Content observers whenever a contacts gets changed, but we can't get which contacts have been added/updated/deleted. So I have read the official APIs and prepared my design how to capture that particular contact.
So what I thought at the start
We will store all the contact IDs, deleted flag and version
Whenever contacts get changed I will get my table's row count and row count from Android's system.
If my rowcount is less than systems row count then a contact has been deleted.
If my rowcount is greater than systems row count then a contact has been added.
And if these are not the cases then one of the contacts version has been changed.
I have also learned that Android doesn't delete the contact if it is deleted by user, but it sets 0 on deleted flag. So in these cases the row count will be same.
Android also changes the row ID of a contact many times as stated in the official docs. So how can we uniquely identify them like lookup uri and if not then we have to put observer for that also.
So I want to know whether the above is correct? And in the case a contact is added will it be added to the last row of cursor or not means if I check the last row of system database for contacts will it give me the contact added or not.
Let me explain as much as I could. Basically your policy looks pretty good, but actually it is bit more complex than you thought.
On Android, a contact can be associated with several raw contacts, which may be provided from many data providers, such as Google, Facebook, Skype and so on. For example, if one of your friends in your local contacts is also using Skype, there are two raw contacts existing separately in ContactContracts.RawContacts, but they will be aggregated automatically and show up just as one contact when you query to ContactsContract.Contacts.
That is also why it's hard to identify a contact uniquely, because you can split or join them anytime you want. LOOKUP_KEY isn't very handy for this case.
Many apps except Google only provide a one-way sync, i.e. only from service to contacts, so they are read-only. In this case, the deleted flag will not be used and simply deleted during their synchronization process. Thus, you can not simply rely on the flag.
Though there isn't a good simple solution, I guess it's much easier to achieve what you want, if you observe for a specific RawContacts, not Contacts. Hope this helps your understanding.
I think the best practice is to monitoring whenever a contact has aggregate to another one and identify them by the contactName, not the _ID or CONTACT_ID.
Take a look at this possibly contacts operations:
Insert
A Contact cannot be created explicitly. When a raw contact is inserted, the provider will first try to find a Contact representing the same person. If one is found, the raw contact's CONTACT_ID column gets the _ID of the aggregate Contact. If no match is found, the provider automatically inserts a new Contact and puts its _ID into the CONTACT_ID column of the newly inserted raw contact.
Update
Only certain columns of Contact are modifiable: TIMES_CONTACTED, LAST_TIME_CONTACTED, STARRED, CUSTOM_RINGTONE, SEND_TO_VOICEMAIL. Changing any of these columns on the Contact also changes them on all constituent raw contacts.
Delete
Be careful with deleting Contacts! Deleting an aggregate contact deletes all constituent raw contacts. The corresponding sync adapters will notice the deletions of their respective raw contacts and remove them from their back end storage.
Query
If you need to read an individual contact, consider using CONTENT_LOOKUP_URI instead of CONTENT_URI.
If you need to look up a contact by the phone number, use PhoneLookup.CONTENT_FILTER_URI, which is optimized for this purpose.
If you need to look up a contact by partial name, e.g. to produce filter-as-you-type suggestions, use the CONTENT_FILTER_URI URI.
If you need to look up a contact by some data element like email address, nickname, etc, use a query against the ContactsContract.Data table. The result will contain contact ID, name etc.
The problem, though, is that you could have two 'Phillip Morris' in your contact list that aren't the same person.
For further information, see this section of Android Classes Documentation.
I have to develop a application with the following scenario:
1--User create a profil (name,lastname,address....)
2--The information are inserted in the database
3--The administrator should receive an e-mail to be notified by the new profil ,if the administrator dont
approve the profil he will delete it.
Is there a way to send automatically an e-mail when a row is inserted in the database?
I'm using java.
If you are doing this through a common interface, then I'd suggest putting a seperate call next to the insert routine (between Java and database).
I heard you can do a whole lot of things with triggers in MS SQL, but I was told to keep my hands away from triggers. Made by the devil to make a day turn bad. People that has succesfully mastered triggers will tell you otherwise.