Search code examples
androidalarmmanagerandroid-async-http

Why AlarmManager executes Async Http Request twice?


UPDATE: I've found my "twice" problem reason. I started "runAlarm()" twice. So the code below works okay. It sends Async HTTP request periodically. You should add to manifest this line:

<receiver  android:process=":remote" android:name="Alarm"></receiver>

ORIGINAL QUESTION: I did HTTP requests periodically using AlarmManager. It works okay in loop. But each HTTP request is executed twice. I've used some AlarmManager example without understanding what means "bla-bla" there. If you ask me why I don't use Timer, my answer is that I get error trying to touch Views out of timer thread to show results of HTTP requests. My code is below. Thanks in advance!.

    private void startHttpRequests() {
         setAlarm();
    }

public void setAlarm()
{
    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override public void onReceive( Context context, Intent _ )
        {
            asyncPostRequest();
            context.unregisterReceiver( this ); // this == BroadcastReceiver, not Activity
        }
    };
    this.registerReceiver( receiver, new IntentFilter("com.blah.blah.somemessage") );
    PendingIntent pintent = PendingIntent.getBroadcast( this, 0, new Intent("com.blah.blah.somemessage"), 0 );
    AlarmManager manager = (AlarmManager)(this.getSystemService( Context.ALARM_SERVICE ));
    pollPeriod=1000*10;
    manager.set( AlarmManager.ELAPSED_REALTIME_WAKEUP,
            SystemClock.elapsedRealtime() + pollPeriod, pintent );
}
private void asyncPostRequest() {
    new HttpPostDemo().execute("http://www.google.com");
}

@Override
protected void onPostExecute(String result)  //HTTP POST result
{
    printDebug("received="+result);
    setAlarm();
}

public class HttpPostDemo extends AsyncTask<String, Void, String>
{
    @Override
    protected String doInBackground(String... urls)
    {
        BufferedReader inBuffer = null;
        String url= urls[0];
        String result = "fail";
        try {
            HttpClient httpClient = new DefaultHttpClient();
            HttpPost request = new HttpPost(url);
            List<NameValuePair> postParameters =
                    new ArrayList<NameValuePair>();
            postParameters.add(new BasicNameValuePair("operanda", "5"));
            postParameters.add(new BasicNameValuePair("operandb", "6"));
            postParameters.add(new BasicNameValuePair("answer", "11"));
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(
                    postParameters);

            request.setEntity(formEntity);
            HttpResponse httpResponse = httpClient.execute(request);
            inBuffer = new BufferedReader(
                    new InputStreamReader(
                            httpResponse.getEntity().getContent()));

            StringBuffer stringBuffer = new StringBuffer("");
            String line = "";
            String newLine = System.getProperty("line.separator");
            while ((line = inBuffer.readLine()) != null) {
                stringBuffer.append(line + newLine);
            }
            inBuffer.close();

            result = stringBuffer.toString();

        } catch(Exception e) {
            // Do something about exceptions
            result = e.getMessage();
        } finally {
            if (inBuffer != null) {
                try {
                    inBuffer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

Solution

  • public class HttpRequestAlarm extends BroadcastReceiver {
    
        private static final int REQUEST_CODE = 0;
    
        private static final String TAG_CLASS_NAME = HttpRequestAlarm.class
                .getName();
    
        private Context context;
    
        private int timeInterval;
    
        public HttpRequestAlarm() {
        }
    
        public HttpRequestAlarm(Context context, int timeInterval) {
            this.context = context;
            this.timeInterval = timeInterval;
        }
    
        @Override
        public void onReceive(Context context, Intent intent) {
            asyncPostRequest();
        }
    
        public void start() {
            Intent intentAlarm = new Intent(context, HttpRequestAlarm.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
                    REQUEST_CODE, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
            AlarmManager alarmManager = (AlarmManager) context
                    .getSystemService(Context.ALARM_SERVICE);
            alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
                    System.currentTimeMillis(), timeInterval * 1000, pendingIntent);
            Log.i(TAG_CLASS_NAME, "Alarm scheduled for every " + timeInterval
                    + " seconds");
        }
    
        public void stop() {
            Intent intentAlarm = new Intent(context, HttpRequestAlarm.class);
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
                    REQUEST_CODE, intentAlarm, 0);
            AlarmManager alarmManager = (AlarmManager) context
                    .getSystemService(Context.ALARM_SERVICE);
            alarmManager.cancel(pendingIntent);
            Log.i(TAG_CLASS_NAME, "Alarm stopped");
        }
    }
    

    Register receiver only once in your project's Manifest.xml as below

        <receiver android:name="<your.package.name.>HttpRequestAlarm" />
    

    And finally create an object of HttpRequestAlarm and call start method. This will schedule your alarm to trigger repeatedly after every provided timeInterval.

    Note: If you want to execute your http call even when your device is alseep then you will have to acquire wakelock before http call and release it once call completes.