I'm making a simple alarm clock app and now I'm having problem with the service which checks if the current time matches the set time and starts another activity. Here's the code:
#Override
public int onStartCommand(Intent intent, int flags, int startID){
hourSet = intent.getIntExtra("hourSet", 0);
minuteSet = intent.getIntExtra("minuteSet", 0);
checkTime();
return START_STICKY;
}
private void checkTime(){
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
time.setToNow();
currentHour = time.hour;
currentMinute = time.minute;
if(currentHour == hourSet && currentMinute == minuteSet){
Intent i = new Intent(AlarmService.this, AlarmTime.class);
startActivity(i);
cancel();
}
}
}, 0, UPDATE_INTERVAL );
}
I have debugged the service, everything is fine until the if statement. When the current time matches the set time, the app crashes.
So how to fix this ?
Why people dont include catLog?
Problem is you are trying to start activity on service task, which is not possible, but if you add magic code like
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
before startActivity call, it starts on the new task and everything should work just fine :)
Related
I have a background service to be called everyday at 1pm. At 1 pm, 3 values in my Firebase database should be set to 0. When the user launches a certain activity the background service is triggered. The values reset to 0 at 1pm like i want but, every time after 1pm when the activity is launched by the user the service runs resetting my values. How can I get the values reset to 0 at 1pm and not again until 1pm the next day?
Below is my code within the Service class
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 13);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
timer = new Timer();
timer.schedule(new TimerTask()
{
#Override
public void run()
{
String id = FirebaseAuth.getInstance().getCurrentUser().getUid();
FirebaseDatabase.getInstance().getReference().child("Users").child(id).child("steps").setValue(0);
FirebaseDatabase.getInstance().getReference().child("Users").child(id).child("bonusScore").setValue(0);
FirebaseDatabase.getInstance().getReference().child("Users").child(id).child("stepsScore").setValue(0);
}
}, calendar.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS));
return START_STICKY;
}
#Override
public void onDestroy()
{
super.onDestroy();
}
This is the Code starting the service. This method is called in the oncreate method of this activity.
private void startBackgroundService()
{
startService(new Intent(this, BackgroundService.class));
}
you can use work manager to schedule a task.here you can find getting started guide......
I am building an app to test all the hardware buttons on device. For Home button, I am starting a service and relaunching the same activity from that service(updating the UI that home button test is performed). The problem is, all the previous progress of tests is erased and this activity starts from scratch when it is relaunched. For ex: I performed back key, menu, volume up key and home in the given order. When activity is relaunched after home test, it considers the back key, menu, and volume up key as not performed.
When I launch this as an independent application, it works fine(app relaunches with previous progress intact) but when I launch it from a deep link URL then this issue arises.
Below is my code of my Service class:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
timer=new Timer();
TimerTask timerTask=new TimerTask() {
#Override
public void run() {
if(getRecentApp().equals(getLauncherPackage())){
if(VolumeKeyTest.isHomeKeyPressed) {
if(!isAppRelaunched) {
bringApplicationToFront();
}
//VolumeKeyTest.isHomeKeyPressed=false;
if(timer != null) {
timer.cancel();
timer.purge();
timer = null;
}
}
}
}
};
timer.schedule(timerTask,0,500);
//return START_STICKY_COMPATIBILITY;
return super.onStartCommand(intent, flags, startId);
}
private void bringApplicationToFront() {
Intent notificationIntent = new Intent(getApplicationContext(),VolumeKeyTest.mClass);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
timer = new Timer();
try{
pendingIntent.send();
isAppRelaunched = true;
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
add this line to activity in manifest file
android:launchMode="singleTop"
Add this method to the same activity
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
//do the task here to be refreshed
}
Whenever new intent is called it will open the same actvity which is previously opened. If not then it will open new activity.
Read this more clarification https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en
I solved it using the link
https://inthecheesefactory.com/blog/understand-android-activity-launchmode/en
I added this to my <activity> tag in manifest
android:launchMode="singleInstance"
I've just made a service to set something, Added a log and a timer, the timer delay is taken form sharedpreferences value, the value is returning 5 minutes, the problem that the Service is looping in a crazy way, it's not a 1 sec delay, nope .. it's less than a second delay and it's outputting the log message .
And to mention, I'm using the same code with another service, I have this problem only in this service, Codes :
Manifest :
<service
android:name=".services.ServiceTest"
android:enabled="true"
android:exported="false" >
</service>
Switch that starts the service :
Intent BroadcastIntent = new Intent(getActivity(),ReceiverTest.class);
BroadcastIntent.setAction(packagetest+"startservice");
getActivity().sendBroadcast(BroadcastIntent);
Receiver takes the action, in a if statement and runs the service via intent in the following way :
Intent ServiceTestIntent = new Intent(context, ServiceTest.class);
context.startService(ServiceTestIntent);
The Service :
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences Preference = PreferenceManager.getDefaultSharedPreferences(this);
int Delay= Preference.getInt("Value", 2 * 60 * 1000);
MyTimer = new Timer();
new Thread()
{
public void run() {
MyTimer.schedule(new TimerTask() {
#Override
public void run() {
Log.i(Fragment.TAG,"Message Test");
}
}, Delay, Delay);
}
}.start();
return START_NOT_STICKY;
}
The delay returns 5 minutes (5*60*1000) and then i store it in the sharedpreferences, When i log the value it says 5 minutes, so it's a correct time, even though the default is 2 minutes, the service loops directly and output the message .
Receiver :
if(intent.getAction().equals(mainactivity.package+"startservice"))
{
context.startService(ServiceIntent);
}
UPDATE :
Another thing is, I got 3 other services with different receivers, When i switch any of them, the Test service will be launched, even though i didn't start it or reference it, or anything related to it in the other switches .
I've tried rebooting/App full deletion using Root App remover .
Add a log statement to show the delay. Either the delay value is wrong or the service is being started multiple times:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences Preference = PreferenceManager.getDefaultSharedPreferences(this);
final int Delay= Preference.getInt("Value", 2 * 60 * 1000);
Log.i(Fragment.TAG, String.format("onStartCommand(): delay=%d", Delay));
final Timer MyTimer = new Timer();
new Thread()
{
public void run() {
MyTimer.schedule(new TimerTask() {
#Override
public void run() {
Log.i(Fragment.TAG, "Message Test");
}
}, Delay, Delay);
}
}.start();
return START_NOT_STICKY;
}
There's broadcastReceiver receive boot message and set a alarmmanager.
It start a service every DELAY mins:
Intent intent = new Intent();
intent.setAction("org.jxdwinter.getMessageServcie");
PendingIntent pendingintent = PendingIntent.getService(arg0, 0, intent, 0);
am = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), DELAY, pendingintent);
The service poll data from romate server in a new thread:
public int onStartCommand(Intent intent, int flags, int startId)
{
this.getMessage.start();
return Service.START_NOT_STICKY;
}
private class GetMessage extends Thread
{
public void run()
{
... ....
}
}
And when the app started, I can get the data at very first time and there's no
error.
Then the service start again in DELAY mins , there's an error:Thread already started.
Why is happened? Pls help me with this. Thank you!
Maybe you could just create a new instance of your thread each time you need it to run:
public int onStartCommand(Intent intent, int flags, int startId)
{
new GetMessage().start();
return Service.START_NOT_STICKY;
}
Is instance of GetMesdsage class you are using by any chance static? If yes, do not doe this - initialize new one
I get my Broadcast receiver to set a recurring alarm, to fire up a service. Unfortunately this does not result in the service being called repeatedly (based on logcat). I've experimented with different values for the time interval too. Can someone help? (I'm testing through Eclipse on Android 3.2 Motorola xoom)
Below is the code for the Broadcast receiver.
alarm = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
Intent intentUploadService = new Intent (arg0, com.vikramdhunta.UploaderService.class);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 3);
PendingIntent pi = PendingIntent.getBroadcast(arg0, 0, intentUploadService , 0);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 5, pi);
Below is the code for the Service class
public UploaderService()
{
super("UploaderService");
mycounterid = globalcounter++;
}
#Override
protected void onHandleIntent(Intent intent) {
synchronized(this)
{
try
{
for (int i = 1;i < 5;i++)
{
// doesn't do much right now.. but this should appear in logcat
Log.i(TAG,"OK " + globalcounter++ + " uploading..." + System.currentTimeMillis());
}
}
catch(Exception e)
{
}
}
}
#Override
public void onCreate() {
super.onCreate();
Log.d("TAG", "Service created.");
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.i(TAG, "Starting upload service..." + mycounterid);
return super.onStartCommand(intent,flags,startId);
}
Ok Looks like I got this one. Two changes were needed -
1 - i made a mistake of using PendingIntent.getBroadcast when I needed to do getService instead (hell, who knew!)
2 - In getService, I should have supplied PendingIntent.FLAG_UPDATE_CURRENT in the end instead of 0. FLAG_ONE_SHOT did not work. I guess since the interval is only 5 seconds, this is the right way.
Now I get the right service/function to be called every 5 seconds. Hurray!