I'm trying to make a Service, wake up and call itself again after one minute (in this example, I know its bad for battery).
Here is part of the code:
public class SpeechService extends Service {
#Override
public void onCreate() {
super.onCreate();
setUpNextAlarm();
}
public void setUpNextAlarm(){
Intent intent = new Intent(SpeechService.this, this.getClass());
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0);
long currentTimeMillis = System.currentTimeMillis();
long nextUpdateTimeMillis = currentTimeMillis + 1 * DateUtils.MINUTE_IN_MILLIS;
// Schedule the alarm!
AlarmManager am = (AlarmManager)ContextManager.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP,nextUpdateTimeMillis, pendingIntent);
Log.e("test","I am back!");
}
protected void onHandleIntent(Intent intent)
{
Log.e("test","I am back!");
setUpNextAlarm();
}
}
As you can see I'm calling setUpNextAlarm on service create, I see the log at the end, but then the service is never being called again. I have tried this in an IndentService, it works but I need it to work in a normal Service :(.
Thank you
Use
PendingIntent.getService
not
PendingIntent.getBroadcast
You are getting a Broadcast Intent.
I just ended up using a Service and an IntentService. The IntentService was using the AlarmManager and then it was calling the Service.
Related
So I made an app that upon a button click sets up a repeating task using an Alarm Manager.
In on create:
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
servicePendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
On the button click:
alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
firingCal= Calendar.getInstance();
firingCal.setTimeInMillis(System.currentTimeMillis());
firingCal.set(Calendar.HOUR_OF_DAY, 1); // At the hour you want to fire the alarm
firingCal.set(Calendar.MINUTE, 47); // alarm minute
firingCal.set(Calendar.SECOND, 0); // and alarm second
long intendedTime = firingCal.getTimeInMillis();
long interval = 1000 * 60 * 1;
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, intendedTime, interval, servicePendingIntent);
In the AlarmReceiver class:
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(context, WallpaperService.class);
context.startService(myIntent);
Log.d(TAG,"Am apelat serviciul");
context.stopService(myIntent);
}
And in the WallpaperService class I just make a get request and set an wallpaper.
public class WallpaperService extends Service {
String requestLink="";
boolean requestFinished = false;
public final String TAG = "Service";
public static int SERVICE_ID = 1;
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG,"Wallpaper Service started");
Toast.makeText(WallpaperService.this,"Service started",Toast.LENGTH_LONG);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG,"In onStartCommand");
taskToBeRepeated();
stopSelf();
return START_STICKY;
}
.....
}
And the behaviour is that when I start the app and I click the button everything works well the first time the Alarm Manager fires ( With the app in the background). The second time the receiver gets triggered I get the error in the tile. To be more specific :
java.lang.RuntimeException: Unable to start receiver com.example.dailywallpaper.AlarmReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.example.dailywallpaper/.WallpaperService }: app is in background uid UidRecord{3e313bf u0a357 RCVR bg:+1m21s273ms idle change:uncached procs:1 seq(0,0,0)}
What seems to be the problem ? And why is working the first time and then it gives the error? How can I fix it ?
you need to read android official documentation about the policy of using background service or alarms in android 8 and above and adapt your app with this limitations.
I suggest you to read this two articles very carefully :
https://developer.android.com/guide/components/services
https://developer.android.com/about/versions/oreo/background
At point A in my application I start my service and expect the service get closed from point B. However, there might be few scenarios that point B doesn't ask service to get closed. In this case I want the service close itself after fixed amount of time.
I have written following code into my Service class and expect the service gets closed after 10 seconds from launch time (It will be 45min in the future but I don't want to stay that long for test).
public class ChatService extends Service implements ITCPConnection
{
private static final int SERVICE_LIFE_TIME = 10 * 1000; // In millis
private AlarmReceiver mAlarmReceiver;
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
#Override
public void onCreate()
{
super.onCreate();
//
mAlarmReceiver = new AlarmReceiver();
registerReceiver(mAlarmReceiver, new IntentFilter());
//
Intent intent = new Intent(this, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + SERVICE_LIFE_TIME, alarmIntent);
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.e(TAG, "onDestroy()");
// Unregister receiver
if (mAlarmReceiver != null)
{
unregisterReceiver(mAlarmReceiver);
}
disconnect();
}
public void disconnect()
{
// If the alarm has been set, cancel it.
if (alarmMgr!= null)
{
alarmMgr.cancel(alarmIntent);
}
...
Log.e(TAG, "disconnect()");
}
/*****************
* Alarm Receiver
*****************/
private static class AlarmReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.e(TAG, "Stop service from AlarmReceiver");
context.stopService(intent);
}
}
}
My problem is AlarmReceiver.onReceive() never gets called and therefore my service will be alive indefinitely.
What you are trying to do is to targeting a broadcast receiver explicitly.
According to this, it cannot be done over a dinamically created (i.e. not declared into the manifest) broadcast receiver, because the os would not know how to resolve it.
To check if this is the root of the problem, you can go with the implicit way and set an action inside the intent and by filtering it in the IntentFilter.
Anyway, using the post delayed can be seen as a valid alternative, since you expect the service to be shut down naturally or still be around to intercept the delayed event.
Another (unrelated) thing is that you are calling
context.stopService(intent);
by using the broadcast intent and not the intent that started the service. You could simply call stopSelf().
I want to make a background running service (independent of an app) which would download weather data from server periodically every day. I already have code to download data from the server and store it in the database.
What I would like to know is, what is the best way to run the service periodically.
You can Create a Android Intent Service :-
public class BackendService extends IntentService {
public BackendService() {
super("BackendService");
}
#Override
protected void onHandleIntent(Intent intent) {
// Your Download code
}
}
Then set a Alarm Receiver to set the interval in which service will be called.
public void backendscheduleAlarm() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), BackendAlarm.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, BackendAlarm.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 1 hour
long firstMillis = System.currentTimeMillis(); // first run of alarm is immediate
int intervalMillis = 3000; //3600000; // 60 min
AlarmManager backendalarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
backendalarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, intervalMillis, pIntent);
}
And Create a Broadcast Receiver class to call that service:
public class BackendAlarm extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
// Triggered by the Alarm periodically (starts the service to run task)
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, BackendService.class);
i.putExtra("foo", "bar");
context.startService(i);
} }
read about Android Services which are mainly made for such background work:
http://developer.android.com/guide/components/services.html
all you need is to start the service on a certain time you set.
I'm working on app in which I want to schedule service in a interval of 6 hours. I'm calling this method from main activity. When this activity open then it call this method and hits the service. I don't want to execute it whenever this method executes. After first exceution of this service it should execute after 6 hours or so not app open. Is there any flag or something I need to do set to do that.
public static void scheduleHeartBeat(Context mContext) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
Intent myIntent = new Intent(mContext, HearBeatService.class);
PendingIntent pendingIntent = PendingIntent.getService(mContext, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() , 6*60*60*1000, pendingIntent);
}
public class HearBeatService extends IntentService {
public HearBeatService() {
super("HearBeatService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("HeartBeat", "Hey Testing!!!");
}
}
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
.....
scheduleHeartBeat(this);
...
}
Thanks in advance.
User broadcastreceiver.
Create class that extends Intent service class
Create class that broadcastreceiver class and call the Intent service (from step1)
Create pending intent for the broadcastreciever(from step2)
Register the pending intent with alarm manager of 6 hours delay
Dont Forget to register your service and receiver in the android manifest.
I am wondering if i can do this, i want to implement a service that will be called when activity launches and should run at regular intervals, and when i stop the activity by closing or pressing back the service should stop and alarm manager should not invoke service before the activity relaunches.
One more thing i want to send some data on which service can operate and give results back to activity.
currently i am doing like this.....
class MyService extends Service{
}
class MyScheduler extends BroadCastReceiver{
//Here alarm manager and pending intent is initialized to repeat after regular intervals.
}
class MyActivity extends Activity{
onCreate(){
//here i am binding the service
}
}
MyBrodcastReceiver is added into manifest
please help and suggest how to do it?
for starting:
this.startService(new Intent(this, MyService.class));
for stoping:
this.stopService(new Intent(this, MyService.class));
for having intervals create a service that calls a BrodcastReceiver periodically like the following sample:
in your service:
// An alarm for rising in special times to fire the pendingIntentPositioning
private AlarmManager alarmManagerPositioning;
// A PendingIntent for calling a receiver in special times
public PendingIntent pendingIntentPositioning;
#Override
public void onCreate() {
super.onCreate();
alarmManagerPositioning = (AlarmManager) getSystemService
(Context.ALARM_SERVICE);
Intent intentToFire = new Intent(
ReceiverPositioningAlarm.ACTION_REFRESH_SCHEDULE_ALARM);
pendingIntentPositioning = PendingIntent.getBroadcast(
this, 0, intentToFire, 0);
};
#Override
public void onStart(Intent intent, int startId) {
long interval = 10 * 60 * 1000;
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
long timetoRefresh = SystemClock.elapsedRealtime();
alarmManagerPositioning.setRepeating(alarmType,
timetoRefresh, interval, pendingIntentPositioning);
}