Alright. I guess I jumped in too quickly to shot out my problem . I figured
out a way (of course with the help of all you beautiful people :) ) to run
my service in background. What I have done is I first call a service from my
intent receiver. This service in turns creates an instance of Alarm Manager.
Since Alarm Manager broadcasts an intent, I have another intent receiver,
which receives this intent and run a service which will do run my logic. It
seems to work for me but not sure if this is the most efficient and
recommendable way to do this. Here is my piece of code:
public class BootCompletedIntentReceiver extends IntentReceiver {
/* the intent source*/
static final String ACTION = "android.intent.action.BOOT_COMPLETED";
private static final String LOG_TAG = "BootCompletedIntentReceiver";
@Override
public void onReceiveIntent(Context context, Intent intent) {
if (intent.getAction().equals(ACTION))
{
// Once we receive the BOOT_COMPLETED intent, we will start a service
that
// will start a service which in turn will run alarm manager
Intent i = new Intent();
i.setClassName("com.jaikishan.smartaddress",
"com.jaikishan.smartaddress.AddressLogService");
Bundle b = new Bundle();
ComponentName cname = context.startService( i,b );
if( cname == null )
Log.e( LOG_TAG,"AddressLogService was not started" );
else
Log.d( LOG_TAG,"AddressLogService started" );
}
}
}
public class AddressLogService extends Service {
private static final String LOG_TAG = "BackgroundService";
@Override
protected void onStart(int startId, Bundle arguments) {
super.onStart( startId, arguments );
Log.d( LOG_TAG, "onStart" );
Intent i = new Intent();
i.setClassName("com.jaikishan.smartaddress",
"com.jaikishan.smartaddress.AddressLoggerIntent");
// We want the alarm to go off 5 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, 5*1000, i);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class AddressLoggerIntent extends IntentReceiver
{
private static final String LOG_TAG = "AddressLoggerIntent";
@Override
public void onReceiveIntent(Context context, Intent intent)
{
context.startService(new Intent(context, AddressLogger.class),
null);
}
}
public class AddressLogger extends Service {
@Override
protected void onStart(int startId, Bundle arguments) {
super.onStart( startId, arguments );
// Do business logic
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
Thanks,
Jaikishan
Post by Jaikishan JalanAlright, I wrote my service as per the discussion, but somehow it is not
public class BootCompletedIntentReceiver extends IntentReceiver {
/* the intent source*/
static final String ACTION = "android.intent.action.BOOT_COMPLETED";
private static final String LOG_TAG = "BootCompletedIntentReceiver";
@Override
public void onReceiveIntent(Context context, Intent intent) {
if (intent.getAction().equals(ACTION))
{
Intent i = new Intent();
i.setClassName("com.jaikishan.smartaddress",
"com.jaikishan.smartaddress.AddressLoggerIntent");
// We want the alarm to go off 5 seconds from now.. //Ideally it will
be 30 minutes or so.
long firstTime = SystemClock.elapsedRealtime();
// Schedule the alarm!
AlarmManager am = (AlarmManager)context.getSystemService("alarm");
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, 5*1000, intent);
Log.v(LOG_TAG,"AddressLoggerIntent Sent");
}
}
}
public class AddressLoggerIntent extends IntentReceiver
{
private static final String LOG_TAG = "AddressLoggerIntent";
@Override
public void onReceiveIntent(Context context, Intent intent) {
// Start up the service. Note that if the service is taking too
long
// to complete -- longer than our alarm's repeat rate -- then this
will
// just leave the current service running, skipping this alarm.
For
// most situations this is probably a reasonable thing to do.
context.startService(new Intent(context,
AddressLoggerService.class),
null);
Log.v(LOG_TAG,"AddressLoggerService Sent");
}
}
public class AddressLoggerService extends Service {
private static final String LOG_TAG = "AddressLoggerService";
@Override
protected void onStart(int startId, Bundle arguments) {
super.onStart( startId, arguments );
Log.v(LOG_TAG, "AddressLogger Service Started");
// Do the processing
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
From my BootIntentReceiver, I set the alarm Manager. Since Alarm Manager
can only send broadcast, I have an intent receiver for it. The intent
receiver calls a service that will run the business logic. However, when I
observe the Logcat, I see "AddressLoggerIntent Sent" message keeps getting
printed infinite times and nothing else happens. Other Log messages are
never printed. This shows that my service is not getting called at all !
(ideally it should be called periodically). My AndroidManifest.xml file
<application>
<receiver android:name=".BootCompletedIntentReceiver">
<intent-filter>
<action
android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</receiver>
<service android:name=".AddressLoggerService"/>
<receiver android:name=".AddressLoggerIntent" />
</application>
Any help will be greatly appreciated.
Post by hackbodIn M5 the alarm manager could only send a broadcast, so you will need
to have a receiver for that (could be the same one, checking the
Intent action) which then starts the service. In a future SDK you
will be able to directly start a service.
Also I would highly recommend going through the ApiDemos -- there are
examples of services, alarms, and using the two together.
Post by Jaikishan JalanSo, is this the correct way ?
// My intent receiver which will listen for BOOT_COMPLETED Signal
public class AddressLogIntent extends IntentReceiver{
static final String ACTION = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceiveIntent(Context context, Intent intent) {
if (intent.getAction().equals(ACTION))
{
Intent AddressIntent = new
Intent(AddressLogIntent.this,AddressLogService.class);
// We want the alarm to go off 15 seconds from now.
long firstTime = SystemClock.elapsedRealtime();
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime,
15*1000, intent);
}
}
}
public class AddressLogService extends Service
{
@Override
protected void onCreate()
{
//Simply do my processing
}
}
Is this the correct way to invoke a background process that runs after
every
Post by Jaikishan Jalan15 seconds after the BOOT event is completed? I created an
intentreceiver
Post by Jaikishan Jalanfor the BOOT event and then create an Alarm Manager and schedule it
after
Post by Jaikishan Jalanevery 15 seconds. This alarm manager will call a service that will do my
processing. I expect this alarm to run infinitely until the emulator is
closed.
Thanks,
Jaikishan
-----Original Message-----
Sent: Sunday, July 13, 2008 12:06 PM
To: Android Developers
Subject: [android-developers] Re: Running Background Process
Yeah it is almost certainly due to the process being killed to reclaim
memory. In the situation where you just have a receiver that starts a
thread, the process will be run as a foreground process (oom_adj=0)
for the time it is in onReceiveIntent(), but upon returning from that
the system does not consider there to be any active objects running in
the process so it is lowered to an empty process (oom_adj=15).
Empty processes are killed very aggressively by the system's memory
management, so it is very likely for your process to be killed as
other things go on during boot. If you look at the logcat output, you
will probably see lines in the log about your process starting, and
then later dying. You can also use the command "adb dumpsys activity"
to see the current state of the activities and application processes
being managed by the system; this includes the current oom_adj values
for each process.
Fwiw, a lot of memory optimization work has been done since M5 so in
future SDKs it is less likely for your process to be killed when
empty... but leaving it in the state where the system thinks it is
empty but you still have stuff you want running in it is a bug, and
will cause problems sooner or later.
Post by JBQFor a 30-minute interval, I'd recommend an alarm manager. It'll save
some RAM that'll make the device more responsive for foreground
applications, and it'll save you some bookkeeping (tracking a 30-
minute interval through your service getting killed and restarted
isn't as easy as it seems).
As for the apparently random behavior, I don't actually know for sure.
My guess is that the system is running under enough memory pressure
(which is common during boot as there are many things going on) to
cause apparently inactive processes to get killed so quickly that your
thread never gets a chance to run at all.
JBQ
Post by Jaikishan JalanThanks Mark and JBQ for your reply. Ok, ideally when the application
will be
Post by JBQPost by Jaikishan Jalanreleased, my application will make a network request after every 30
minutes.
Post by JBQPost by Jaikishan JalanSo what do you recommend? - Service or Alarm Manager? My second
question
Post by Jaikishan Jalanis
Post by JBQPost by Jaikishan Jalanwhy the random behavior? Is there any reason behind why the thread
sometime
Post by JBQPost by Jaikishan Jalanruns and sometime it does not.
-Jaikishan
-----Original Message-----
Sent: Sunday, July 13, 2008 10:39 AM
To: Android Developers
Subject: [android-developers] Re: Running Background Process
First, I'm not entirely sure what you're trying to achieve, but
making
Post by Jaikishan JalanPost by JBQPost by Jaikishan Jalanyour code wake up every 15 seconds might cost your users a lot of
battery life for little result, when the user isn't actively using
the
Post by Jaikishan JalanPost by JBQPost by Jaikishan Jalandevice. If you do some network activity every 15 seconds over a cell
network, you'll only have a few hours of battery life.
-if you really want to have a process stick around, you need to have
a
Post by Jaikishan JalanPost by JBQPost by Jaikishan JalanService in that process, so that the system can make the appropriate
decisions when it tries to make space for other applications. When
the
Post by Jaikishan JalanPost by JBQPost by Jaikishan Jalanprocess that hosts your service is killed, it'll eventually get
restarted automatically, so you can restart whatever you were doing
in
Post by Jaikishan JalanPost by JBQPost by Jaikishan Jalanthe service's onCreate function. In that case, you'll find that
using
Post by Jaikishan JalanPost by JBQPost by Jaikishan Jalana Handler is a much better idea than using Thread.sleep.
-if you can work without necessarily having a process stay up all
the
Post by Jaikishan JalanPost by JBQPost by Jaikishan Jalantime, you should look at the AlarmManager, which will allow the
system
Post by Jaikishan JalanPost by JBQPost by Jaikishan Jalanto free the memory associated with your process between ticks.
JBQ
Post by Jaikishan JalanHello,
I have written an intentreceiver which gets launched when the boot
has
do
Post by Jaikishan JalanPost by JBQPost by Jaikishan JalanPost by Jaikishan Jalanpublic class AddressLogService extends IntentReceiver{
/* the intent source*/
static final String ACTION =
"android.intent.action.BOOT_COMPLETED";
@Override
public void onReceiveIntent(Context context, Intent intent) {
if (intent.getAction().equals(ACTION))
{
NewRunnable AddressLog = new NewRunnable(context);
Thread tr = new Thread(null,AddressLog,"Address Logger");
tr.start();
}
}
private class NewRunnable implements Runnable {
private Context context;
// Initializing the Runnable Class
public NewRunnable(Context c){
context = c;
}
public void run(){
while(true){
isServerUp = true;
if(isServerUp ){
// Do some processing
Thread.sleep(15 * 1000);
}
}catch(Exception e){}
}
}
}
}
I have included the required receiver details and permission in
AndroidManifest.xml
The problem is when I launch my emulator, this thread sometimes
run
certain
server
is
to
--
Thanks,
Jaikishan
--
Thanks,
Jaikishan
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-***@googlegroups.com
To unsubscribe from this group, send email to
android-developers-***@googlegroups.com
Announcing the new M5 SDK!
http://android-developers.blogspot.com/2008/02/android-sdk-m5-rc14-now-available.html
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---