I want to write a service in android which will keep track of outgoing calls and SMS in background. Whenever an outgoing call event or outgoing SMS event is received, I want to fetch the details like phone number, date, call duration (in case of outgoing call) and cost of call or SMS. I want to save these details in local database.
I tried using broadcast receiver along with services, but I am not able to calculate the actual call duration. And for SMS I found out that we need to check the SMS folder after some particular time period whether it is updated. Is there any event which will notify after the SMS is sent.
Following is the Code I have tried so far-
My MainActivity.java
public class MainActivity extends Activity {
TextView call = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
call = (TextView) findViewById(R.id.call);
Intent intent = new Intent(this, HelloService.class);
startService(intent);
}
}
My Service Class
public class HelloService extends Service {
CallDurationReceiver receiver = null;
#Override
public void onCreate() {
receiver = new CallDurationReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
filter.addAction(android.telephony.TelephonyManager.ACTION_PHONE_STATE_CHANGED);
registerReceiver(receiver, filter);
HandlerThread thread = new HandlerThread("ServiceStartArguments");
thread.start();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
// If we get killed, after returning from here, restart
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}
#Override
public void onDestroy() {
unregisterReceiver(receiver);
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
}
}
My Broadcast receiver -
public class CallDurationReceiver extends BroadcastReceiver {
// instance variables of sharedpreferences
SharedPreferences mSharedPrefernce;
Editor e;
// String variables for number,date,time,calltype
String number, date, time, calltype;
long startTime, endTime;
#Override
public void onReceive(final Context context, Intent intent) {
Log.v("info", "calls info....");
// initialising the sharedpreferences
mSharedPrefernce = context.getSharedPreferences("MyPref", 0);
e = mSharedPrefernce.edit();
Bundle bundle = intent.getExtras();
if (bundle == null)
return;
// initialising the variables
number = null;
startTime = 0;
endTime = 0;
// getting incoming call details
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
if ((state != null)
&& (state
.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))) {
Log.v("info", "Phone Ringing..");
number = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.v("info", "Incomng Number: " + number);
calltype = "Incoming";
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
date = today.monthDay + "-" + (today.month + 1) + "-" + today.year;
time = today.format("%k:%M:%S");
// putting the values into the SharedPreferences
e.putString("number", number);
e.putString("Type", calltype);
e.putString("date", date);
e.putString("time", time);
e.commit();
Toast.makeText(
context,
"Detect Calls sample application\nIncoming number: "
+ number, Toast.LENGTH_SHORT).show();
}
// getting outgoing call details
else if (state == null) {
number = bundle.getString(Intent.EXTRA_PHONE_NUMBER);
Log.v("info", "Outgoing Number: " + number);
calltype = "Outgoing";
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
date = today.monthDay + "-" + (today.month + 1) + "-" + today.year;
time = today.format("%k:%M:%S");
// putting the values into the SharedPreferences
e.putString("number", number);
e.putString("Type", calltype);
e.putString("date", date);
e.putString("time", time);
e.commit();
Toast.makeText(
context,
"Detect Calls sample application\nOutgoing number: "
+ number, Toast.LENGTH_SHORT).show();
}
// called when the call is answered
else if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
Log.v("info", "Call Ansered..");
startTime = System.currentTimeMillis();
e.putLong("start", startTime);
e.commit();
}
// called when the call is ended
else if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE)) {
Log.v("info", "Call Ended..");
String phonenumber=null, type=null, date1=null, time1=null, duration=null;
// getting the values from the SharedPreferences
phonenumber = mSharedPrefernce.getString("number", "");
type = mSharedPrefernce.getString("Type", "");
date1 = mSharedPrefernce.getString("date", "");
time1 = mSharedPrefernce.getString("time", "");
long start=0;
start = mSharedPrefernce.getLong("start", 0);
Log.v("info", "startTime=" + start);
// clearing the SharedPreferences
mSharedPrefernce.edit().clear();
endTime = System.currentTimeMillis();
Log.v("info", "endTime=" + endTime);
long totalTime =0;
totalTime = endTime - start;
DateFormat df = new SimpleDateFormat("HH':'mm':'ss");
df.setTimeZone(TimeZone.getTimeZone("GMT+0"));
duration = df.format(new Date(totalTime));
System.out.println("GOT SOMETHING - "+phonenumber + " " + date1 + " " + time1 + " " + duration + " " + type);
Toast.makeText(context, phonenumber + " " + date1 + " " + time1 + " " + duration + " " + type, Toast.LENGTH_LONG).show();
}
}
}
and the Manifest File -
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.sumasoft.mb.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.sumasoft.mb.HelloService" >
</service>
<receiver android:name=".CallDurationReceiver">
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
</application>
I even tried fetching the last outgoing call details from call log but I get the all calls, I just need the last outgoing call.
here is the code -
private String getCallDetails() {
StringBuffer sb = new StringBuffer();
Cursor managedCursor = MainActivity.managedCursor;
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);
sb.append( "Call Details :");
while ( managedCursor.moveToNext() ) {
String phNumber = managedCursor.getString( number );
String callType = managedCursor.getString( type );
String callDate = managedCursor.getString( date );
Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = managedCursor.getString( duration );
String dir = null;
int dircode = Integer.parseInt( callType );
switch( dircode ) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
sb.append( "\nPhone Number:--- "+phNumber +" \nCall Type:--- "+dir+" \nCall Date:--- "+callDayTime+" \nCall duration in sec :--- "+callDuration );
sb.append("\n----------------------------------");
}
managedCursor.close();
return sb.toString();
}
Thanks in advance.
Related
I have fetched all the call details through this code.
private void getCallDetails() {
StringBuffer sb = new StringBuffer();
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
return;
}
Cursor managedCursor = getActivity().getContentResolver().query(CallLog.Calls.CONTENT_URI,
null, null, null, CallLog.Calls.DATE + " DESC LIMIT 40");
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);
// sb.append("Call Details :");
String finalDate[];
while (managedCursor.moveToNext()) {
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
Date callDayTime = new Date(Long.valueOf(callDate));
String durationn=managedCursor.getString(duration);
System.out.println("Ph No....."+ phNumber);
System.out.println("Type....."+callType);
System.out.println("DAte....."+ callDate);
System.out.println("Duration....."+ callDayTime);
System.out.println("Call date time is "+callDayTime);
String calldatechange=callDayTime.toString();
String callDuration = managedCursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
phnoList.add(phNumber);
calldura.add(durationn);
System.out.println("call duration is"+calldura);
//calDatList.add(callDate);
calltimeList.add(calldatechange);
/* forcalLog.add("\nPhone Number:--- " + phNumber + " \nCall Type:--- "
+ dir + " \nCall Date:--- " + callDayTime
+ " \nCall duration in sec :--- " + callDuration);*/
sb.append(phNumber +","+ dir + ","+ callDayTime + ","+ callDuration);
// sb.append("\n---------------------------------------------");
}
System.out.println("Myphone is::"+ phnoList.size());
System.out.println("callDate is::"+ calDatList);
System.out.println("calltimeList is::"+ calltimeList);
managedCursor.close();
Also i have fetched the time at which the call is disconnected.I am able to show a popup at the time of call disconnect.Now i want to fetch all the details of the last call at the place where call disconnect intent is checked which has been done through broadcast receiver and append all the details in web service.How can i do that.
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
Toast.makeText(context,"the no. is"+savedNumber,Toast.LENGTH_LONG).show();
// onOutgoingCallStarted(context,"",callStartTime);
}
else
{
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Log.d("Testing", "Outgoing call has been disconnect");
intent = new Intent(context, MyCustomDialog.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
System.out.println("CAll has been disconnect...............");
// Toast.makeText(this, "CAll has been disconnect", Toast.LENGTH_LONG).show();
break;
}
}
Here i am fetching the call disconnect action.At the same time i want to send all the details through web service.
I have an application "x" that starts a service(in some other package) on button click. This service should now read call logs and send data to application "y" which should write the data in sd card. Presently, my service runs on button click but the application "y" doesn't as I have a toast in application "y" and it never comes up. The permissions are given in for reading logs and since am using custom action the same is included in intent filter of application "y". Can someone tell the reason for this problem.
service code
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TAG", "Service started.");
super.onStartCommand(intent, flags, startId);
StringBuffer sb = new StringBuffer();
String strOrder = android.provider.CallLog.Calls.DATE + " DESC";
/* Query the CallLog Content Provider */
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return 0;
}
Cursor managedCursor = getContentResolver().query(CallLog.Calls.CONTENT_URI, null,
null, null, strOrder);
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);
sb.append("Call Log :");
int h = 0;
while (managedCursor.moveToNext() && h != 20) {
String phNum = managedCursor.getString(number);
String callTypeCode = managedCursor.getString(type);
String strcallDate = managedCursor.getString(date);
Date callDate = new Date(Long.valueOf(strcallDate));
String callDuration = managedCursor.getString(duration);
String callType = null;
h++;
int callcode = Integer.parseInt(callTypeCode);
switch (callcode) {
case CallLog.Calls.OUTGOING_TYPE:
callType = "Outgoing";
break;
case CallLog.Calls.INCOMING_TYPE:
callType = "Incoming";
break;
case CallLog.Calls.MISSED_TYPE:
callType = "Missed";
break;
}
sb.append("\nPhone Number:--- " + phNum + " \nCall Type:--- "
+ callType + " \nCall Date:--- " + callDate
+ " \nCall duration in sec :--- " + callDuration);
sb.append("\n----------------------------------");
}
managedCursor.close();
managedCursor.close();
Intent sendIntent = new Intent();
String CUSTOM_ACTION = "com.example.sonali.callreadingservice.CALL_LOGS";
sendIntent.setAction(CUSTOM_ACTION);
sendIntent.putExtra(Intent.EXTRA_TEXT, (Serializable) sb);
sendIntent.setType("text/plain");
startActivity(sendIntent);
this.stopSelf();
return 0;
}
#Override
public void onDestroy() {
Log.d("slog", "onDestroy()");
super.onDestroy();
}
application "y" main activity
``public class MainActivity extends AppCompatActivity {
TextView textView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
textView = (TextView) findViewById(R.id.textview_call);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
handleSendText(intent);
}
void handleSendText(Intent intent) {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
try {
if (sharedText != null) {
textView.setText(sharedText);
File sdCard = Environment.getExternalStorageDirectory();
FileWriter writer = new FileWriter(sdCard);
// Writes the content to the file
writer.write(sharedText);
writer.flush();
writer.close();
}
} catch (Exception e) {
}
}
intent-filter of application "y"
`
`<intent-filter>
<action android:name="com.example.sonali.callreadingservice.CALL_LOGS" />
<category android:name="android.intent.category.LAUNCHER" />
<data android:mimeType="text/plain" />
</intent-filter>
You need to add your custom action in the Manifest to the Activity.
<activity
android:name="MainActivity">
<intent-filter>
<action android:name="com.example.sonali.callreadingservice.CALL_LOGS"/>
</intent-filter>
</activity>
i want to get correct duration for this code i get duration this code using but when i call action start example outgoing call when i call button click to start the time also when i call cut the process to get duration total duration but i want when call attend to start the time duration to stop call get correct duration how to get this my code
//public class CallDurationReceiver extends BroadcastReceiver {
DatabaseHandler db;
// instance variables of sharedpreferences
SharedPreferences mSharedPrefernce;
Editor e;
// String variables for number,date,time,calltype
String number = "";
String date = "";
String time = "";
String calltype = "";
String totime = "";
long startTime, endTime;
CounterClass timer = new CounterClass(180000,1000);
String hms;
#Override
public void onReceive(final Context context, Intent intent) {
db = new DatabaseHandler(context);
// Log.v("info", "calls info....");
// initialising the sharedpreferences
mSharedPrefernce = context.getSharedPreferences("MyPref", 0);
e = mSharedPrefernce.edit();
Bundle bundle = intent.getExtras();
if (bundle == null)
return;
// initialising the variables
number = null;
startTime = 0;
endTime = 0;
// getting incoming call details
String state = bundle.getString(TelephonyManager.EXTRA_STATE);
if ((state != null)
&& (state
.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING))) {
// Log.v("info", "Phone Ringing..");
number = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
// Log.v("info", "Incomng Number: " + number);
calltype = "Incoming";
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
date = today.monthDay + "-" + (today.month + 1) + "-" + today.year;
time = today.format("%k:%M:%S");
// putting the values into the SharedPreferences
e.putString("number", number);
e.putString("Type", calltype);
e.putString("date", date);
e.putString("time", time);
e.commit();
db.addContact(new PhoneNumberDetails(number,date,time,null,calltype));
Toast.makeText(context,"Detect Calls sample application\nIncoming number: "+ number, Toast.LENGTH_SHORT).show();
db.addContact(new PhoneNumberDetails(number, date, time, "duration", calltype));
}
// getting outgoing call details
else if (state == null) {
number = bundle.getString(Intent.EXTRA_PHONE_NUMBER);
// Log.v("info", "Outgoing Number: " + number);
calltype = "Outgoing";
Time today = new Time(Time.getCurrentTimezone());
today.setToNow();
date = today.monthDay + "-" + (today.month + 1) + "-" + today.year;
// Log.v("date Info","date:" + date);
time = today.format("%k:%M:%S");
Log.v("time Info","time:" + time);
// putting the values into the SharedPreferences
e.putString("number", number);
e.putString("Type", calltype);
e.putString("date", date);
e.putString("time", time);
e.commit();
Toast.makeText(context,"Detect Calls sample application\nOutgoing number: "+ number, Toast.LENGTH_SHORT).show();
//db.addContact(new PhoneNumberDetails(number, date, time, "totime",calltype));
}
// called when the call is answered
else if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
Log.v("info", "Call Ansered..");
timer.start();
startTime = System.currentTimeMillis();
e.putLong("start", startTime);
e.commit();
}
// called when the call is ended
else if (state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE)) {
Log.v("info", "Call Ended..");
timer.cancel();
Log.v("Time", ""+hms);
Toast.makeText(context, hms, Toast.LENGTH_LONG).show();
String phonenumber=null, type=null, date1=null, time1=null, duration=null;
// getting the values from the SharedPreferences
phonenumber = mSharedPrefernce.getString("number","");
type = mSharedPrefernce.getString("Type", "");
date1 = mSharedPrefernce.getString("date", "");
time1 = mSharedPrefernce.getString("time", "");
long start=0;
start = mSharedPrefernce.getLong("start", 0);
Log.v("info", "startTime=" + start);
// clearing the SharedPreferences
mSharedPrefernce.edit().clear();
endTime = System.currentTimeMillis();
Log.v("info", "endTime=" + endTime);
long totalTime =0;
totalTime = endTime - start;
String totime=Long.toString(0);
long result=Long.parseLong(totime);
DateFormat df = new SimpleDateFormat("HH':'mm':'ss");
df.setTimeZone(TimeZone.getTimeZone("GMT+0"));
duration = df.format(new Date(totalTime));
db.addContact(new PhoneNumberDetails(phonenumber, date1, time1, duration, type));
System.out.println("GOT SOMETHING - "+phonenumber + " " + date1 + " " + time1 + " " + duration + " " + type);
Log.d("testing","" +phonenumber);
Toast.makeText(context, phonenumber + " " + date1 + " " + time1 + " " + duration + " " + type, Toast.LENGTH_LONG).show();
}
}
public class CounterClass extends CountDownTimer {
public CounterClass(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
}
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#Override
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis),
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
System.out.println(hms);
Log.v("Timing", hms);
}
}
}
I want to get the dialled phonenumber
For getting the incomming call number I used this code, it worked fine
number = intent.getStringExtra("incoming_number");
I searched regarding how can I get the dialled number and I got a common code everywhere, and I used this in my program but its giving nullpointer exception, So can anyone tell what mistake I am making or how may I calculate dialled phone number
else if (callstate == TelephonyManager.CALL_STATE_OFFHOOK) {
Log.i("state", "offhook state");
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i("number", number);
}
In the manifest:
<receiver android:name="Incommingcall" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.CALL_PRIVILEGED" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
At the time of outgoing call, your intent action will be Intent.ACTION_NEW_OUTGOING_CALL in onReceive
So you can try this:
#Override
public void onReceive(final Context context, final Intent intent) {
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
dialled_num = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
}
}
Refer here for more info.
Hope it helps.
Try this to get all call types:
private void getCallDetails()
{
final StringBuffer sb = new StringBuffer();
Cursor managedCursor = managedQuery(CallLog.Calls.CONTENT_URI, null, null, null, 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);
sb.append("Call Details :");
while (managedCursor.moveToNext())
{
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
Date callDayTime = new Date(Long.valueOf(callDate));
String callDuration = managedCursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode)
{
case CallLog.Calls.OUTGOING_TYPE:
dir = "DIALED";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "RECEIVED";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
sb.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- " + dir + " \nCall Date:--- " + callDayTime + " \nCall duration in sec :--- " + callDuration);
sb.append("\n----------------------------------");
}
managedCursor.close();
call.setText(sb.toString());
}
}
I am exporting logs using csv file in android.I am getting only call logs but not getting sms logs.Here is the code
while (curLog.moveToNext()) {
String callName = curLog
.getString(curLog
.getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME));
if (callName == null)
callName="Unknown";
String callNumber = curLog.getString(curLog
.getColumnIndex(android.provider.CallLog.Calls.NUMBER));
String callDate = curLog.getString(curLog
.getColumnIndex(android.provider.CallLog.Calls.DATE));
String callType = curLog.getString(curLog
.getColumnIndex(android.provider.CallLog.Calls.TYPE));
String duration = curLog.getString(curLog
.getColumnIndex(android.provider.CallLog.Calls.DURATION));
data.add(new String[] {callName,callNumber,callDate,callType,duration});
}
Please suggest how to fix it.....
This is my way of getting the SMS. It can get body, content, date of the current message as well as check if it is incoming or outgoing. In addition, it can get the contact name that matches the phone number by another method.
First of all, add permission to AndroidManifest.xml file.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.app.myapp" >
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
...
</manifest>
Secondly, implement SMS Observer class to get the information you need
public class SMSObserver extends ContentObserver {
private Context context;
private static final String TAG = "SMSObserver";
private static final Uri SMS_URI = Telephony.Sms.CONTENT_URI; //get uri depending on different devices
public SMSObserver(Handler handler, Context context) {
super(handler);
this.context = context;
}
#Override
public boolean deliverSelfNotifications() {
return true;
}
//this onChange method will be fired up when you send or receive message
#Override
public void onChange(boolean selfChange) {
Cursor cursor = context.getContentResolver().query(SMS_URI, null, null, null, Telephony.Sms.DATE + " DESC");
String phNumber = null;
//make sure there is a message being operating
if (cursor != null && cursor.moveToFirst()) {
try {
//the meanings of those variables are quite straight forward
String type = cursor.getString(cursor.getColumnIndex(Telephony.Sms.TYPE));
String content = cursor.getString(cursor.getColumnIndex(Telephony.Sms.BODY));
String date = cursor.getString(cursor.getColumnIndex(Telephony.Sms.DATE));
Date SMSDate = new Date(Long.valueOf(date));
phNumber = cursor.getString(cursor.getColumnIndex(Telephony.Sms.ADDRESS)); //this is phone number rather than address
String contact = getContactDisplayNameByNumber(phNumber); //call the metod that convert phone number to contact name in your contacts
int typeCode = Integer.parseInt(type);
String direction = "";
//get the right direction
switch (typeCode) {
case Telephony.Sms.MESSAGE_TYPE_INBOX:
direction = "INCOMING";
break;
case Telephony.Sms.MESSAGE_TYPE_OUTBOX:
direction = "OUTGOING";
break;
case Telephony.Sms.MESSAGE_TYPE_SENT:
direction = "SENT";
break;
default:
direction = "UNKNOWN";
Log.e(TAG, typeCode + " is unknown");
break;
}
} catch (CursorIndexOutOfBoundsException e) {
Log.e(TAG, "SMSHelper: outgoingSMS", e);
} finally {
cursor.close();
}
}
Toast.makeText(context, "\nName: " + contact + "\nPhone Number:--- " + phNumber + " \nContent:--- "
+ content + " \nCall Date:--- " + SMSDate
+ " Direction: " + direction, Toast.LENGTH_LONG).show();
Log.i(TAG, "\nName: " + contact + "\nPhone Number:--- " + phNumber + " \nContent:--- "
+ content + " \nCall Date:--- " + SMSDate
+ " Direction: " + direction + "\n----------------------------------");
super.onChange(selfChange);
}
/**
* http://stackoverflow.com/questions/3712112/search-contact-by-phone-number
* Look up phone number
*
* #param number phone number
* #return the name matched with the phone number
*/
private String getContactDisplayNameByNumber(String number) {
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
String name = "<Not in contact list>";
ContentResolver contentResolver = context.getContentResolver();
Cursor contactLookup = contentResolver.query(uri, new String[]{BaseColumns._ID, ContactsContract.PhoneLookup.DISPLAY_NAME}, null, null, null);
try {
if (contactLookup != null && contactLookup.getCount() > 0) {
contactLookup.moveToFirst();
name = contactLookup.getString(contactLookup.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
//String contactId = contactLookup.getString(contactLookup.getColumnIndex(BaseColumns._ID));
Log.i(TAG, "Found number in contacts: " + number + " = " + name);
} else {
Log.e(TAG, "Cursor is null or empty " + number + " not found in contacts");
}
} finally {
if (contactLookup != null) {
contactLookup.close();
}
}
return name;
}
}
If the device is on running Android 6.0 (API level 23) and the
app's target SdkVersion is 23 or higher, the SMS permission will be
considered as dangerous permission. Therefore you must get the right
permission beforehand .
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED
&&ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) {
//grant permission
ActivityCompat.requestPermissions( this,
new String[]{Manifest.permission.READ_CONTACTS,Manifest.permission.READ_SMS},
10);
return;
}
Lastly, instantiate the SMSObserver class in the HomeActivity class or any
other Activity classes.
//sms log
smsObserver = new SMSObserver(new Handler(), getApplicationContext());
getContentResolver().registerContentObserver(Telephony.Sms.CONTENT_URI, true, smsObserver);