1. java
  2. android
  3. c#
  4. .net
  5. javascript
  6. php
  7. jquery
  8. html
  9. sql

Como implementar um serviço que rode em segundo plano

Prezados boa noite, estou implementando um serviço em um app android que deverá obter via GPS o seu location gravar no SQlite e em intervalos definidos enviar para um WS Soap, tudo isto em segundo plano e não pretendo atualizar a View

Para esta tarefa tenho um Alarm e uma classe Services que instancia uma classe Tracking tudo isto vemos com frequência em tutoriais na Web o que me fez recorrer ao site é que estou encontrando problemas ao chamar a classe Tracking ou melhor a classe que faz o controle do rastreamento eu recebo o seguinte erro

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

Minha pergunta é porque o erro? Então darei detalhes de como estou procedendo abaixo

TrackingController é uma classe que tem como atributo classe que implementam LocationListener

minha classe de serviço instancia a classe TrackingController no evento onCreate trackingController = new TrackingController(this)

como pretendo executar em segundo plano minha service tem uma Thread e é dentro do run que eu chamo o trackingController.start() o método start em algum momento ira chamar o locationManager.requestLocationUpdates(type, periodo, 0, this) e é neste momento que o erro ocorre quando passa por esta linha de código.

Sei que a classe service faz uso da Thread principal contudo estou criando uma nova Thread para fazer o trabalho em segundo plano segue o código abaixo

    @Override
    public void onCreate() {

        Log.i(TAG, "service create");

        this.context = this;
        this.isRunning = false;
        trackingController = new TrackingController(this);

        this.backgroundThread = new Thread(myTask);
    }

    private Runnable myTask = new Runnable() {

        public void run() {
         // Do something here
         trackingController.start();

         stopSelf();
        }

Segue conforme solicitado a classe de controle de rastreamento

public class TrackingController implements PositionProvider.PositionListener {

    private static final String TAG = TrackingController.class.getSimpleName();
    private Context context;
    private PositionProvider positionProvider;
    private boolean isOnline;
    private DAOPosicao dao;

    public TrackingController(Context context) {
        this.context = context;
        positionProvider = new SimplePositionProvider(context, this);
        dao = new DAOPosicao(context);
        isOnline = true;
    }

    @Override
    public void onPositionUpdate(Posicao position) {

        if (position != null) {
            write(position);
        }
    }

    public void start() {
        if (isOnline) {
            read();
        }
        try {
            positionProvider.startUpdates();
        } catch (SecurityException e) {
            Log.w(TAG, e);
        }
    }

    public void stop() {
        try {
            positionProvider.stopUpdates();
        } catch (SecurityException e) {
            Log.w(TAG, e);
        }
    }

    private void read() {
        // Ler o banco select * from posicao
    }

    // Fluxo 
    // gravar -> ler -> enviar -> deletar -> ler

    private void log(String action, Posicao position) {
        if (position != null) {
            action += " (" +
                    "id:" + position.getId() +
                    " time:" + position.getTime().getTime() / 1000 +
                    " lat:" + position.getLatitude() +
                    " lon:" + position.getLongitude() + ")";
        }
        Log.d(TAG, action);
    }

    private void write(Posicao position) {
        // Grava no banco Insert Into position.....
    }

    private void delete(Posicao position) {
        log("delete", position);
    }

    private void send(final Posicao position) {
        // Enviar para o servidor e deletar se conseguir
    }
}

Não estou conseguindo corrigir ou achar o erro se alguém puder dar alguma dica agradeço.

Refiz a classe de serviço mesmo assim o erro ainda ocorreu vou expor os métodos principais abaixo

@Override
    public void onCreate() {
        Log.i(TAG, "service create");
        this.context = this;
        this.backgroundThread = new Thread(myTask);
    }

    private Runnable myTask = new Runnable() {
        public void run() {
            lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

            final String PROVIDER = lm.GPS_PROVIDER;

            MyLocationListener myLocationListener = new MyLocationListener();
            lm.requestLocationUpdates(PROVIDER, 300 * 1000, 0, myLocationListener);
            Log.d("LOC_SERVICE", "Service RUNNING!");
            stopSelf();
        }
    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if(!this.isRunning) {
            this.isRunning = true;
            this.backgroundThread.start();
        }
        stopSelf();
        return START_STICKY;
    }
`

Vejam que agora toda implementação para obter as coordenadas estão dentro do método run da Thread mais da mesma forma ao passar pelo requestLocationUpdates da classe LocationManager o erro ocorre.

  • Pode postar a classe TrackingController?

    A H Gusukuma   09 de mai de 2016
  • Olá Boa noite! vou editar e colocar a classe no topico

    rlira   09 de mai de 2016
  • Olá, infelizmente o problema deve estar em outra classe, talvez na SimplePositionProvider ou no PositionProvider.

    A H Gusukuma   10 de mai de 2016
  • Olá H Gusokuma, então se eu removo a Thread e chamo trackingController do serviço o erro não ocorre só que preciso que o processo ocorra em segundo plano, com ela o erro ocorre.

    rlira   10 de mai de 2016
  • Verifica se existe um "new Handler()" nessas classes.

    A H Gusukuma   10 de mai de 2016
Mostrar todos os 8 comentários>
  1. Você vai ver essas setas em qualquer página de pergunta. Com elas, você pode dizer se uma pergunta ou uma resposta foram relevantes ou não.
  2. Edite sua pergunta ou resposta caso queira alterar ou adicionar detalhes.
  3. Caso haja alguma dúvida sobre a pergunta, adicione um comentário. O espaço de respostas deve ser utilizado apenas para responder a pergunta.
  4. Se o autor da pergunta marcar uma resposta como solucionada, esta marca aparecerá.
  5. Clique aqui para mais detalhes sobre o funcionamento do GUJ!

2 respostas

Não é a resposta que estava procurando? Procure outras perguntas com as tags android java ou faça a sua própria pergunta.