I am new to android. I am getting a problem while restoring the call log, which I stored in a database.
I am storing the call log with the following code:
Cursor managedCursor = cr.query(CallLog.Calls.CONTENT_URI, null,
CallLog.Calls.NUMBER + "=?",
new String[] {(ActiveUserContacts.get(i).getnumber()) },
null);
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
int name = managedCursor.getColumnIndex(CallLog.Calls.CACHED_NAME);
int NEW = managedCursor.getColumnIndex(CallLog.Calls.NEW);
while (managedCursor.moveToNext()) {
CallLogsModel Log = new CallLogsModel(Integer.toString(i),
managedCursor.getString(type),
managedCursor.getString(date),
managedCursor.getString(duration),
managedCursor.getString(number),
managedCursor.getString(name),
managedCursor.getString(NEW));
StoreData.addCallLog(UserNAME, Log);
}
managedCursor.close();
And I restore it with the code:
ContentValues values = new ContentValues();
values.put(CallLog.Calls.TYPE, PrevContents.get(i).getType());
values.put(CallLog.Calls.DATE, PrevContents.get(i).getDate());
values.put(CallLog.Calls.DURATION, PrevContents.get(i).getDuration());
values.put(CallLog.Calls.NUMBER, PrevContents.get(i).getNumber());
values.put(CallLog.Calls.CACHED_NAME, PrevContents.get(i).getName());
values.put(CallLog.Calls.NEW, PrevContents.get(i).getNew());
getActivity().getContentResolver().insert(CallLog.Calls.CONTENT_URI, values);
However, everything but the time of call got restored. Did I make a mistake?
Your PrevContents.get(i).getDate() may not be the right type or in the right format for the call log. Some of the examples I see of records inserted into the call log (e.g., android adding number to Call logs) use System.currentTimeMillis() as the date, which is actually of type long. You probably want to use managedCursor.getLong(date) in the code you use to retrieve the date, and store it as a long.
Another note: it looks as if you're getting 1 record when you query the call log, put that in your cursor, save that 1 record, then do the same thing for the next record, and get all the records by looping through all of the call log records manually (I assume that's what that index 'i' is for). You don't need to do that--the query can get all records for you, then you can use managedCursor.moveToNext() to do the looping. Take a look at http://android2011dev.blogspot.com/2011/08/get-android-phone-call-historylog.html for an example of how to do this. When you do the restoration you may need a loop (though there may be an easier way to do that, too).
Related
I am working on a Adaptive To-Do application, In this user will have a button to reschedule the pending tasks(Tasks with past date), when the user clicks reschedule, it'll change the pending tasks date to current free date(Dates which are not assigned to any task. What i cant understand is how to retrieve date from database and compare it with the available dates.But formater shows error, and if comparision also.
public void UpdateData() {
Calendar cal = Calendar.getInstance();
SQLiteDatabase db = mHelper.getReadableDatabase();
Cursor cursor = db.query(TaskContract.TaskEntry.TABLE_NAME,
new String[]{TaskContract.TaskEntry._ID,
TaskContract.TaskEntry.COLUMN_DATE,
},
null, null, null, null, null);
//Calendar reminderCalendar = Calendar.getInstance();
//reminderCalendar.set(year, month, day);
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
String str1 = TaskContract.TaskEntry.COLUMN_DATE;
Date date1 = formatter.parse(str1);//Show Error UnHandled Exception java.text.parse exception.
if (date1.before(cal))// Shows error and says to flip to (cal.before(date1)) {
ContentValues cv = new ContentValues();
final Calendar c = Calendar.getInstance();
int yy = c.get(Calendar.YEAR);
int mm = c.get(Calendar.MONTH);
int dd = c.get(Calendar.DAY_OF_MONTH);
}
}
String str1 = TaskContract.TaskEntry.COLUMN_DATE;
Assuming your column is called MYDATE, your code is saying that str1 = "MYDATE";
Can you tell me what date MYDATE is? Nor can the formatter, hence the exception.
I believe what you want is:-
String str1 = "";
if (cursor.moveTofirst) {
str1 = cursor.getString(cursor.getColumnIndex(TaskContract.TaskEntry.COLUMN_DATE));
} else {
// handle no data being extracted for some reason
}
cursor.close(); // assuming you've done with the Cursor
Date date1 = formatter.parse(str1);
..........
To further explain when you say :-
`Cursor cursor = db.query(......`
You are saying get me a cursor from the table(1st parameter), with the columns (2nd parameter, null for all columns), 3rd parameter where clause and so on.
If it works you will get a Cursor named cursor which contain your data as a number of rows of columns (like a spreadhsheet).
To get to the data you need to do the equivalent of get the data from cell A1 (A being the first column of the first row).
However you move to a Row and then get the nth column using one the get???? methods. Above move's to the first row (we'd only expect the 1 row by the looks of your code (more later)).
At a row you can get data from columns by using the index/offset to that column. The first column being 0, the next 1 etc.
However, having to work this out and perhaps change it if you change the query can introduce difficulties, so it's probably much easier to find the index/offest by using the column name. Hence, getColumnIndex(column_name_as_a_string)
Back to moving, to explain why the moveToFirst is in an if.
A cursor can contain 0 or more rows, a cursor, if the query works will not be null, rather an empty cursor is returned (this is a relatively frequent occurrence, and also sometimes a very useful situation).
So rather than issuing an exception because a Cursor can't move to a position, it returns false (true if it can and does move).
So if(cursor.moveToFirst) {....} is saying only do if there is data in the cursor.
There are other move methods, moveToLast(), moveToNext(), moveToPrevious() and moveToPosition(int).
Perhaps the most common is moveToNext e.g.
while(cursor.moveToNext()) {
// use the respective column data here
}
traversing all rows of the cursor
Part of my functionality requires updating a value in every row (only happens rarely, when a user selects a certain setting).
Trouble is, the query takes a good few minutes to perform (at best), and there's only 269 test records. Is there any way this could be optimized?
String allRecords = "SELECT id, weight FROM Workout_Entry";
Cursor cursor = db.rawQuery(allRecords, null);
int rows = cursor.getCount();
int id;
double weight;
try
{
if (cursor.moveToFirst())
{
do
{
for (int i = 0; i < rows; i++)
{
id = cursor.getInt(0);
weight = cursor.getInt(1) / 2.2;
String strFilter = "id = " + id;
ContentValues args = new ContentValues();
args.put("weight", weight);
db.update("Workout_Entry", args, strFilter, null);
}
} while (cursor.moveToNext());
}
} finally
{
cursor.close();
}
(db).close();
Thanks!
Just push the work to the database engine instead of pulling the data out one row at a time and firing up a new update query each time. Replace your code with something like:
db.execSQL("UPDATE Workout_Entry SET weight=weight/2.2");
Also, since this seems to be some kind of metric/imperial unit conversion, consider keeping the data in just one format in the database and convert/format to the appropriate unit for display purposes.
You should learn to use transactions - you can see example of how you use that in this presentation of mine.
Also showing the impact of not using the transaction.
Ok, I've realised my error. I had a do while loop for every record, and inside of that was a for loop which looped through x many times, where x was the amount of existing records.
So it was going through O(n)² times instead of O(n).
Thanks to those who replied! I found both of your comments useful.
I want to start an activity once i get a missed call.but iam unable to read the latest missed call entry from the call log, instead it reads the entry before the current one. iam reading it when phone state is idle.
Example: say there are two missed call entries one at 11:10 and other at 11:11. I get a missed call at 12:12, my activity needs to show missed calls obtained at 12:12,11:11,11:10. but rather it reads 11:11,11:10. Latest entry is missing. what should i do? I am using a service and reading call log, phone state.
Cursor c = getContentResolver().query(allCalls, null, null, null, order);
if (c.moveToFirst()) {
do{
// getting number,type,ack etc}
while (c.moveToNext()); }
You will need to listen for it using TelephonyManager and PhoneStateListener.
This code will show you how to do it:
if(lastStart == TelephonyManager.CALL_STATE_RINGING)
{
long now = System.currentTimeMillis();
long duration = (now-ringStartTime)/1000;
bindService.AddMissCallInfo(ringPhoneNumber, ringStartTime, duration);
Log.i(Constants.Tag,"service add miss call!");
}
Code taken from: http://code.google.com/p/android-miss-call/source/browse/trunk/src/com/call/DialPhoneStateListener.java?r=3
you can used like this.
c=mContext.getContentResolver().query(CallLog.Calls.CONTENT_URI, projection, null, null, CallLog.Calls._ID + " DESC");
if(c.getCount()!=0){
c.moveToFirst();
lastCallnumber = c.getString(0);
lastCallnumber=FormatNumber(lastCallnumber);
String type=c.getString(1);
String duration=c.getString(2);
String name=c.getString(3);
String id=c.getString(4);
System.out.println("CALLLLing:"+lastCallnumber+"Type:"+type+"\t id:"+id);
if(type.equals("3")){
//you can get last missedcall here
}
You can try it may be helpful for you.
I am trying to access call logs through android application. I have taken data through app and update the value of database but after updating I can't get the updated values in call list.
code I tried below:
Uri allCalls = Uri.parse("content://call_log/calls");
Cursor c = managedQuery(allCalls, null, null, null, null);
if (c.moveToFirst()) {
do {
String callType = "";
switch (
Integer.parseInt(c.getString(c.getColumnIndex(Calls.TYPE)))
) {
case 1: callType = "Incoming";
break;
case 2: callType = "Outgoing";
break;
case 3: callType = "Missed";
}
} while (c.moveToNext());
}
ContentValues values = new ContentValues();
values.put("name", "Unknown");
int k = getContentResolver().update(allCalls, values,null, null);
I got the integer value for k as how many number of rows updated but in call list I didnt get updated value.
Edit: I am able to insert and delete the call list values and when I check in call list it shows the result as inserting new row or deleting the existing one But when I update the values I can update, it return values as result of update query when I check by clicking callLog list, update value remain for a fraction of second and then old value displaying...
I don't know where I made a mistake, please help me...
Seeing this question is over a year old, I don't know if you're still looking for an answer to this. Thought you'd like to know the answer anyway.
Your code is completely fine, it updates the call record as it is supposed to. But since you're changing just the name, it is unlikely to stick. The name field in the Call Logs is a cached name, as indicated in the Android Documentation, and is probably refreshed every time you view the logs.
If you're just changing the name, the name associated with the number will be refreshed from the Contacts list, and that is why you won't see the updated name in the Logs. Or, you'll see the change until the list is refreshed/updated.
So I'm still building a Database to support a project of mine. There are two different things to be saved: first, attribute values of some player objects and second, simple values stored in a java class.
ATM my problem lies in the process of loading values of a player object and writing it in the respective class.
Now let's see some code:
Following you see the method I want to use for saving the values in the database.
That works fine atm, but I just realized I'm still passing the contentValues object an extra value for the 'ID' , which I did set - and planned to keep that way - as autoincrement.
Any Idea how to work this in accordingly?
public void savePlayer(Player player[]) {
for (int i = 0; i <= 3; i++) {
playerValues.put("ID", i);
playerValues.put("Name", player[i].getName());
playerValues.put("HP", player[i].getHp());
playerValues.put("Satisfaction", player[i].getsatisfaction());
playerValues.put("Hygiene", player[i].isHygieneInt());
playerValues.put("IsAlive", player[i].isAliveInt());
}
db.insert("playertable", null, playerValues);
}
Okay, hold on to your hats because this might look a bit like spaghetti - the load-method:
public void loadPlayer() {
String[] namecolumn = { "Name" };
String[] intcolumn = { "ID, HP, Satisfaction, Hygiene, IsAlive" };
String[] namesToString = new String[4];
for (int j = 0; j <= 3; j++) {
Cursor playerCursorName = db.query("playertable", namecolumn, "ID="
+ j, null, null, null, null);
namesToString = cursorToString(playerCursorName);
Resource.playerArray[j].setName(namesToString[j]);
}
for (int i = 0; i < 3; i++) {
int[] restToInt;
Cursor playerCursorInt = db.query("playertable", intcolumn, "ID="
+ i, null, null, null, null);
restToInt = cursorToInt(playerCursorInt, 4);
Resource.playerArray[i].setHp(restToInt[i]);
Resource.playerArray[i].setsatisfaction(restToInt[i]);
Resource.playerArray[i].setHygieneInt(restToInt[i]);
Resource.playerArray[i].setAliveInt(restToInt[i]);
}
}
Yeah, I know this looks pretty ugly but let me explain it:
Because there are 4 player objects I planned on iterating through the database entries by using the ID as identifier to get exactly one row at a time and writing the name and the other values of this object in the java class where I want to manage them within my project.
Note: same problem with autoincrement here than in the save method
In addition, I get a CursorIndexOutOfBoundsException when calling loadPlayer because
Index -1 is being requested - isn't that the result of an operation on the database resulting in an error?
Yeah that's pretty much it, I'll provide you with additional code if requested, hope someone can help me
You are using Cursors in a slightly odd way here.
The point of a Cursor is to ask SQLite to do the hard work of fetching data for you, and your job is simply to use the cursor to iterate through the returned values.
Firstly, I would change the query here to ask for all values in the table (and perhaps put some condition to constrain what you get back), to make sure your cursor then contains all your values.
Then, I would loop through the cursor's values by using a while loop, (with cursor.moveToPosition(-1) before the loop) moving along the cursor by using cursor.moveToNext().
See the API for more information:
http://developer.android.com/reference/android/database/Cursor.html
With regard to the autoincrement problem, as far as I can remember you can leave out the ID and use db.insert() without that field and the database will provide an ID for you.
You shouldn't have the same issue in your load method because it doesn't make sense to autoincrement when loading, you just get back what's in the database.