I've got two services running. They do their work and then reschedule themselves via the AlarmManager. In the BroadcastReceiver the only thing that happens is the launching of the service via Context.startService(). Both services are IntentServices, which as far as I can tell shouldn't be causing timeout problems. I've tried IntentServices, threading, and AsyncTasks but am repeatedly bumping up against the timeout error in the receivers themselves.
The timeout message is:
01-18 11:29:04.200: WARN/ActivityManager(73): Timeout of broadcast BroadcastRecord{433a4168 my.package.action.a} - receiver=android.os.BinderProxy#43399978
01-18 11:29:04.210: WARN/ActivityManager(73): Receiver during timeout: ResolveInfo{43394a30 my.package.MyReceiverA p=0 o=0 m=0x108000}
The basic structure of the two receivers:
public class MyReceiverA extends BroadcastReceiver {
public static final String ACTION_TO_BROADCAST = "my.package.action.a";
public void onReceive(Context context, Intent intent) {
// start the service
Intent serviceIntent = new Intent().setClassName(context,
MyServiceA.class.getName());
context.startService(serviceIntent);
}
}
And the services:
public class MyServiceA extends IntentService {
public ActivityMonitorService() {
super(TAG);
}
public IBinder onBind(Intent intent) {
// We don't allow anyone to bind to us
return null;
}
public void onCreate() {
super.onCreate();
_context = getApplicationContext();
_config = new Config();
if (_handler == null) {
_handler = new Handler();
}
}
/**
* Schedules an alarm to run ourselves again after ALARM_INTERVAL has passed.
*/
private void reschedule() {
Intent intent = new Intent(MyReceiverA.ACTION_TO_BROADCAST);
PendingIntent pendingIntent = PendingIntent.getBroadcast(_context, 0, intent, 0);
AlarmManager manager = (AlarmManager) _context.getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC, now + delay, pendingIntent);
}
private void doWork() {
// Do some work. This could take a while. It also accesses a database that the two
// services share through synchronized blocks of code in static accessor functions.
}
protected void onHandleIntent(Intent intent) {
try {
doWork();
} catch (Exception e) {
// log it
} finally {
reschedule();
}
}
}
I figured out what was going on. Changing the two services to be a single one fixed the problem, meaning there was some sort of deadlock or race going on in the two. I'm assuming it's with their database access but haven't had a chance to verify it yet.
When changing to a single service the problem wasn't that the alarm was firing late, it's that the loaded down phone was pausing my service to give the music player the resources it needed. Looks like my options are to live with it or run the service in the foreground.
Related
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().
My intention is to have download service created when the app first runs and checks for update every 24 hours. I originally had everything running my main activity but it seems to much to run everything on one thread and one class. So this is my attempt to move it to another class and into service. It suppose to run and check for an update ever 24 hours and if there is no internet try again in 4 hours. I specifically want to involve any recursive problems, having two or three same services checking update, just one every 24 hours. But having problem with integrating my code into service, what am I doing wrong?
public class DownloadService extends IntentService {
// TODO 0 - Define your Download Service as Android component in
// AndroidManifest.xml
private int result = Activity.RESULT_CANCELED;
public DownloadService() {
super("DownloadService");
}
// Will be called asynchronously be Android
#Override
protected void onHandleIntent(Intent intent) {
private final Runnable mUpdateUi = new Runnable(){
public void run(){
check();
}
};
private void start(){
new Thread(
new Runnable(){
public void run(){
Log.d(TAG, "inside start");
Looper.prepare();
mHandler = new Handler();
check();
Looper.loop();
}
}
).run();
}
private void check(){
if (isNetworkAvailable()== true){
try {
new checkupdate().execute();
delayTime = 86400000;
Toast.makeText(DownloadService.this, "Daily update check!", Toast.LENGTH_SHORT).show();
}
catch (IOException e) {
e.printStackTrace();
delayTime = 21600000;
}
}else{
delayTime = 21600000;
Toast.makeText(DownloadService.this, "No internet for Daily update check, try again in little!", Toast.LENGTH_SHORT).show();
}
reCheck();
}
private void reCheck(){
mHandler.postDelayed(mUpdateUi, delayTime);
}
}
IntentService already handles setting up a worker thread and queue, and termination when the queue is empty. Which makes it a very good candidate for something like a download service to manage the actual work of downloading data, but not really a great candidate for a time scheduler.
I'd suggest using an AlarmManager to schedule your work instead. What you want is to trigger an Intent to start your DownloadService, by sending it intent with an Action indicating what to do.
Note also that if you want to cancel an IntentService with an Action, you will need to implement onStartCommand in addition to the usual onHandleIntent, so that you can respond to the action immediately -- you cannot do this from onHandleIntent, since the intent won't be sent to that until the current task in the queue is completed. Here's a quick example:
public class DownloadService extends IntentService {
private static final String TAG = "DownloadService";
////////////////////////////////////////////////////////////////////////
// Actions
public static final String ACTION_CANCEL = "package.name.DownloadService.action.CANCEL";
public static final String ACTION_DOWNLOAD = "package.name.DownloadService.action.DOWNLOAD";
////////////////////////////////////////////////////////////////////////
// Broadcasts
public static final String BROADCAST_DOWNLOADED = "package.name.DownloadService.broadcast.DOWNLOADED";
public static final String BROADCAST_ERROR = "package.name.DownloadService.broadcast.ERROR";
////////////////////////////////////////////////////////////////////////
// Extras
public static final String MESSAGE = "package.name.DownloadService.extra.MESSAGE";
// etc.
private boolean isCancelled;
// usual stuff omitted
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null) {
String action = intent.getAction();
Log.v(TAG, "onStartCommand() - action: "+action);
if(ACTION_CANCEL.equals(action)) {
isCancelled = true;
// insert code here to signal any objects to cancel
// their work, etc.
stopSelf();
}
}
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void onHandleIntent(Intent intent) {
if(intent != null) {
final String action = intent.getAction();
Log.v(TAG, "onHandleIntent() - action: "+action);
if(ACTION_DOWNLOAD.equals(action)) {
handleDownloading(intent);
}
else if(ACTION_CANCEL.equals(action)) {
// nothing to do here, handled in onStartCommand
}
}
}
////////////////////////////////////////////////////////////////////
private void handleDownloading(Intent intent) {
// get stuff you need from the intent using intent.getStringExtra(), etc.
if(!isCancelled) {
// do downloading, call broadcastDownloaded() when done
}
else {
// stop work, send broadcast to report cancellation, etc.
}
}
// send a broadcast to a BroadcastReceiver (e.g. in your activity)
// to report that the download completed
private void broadcastDownloaded() {
Log.v(TAG, "broadcastDownloaded()");
Intent broadcastIntent = new Intent();
if (broadcastIntent != null) {
broadcastIntent.setAction(BROADCAST_DOWNLOADED);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(broadcastIntent);
}
}
private void broadcastError(String message) {
Log.v(TAG, "broadcastError(), message: "+message);
Intent broadcastIntent = new Intent();
if (broadcastIntent != null) {
broadcastIntent.setAction(BROADCAST_ERROR);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
if(message != null) {
broadcastIntent.putExtra(MESSAGE, message);
}
sendBroadcast(broadcastIntent);
}
}
}
This is not how IntentService is meant to be used. As per the documentation, IntentService already creates its own worker threads. You should not be creating your own:
Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.
Apart from the fact that your code as shown here won't compile (your start method is inside the onHandleIntent method), your general approach seems to be to start your own worker thread. What would happen in this approach is that you would start the thread, onHandleIntent would complete and then the service would be stopped. In addition to not actually working, this approach is also a bad idea because (at best if you're lucky) the service would be running continually 24/7.
What you should do instead is actually do your main work in onHandleIntent which IntentService will queue on a worker thread for you. Then instead of using postDelayed use AlarmManager to set an alarm to send an Intent to start the service again in 24 hours or 4 hours.
I'm working on an Android app that sues a background task to fetch XML from a URL every x seconds (user defined interval, defaulting to 60). My structure is as so:
MainActivity
This schedules an Alarm via AlarmManager:
public static void scheduleAlarm(Context voContext, int viCheckInterval)
{
try {
moAlarmManager = (AlarmManager) voContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(voContext, AlarmReceiver.class);
moAlarmIntent = PendingIntent.getBroadcast(voContext, 0, intent,
PendingIntent.FLAG_CANCEL_CURRENT);
Calendar time = Calendar.getInstance();
time.setTimeInMillis(System.currentTimeMillis());
time.add(Calendar.SECOND, viCheckInterval);
moAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(),
time.getTimeInMillis(), moAlarmIntent);
} catch (Exception e) {
Log.e("MessageCheckAlarmHandler", e.toString());
}
}
AlarmReceiver
This is a BroadcastReceiver that starts the service:
#Override
public void onReceive(Context context, Intent intent)
{
Context oAppContext = context.getApplicationContext();
if (oAppContext == null) {
oAppContext = context;
}
Intent serviceIntent = new Intent(oAppContext, MessagingService.class);
oAppContext.startService(serviceIntent);
}
MessagingService
This creates our in-house logger (logging over TCP) and starts an AsyncTask called FetchPageTask:
public class MessagingService extends Service
{
#Override
public void onCreate()
{
super.onCreate();
...
this.acquireLocks();
try {
String sCheckerUrl = oPreferences.getString("pref_server", "");
int sCheckerPort = Integer.parseInt(oPreferences.getString("pref_server_port",
"8050"));
sCheckerUrl = String.format(URL, sCheckerUrl, sCheckerPort);
this.moFetchInboxTask = new FetchPageTask(this.logger, this);
this.moFetchInboxTask.execute(sCheckerUrl);
} finally {
this.releaseLocks();
this.stopSelf();
}
}
#Override
public void onDestroy()
{
super.onDestroy();
this.logger.close();
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
/**
* Acquire a WakeLock and a WifiLock.
*/
private void acquireLocks()
{
try {
// Acquire a wake lock to prevent the device from entering "deep sleep"
PowerManager oPowerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
this.moWakeLock = oPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
this.moWakeLock.acquire();
// Acquire a WiFi lock to ensure WiFi is enabled
WifiManager wm = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
this.moWifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL, TAG);
this.moWifiLock.acquire();
} catch (Exception e) {
this.logger.error(TAG + "->onCreate()", "Error acquiring locks: " + e.toString());
}
}
/**
* Release our WakeLock and WifiLock.
*/
private void releaseLocks()
{
try {
this.moWakeLock.release();
this.moWifiLock.release();
} catch (Exception e) {
this.logger.error(TAG + "->releaseLocks()", e.toString());
}
}
}
FetchPageTask
This extends AsyncTask and does all the work of fetching the page and parsing the XML. It also then adds notifications and performs actions on the data retreived if need be.
This all works fine once, but does not run subsequently. I know that the AsyncTask works as I was previously doing it using pure Java via ScheduledExecutorService and ScheduledFuture and it worked. The only reason I decided to change to using AlarmManager is for maintainability purposes.
First, you are setting up your alarm to occur immediately, and then every ~43 years thereafter. That is unlikely to be what you want. Modify the third parameter of your call to setRepeating() to be the desired period in milliseconds, which right now is set to the number of milliseconds since midnight 1 January 1970.
Second, you are acquiring your WakeLock too late. There is no guarantee that your acquireLocks() will get a chance to run before the device falls asleep. My WakefulIntentService or the new WakefulBroadcastReceiver offer better patterns for passing control to an IntentService.
I think you don't need the Calendar here. You just want to run the action every x seconds, so It would be something like this:
moAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
viCheckInterval, moAlarmIntent);
// viCheckInterval should be long miliseconds
I have problem and after some search I have not found any positive solutions.
After research I have idea that there is not implementation for my problem but this question may be is my last chance.
What do I need to get?
There is application that gets information about mobile network strength signal. I do it by
PhoneStateListener. Of course it works great but when my device goes to sleep mode, listener does not work:
https://code.google.com/p/android/issues/detail?id=10931
https://code.google.com/p/android/issues/detail?id=7592
WakeLock solves problem only in case, if device switch off by timeout. In case when I press hard power button, my device gets sleep mode as well. We can not override power button action.
My goal is get strength signal always when my device is enabled. It does not matter what mode is. All time it should collecting data.
Question:
Are there any ideas? How to achieve that? Are there ways to do this or may be there are some hacks? All solves are welcome. If you had some useful experience, please share this.
Thanks to all for help!!! I hope, this topic will get complete information about this problem.
Alarm manager is the way to go - the tricky part is to keep the phone awake after the alarm manager receiver returns. So
setup an alarm (notice you should also register an "On Boot completed" receiver to set up the alarm after a reboot - your alarms do not survive a reboot) :
Intent monitoringIntent = new Intent(context, YourReceiver.class);
monitoringIntent.setAction("your action");
PendingIntent pi = PendingIntent.getBroadcast(context, NOT_USED,
monitoringIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager)
context.getSystemService(Context.ALARM_SERVICE);
// here is the alarm set up
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + INITIAL_DELAY,
INTERVAL_BETWEEN_ALARMS, pi);
receive it - the receiver holds a WakeLock in its onReceive() which never fails :
public abstract class YourReceiver extends BroadcastReceiver {
#Override
final public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if ("your action".equals(action)) {
// monitoring - got broadcast from ALARM
try {
d("SS : " + new Signal().getSignalStrength(context));
} catch (InterruptedException e) {
e.printStackTrace();
}
// Actu8ally the lines above will ANR
// I did it with WakefulIntentService :
// WakefulIntentService.sendWakefulWork(
// context, YourWakefulService.class);
// Will be posting it asap
} else {
w("Received bogus intent : " + intent);
return;
}
}
}
If you are lucky (yourRetrieveSignal() is fast enough) this will work, otherwise you will need a (Wakeful)IntentService pattern in your receiver.
The WakefulIntentService will take care of the wake lock (if you want to avoid a dependency have a look here) - EDIT : keep in mind you can't define listeners in an intent service - see here.
If the receiver ANRs on you, you have to try the WakefulIntentService pattern. In either case you might use this :
This proved the most difficult part actually :
class Signal {
static volatile CountDownLatch latch; //volatile is an overkill quite probably
static int asu;
private final static String TAG = Signal.class.getName();
int getSignalStrength(Context ctx) throws InterruptedException {
Intent i = new Intent(TAG + ".SIGNAL_ACTION", Uri.EMPTY, ctx,
SignalListenerService.class);
latch = new CountDownLatch(1);
asu = -1;
ctx.startService(i);
Log.d(TAG, "I wait");
latch.await();
ctx.stopService(i);
return asu;
}
}
where :
public class SignalListenerService extends Service {
private TelephonyManager Tel;
private SignalListener listener;
private final static String TAG = SignalListenerService.class.getName();
private static class SignalListener extends PhoneStateListener {
private volatile CountDownLatch latch;
private SignalListener(CountDownLatch la) {
Log.w(this.getClass().getName(), "CSTOR");
this.latch = la;
}
#Override
public void onSignalStrengthChanged(int asu) {
Signal.asu = asu;
latch.countDown();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.w(TAG, "Received : " + intent.getAction());
Tel = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
listener = new SignalListener(Signal.latch);
#SuppressWarnings("deprecation")
final int listenSs = PhoneStateListener.LISTEN_SIGNAL_STRENGTH;
Tel.listen(listener, listenSs);
return START_STICKY;
}
#Override
public void onDestroy() {
Log.w(TAG, "onDestroy");
Tel.listen(listener, PhoneStateListener.LISTEN_NONE);
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
This is working code (but not the pinnacle of elegance admittedly - comments/corrections welcome). Do not forget to register your services in the manifest and acquire permissions.
EDIT 2013.07.23 : I did not use the onReceive - if you use it it will ANR - this is working code if you use a WakefulIntentService in onReceive and in there you call SignalListenerService.
From my understanding of PhoneStateListener you can't do this while the application CPU is in sleep mode. You can either keep the device awake, which would ruin battery life. Alternatively you can use an alarm (see AlarmManager) to wake the device on intervals, so you can collect the data (impacts battery life still).
Some samples of using AlarmManager can be found here
CommonsWare's location polling example is really good about waking the phone and putting it to sleep again. I think it might help have a look: https://github.com/commonsguy/cwac-locpoll
One of the possible workarounds of android issue 10931 is to send the android.intent.action.SCREEN_ON intent to the 'phone' process after the screen turned off.
Create and register BroadcastReceiver to listen for notifications when the screen turns off
start(Context context) {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
context.registerReceiver(mScreenReceiver, filter);
}
final BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
#Override
public void onReceive(final Context context, final Intent intent) {
if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
Log.v(LOGTAG, "Screen is off. Running workaround");
new Thread(mReportScreenIsOnRunnable).start();
}
}
};
Send the SCREEN_ON intent to the phone process only.
public final Runnable mReportScreenIsOnRunnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Runtime.getRuntime().exec(new String[] { "su", "-c",
"am broadcast -a android.intent.action.SCREEN_ON com.android.phone" });
} catch (IOException e) {
e.printStackTrace();
}
}
};
After receiving this intent the phone process would resume sending cell location
updates.
Root privileges are required.
This solution is a bit hacky, dangerous and works not on all phones. It can lead to higher power consumption, but not so much more than if you keep the screen turned on.
I'm designing my first Android app.
This app consist in several Runnable that do some stuff. Initially I made this Runnable to be execute by a Thread (a Thread for each Runnable). Each Runnable is also Observable, so it can notify changes to Activity. User click on a start button, one or more Runnable starts, them do their job notifying gui during execution and then stops. All works fine.
First question: Is that approach the right one? In order to answer this question please keep reading.
I need two other things in my app:
to be sure that execution of my jobs doesn't stops, even if user goes away from my app to do something else;
to plan the execution of my Runnable that has to start and execute in background. Example: user decides that wants a "job" to be execute everyday at 16:00.
I've seen that I can do that with an AlarmManager and Service.
Second question: I need a Service that can manage several Runnable asynchronously, so when AlarmManager starts I ask this Service to do the requested job; I'll also modify the first part of application: instead of Thread I'll use this Service, so I can be sure that execution doesn't stop.
What kind of Service I need? IntentService can do this job?
It's right to proceed in this way? There is a better solution?
Can you give me some example of how I can implement all that?
I hope that I explained clearly my situation, otherwise I'll try to do it better.
Regards
First question: Is that approach the right one?
No, you should implement and run your Runnables in Threads in a Service.
An IntentService would be your best option if you don't require your Service to handle multiple requests simultaneously. If you start a Service it will keep running in the background even if the Activity that started it goes to the background or stops.
A Runnables can send a broadcast indicating a UI update is needed. The Activity should register a BroadcastReceiver to listen to the broadcast message and update the UI accordingly.
You can use an AlarmManager to schedule the execution of your jobs as you indicated. One way to do it is to schedule the AlarmManager to send a broadcast to be received by your IntentService which acts upon it by running the appropriate job.
Here is an example that combines all that:
Here is the IntentService
public class MyIntentService extends IntentService {
public static final String ACTION_START_JOB = "com.mycompany.myapplication.START_JOB";
public static final String ACTION_UPDATE_UI = "com.mycompany.myapplication.UPDATE_UI";
private final IBinder mBinder = new MyBinder();
// You can have as many Runnables as you want.
Runnable run = new Runnable() {
#Override
public void run() {
// Code to run in this Runnable.
// If the code needs to notify an Activity
// for a UI update, it will send a broadcast.
Intent intent = new Intent(ACTION_UPDATE_UI);
sendBroadcast(intent);
}
};
public MyIntentService() {
super("MyIntentService");
}
#Override
public void onCreate() {
// You need to register your BroadcastReceiver to listen
// to broadcasts made by the AlarmManager.
// The BroadcastReceiver will fire up your jobs when these
// broadcasts are received.
IntentFilter filter = new IntentFilter(ACTION_START_JOB);
registerReceiver(jobBroadcastReceiver, filter);
}
#Override
public void onDestroy() {
// You should unregister the BroadcastReceiver when
// the Service is destroyed because it's not needed
// any more.
unregisterReceiver(jobBroadcastReceiver);
}
/**
* This method is called every time you start this service from your
* Activity. You can Spawn as many threads with Runnables as you want here.
* Keep in mind that your system have limited resources though.
*/
#Override
protected void onHandleIntent(Intent intent) {
Intent intentFireUp = new Intent();
intentFireUp.setAction(ACTION_START_JOB);
PendingIntent pendingIntentFireUpRecording = PendingIntent
.getBroadcast(MyIntentService.this, 0, intentFireUp, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
int year = 2013, month = 5, day = 10, hourOfDay = 7, minute = 13, second = 0;
cal.set(year, month, day, hourOfDay, minute, second);
long startTime = cal.getTimeInMillis() + 5 * 60 * 1000; // starts 5
// minutes from
// now
long intervalMillis = 24 * 60 * 60 * 1000; // Repeat interval is 24
// hours (in milliseconds)
// This alarm will send a broadcast with the ACTION_START_JOB action
// daily
// starting at the given date above.
alarm.setRepeating(AlarmManager.RTC_WAKEUP, startTime, intervalMillis,
pendingIntentFireUpRecording);
// Here we spawn one Thread with a Runnable.
// You can spawn as many threads as you want.
// Don't overload your system though.
new Thread(run).run();
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
// Depending on your implementation, you may need to bind
// to this Service to run one of its methods or access
// some of its fields. In that case, you will need a Binder
// like this one.
public class MyBinder extends Binder {
MyIntentService getService() {
return MyIntentService.this;
}
}
// Spawns a Thread with Runnable run when a broadcast message is received.
// You may need different BroadcastReceivers that fire up different jobs.
BroadcastReceiver jobBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
new Thread(run).run();
}
};
}
And here is the Activity
public class MyActivity extends Activity {
Service mService;
boolean mBound = false;
ToggleButton mButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (ToggleButton) findViewById(R.id.recordStartStop);
mButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (mButton.isChecked()) {
Intent intent = new Intent(MyActivity.this,
MyIntentService.class);
startService(intent);
}
}
});
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(MyIntentService.ACTION_UPDATE_UI);
registerReceiver(uiUpdateBroadcastReceiver, filter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(uiUpdateBroadcastReceiver);
}
BroadcastReceiver uiUpdateBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Here goes the code to update your User Interface
}
};
ServiceConnection myServiceConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
mBound = false;
}
// If you need
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyIntentService mService = ((MyBinder) service).getService();
mBound = true;
}
};
}
And don't forget to add the Service definition in your AndroidManifest.xml file:
<manifest ... >
...
<application ... >
<service android:name=".MyIntentService" />
...
</application>
</manifest>