Advertisment

Android Programming Tutorial: Creating an Android Service to Copy Call Log to a Calendar

author-image
Rahul
New Update

This article is in continuation to the article "Transferring Call Logs to Calendars in Android" in May 2013 PCQuest: http://bit.ly/10R0f4r. If you want to copy the relevant entries from your call log to calendar on a periodic basis, you would need to fire your application on a periodic basis and click on the button to copy.

Advertisment

Or, you can use an Android service to fire in the background and do the work for you on a recurring basis. After all, that is what services are meant for. This article explains how you can use an Android service to periodically copy your call log to your calendar.

Copy the CallLog2Calendar Eclipse project folder we had created in the previous article into a new folder. Name the new folder as CallLog2Calendar2.                      

Open the new folder in Eclipse. We will create the new service class by deriving from the IntentService class. The IntentService is a wrapper class derived from the Service class that takes care of a lot of the infrastructure work you would otherwise do for a service, http://bit.ly/bjNnp4. Remember to select the option to include constructors from the superclass when you create the new Java class.

Add the following constructor.

public Copy2Calendar()

{

super("Copy2Calendar");

}

Move the following code from onCreate of the activity to the onHandleIntent stub of the service.

String strWhere = "(" + CallLog.Calls.CACHED_NAME + " = ‘Manisha Saldanha' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Tejeswar Das' OR " +

CallLog.Calls.CACHED_NAME + " = ‘K Murali Krishna' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Sabitri Sahu' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Shymala B' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Deepa Agrawal' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Swati Ranade' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Kiran Shah' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Kashappa Mashal' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Virendra Dharwadker'

OR " +

CallLog.Calls.CACHED_NAME + " = ‘Vinod Joshi' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Ravi Kumar' OR " +

CallLog.Calls.CACHED_NAME + " = ‘Saroj Mallick') AND " +

CallLog.Calls.TYPE + " < > " + CallLog.Calls.MISSED_TYPE + "

AND " +

CallLog.Calls.DURATION + " > 0";

final Cursor curCallLog = getContentResolver().query(CallLog.Calls.CONTENT_URI, null, strWhere,

null, null);

Also move the following utility functions from the activity to the service class.

public void newCalendarEvent(String strTitle, long lngStart, long lngEnd) {

ContentValues values = new ContentValues();

values.put(Events.DTSTART, lngStart);

values.put(Events.DTEND, lngEnd);

values.put(Events.TITLE, strTitle);

values.put(Events.CALENDAR_ID, MY_CALENDAR_ID);

values.put(Events.EVENT_TIMEZONE, "Asia/Kolkata");

getContentResolver().insert(Events.CONTENT_URI, values);

}

public boolean DoesNotExist(long lngStart, String strTitle) {

String strWhere = Events.DTSTART + " = " + lngStart + " AND " + Events.TITLE + " = ‘" + strTitle + "'";

final Cursor curCalendar = getContentResolver().query(Events.CONTENT_URI, null, strWhere, null, null);

if (curCalendar.getCount() == 0) return true;

else return false;

}

Also move the calendar ID constant from the activity to the service.

public int MY_CALENDAR_ID = 8;

Take the code from the button click event of the browser and add to the onHandleIntent function in the service.

int intIndex;

String strTitle;

long lngStart;

long lngEnd;

curCallLog.moveToFirst();

while (!curCallLog.isAfterLast()) {

intIndex = curCallLog.getColumnIndex(CallLog.Calls.CACHED_NAME);

strTitle = "CallLog: " + curCallLog.getString(intIndex);

intIndex = curCallLog.getColumnIndex(CallLog.Calls.DATE);

lngStart = curCallLog.getLong(intIndex);

intIndex = curCallLog.getColumnIndex(CallLog.Calls.DURATION);

lngEnd = lngStart + 1000 * curCallLog.getLong(intIndex);

if (DoesNotExist(lngStart, strTitle)) newCalendarEvent

(strTitle, lngStart, lngEnd);

curCallLog.moveToNext();

}

Delete the remaining code in onCreate() of the activity and call finish(). The following is how the new onCreate() should look like.

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

finish();

}

Now that you will use the service to start the class, you do not need to click the button to copy the call log. The activity can finish as soon as it starts.

Add the service to the manifest.

Advertisment

Advertisment

We will now use an alarm to start the service at regular intervals. Let us create a receiver that will receive the alarm notification and start the service.



In the onReceive handler, create the intent to start the service. And then start the service.

@Override

public void onReceive(Context arg0, Intent arg1) {

// TODO Auto-generated method stub

Intent itnStart = new Intent(arg0, Copy2Calendar.class);

arg0.startService(itnStart);

}

Create a class level variable that identifies the alarm that we are creating.

public static final String RESTART_COPY2CALENDAR2_SERVICE = "com.amaresh.calllog2calendar.RESTART_COPY2CALENDAR2_SERVICE";

Add the receiver to the manifest.

Advertisment

< receiver android:name="AlarmReceiver">

< intent-filter>

< action android:name= "com.amaresh.calllog2calendar.RESTART_COPY2CALENDAR2_SERVICE"/>

< /intent-filter>

< /receiver>

Within the Copy2Calendar service, create class level variables to hold the alarm manager and a pending intent that will be fired when the alarm is triggered.

private AlarmManager almCopy2Calendar2;

private PendingIntent pinAlarm;

Override the onCreate handler of the service to set

the alarm.

@Override

public void onCreate() {

final long lngDayInMilliSeconds = 24 * 60 * 60 * 1000;

super.onCreate();

almCopy2Calendar2 = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

String RESTART_COPY2CALENDAR2_SERVICE = AlarmReceiver.RESTART_COPY2CALENDAR2_SERVICE;

Intent itnService = new Intent(RESTART_COPY2CALENDAR2_SERVICE);

pinAlarm = PendingIntent.getBroadcast(this, 0, itnService, 0);

long lngTomorrowMidNight = ((System.currentTimeMillis() / lngDayInMilliSeconds) + 1) * lngDayInMilliSeconds;

almCopy2Calendar2.setInexactRepeating(AlarmManager.RTC, lngTomorrowMidNight, AlarmManager.INTERVAL_DAY, pinAlarm);

}

The code above finds the present system date and time in milliseconds. By doing an integer division with the number of milliseconds in a day, it isolates the date part and excludes the time part. Then by adding one full day to it, you get the forthcoming midnight when the alarm will fire the first time. Subsequently, it will fire periodically once per day, at midnight. I have chosen midnight as I expect my regular activity at a minimum then, you can chose any other timing of your convenience.

The code to set the alarm is in the onCreate() of the service, which means the alarm is set when the service is created. How will the service start then? This is a chicken and egg situation, as the alarm is set when the service starts and the service starts when the alarm fires. We can use the activity to start the service, but we need to make sure the alarm persists between restarts of the device. It is a good idea to start the service with every reboot of the device, and then the service will set the alarm. The alarm will start the service when the alarm fires at midnight every day. The service copies the call log of the day to the calendar, and then stops.

We need a receiver to receive the notification that the device has rebooted.

Advertisment

Add the following two lines to the onReceive method.

Intent itnStart = new Intent(context, Copy2Calendar.class);

context.startService(itnStart);

This receiver, like the alarm receiver, also needs to be registered in the manifest. We also need to mention in the manifest that this receiver will receive the device reboot notifications.

< receiver android:name="BootReceiver">

< intent-filter>

< action android:name = "android.intent.action.BOOT_COMPLETED"/>

< action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>

< /intent-filter>

< /receiver>

We next give the application manifest permission to receive the device reboot notifications.

Delete the file representing the adapter class from the package explorer of Eclipse, as we are no longer displaying the filtered call log in the activity. The application is now ready to deploy and use.

Advertisment