Reputation: 4178
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
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
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