Autore Topic: Invio parametri tramite URL con un timer  (Letto 1348 volte)

Offline Nikholas

  • Nuovo arrivato
  • *
  • Post: 4
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S
  • Sistema operativo:
    Ubuntu 11.04
Invio parametri tramite URL con un timer
« il: 22 Aprile 2011, 11:45:26 CEST »
0
Ciao a tutti,
premetto che sono alle prime armi per quanto riguarda il java e lo sviluppo di app per Android!! Come da titolo ho la necessità di inviare dei parametri tramire URL in maniera ciclica (ogni minuto) e quindi come base di partenza ho utilizzato il codice seguente, sviluppato da Massimo Carli nel suo libro:

Codice (Java): [Seleziona]
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class SimpleHttpClientTestActivity extends Activity {
        /*
         * Tag del Log
         */

        private final static String LOG_TAG = "SimpleHttpClientTestActivity";
        /*
         * Identificativo della ProgressDialog di attesa
         */

        private final static int WAITING_PROGRESS_DIALOG_ID = 1;
        /*
         * Indirizzo del server a cui accedere
         */

        private final static String TARGET_URL = "http://mioserver.com:8080/home/file.jsp?parametro1=xxx&parametro2=xxx";
        /*
         * Riferimento all'Handler
         */

        private Handler myHandler;
        /*
         * Riferimento alla ProgressDialog
         */

        private ProgressDialog progressDialog;

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                // Otteniamo il riferimento alla TextView
                final TextView outputView = (TextView) findViewById(R.id.outputView);
                myHandler = new Handler() {

                        @Override
                        public void handleMessage(Message msg) {
                                // Estrapoliamo il messaggiodi testo dal msg
                                outputView.setText(msg.obj.toString());
                                Log.i(LOG_TAG, msg.obj.toString());
                        }

                };
        }

        /*
         * Incapsula a logica di invio della richiesta Http
         */

        public void sendHttpRequest(View button) {
                // Avviamo un Thread con il corrispondente codice di connessione
                Thread workerThread = new Thread(new Runnable() {

                        @Override
                        public void run() {
                                try {
                                        // Creiamo il riferimento al HttpClient
                                        HttpClient httpClient = new DefaultHttpClient();
                                        // Creiamo la HttpUriRequest relativamente al metodo GET
                                        HttpGet request = new HttpGet();
                                        // Impostiamo il valore dell'URI di destinazione
                                        URI targetUri = new URI(TARGET_URL);
                                        request.setURI(targetUri);
                                        // A questo punto invochiamo il server
                                        httpClient.execute(request, myResponseHandler);
                                } catch (Exception e) {
                                        showMessageOnOutput(e.getMessage());
                                        Log.e(LOG_TAG, e.getMessage());
                                } finally {
                                        dismissDialog(WAITING_PROGRESS_DIALOG_ID);
                                }

                        }

                });
                // Visualizziamo una Dialog di attesa
                showDialog(WAITING_PROGRESS_DIALOG_ID);                
                // Lo avviamo
                workerThread.start();
        }

        @Override
        protected Dialog onCreateDialog(int id) {
                switch (id) {
                case WAITING_PROGRESS_DIALOG_ID:
                        progressDialog = new ProgressDialog(this,
                                        ProgressDialog.STYLE_SPINNER);
                        progressDialog.setTitle("HTTP Connection");
                        progressDialog.setMessage("Connecting...");
                        progressDialog.setIndeterminate(true);
                        return progressDialog;
                default:
                        return null;
                }
        }

        /**
         * Invia un messaggio all'Handler relativo al MainThread per la sua
         * visualizzazione nella TextView di output
         *
         * @param message
         *            Messaggio da visualizzare
         */

        private void showMessageOnOutput(String message) {
                Message messageToSend = myHandler.obtainMessage();
                messageToSend.obj = message;
                myHandler.sendMessage(messageToSend);
        }

        private final ResponseHandler<String> myResponseHandler = new ResponseHandler<String>() {

                @Override
                public String handleResponse(HttpResponse response)
                                throws ClientProtocolException, IOException {
                        // Estraiamo il risultato dalla risposta. Otteniamo quindi il content
                        // da cui leggere le informazioni
                        InputStream content = response.getEntity().getContent();
                        byte[] buffer = new byte[1024];
                        int numRead = 0;
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        while((numRead=content.read(buffer))!=-1){
                                baos.write(buffer, 0, numRead);
                        }
                        // Chiudiamo lo stream
                        content.close();
                        // Otteniamo il risultato
                        String result = new String(baos.toByteArray());
                        showMessageOnOutput(result);
                       
                        return result;
                }

        };

}

Il codice chiaramente instaura un canale di comunicazione tra il client ed un server tramite protocollo HTTP, a cui passa dei parametri che saranno elaborati da una servlet;
il tutto funziona perfettamente, infatti premendo il pulsante la url viene passata al server.
Il passo successivo chiaramente è stato quello di automatizzare il processo, eliminando il pulsante ed inserendo un timer che ad ogni deltaT di tempo prestabilito, va ad innescare il metodo per l'invio dei dati. Di seguito posto il codice utilizzato:

Codice (Java): [Seleziona]
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.os.Looper;


public class SimpleHttpClientTestActivity extends Activity {
        /*
         * Tag del Log
         */

        private final static String LOG_TAG = "SimpleHttpClientTestActivity";
        /*
         * Identificativo della ProgressDialog di attesa
         */

        private final static int WAITING_PROGRESS_DIALOG_ID = 1;
        /*
         * Indirizzo del server a cui accedere
         */

        private final static String TARGET_URL = "http://mioserver.com:8080/home/file.jsp?parametro1=xxx&parametro2=xxx";
        /*
         * Riferimento all'Handler
         */

        private Handler myHandler;
        /*
         * Riferimento alla ProgressDialog
         */

        private ProgressDialog progressDialog;
               
        long startUp = 5000;     // millisecondi di attesa per fare partire il timer
    long periodo = 5000;     // millisecondi di attesa per la ripetizione del timer
   
    Timer timer = new Timer();      //istanziamo un'oggetto di tipo timer
   
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);         
               
        // Otteniamo il riferimento alla TextView
                final TextView outputView = (TextView) findViewById(R.id.outputView);
                myHandler = new Handler() {
                        @Override
                        public void handleMessage(Message msg) {
                                // Estrapoliamo il messaggiodi testo dal msg
                                outputView.setText(msg.obj.toString());
                                Log.i(LOG_TAG, msg.obj.toString());
                        }
                };
                               
                Log.i(LOG_TAG, "Chiamo il metodo timer!!" );
                metodTimer();
                Log.i(LOG_TAG, "Ritorno dal metodo timer!!" );
               
        }
               
        public void metodTimer(){
        //il metodo run viene eseguito ad ogni scadenza del timer
        timer.scheduleAtFixedRate(new TimerTask() {                                    
            public void run() {
                Looper.prepare();                               //////////////////////////new add
                Log.i(LOG_TAG, "Sono dentro il run del timer, chiamo sendHttpRequest()" );                
                sendHttpRequest();
                Log.i(LOG_TAG, "Sono dentro il run del timer, ritorno da sendHttpRequest()" );
                Looper.loop();                                  ///////////////////////////new add                
            }
        }, startUp, periodo);    
        }
       
        /*
         * Incapsula a logica di invio della richiesta Http
         */

        public void sendHttpRequest(){                                 
                // Avviamo un Thread con il corrispondente codice di connessione
                Thread workerThread = new Thread(new Runnable() {

                        @Override
                        public void run() {
                                try {
                                        // Creiamo il riferimento al HttpClient
                                        HttpClient httpClient = new DefaultHttpClient();
                                        // Creiamo la HttpUriRequest relativamente al metodo GET
                                        HttpGet request = new HttpGet();
                                        // Impostiamo il valore dell'URI di destinazione
                                        URI targetUri = new URI(TARGET_URL);
                                        request.setURI(targetUri);
                                        // A questo punto invochiamo il server
                                        httpClient.execute(request, myResponseHandler);
                                } catch (Exception e) {
                                        showMessageOnOutput(e.getMessage());
                                        Log.e(LOG_TAG, e.getMessage());
                                } finally {
                                        dismissDialog(WAITING_PROGRESS_DIALOG_ID);
                                }
                        }

                });
                // Visualizziamo una Dialog di attesa
                showDialog(WAITING_PROGRESS_DIALOG_ID);                
                // Lo avviamo
                workerThread.start();
        }

        @Override
        protected Dialog onCreateDialog(int id) {
                switch (id) {
                case WAITING_PROGRESS_DIALOG_ID:
                        progressDialog = new ProgressDialog(this,
                                        ProgressDialog.STYLE_SPINNER);
                        progressDialog.setTitle("HTTP Connection");
                        progressDialog.setMessage("Connecting...");
                        progressDialog.setIndeterminate(true);
                        return progressDialog;
                default:
                        return null;
                }
        }

        /**
         * Invia un messaggio all'Handler relativo al MainThread per la sua
         * visualizzazione nella TextView di output
         *
         * @param message
         *            Messaggio da visualizzare
         */

        private void showMessageOnOutput(String message) {
                Message messageToSend = myHandler.obtainMessage();
                messageToSend.obj = message;
                myHandler.sendMessage(messageToSend);
        }

        private final ResponseHandler<String> myResponseHandler = new ResponseHandler<String>() {

                @Override
                public String handleResponse(HttpResponse response)
                                throws ClientProtocolException, IOException {
                        // Estraiamo il risultato dalla risposta. Otteniamo quindi il content
                        // da cui leggere le informazioni
                        InputStream content = response.getEntity().getContent();
                        byte[] buffer = new byte[1024];
                        int numRead = 0;
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        while((numRead=content.read(buffer))!=-1){
                                baos.write(buffer, 0, numRead);
                        }
                        Chiudiamo lo stream
                        content.close();
                        Otteniamo il risultato (dopo che chiudo lo stream evito di visualizzare il responso
                        String result = new String(baos.toByteArray());
                        showMessageOnOutput(result);
                       
                        return result;
                }

        };

}
 
Chiaramente per ovvi motivi il deltaT inserito risulta di soli 5 secondi. Inizialmente ricevevo il seguente errore nel log:
Can't create handler inside thread that has not called Looper.prepare()
Leggendo varie cose, anche in questo forum, ho appurato che evitare il problema bisognava aggiungere Looper.prepare(); e Looper.loop();    
Dal codice si evince che ho inserito i due metodi all'interno del run del timer, il problema è che l'invio dei parametri avviene una sola volta, poi l'app rimane ferma, ovvero il timer non ripete il ciclo.  :-(
A questo punto mi chiedo se il problema deriva dal timer o da qualche altra cosa, o molto probabilmente dal layout stesso del codice; per semplicità ho escluso la parte che elabora i parametri da passare, inserendo una semplice url pre-compilata.
Sarei contento di ricevere qualsiasi aiuto! Grazie  ;-)
« Ultima modifica: 22 Aprile 2011, 11:47:00 CEST da Nikholas »

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Invio parametri tramite URL con un timer
« Risposta #1 il: 22 Aprile 2011, 12:02:19 CEST »
0
Continua ad usare l'Handler per l'invio ogni tot secondi usando il metodo sendMessageDelayed.

Offline Nikholas

  • Nuovo arrivato
  • *
  • Post: 4
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S
  • Sistema operativo:
    Ubuntu 11.04
Re:Invio parametri tramite URL con un timer
« Risposta #2 il: 22 Aprile 2011, 12:32:40 CEST »
0
Continua ad usare l'Handler per l'invio ogni tot secondi usando il metodo sendMessageDelayed.

Scusa l'ignoranza, purtroppo al mio stato attuale di conoscenza mi limito ad incollare parti di codice e a fare piccoli esperimenti; cerco di procedere per gradi!
Per prima cosa parto dal presupposto che per innescare l'invio devo chiamare in ogni caso il metodo sendHttpRequest(), giusto?
Con sendMessageDelayed a questo punto il timer va escluso? Vi sarei grato per un help!!
Eventualmente potete postare qualche esempio di codice o qualche link? Grazie!
Adesso cerco di capire come funziona sendMessageDelayed.
« Ultima modifica: 23 Aprile 2011, 11:25:28 CEST da Nikholas »

Offline Nikholas

  • Nuovo arrivato
  • *
  • Post: 4
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S
  • Sistema operativo:
    Ubuntu 11.04
Re:Invio parametri tramite URL con un timer
« Risposta #3 il: 25 Aprile 2011, 11:25:24 CEST »
0
Allora! Dopo aver trattato con molta attenzione l'argomento dei thread e dei relativi metodi handler() e Looper() per l'interazione tra il main e il worker thread, e dato che in questo caso non è strettamente necessario creare un canale di comunicazione tra i due thread, ho ottimizzato il codice togliendo la parte dell'handler e del sendmessage; in ogni caso il timer crea problemi, quindi come suggerito da un buon manuale di java conviene utilizzare un classico ciclo while con una sleep all'interno del workerthread. Probabilmente è uno dei pochi casi che richiede un uso "educato" della sleep, in quanto anche se l'esecuzione del thread si addormente momentaneamente, viene eseguito l'altro thread o il thread che ha maggiore priorità.
In ogni caso se potete suggerirmi altri metodi, sono ben lieto di ricevere consigli!!!

Offline MarcoDuff

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1073
  • Respect: +202
    • Google+
    • marcoduff
    • Mostra profilo
    • MarcoDuff's Blog
  • Dispositivo Android:
    Samsung Galaxy Nexus
  • Play Store ID:
    MarcoDuff
  • Sistema operativo:
    Windows 7
Re:Invio parametri tramite URL con un timer
« Risposta #4 il: 26 Aprile 2011, 13:45:37 CEST »
0
quindi come suggerito da un buon manuale di java conviene utilizzare un classico ciclo while con una sleep all'interno del workerthread.

IMHO un manuale java che ti consiglia un ciclo con uno sleep interno non è un buon manuale.

In ogni caso se potete suggerirmi altri metodi, sono ben lieto di ricevere consigli!!!

Si, usa sendMessageDelayed!  o_O

Offline Auron

  • Utente junior
  • **
  • Post: 104
  • Respect: +1
    • Mostra profilo
  • Dispositivo Android:
    Motorola Milestone Android 2.2.1
  • Sistema operativo:
    Windows
Re:Invio parametri tramite URL con un timer
« Risposta #5 il: 18 Maggio 2011, 01:16:45 CEST »
0
Potreste postarmi il file JSP per favore? sono alle prime armi con Android e non avendo il file JSP richiesto non posso effettuare nessun tipo di connessione.

Grazie in anticipo
È stata trovata una soluzione al tuo problema?Evidenzia il post più utile premendo . È un ottimo modo per ringraziare chi ti ha aiutato ;-)

Offline Essio

  • Nuovo arrivato
  • *
  • Post: 49
  • Respect: 0
    • alessiomorotti
    • Mostra profilo
  • Dispositivo Android:
    vodafone 848-SAMSUNG GALAXY Tab
  • Sistema operativo:
    Window Vista
Re:Invio parametri tramite URL con un timer
« Risposta #6 il: 16 Novembre 2011, 10:17:55 CET »
0
Ciao a tutti,

scusate se rispondo a questa pubblicazione dopo tanto tempo, ma dovendo affrontare un problema del tutto simile ho trovato la soluzione.
Timer e TimerTask , non sono ben gradite dalle applicazioni Android , a questo proposito leggete questo articolo :
http://cart.kolix.de/?p=1438
Per cui la soluzione a questo quesito è mediante l' utilizzo di un Handler:
Codice (Java): [Seleziona]
       private Handler handler = new Handler();
       handler.postDelayed(runnable, startUp)
     
        private Runnable runnable = new Runnable() {
                   @Override
                   public void run() {
                           
                           sendHttpRequest();
                     
                      handler.postDelayed(this, periodo);
                   }
        };
A tutti coloro può essere ancora utile...
Morotti Alessio