Frank Bozzo
Frank Bozzo

Reputation: 15403

ANR issues with Broadcast Receiver in a Service

My aim is to start a service that listens for changes to the device's screen state (on or off) and acts upon those changes. I am aware that this is not ideal, but, nonetheless, it's what I am trying to accomplish.

For some reason, my broadcast receiver only seems to fire when the screen comes on, but not when it goes off. In addition, logcat reveals numerous ANRs and it appears that the service is being repeatedly killed and restarted.

I followed a tutorial found :here

Here is my relevant code:

ScreenReceiver.java

    public class ScreenReceiver extends BroadcastReceiver {

        private boolean screenOff;

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                screenOff = true;
            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
                screenOff = false;
            }
            Intent i = new Intent(context, UpdateService.class);
            i.putExtra("screen_state", screenOff);
            context.startService(i);
        }

    }

UpdateService.java (Updated as per suggestion, now causes Force Close)

    public class UpdateService extends IntentService {

        public UpdateService(String name) {
        super(name);
        // TODO Auto-generated constructor stub
    }

        @Override
        public void onCreate() {
            super.onCreate();
            // register receiver that handles screen on and screen off logic
            IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
            filter.addAction(Intent.ACTION_SCREEN_OFF);
            BroadcastReceiver mReceiver = new ScreenReceiver();
            registerReceiver(mReceiver, filter);
        }

        @Override
        protected void onHandleIntent(Intent intent) {
            boolean screenOn = intent.getBooleanExtra("screen_state", false);
            if (!screenOn) {



                String command8 = "*******";
                String command9 = "*********";
                    int timeout = 5;

   try {
   RootTools.Result result = new RootTools.Result() {
   @Override
   public void process(String line) throws Exception {
   // Do something with current line;
   // Maybe store it using setData()
   }

   @Override
   public void onFailure(Exception ex) {
   // Do something if we failed while trying to run a command or read its output

   setError(1);
   }

   @Override
   public void onComplete(int diag) {


   }

   };

   RootTools.sendShell(
   new String[] {

   command8,
   command9},
   timeout,
   result
   );
   if(0 != result.getError())
   return;
   //Do something with getData() if needed.
   } catch (IOException e) {
   //Handle exception
   } catch (InterruptedException e) {
   //Handle exception
   } catch (RootToolsException e) {
   //TODO Auto-generated catch block
   e.printStackTrace();
   }

            } else {

             String command8 = "*******";
                String command9 = "*******";
                 String command10 = "********";
                    String command11 = "********";
                    int timeout = 5;

   try {
   RootTools.Result result = new RootTools.Result() {
   @Override
   public void process(String line) throws Exception {
   // Do something with current line;
   // Maybe store it using setData()
   }

   @Override
   public void onFailure(Exception ex) {
   // Do something if we failed while trying to run a command or read its output

   setError(1);
   }

   @Override
   public void onComplete(int diag) {
   //TODO

   }

   };

   RootTools.sendShell(
   new String[] {

   command8,
   command9,
   command10,
   command11},
   timeout,
   result
   );
   if(0 != result.getError())
   return;
   //Do something with getData() if needed.
   } catch (IOException e) {
   //Handle exception
   } catch (InterruptedException e) {
   //Handle exception
   } catch (RootToolsException e) {
   //TODO Auto-generated catch block
   e.printStackTrace();
   }
            }
        }

        @Override
        public IBinder onBind(Intent arg0) {
            // TODO Auto-generated method stub
            return null;
        }

}

The Broadcast Receiver is started by a button press, with this code:

 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ScreenReceiver();
    registerReceiver(mReceiver, filter);

Upvotes: 2

Views: 6900

Answers (1)

CommonsWare
CommonsWare

Reputation: 1007359

onStart() is not merely deprecated, but is called on the main application thread. The definition of ANR is that you are spending too much time on the main application thread. Please move your onStart() logic into a background thread, perhaps by subclassing IntentService and putting the logic in onHandleIntent().

Upvotes: 3

Related Questions