0
votes

I am experiencing some lag/black screen in my application since I start using AlarmManager + BroadcastReceiver. I have 2 BroadcastReceivers, one to when the phone gets restarted and another that AlarmManager call in the given period of time to send data to the server.

This is the code for BootReceiver to start the alarmManager once the cellphone is rebooted (it is working so far):

private final String BOOT_COMPLETED_ACTION = "android.intent.action.BOOT_COMPLETED";

@Override
public void onReceive(Context context, Intent intent) {
    // when the boot is completed, restart the alarm manager
    if(intent.getAction().equals(BOOT_COMPLETED_ACTION)){
        SharedPreferences mPrefs = context.getSharedPreferences("GPS_TRACKING", Context.MODE_PRIVATE);
        if (mPrefs.getBoolean("hasGeolocation", false) && 
                !mPrefs.getBoolean("isThreadOn", false)){
            EngineerTracker tracker = new EngineerTracker(context); 
            try {
                tracker.startEngineerTrackingLocation();
            } catch (ApplicationException e) {
                e.printStackTrace();
            }
        }
    }
}

The method to start and stop the alarm manager is this:

    public void startEngineerTrackingLocation() throws ApplicationException{
    PendingIntent pendingIntent = null;
    AlarmManager manager = null;
    ProjectGeospatialConfig geospatialConfig;

    // check if the intent is running, if it is not, start it
    if (PendingIntent.getBroadcast(context, 0, 
            new Intent(context, EngineerGeospatialTrackingReceiver.class), 
            PendingIntent.FLAG_NO_CREATE) == null){

        // fetch the geospatial configuration, it may come null, so verify before using
        geospatialConfig = getFirstFoundGeospatialConfiguration();

        // if not null and use gps
        if (geospatialConfig != null && geospatialConfig.isUseGps()){
            // session information
            SessionInformationDTO sessionInformation = dao.getObjectForKey(SqlLiteStorageKey.USER_INFORMATION);
            Integer currentResourceId = sessionInformation.getSecurityHandler().getCurrentUser().getId();

            // Retrieve a PendingIntent that will perform a broadcast and add resource id as extra
            Intent alarmIntent = new Intent(context, EngineerGeospatialTrackingReceiver.class);
            alarmIntent.putExtra("resourceId", currentResourceId.toString());

            // set pending intent
            if (pendingIntent == null){
                pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
            }

            // set manager
            if (manager == null){
                manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            }

            // set interval between alarms
            int interval = (geospatialConfig.getGpsTrackingInterval() *1000) * 60;

            // set alarm repetition
            manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 
                        interval, pendingIntent);

            // set variables for gps tracking
            SharedPreferences mPrefs = getApplicationContext().getSharedPreferences("GPS_TRACKING", Context.MODE_PRIVATE);
            Editor editor = mPrefs.edit();

            // these variables will be measured once db is set
            editor.putBoolean("hasExecuted", false);
            editor.commit();        
        }
    }       
}

both are also working so far, the flag is meant to know when the service has been executed once and will not attempt again at the basic activity (template for all activitied)

The broadcast that is invoked in the alarm manager to send the information in the defined interval is this:

public class EngineerGeospatialTrackingReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    String resourceId = intent.getStringExtra("id");
    sendLocation(context, resourceId);
}

private void sendLocation(final Context context, final String resourceId){      
    new RemoteRequestTask<Void>(null, false, null) {

        @Override
        public Void executeTask() throws ApplicationException {
            // working code
        }

        @Override
        public void completed(Void refreshed) {
        }

        @Override
        public void onException(final ApplicationException ex) {
        }
    }.start();
}}

Both receivers were added to the AndroidManifest. Beside the slowness, i also get a black screen when transitioning from an activity to another.

1

1 Answers

0
votes

Use Traceview to determine where you are spending your time, and consider enabling StrictMode to point out where you are doing unfortunate things on the main application thread.

You want onReceive() to be very quick, ideally under 1ms, as. However, it looks like you might be doing database I/O in there (e.g., references to dao), which means that work should be handled off the main application thread, perhaps by an IntentService that you start from onReceive().