delete events from Calendar Provider on Android - java

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.

Related

How much can I trust OracleDB's ROWID in a long run?

I am working on a small POC using Spring Boot and OracleDB.
The situation is :
While application startup, I load few properties (some data) from the DB in the cache. There are going to be frequent request where I will be needing this data, hence I decided to cache it. The data in the DB will rarely change. Only once in a while some one can insert/delete/update a couple of rows using the sql script. While it changes, I have implemented Oracle's DB change notification to send notification to the spring boot service that some data has changed and the data in the cache is is now in the stale state.
In the notification event, I only get the ROWID pseudocolumn which can be used to point to what portion of data from the db is different from the cache that I have. To be on the safer side, I have decided to cache ROWIDs to map the data in cache and data object in the notification event that DB sends me. While working for a couple of days, I have found out that the ROWID doesn't change but how much shall I trust this non-changing behavior of the ROWIDs in the long run or in the production environment?
Few Scenarios explained for clarification:
Cache will reload itself every time the server restarts. Therefore, data change while the server is down situation is out of picture.
I am (up until the poc) getting every insert/update/delete notification in the made in the db using the sql query/script.
Example of event.toString() for reference:
Connection information : local=view-localhost/127.0.0.1:47632, remote=view-localhost/127.0.0.1:57117
Registration ID : 1201
Notification version : 1
Event type : QUERYCHANGE
Database name : orcl
Query Change Description (length=1)
query ID=41, query change event type=QUERYCHANGE
Table Change Description (length=1): operation=[INSERT], tableName=SYSTEM.PRODUCT, objectNumber=73323
Row Change Description (length=1):
ROW: operation=INSERT, ROWID=AAAR5rAABAAAbHZAAA
Assuming your table does not have row_movement enabled (check dba_tables).
You need to be careful of deletes then inserts - these will logically give a row a new rowid (it’s a completely new row after all).
You also will need to be aware of table moves, this is an intensive operation that requires indexes are rebuilt anyway so is unlikely to happen without much notice.
Otherwise, a row will keep it’s rowid.

Finding entity by unique name, create if not found , fill it and then save. Twice saved by two transactions because of concurrency

I've stumbled upon a problem, which we could not solve via locking strategies and transaction isolation. We have an application, which pushes message to an active MQ. We have a constant listener for this queue.
We have a state report within this message, which should be updated or created (if not there). The report is queried by a unique name ('applicationId'), but this is not a primary key, nor is there a unique constraint on it.
The report is afterwards filled /updated and saved to the database.
I cannot immediately save/persist the entity, when no entity is found and fill the created entity when no matching report is found. I must stick to saving the report at the end of filling the report with data. This is because the underlying table will be fetched every 5 min. or so by an external system and then be deleted.
The problem is: I have 3 incoming messages for the same applicationId within a few milliseconds. After the first two incoming messages, there are 2 reports with the same applicationId in the db and the 3rd update request fails because the find query expects a single result
This is an excerpt of the code:
#Override
public Report saveReportinDB(APPLICATION application)
{
// check if already exists by key applicationId
Report report = this.reportRepository.findOneByApplicationID(application.getAppId());
if (report == null)
{
report = new Report();
}
/*this takes longer, so the next application is comming
in and does not find a report with the same applicationId
within the db because the report which is filled
at the moment is not yet persisted*/
fillReportWithData(application, report);
report = ReportRepository.save(report);
Any ideas how to solve this problem?
The code that runs between 'find whether app id is used yet' and 'finish the work to persist the app id' needs to be atomic, i.e., inside a lock that is somewhere common to both servers.
Personally, I'd explore making the database serve that function (by writing the app record in a 'pending' state), but if you can't do that, a separate lock record, keyed on app id, seems appropriate.

Concurrency control in web application

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.

How to programmatically insert call log entries WITH display name and photo?

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.

Possible Data caching issue with flex datagrid

I have an application in which there are 5 tabs. Each tab has a datagrid. The dataprovider to the datagrid in 1st tab is the common dataprovider to datagrids in other tabs. data in each of the tab varies based on status except for the 1st tab where i display all the data. Now the data for main tab is refreshed every minute using a timer to fetch new data from the backend[Use Blazeds to interact with server side code i.e Java].
After i perform any operation on any of the row in any of the tab other than the 1st one i need to delete the row from that datagrid. I am able to do that by removing the entry from the dataprovider but as soon as i go back to the main tab and return to the tab where i had done the operation i find the deleted entry back. The point to note here is that the entry is not there in the main tab nor it is in the tab where i performed the operation but as soon as i navigate between the tabs it is shown in the UI. But if i do a refresh using F5 it behaves normally.
I was just wondering whether this issue is due to the data caching on the client side and if so what can be a solution to this ?
After you delete the object from the arrayCollection / data - run a collectionName.refresh() on it.
That said, my best guess is that I think you're running into a situation where you're updating a pointer or copy ref rather than the actual data and it's getting reset into that pointer with binding or similar.
If you add a binding listener / change watcher on the object that is bound to the datagrid that traces to console when it gets a CHANGE event, I bet you get a surprise!
(btw, this is how to debug this type of issue quickly).
From your situation its very hard to say without looking at your code. I do agree with the comments passed by the Flextras.
once you deleted it does not show in the tab and when you navigate
to Main tab it does not either show
there and only when you come back
again to the the same tab it does not
get reflected.
It seems there could be an issue with your DB Queries [May be]. Why don't you recheck with your queries where once the delete operation is performed, does the DB tables get reflected or not.
If the above turns out to be false, then get back to the next step.
What does trace() of the dataprovider
give you. I mean what does it
contain? Try this on the select event
of the tab.
Your dataprovider May be holding previous values, though the item from
the grid being deleted is not reflecting the dataprovider. Did you
try to refresh the datagrid or why don't you call invalidateProperties()
method to check.
Once again a some piece of code tabs
could help you and us a lot of time in giving a correct riposte to the question.

Categories

Resources