I have an Intent service running that performs a do while loop.
The service is started from an activity when a button is pressed.
Problem is when I press the button again a new service is started along side the previous service from the first press.
I want the previous service to be stopped and the new service to replace it.
Essentially i want to know how to either kill services or pass data to the running thread in order to change the do while conditions. Im not sure how to handle this.
Thanks for your help.
startAlarm.setOnClickListener(new View.OnClickListener() {
int x=0;
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
getActivity().startService(alarmService);
System.out.println("Service has started.");
}
});
public class AlarmService extends IntentService{
public AlarmService() {
super("Alarm run service");
// TODO Auto-generated constructor stu
}
#Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
int hour = intent.getExtras().getInt("hourval");
int minute = intent.getExtras().getInt("minval");
System.out.println("Hour is : " + hour + " minute is : " + minute);
int currentHour;
int currentMinute;
do{
System.out.println("in the loop");
Calendar cal = Calendar.getInstance();
currentHour = cal.get(Calendar.HOUR_OF_DAY);
currentMinute = cal.get(Calendar.MINUTE);
System.out.println(currentHour + ":" + currentMinute + "and " + hour +":" +minute);
}while(currentHour != hour || currentMinute != minute);
System.out.println("Left loop");
Intent alarmRingStart = new Intent(getApplicationContext(),AlarmRing.class);
alarmRingStart.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(alarmRingStart);
System.out.println("Alarm has gone off");
}
#Override
public void onDestroy(){
super.onDestroy();
}
}
you can first stopService, and in service.onDestroy set a flag indicating the while loop should exit. you should always check the value of that flag.
Related
I'd like to know if there's some way to set a timeout for an Intent started via startActivityForResult, so when the time is passed some actions can be performed with the activity of the mentioned intent (in my case finishing it).
There doesn't seem to be any direct way to set a timeout directly to the Intent, but this doesn't look too much to worry about, as I guess I could create a CountDownTimer that in onFinish() would call the code to finish the intent.
Problem is I don't see a way to finish that ActivityForResult.
Is there any way to do this?
Well, I finally got to solve the problem, indeed it wasn't very difficult.
For my particular case of INTENT_PICK the following code is valid to stop the activity after 2 minutes:
final int RQS_PICKCONTACT = 1;
[...]
Intent intentPickContact = new Intent(Intent.ACTION_PICK, uriContact);
startActivityForResult(intentPickContact, RQS_PICKCONTACT);
mcd = new CountDownTimer(120000, 10000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
try
{
finishActivity(RQS_PICKCONTACT);
}
catch (Exception ex)
{
}
}
}.start();
In my case I wanted to limit the time a user was doing a task so I created my own timer class.
public class Timer {
private static final String TAG = "Timer" ;
int timeout;
Context mContext;
boolean compleatedTask;
String timeoutKey;
CountDownTimer countDown;
public Timer(Context mContext, int timeout, String timeoutKey){
this.timeout = timeout;
this.mContext = mContext;
this.timeoutKey = timeoutKey;
}
public void startTimer() {
this.countDown = new CountDownTimer(this.timeout, 1000) {
public void onTick(long millisUntilFinished) {
Log.i(TAG, "OnTick, context: " + mContext + ", milisUntilFinished: " + millisUntilFinished + ", compleatedTask: " + compleatedTask);
if(compleatedTask)
cancel();
}
public void onFinish() {
Log.i(TAG, "OnFinish, context: " + mContext + ", compleatedTask: " + compleatedTask);
try
{
if(!compleatedTask){
Intent intent = new Intent(mContext, UnsuccessfullPosTaskActivity.class);
intent.putExtra("error", StateMachine.databaseAccess.getDictionaryTranslation(timeoutKey, StateMachine.language));
mContext.startActivity(intent);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
};
countDown.start();
}
public void setCompleatedTask(boolean compleatedTask){
this.compleatedTask = compleatedTask;
if(compleatedTask)
countDown.onFinish();
}
}
Then in your activity
int timeout = 1000;
Timer timer = new Timer(Activity.this, timeout);
timer.startTimer();
//do stuff
if(conditionToStop)
timer.setCompleatedTask(true);
And if you are using recycle views and you want to stop the counter when they click an option just send the timer object to your custom recycle view adapter.
I know there are many threads on Stackoverflow on this topic, and I have read each and every single one, but I am still very confused and am very sorry but I feel like I should post this.
When the application is run nothing really happens with the receivers, as if they are not receiving anything
My service:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int timerValue = pv.getTimerValues();
aCounter = new CountDownTimer((timerValue), 1000) { // set to
// timerValue
// later
public void onTick(long millisUntilFinished) {
int minutes, seconds;
String sSeconds, sMinutes, toSend;
seconds = (int) (millisUntilFinished / 1000) % 60;
minutes = (int) ((millisUntilFinished / (1000 * 60)) % 60);
sSeconds = Integer.toString(seconds);
sMinutes = Integer.toString(minutes);
toSend = (sMinutes + ":" + sSeconds);
sendMessage(toSend);
countDownCheck();
}
public void onFinish() {
MediaPlayer dingeffect = MediaPlayer.create(
getApplicationContext(), R.raw.timerfinished);
// mPlayer0.stop();
try {
dingeffect.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dingeffect.start();
// Intent intent2 = new Intent(ServiceTest.this, Meditate.class);
//startActivity(intent2);
sendMessage("finished");
}
};
aCounter.start();
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
private void sendMessage(String send) {
Intent intent1 = new Intent("countdowntimer");
// You can also include some extra data.
intent1.putExtra("message1", send);
sendBroadcast(intent1);
}
My receiving activity:
Inside the onCreate:
registerReceiver(mMessageReceiver1, new IntentFilter("countdowntimer"));
final Intent countDownService = new Intent(Meditate2.this,
ServiceTest.class);
startService(countDownService);
and my broadcastreceiver inside the same activity
private BroadcastReceiver mMessageReceiver1 = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message1");
setTimer(message);
}
};
In the manifest I have declared the service as such:
<service android:name=".ServiceTest"></service>
The weird thing is, it was working then after I fixed some other stuff this stopped working, so I really have no clue why it is not. Help please!
I will tell you what is different between your code and my (working) code.
In the activity onCreate:
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver1, new IntentFilter("countdowntimer"));
In the activity onDestroy:
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver1);
In sendMessage:
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
I don't know if this makes a lot of difference, but I used LocalBroadcastManager.getInstance.
Your broadcast receiver should know what intents to listen to.
Register your receiver with an intentFilter that listens to your countdowntimer intent like this:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("countdowntimer");
activity.registerReceiver(this, intentFilter);
Below given code is written to track battery level of device and store it in db. In order to get battery level, function "batterylevel" is called every 3 minutes, and battery level is inserted to db table. And also code saves the time, when device gets full charged, in another db table. Everything works fine for some time. But problem occurs after about 30 minutes, the running service automatically enters to its oncreate method, after that service won't show any logs, eventually service stops causing force close while trying to stop the service manually.
public class BatteryLevelService extends Service {
BroadcastReceiver batteryLevelReceiver;
Timer t ;
Calendar cal;
Date lastBatteryFullTime;
Context context;
int sec;
int lastFullChargeYear,lastFullChargeMonth,lastFullChargeDay;
int lastFullChargeHour,lastFullChargeMinute,lastFullChargeSecond;
private File dir;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate(){
Log.d("Service", "oncreate Service Started");
}
private void batteryLevel() {
cal=Calendar.getInstance();
long currentHour=cal.get(Calendar.HOUR_OF_DAY);
long currentMinute=cal.get(Calendar.MINUTE);
long currentSecond=cal.get(Calendar.SECOND);
final String currentTime=currentHour+" : "+currentMinute+" : "+currentSecond;
Intent batteryIntent = registerReceiver(null,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int rawlevel = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int level = -1;
if (rawlevel >= 0 && scale > 0) {
level = (rawlevel * 100) / scale;
}
MainActivity.sqladp.insertBatteryLevel(level, currentTime);
if(level==100){
cal=cal.getInstance();
lastFullChargeYear=cal.get(Calendar.YEAR);
lastFullChargeMonth=cal.get(Calendar.MONTH);
lastFullChargeDay=cal.get(Calendar.DAY_OF_MONTH);
lastFullChargeHour=cal.get(Calendar.HOUR_OF_DAY);
lastFullChargeMinute=cal.get(Calendar.MINUTE);
lastFullChargeSecond=cal.get(Calendar.SECOND);
lastBatteryFullTime=new Date(lastFullChargeYear, lastFullChargeMonth, lastFullChargeDay, lastFullChargeHour, lastFullChargeMinute);
String[] lastFullChargeTime=lastBatteryFullTime.toString().split("GMT");
MainActivity.sqladp.deleteLastFullBattery();
MainActivity.sqladp.insertLastUsage("Battery", "", lastFullChargeTime[0], "");
}
Log.d("Battery level", ""+level + "%");
}
#Override
public void onStart(Intent intent, int startId) {
Log.d("Service", "Service Started");
t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Called each time when 1000 milliseconds (1 second) (the period parameter)
batteryLevel();
Log.d("", "batlevel ");
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
3*60*1000);
}
#Override
public void onDestroy() {
Log.d("service", "onDestroy");
t.cancel();
}
The method onStart() is only used for old Android versions (<2.0). For later versions you should use onStartCommand() as bellow:
#Override
public int onStartCommand(Intent intent, int flags, int startId)
this will solve your problem
I am trying to create a service with background task. 24 hrs once the thread would start and do the process.
I have tried like this. but its not worked.
public class MyService extends Service {
int counter = 0;
static final int UPDATE_INTERVAL = 10 * 1000; // / 1000 = 1 second
private Timer timer = new Timer();
Home home;
private boolean isRunning = true;
#Override
public IBinder onBind(Intent intent) {
// Not implemented...this sample is only for starting and stopping
// services.
// Service binding will be covered in another tutorial
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
// Announcement about starting
Toast.makeText(this, "Starting the Demo Service", Toast.LENGTH_SHORT)
.show();
// Start a Background thread
isRunning = true;
// Thread backgroundThread = new Thread(new BackgroundThread());
BackgroundThread();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// Stop the Background thread
isRunning = false;
// Announcement about stopping
Toast.makeText(this, "Stopping the Demo Service", Toast.LENGTH_SHORT)
.show();
}
private void BackgroundThread() {
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// TODO Auto-generated method stub
Calendar c = Calendar.getInstance();
String month = String.valueOf(c.get(Calendar.MONTH) + 1);
String year = String.valueOf(c.get(Calendar.YEAR));
String day = String.valueOf(c.get(Calendar.DAY_OF_MONTH));
String months = null;
if (month.startsWith("0") || month.startsWith("1")) {
months = year + "-" + month + "-" + day;
home.loadCalender(months);
} else {
months = year + "-" + "0" + month + "-" + day;
home.loadCalender(months);
}
}
}, 0, UPDATE_INTERVAL);
/*
* counter = 0; while(isRunning) { System.out.println(""+counter++);
* //Thread.currentThread().sleep(5000);
*
* }
*/
System.out.println("Background Thread is finished.........");
}
}
In my main activity, i have started the Service...
plz help me to do this task.
Use AlarmManager to schedule your alarm to occur once per day, using setRepeating() (or perhaps setInexactRepeating(). Please do not waste the user's RAM trying to have a service running all of the time watching the clock tick.
I write an app that schedule to start accelerometer every 15 seconds and run it 10 seconds to retrieve sensor data. I start accelerometer using alarmManager and keep it running with wakelock when screen go off. But I found sometimes:
The accelerometer can't retrieve data after some periods. I mean it have been started according to logcat,but there is not any sensor data,then it is closed and it starts again without data.
I don't know why the accelerometer didn't start any more after some periods and it is fine before. I found logcat says "listener with binder android.os.BinderProxy doesn't exist accelerometer". I don't know why.
following is kernel code:
Activity.java
Intent intent = new Intent(getApplicationContext(),SensorService.class);
PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
long curTime = Calendar.getInstance().getTimeInMillis();
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, curTime, _intervalTime, pendingIntent);
SensorService.java
public void onStart(Intent intent, int startId) {
new Thread(new Runnable(){
public void run() {
// TODO Auto-generated method stub
wl.acquire();
Log.d(TAG,"I'm bright!");
try {
Thread.sleep(_delayClose);// kill self after _delayClose ms
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stopSelf();// SensorService.this.stopSelf()
}
}).start();
this.mSensorManager.registerListener( _sensorHandle,
accSensor,
sensorDelay)
}
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
this.mSensorManager.unregisterListener(_sensorHandle);
Log.d(TAG,"TIEM UP");
if(wl.isHeld())
{
wl.release();
}
}
I'm guessing that there must be some considerable overhead in registering and unregistering sensor listener that often, plus the alarmManager overhead.
Given that you want sensor data that often, how about just keep your listener registered and have it internally manage when it should and shouldnt do something useful with the samples it's receiving?
public class SensorSamplrActivity extends Activity {
private final static String TAG = "samplr";
private final static int SAMPLE_INTERVAL_SECS = 15;
private final static int SAMPLE_DURATION_SECS = 10;
private SensorManager mSensorManager;
private long whenToStartSample = System.currentTimeMillis();
private long whenToEndSample = System.currentTimeMillis() + SAMPLE_DURATION_SECS;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_GAME);
}
private SensorEventListener mSensorListener = new SensorEventListener() {
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
long now = System.currentTimeMillis();
if (now < whenToStartSample){
// ignore the event & wait for next time to sample
Log.d(TAG,"ignoring events for " + (whenToStartSample - now) + "ms");
return;
}
if (whenToStartSample <= now && whenToEndSample > now){
Log.d(TAG,"Do something with this event # " + now);
}
else {
// we've gone past whenToEndSample so reset timers
whenToStartSample = now + (SAMPLE_INTERVAL_SECS * 1000);
whenToEndSample = whenToStartSample + (SAMPLE_DURATION_SECS * 1000) ;
}
}
};
#Override
public void onDestroy(){
super.onDestroy();
mSensorManager.unregisterListener(mSensorListener);
}
}