Pregunta

Con el fin de obtener los datos XML desde un servidor en varias ocasiones, Estoy intentando utilizar AsyncTask y el temporizador de acuerdo de la marca Murphy sugerencia .

Me sale el siguiente error:

01-07 16:11:26.705: ERROR/AndroidRuntime(729): 
Caused by: java.lang.RuntimeException: 
Can't create handler inside thread that has not 
called Looper.prepare()

Estoy usando SDK 1.5 con Eclipse en Windows.

He mirado en la documentación, en StackOverflow y en el grupo de desarrolladores de Android, pero no me queda claro cuál es la causa del error o cómo solucionarlo.

puedo conseguir los datos una vez - es decir, sin asíncrono y temporizador - y analizarlo a través de SAX sin problemas

.

código de la aplicación completa a continuación.

Por favor, disculpe los errores ingenuos: Soy bastante nuevo en Android

.
package com.foo.bar.myactivity;

import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;

public class MyActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        Timer timer;
        timer = new Timer();
        timer.schedule(new MyTimerTask(), 0, 1000); 
    }

    public class MyAsyncTask extends AsyncTask<String, Integer, MyData> {
        protected MyData doInBackground(String... string) {
            MyData myData = new MyData();
            try {
                URL url = new URL("http://www.example.com/my.xml");
                SAXParserFactory spf = SAXParserFactory.newInstance();
                SAXParser sp = spf.newSAXParser();

                XMLReader xr = sp.getXMLReader();

                MyHandler myHandler = new MyHandler();
                xr.setContentHandler(myHandler);

                System.setProperty("http.proxyHost", "www-cache.example.com");
                System.setProperty("http.proxyPort", "80");

                xr.parse(new InputSource(url.openStream()));

                myData = myHandler.getParsedData();
                return myData;

            } catch (Exception e) {
                Log.e(">>>>>>>>>>>> Error getting myData: ", e.getMessage(), e);
                return myData;
            }

        }

        protected void onProgressUpdate(Integer... progress) {
            // setProgressPercent(progress[0]);
        }

        protected void onPostExecute(MyData myData) {
            Log.d(">>>>>>>>>>>>>My data: ", myData.toString());
        }
    }

    public class MyTimerTask extends TimerTask {
        public void run() {
            try {
                new MyAsyncTask().execute("");
            } catch (Exception e) {
                Log.e(">>>>>>>>>>>> Error executing MyAsyncTask: ", e.getMessage(), e);
            }
        }
    }

}
¿Fue útil?

Solución

El problema está en el uso de TimerTask. TimerTask plazo debe publicar a un manipulador, algo como esto:

private Handler mHandler = new Handler(); 

public class MyTimerTask extends TimerTask {
    public void run() {
        mHandler.post(
            new Runnable() { 
                public void run() { 
                    new MyAsyncTask().execute("");
                } 
            };     
        )
    }
}

Por supuesto, esto se está poniendo un poco feo, así que recomiendo sacar la clase anónima.

Otros consejos

Tengo que esto funcione gracias a la respuesta de James.

He incluido el código de abajo en caso de que sea útil para cualquier persona.

desarrollador Advertencia! El código funciona para mí, pero puede contener errores.

package com.example.test;

import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

public class MyXmlPoller extends Activity {

    private Handler handler = new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        new Timer().schedule(new MyTimerTask(), 0, 1000);
    }

    private class MyAsyncTask extends AsyncTask<Integer, Integer, MyData> {

        protected MyData doInBackground(Integer... counter) {
            MyData myData = new MyData();

            try {
                URL url = new URL("http://www.example.com/my.xml");
                SAXParserFactory spf = SAXParserFactory.newInstance();
                SAXParser sp = spf.newSAXParser();

                XMLReader xr = sp.getXMLReader();

                MySAXHandler mySAXHandler = new Handler();
                xr.setContentHandler(mySAXHandler);

                xr.parse(new InputSource(url.openStream()));

                myData = mySAXHandler.getParsedData();

                return myData;

            } catch (Exception e) {
                Log.e("!!!!!!!!!! MyAsyncTask doInBackground error", e.getMessage(), e);
                return myData;
            }

        }

        protected void onPostExecute(MyData myData) {
            Log.d("+++++++++++++ MyAsyncTask onPostExecute", myData.toString());
        }
    } // MyAsyncTask

    public class MyTimerTask extends TimerTask {
        private Runnable runnable = new Runnable() {
            public void run() {
                new MyAsyncTask().execute();
            }
        };

        public void run() {
            handler.post(runnable);
        }
    }
}

El problema parece ser que no ha llamado Looper.prepare(). Usted podría tener un vistazo a la documentación de la noreferrer"> Handler necesita un bucle de mensajes en para procesar mensajes y un hilo por defecto no tiene uno.

Parece que AsyncTask utiliza un Handler internamente por lo que añadir Looper.prepare() en la parte superior de su método de run() en MyTimerTask y que debe resolver su problema

Me gustaría utilizar el servicio con el gerente de alarma

   I    Intent updateIntent = new Intent(ACTION_UPDATE_ALL);
        updateIntent.setClass(this, UpdateService.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 0, updateIntent, 0);
        AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC, nextUpdate, pendingIntent);

El problema es que no puede crear el objeto Handler en el hilo que doInBackground () se ejecuta. Me volvería a poner en práctica el método OnPreExecute () y poner su código de configuración en ese país. Trate de mover estas líneas en el OnPreExecute () método:

            URL url = new URL("http://www.example.com/my.xml");
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();

            XMLReader xr = sp.getXMLReader();

            MyHandler myHandler = new MyHandler();
            xr.setContentHandler(myHandler);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top