Android - remove missed call notification - android

is there anyway to remove a missed call notification by code? And somehow remove the last missed call from call history?

yes, it is possible.Try this:
Uri UriCalls = Uri.parse("content://call_log/calls");
Cursor cursor = getApplicationContext().getContentResolver().query(UriCalls, null, null, null, null);
Reading call log entries...
if(cursor.getCount() > 0){
cursor.moveToFirst();
while(!cursor.isAfterLast()){
String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER)); // for number
String name = cursor.getString(cursor.getColumnIndex(CallLog.Calls.CACHED_NAME));// for name
String duration = cursor.getString(cursor.getColumnIndex(CallLog.Calls.DURATION));// for duration
int type = Integer.parseInt(cursor.getString(cursor.getColumnIndex(CallLog.Calls.TYPE)));// for call type, Incoming or out going
cursor.moveToNext();
}
}
Deleting entry in call log...
String queryString= "NUMBER='" + number + "'";
if (cursor.getCount() > 0){
getApplicationContext().getContentResolver().delete(UriCalls, queryString, null);
}
Permission:
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
Note: Please refer this doc over call log for more clearity.
Using the above code you can get the desired result.

Refer to this
You can clear your missed call by calling cancel(ID) or calcelAll() to clear your notifications bar.

For the part where you want to remove the last call from the log you need to move the method that is deleting the entry into a class which is a subclass of the Thread class. This allows you to then set it to sleep for a short period to allow Android to actually write to the call log BEFORE you you run the delete query. I had the same problem, but manage to resolve it with the code below:
public class DelayClearCallLog extends Thread {
public Context context;
public String phoneNumber;
public DelayClearCallLog(Context ctx, String pNumber){
context = ctx;
phoneNumber = pNumber;
}
public void run() {
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
clearCallLog(context, phoneNumber);
}
public void clearCallLog(Context context, String phoneNumber) {
// implement delete query here
}
}
Then call the the method as follows:
DelayClearCallLog DelayClear = new DelayClearCallLog(context, phoneNumber);
DelayClear.start();

Related

Detect Multiple SMS sent due to length of content

I have setup a background service to registerContentObserver to get notified whenever an SMS is sent. Upon receiving this event, I would increment a variable to know the count of messages sent. This is working as expected.
When someone sends SMS with more than 140 characters, the mobile carrier would treat this as multiple SMS, but it seems that I get only 1 callback for the sent message. This is causing my app to miss counting some messages.
Is there any proper way to know how many messages were actually sent?
When an app is responsible for writing its own messages to the Provider, it's most likely going to write the whole message in one go, regardless of whether the message must be sent as multipart. This would be why your Observer is often firing only once for each complete message, no matter how big.
Since KitKat, the system will automatically save the outgoing messages for any non-default apps, and for multipart messages, each part will be saved individually, firing your Observer each time. Of course, this doesn't help for anything prior to KitKat, or if a default app saves its own messages on later versions.
One possibility is to fetch the message body in your ContentObserver, and determine how many message parts it would've been split into. The SmsMessage.calculateLength() method can do this for us. It returns an int array, the first element of which will have the message count for the given text.
For example, using the old onChange(boolean) method, to support API < 16:
private class SmsObserver extends ContentObserver {
private static final Uri SMS_SENT_URI = Uri.parse("content://sms/sent");
private static final String COLUMN_ID = "_id";
private static final String COLUMN_BODY = "body";
private static final String[] PROJECTION = {COLUMN_ID, COLUMN_BODY};
// You might want to persist this value to storage, rather than
// keeping a field, in case the Observer is killed and recreated.
private int lastId;
public SmsObserver(Handler handler) {
super(handler);
}
#Override
public void onChange(boolean selfChange) {
Cursor c = null;
try {
// Get the most recent sent message.
c = getContentResolver().query(SMS_SENT_URI, PROJECTION, null,
null, "date DESC LIMIT 1");
if (c != null && c.moveToFirst()) {
// Check that we've not already counted this one.
final int id = c.getInt(c.getColumnIndex(COLUMN_ID));
if (id == lastId) {
return;
}
lastId = id;
// Get the message body, and have the SmsMessage
// class calculate how many parts it would need.
final String body = c.getString(c.getColumnIndex(COLUMN_BODY));
final int numParts = SmsMessage.calculateLength(body, false)[0];
// Add the number of parts to the count,
// however you might be doing that.
addToCount(numParts);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (c != null) {
c.close();
}
}
}
}
Should you be supporting API 16 and above, we can use the onChange(boolean, Uri) overload, and things get a little simpler, since we don't necessarily need to keep track of the last message ID.
#Override
public void onChange(boolean selfChange, Uri uri) {
Cursor c = null;
try {
// type=2 restricts the query to the sent box, so this just
// won't return any records if the Uri isn't for a sent message.
c = getContentResolver().query(uri, PROJECTION, "type=2", null, null);
if (c != null && c.moveToFirst()) {
final String body = c.getString(c.getColumnIndex(COLUMN_BODY));
final int numParts = SmsMessage.calculateLength(body, false)[0];
addToCount(numParts);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (c != null) {
c.close();
}
}
}

How to Delete Call Log

Can any one please tell me how to delete call log from android phone,
I am using following line of code
getActivity().getContentResolver().delete(CallLog.Calls.CONTENT_URI, null, null);
but, this is not working for me I want to delete whole call log history.
Following code work for me..
private void deleteNumber() {
try {
String strNumberOne[] = { "00577698160" };
Cursor cursor = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, CallLog.Calls.NUMBER + " = ? ", strNumberOne, "");
boolean bol = cursor.moveToFirst();
if (bol) {
do {
int idOfRowToDelete = cursor.getInt(cursor.getColumnIndex(CallLog.Calls._ID));
getContentResolver().delete(Uri.withAppendedPath(CallLog.Calls.CONTENT_URI, String.valueOf(idOfRowToDelete)), "", null);
} while (cursor.moveToNext());
}
} catch (Exception ex) {
System.out.print("Exception here ");
}
}
Edit:
following code is also work for me In API 23
make sure u have following permission in manifast.xml:
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
for Deleting Calllogs for particular number try this way:
public void DeleteCallLogByNumber(String number) {
String queryString="NUMBER="+number;
this.getContentResolver().delete(CallLog.Calls.CONTENT_URI,queryString,null);
}
}
Yeah this is working perfectly for me in android Lollipop :)
private void deleteCall(String number) {
Uri CALLLOG_URI = Uri.parse("content://call_log/calls");
getActivity().getContentResolver().delete(CALLLOG_URI, CallLog.Calls.NUMBER +"=?",new String[]{number});
Toast.makeText(getActivity(), "Call Log Deleted", Toast.LENGTH_SHORT).show();
}
This code is working for me.I am deleting call log by its log id please check below code for it.
private void deleteCall(String idd) {
context.getContentResolver().delete(CallLog.Calls.CONTENT_URI, CallLog.Calls._ID + " = ? ",new String[]{String.valueOf(idd)});
}

Intent.ACTION_CALL hide a number

I use this to call a number when button is pressed:
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:79950695"));
startActivity(callIntent);
Is there a way to hide the number ??
What I want to get is a pop with new call but showing only the name without the number ?
Would I need to create some custom Outgoing Call Broadcaster ?
It is not possible to handle In Call UI.
you can save that contact with some name once user clicks on call button and display the name, once done with call you might delete that contact.
You need to handle the settings to display only name but not number in call.
You can't hide. Instead delete the number.
Use this method
private void deleteNumber() {
try {
String strNumberOne[] = { "79950695" };
Cursor cursor = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, CallLog.Calls.NUMBER + " = ? ", strNumberOne, "");
boolean bol = cursor.moveToFirst();
if (bol) {
do {
int idOfRowToDelete = cursor.getInt(cursor.getColumnIndex(CallLog.Calls._ID));
getContentResolver().delete(Uri.withAppendedPath(CallLog.Calls.CONTENT_URI, String.valueOf(idOfRowToDelete)), "", null);
} while (cursor.moveToNext());
}
} catch (Exception ex) {
System.out.print("Exception ");
}
}

Check if the event exists before adding it to the Android calender

I have a list of events in my app. A button on the side lets the user add the event date and time to his/her calender. I use a calender intent to redirect the user to the android calender which the corresponding date and time. Now after the user adds the event to his calender, I would like to disable the 'add event' button which corresponds to the events he/she had already added(so the user avoid adding the same event again). How can I do this? I have gone through the new calender API for android 4.0 but I wasnt able to achieve what I wanted.
Basically what I want is to avoid repeated entries for the same event in the users calender.
Any help would be appreciated.
You should test, if an instance for this event exists. See the documentation of the Android's CalendarContract.Instances class.
Especially the second query method should be helpful in this case.
This examples is some code, I posted on my blog post about the CalendarContract provider - slightly altered for your needs:
long begin = // starting time in milliseconds
long end = // ending time in milliseconds
String[] proj =
new String[]{
Instances._ID,
Instances.BEGIN,
Instances.END,
Instances.EVENT_ID};
Cursor cursor =
Instances.query(getContentResolver(), proj, begin, end, "\"Your event title\"");
if (cursor.getCount() > 0) {
// deal with conflict
}
Be aware: The time is always in UTC millis since the epoch. So you might have to adjust given the user's timezone.
And the last parameter should contain the title of the event you have added to the calendar. Keep the quotes - otherwise Android looks for "your" or "event" or "title"!
And do not forget to include the necessary permissions.
Instances.query is not recommended to be run on the UI thread, but can be done efficiently by ensuring start and end time duration is minimized.
The search string will search all values, not just title, so adding a loop to check for that an exact field value is necessary.
public boolean eventExistsOnCalendar(String eventTitle, long startTimeMs, long endTimeMs) {
if (eventTitle == null || "".equals(eventTitle)) {
return false;
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
return false;
}
// If no end time, use start + 1 hour or = 1 day. Query is slow if searching a huge time range
if (endTimeMs <= 0) {
endTimeMs = startTimeMs + 1000 * 60 * 60; // + 1 hour
}
final ContentResolver resolver = mContext.getContentResolver();
final String[] duplicateProjection = {CalendarContract.Events.TITLE}; // Can change to whatever unique param you are searching for
Cursor cursor =
CalendarContract.Instances.query(
resolver,
duplicateProjection,
startTimeMs,
endTimeMs,
'"' + eventTitle + '"');
if (cursor == null) {
return false;
}
if (cursor.getCount() == 0) {
cursor.close();
return false;
}
while (cursor.moveToNext()) {
String title = cursor.getString(0);
if (eventTitle.equals(title)) {
cursor.close();
return true;
}
}
cursor.close();
return false;
}
I have used following way to check it ...what i am passing event_id to check whether is it in calendar or not....
public boolean isEventInCal(Context context, String cal_meeting_id) {
Cursor cursor = context.getContentResolver().query(
Uri.parse("content://com.android.calendar/events"),
new String[] { "_id" }, " _id = ? ",
new String[] { cal_meeting_id }, null);
if (cursor.moveToFirst()) {
//Yes Event Exist...
return true;
}
return false;
}
Please check this, this might help:
private static boolean isEventInCalendar(Context context, String titleText, long dtStart, long dtEnd) {
final String[] projection = new String[]{CalendarContract.Instances.BEGIN, CalendarContract.Instances.END, CalendarContract.Instances.TITLE};
Cursor cursor = CalendarContract.Instances.query(context.getContentResolver(), projection, dtStart, dtEnd);
return cursor != null && cursor.moveToFirst() && cursor.getString(cursor.getColumnIndex(CalendarContract.Instances.TITLE)).equalsIgnoreCase(titleText);
}

app not showing data when opend it for the second time

i am looking to make game of questions and answers.i had taken a textview and 4 radio group buttons.and i am fetching data from the external data file from the assets folder.when i installs the app into the emulater it works fine.when i reopens the app in the emulater it is just showing question not showing any text in the radio buttons.here is my code in the data base file
public String makeatext(String My_database_table,int i) {
SQLiteDatabase myDB = getDatabase();
String results = new String();
try {
String firstColumn = "questions";
// final String KEY_ROWID = "id";
// Cursor c = myDB.rawQuery("SELECT questions FROM " +
// My_database_table+ ";",null);
Cursor c = myDB.query(true, My_database_table,
new String[] { firstColumn },null, null, null, null, null,
null);
int iquestion = c.getColumnIndex(firstColumn);
if(c.moveToPosition(i)){
results = c.getString(iquestion)+"\n";
}
//while (c.moveToPosition(1)) {
//String firstName = c.getString(iquestion);
//results =(" "+ firstName + " ");
//}
return results;
} catch (Exception e) {
Log.e("ERROR","ERROR in Make test file :"+e.toString());
e.printStackTrace();
// TODO: handle exception
}
return results;
}
and in the Activity file i am just calling it as
String shoow = myDb.makeatext("question", Qno);
showQuestion.setText(shoow);
and on the top of the oncreate methode i initilized the data base asprivate final DataBaseHelper myDb = new DataBaseHelper(this);
can any one say me why this is happenig.do i need to write the for loop in the activity file also or shall i take a cursor in the activity class .
plz help me out
thanks in advance
for radio buttons the code in the database file is as follows as i have 4 buttons the code for 4 buttons will be as same as this
public String makeExtra1(String My_database_table ,int positions) {
String results = new String();
try {
String secondColumn = "Extra1";
Cursor c = myDataBase.query(true, My_database_table,
new String[] { secondColumn }, null, null, null, null, null,
null);
int iExtra1 = c.getColumnIndex(secondColumn);
if(c.moveToPosition(positions)){
results = results+c.getString(iExtra1)+"\n";
}
return results;
} catch (Exception e) {
Log.e("ERROR","ERROR in Make test file :"+e.toString());
e.printStackTrace();
// TODO: handle exception
}
return results;}
and in the Activity file
String showextra1 = myDb.makeExtra1("question", Qno);
r0.setText(showextra1);
i repeted this thing for 4 times as changing the makeExtra2,3,4 and in the assinged to r1,r2,r3 as above.
You should call Cursor.close() after reading data from it. Better to do it finally{} block.
If you want to raise only one answer per query - fill where param of myDataBase.query().
The unreachable code error is because you are writing finally{} block after return results;
Move this line after the finally{} block, eclipse will not give you any error.
Also do use myDB.close(); in this finally block.

Categories

Resources