Latest Entries »

Thursday, January 12, 2012

Android service with dynamic schedule time

Introduction

In this article I will show you how to write example android service which will be restarted after change user preferences. After changes are applied service will show toast with last execution time.


XML Files

First we will write some piece of code that will display preferences and will show them to user. Let's start from define xml with preferences:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory android:title="Update frequency" >
        <ListPreference
            android:defaultValue="15 minut"
            android:entries="@array/listFrequency"
            android:entryValues="@array/listValues"
            android:key="Frequency"
            android:title="Change update frequency" />
    </PreferenceCategory>

</PreferenceScreen>

Here goes entries and entryValues from @array:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="listFrequency">
        <item>1 minuta</item>
        <item>2 minuty</item>
        <item>10 minut</item>
        <item>15 minut</item>
        <item>30 minut</item>
        <item>Wylaczone</item>
    </string-array>
    <string-array name="listValues">
        <item>60000</item>
        <item>120000</item>
        <item>600000</item>
        <item>900000</item>
        <item>1800000</item>
        <item>0000</item>
    </string-array>
</resources>

This xml will look like:

And don't forget to modify AndroidManifest.xml
<application>
     .....
        <service
            android:enabled="true"
            android:name=".service.BackgroundService" >
        </service>
    </application>
 <uses-permission android:name="android.permission.VIBRATE" />

Now let's code.

It's time to create Activity which will extend PreferenceActivity class. In this class we add OnSharedPreferenceChangeListener which will be called after change user preferences.
package com.stock_app.home;

import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.widget.Toast;

import com.stock_app.R;
import com.stock_app.service.BackgroundService;

public class PreferencesActivity extends PreferenceActivity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  addPreferencesFromResource(R.xml.preferences);
  SharedPreferences prefs = PreferenceManager
    .getDefaultSharedPreferences(this);
  prefs.registerOnSharedPreferenceChangeListener(prefchanged);
 }

 OnSharedPreferenceChangeListener prefchanged = new OnSharedPreferenceChangeListener() {

  @Override
  // Method for listening changes of SharedPreferences. 
  public void onSharedPreferenceChanged(
    SharedPreferences sharedPreferences, String key) {
   Intent serviceIntent = new Intent(getBaseContext(),
     BackgroundService.class);
   // Only if key was Frequency we will restart service. 
   if (key.equals("Frequency")) {
    String value = sharedPreferences.getString("Frequency", "0000");
    // If user turned of Service 
    if (value.equals("0000")) {
     stop(serviceIntent);
     String message = "Service is shut down.";
     Toast myToast = Toast.makeText(getApplicationContext(),
       message, Toast.LENGTH_SHORT);
     myToast.show();

    } else {
     // Oherwise restart
     stop(serviceIntent);
     start(serviceIntent);
    }

   }
  }
 };
 // Helper methods for start/stop service 
 private void start(Intent serviceIntent) {
  try {
   startService(serviceIntent);
  } catch (Exception e) {
   // If exception thrown means service is running 
   stopService(serviceIntent);
  }
 }

 private void stop(Intent serviceIntent) {
  try {
   stopService(serviceIntent);
  } catch (Exception e) {
   // If exception thrown means service not is running 
   startService(serviceIntent);
  }
 }
}

Now it's time for Service:

package com.stock_app.service;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.IBinder;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;

public class BackgroundService extends Service {

 private static final String TAG = BackgroundService.class.getSimpleName();
 private static int NOTIFICATION_ID = 1;
 private int icon = (Integer) 0x7f02000d;
 private Toast myToast;

 private Timer updatingTimer;
 public NotificationManager notificationmanager;
 public static boolean isGoing = false;
 SharedPreferences preferences = null;
 private TimerTask notify;

 @Override
 public void onCreate() {
  super.onCreate();

  if (!isGoing) {
   notify = new TimerTask() {
    @Override
    public void run() {
     checkValues();
    }
   };
   notificationmanager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
   updatingTimer = new Timer();
  }

 }

 @Override
 public IBinder onBind(Intent intent) {
  return null;
 }

 @Override
 public void onDestroy() {
  updatingTimer.cancel();
  notify.cancel();
  super.onDestroy();
  isGoing = false;
 }

 public void onStart(Intent intent, int startId) {
  super.onStart(intent, startId);
  String message = "";
  isGoing = true;
  preferences = PreferenceManager.getDefaultSharedPreferences(this);
  try {

   String str_frequency = preferences
     .getString("Frequency", "1800000");
   long frequency = Long.parseLong(str_frequency);

   if (str_frequency.equals("60000")) {
    message = "Changed to one minute";

   } else if (str_frequency.equals("120000")) {
    message = "Changed to 2 minutes";
   } else if (str_frequency.equals("600000")) {
    message = "Changed to 10 minutes";

   } else if (str_frequency.equals("900000")) {
    message = "Changed to 15 minutes";

   } else if (str_frequency.equals("1800000")) {
    message = "Changed to 30 minutes";
   }

   // If running show toast:
   if (message != "" && message != "0000") {
    myToast = Toast.makeText(getApplicationContext(), message,
      Toast.LENGTH_SHORT);
    myToast.show();
   }

   updatingTimer.scheduleAtFixedRate(notify, 1 * 1000, frequency);
  } catch (Exception ex) {
   Log.i(TAG, ex.toString());
  }
 }

 public void displayNotificationMessage(String message) {
  Notification notif = new Notification(icon, message,
    System.currentTimeMillis());

  // enabling vibrate
  boolean checkVibration = preferences
    .getBoolean("checkVibration", false);
  if (checkVibration)
   vibrtationEnabled(notif);

  // enabling sound
  boolean checkSound = preferences.getBoolean("checkSound", false);
  if (checkSound)
   soundEnabled(notif);

  PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
    new Intent(this, BackgroundServiceActivity.class), 0);

  notif.setLatestEventInfo(this, "Notification!", message, contentIntent);
  notif.defaults |= Notification.DEFAULT_LIGHTS;
  notificationmanager.notify(NOTIFICATION_ID, notif);
  NOTIFICATION_ID++;
 }

 public void vibrtationEnabled(Notification notification) {
  long[] vibrate = { 0, 100, 200, 300 };
  Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
  vibrator.vibrate(vibrate, -1);

 }

 public static void soundEnabled(Notification notification) {
  notification.sound = Uri
    .parse("android.resource://com.stock.app/raw/notifsound");
  notification.defaults |= Notification.DEFAULT_SOUND;

 }

 public void checkValues() {
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd kk:mm:ss");
  Calendar c = Calendar.getInstance();
  c.set(Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH,
    Calendar.HOUR, Calendar.MINUTE, Calendar.SECOND);
  Date time = c.getTime();
  displayNotificationMessage(sdf.format(time));
 }
}


Conclusion

This is a sample code that will make your life easier :) If you want full application source code @me.

3 comments:

Unknown said...

Hi maC !! this is a great example ;) Could you send me the source code? Thanx

Unknown said...

Nice example!! Could you share your source code with me?

Anonymous said...

Hi, Grate work , could you send me the source code
thank you

Post a Comment