d4rty
d4rty

Reputation: 4178

Android: Start a thread in a service

i want to start a new thread in my own service which is started from an activity. In this thread I want to update data in a database after every 3 seconds. I created the databse and initializes it in my onStartCommand() method. Where should I implement my Thread and how?

I tried this but it didn't work, the app will be unfortunately closed. Without the call of this method everything works fin.

I create this method, which i called in my onStartCommand

private void startThreadUpdatingDatabase(){
    Log.d("Database", "startThreadUpdatingDatabase(was called)");
    new Thread(new Runnable() { 
        public void run(){
            //do stuff
        }
    }).start();
}

Upvotes: 1

Views: 1572

Answers (2)

Toguard
Toguard

Reputation: 447

If you want to start a recurring task you can try different approaches:

1) Alarm
2) Handler
3) TimerTask (My least favorite)

Alarm:

private AlarmManager mAlarmManager;
private static final long ALARM_INTERVAL = 3 * 60 * 1000;

private void issueAlarm() {
    if(mAlarmManager == null)
        mAlarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    Calendar calendar = Calendar.getInstance(Locale.US);
    calendar.add(Calendar.MILLISECOND, (int) ALARM_INTERVAL);
    Intent intent = new Intent(this, AlarmBroadcastReceiver.class);
    alarmIntent = PendingIntent.getBroadcast(this, ALARM_REQUEST_CODE, intent, 0);
    mAlarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), ALARM_INTERVAL, alarmIntent);
}

Create your AlarmReceiver:

public class AlarmBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //Do DB Stuff here
    }

}

And do not forget to register it in the manifest:

<receiver
    android:name=".AlarmBroadcastReceiver"
    android:exported="false" />

Handler:

@Override
public void onCreate() {
    // Start up the thread running the service.  Note that we create a
    // separate thread because the service normally runs in the process's
    // main thread, which we don't want to block.  We also make it
    // background priority so CPU-intensive work will not disrupt our UI.
    HandlerThread thread = new HandlerThread("ServiceStartArguments",
        Process.THREAD_PRIORITY_BACKGROUND);
    thread.start();

    // Get the HandlerThread's Looper and use it for our Handler
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

And queue up your postedTask

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //As danny117 pointed out, multiple clients starting the service
    //Can trigger this.
    mServiceHandler.removeCallbacks(yourRunnable);
    mServiceHandler.post(yourRunnable);
    return super.onStartCommand(intent, flags, startId);
}

Runnable should look like:

private Runnable yourRunnable = new Runnable() {
        @Override
        public void run(){
        //DB work here
        if(mServiceHandler != null)
            mServiceHandler.postDelayed(this, ALARM_INTERVAL);
        }
}

Also clean up after service stops:

@Override
public void onDestroy() {
    super.onDestroy();
    mServiceHandler.removeCallbacks(yourRunnable);
    mServiceLooper.quit();
}

Timer:

Create your Timer:

private Timer myTimer = new Timer();

Create the recurring Timer Task:

private void scheduleTask() {
    myTimer.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            //Do DB stuff here
        }
    }, 0, ALARM_INTERVAL);
}

References:
Scheduling Repeating Alarms
Creating a Service

Upvotes: 2

danny117
danny117

Reputation: 5651

To repeat with a delay you make a runnable that calls postDelayed of a handler to restart it after a set time period.

//change the notificationSmallIcon (titlebar) so it flashes every few seconds
private static Runnable iconWarnRunnable = new Runnable() {
    @Override
    public void run() {
        if (isWarningRunning) {
            long dely;
            if (notificationSmallIcon == R.drawable.ic_launcher2) {
                notificationSmallIcon = R.drawable.ic_launcher2x;
                dely = iconWarnDelay1;
            } else {
                notificationSmallIcon = R.drawable.ic_launcher2;
                dely = iconWarnDelay2;
            }
            notifyHandler.postDelayed(this, dely);
            myShowNotification();
        } else {
            //just in nick of time
            notificationSmallIcon = R.drawable.ic_launcher2;
        }
    }
};

final HandlerThread myThread = new HandlerThread("myHandlerThread");
private static long iconWarnDelay1;
private static long iconWarnDelay2;


@Override
public void onCreate() {
    iconWarnDelay1 = 2500;
    iconWarnDelay2 = 500;
    myThread.start();
    myThread.setPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
    notifyHandler = new Handler(myThread.getLooper());

... somewhere you start the runnable it's really important that when you start you remove first so you always have just one running.

isWarningRunning = true;
notifyHandler.removeCallbacks(iconWarnRunnable);
notifyHandler.postDelayed(iconWarnRunnable, iconWarnDelay1);

... somewhere stop the runnable

isWarningRunning = false;
notifyHandler.removeCallbacks(iconWarnRunnable);

Upvotes: 0

Related Questions