Android: выдергивание местоположения в обычных интервалах, сбой Looper Prepare (да, я искал !!) - PullRequest
3 голосов
/ 24 марта 2011

Я пытаюсь регулярно получать данные о местоположении и отправлять их по сети.Прежде чем сделать это, я чувствую, что важно убедиться, что я правильно вытягиваю место!Для этого я пытаюсь вытащить местоположение и отправить сообщение обработчику, который отображает его на экране.Я искал и использовал очень полезный сегмент кода при переполнении стека (большое спасибо!) Какой самый простой и надежный способ получить текущее местоположение пользователя на Android?

Вот какой-то код:

MyLocation (из примера):

package com.Locator;

import java.util.Timer;
import java.util.TimerTask;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class MyLocation {
Timer timer1;
LocationManager lm;
LocationResult locationResult;
boolean gps_enabled=false;
boolean network_enabled=false;

public boolean getLocation(Context context, LocationResult result)
{
    //I use LocationResult callback class to pass location value from MyLocation to user code.
    locationResult=result;
    if(lm==null)
        lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    //exceptions will be thrown if provider is not permitted.
    try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
    try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}

    //don't start listeners if no provider is enabled
    if(!gps_enabled && !network_enabled)
        return false;

    if(gps_enabled)
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
    if(network_enabled)
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
    timer1=new Timer();
    timer1.schedule(new GetLastLocation(), 20000);
    return true;
}

LocationListener locationListenerGps = new LocationListener() {
    public void onLocationChanged(Location location) {
        timer1.cancel();
        locationResult.gotLocation(location);
        lm.removeUpdates(this);
        lm.removeUpdates(locationListenerNetwork);
    }
    public void onProviderDisabled(String provider) {}
    public void onProviderEnabled(String provider) {}
    public void onStatusChanged(String provider, int status, Bundle extras) {}
};

LocationListener locationListenerNetwork = new LocationListener() {
    public void onLocationChanged(Location location) {
        timer1.cancel();
        locationResult.gotLocation(location);
        lm.removeUpdates(this);
        lm.removeUpdates(locationListenerGps);
    }
    public void onProviderDisabled(String provider) {}
    public void onProviderEnabled(String provider) {}
    public void onStatusChanged(String provider, int status, Bundle extras) {}
};

class GetLastLocation extends TimerTask {
    @Override
    public void run() {
         lm.removeUpdates(locationListenerGps);
         lm.removeUpdates(locationListenerNetwork);

         Location net_loc=null, gps_loc=null;
         if(gps_enabled)
             gps_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
         if(network_enabled)
             net_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

         //if there are both values use the latest one
         if(gps_loc!=null && net_loc!=null){
             if(gps_loc.getTime()>net_loc.getTime())
                 locationResult.gotLocation(gps_loc);
             else
                 locationResult.gotLocation(net_loc);
             return;
         }

         if(gps_loc!=null){
             locationResult.gotLocation(gps_loc);
             return;
         }
         if(net_loc!=null){
             locationResult.gotLocation(net_loc);
             return;
         }
         locationResult.gotLocation(null);
    }
}

public static abstract class LocationResult{
    public abstract void gotLocation(Location location);
}
}

Теперь, когда я так его использую, он работает нормально (ниже приведен код в классе активности Main):

    MyLocation myLocation = new MyLocation();



    LocationResult locationResult = new LocationResult(){
        @Override
        public void gotLocation(final Location location){
           Message m = new Message();
           m.obj = location.getLongitude() + " " + location.getLattitude();
           threadHandler.sendMessage(m);
        }
    };

Однако я хочу делать это через регулярные промежутки времени, поэтому у меня есть что-то вроде этого (следующий код находится в основном классе активности, на этот раз реализующий Runnable):

....
new Thread(this).start();
....

public void run() {
    MyLocation myLocation = new MyLocation();



    LocationResult locationResult = new LocationResult(){
        @Override
        public void gotLocation(final Location location){
           Message m = new Message();
           m.obj = "SDFSDF";
           threadHandler.sendMessage(m);
        }
    };

    while(true) {

        myLocation.getLocation(this, locationResult);
        try {
        Thread.sleep(30000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
      }
}
}

ПРИМЕЧАНИЕ: threadHandler имеет тип MyHandler, как определено:

class MyHandler extends Handler{

private TextView threadModifiedText;
public MyHandler(TextView tv) {
    threadModifiedText = tv;
}

 public void handleMessage(Message msg) {
        // whenever the Thread notifies this handler we have
        // only this behavior
        threadModifiedText.setText((CharSequence)msg.obj);
 }
}

Я получаю ошибки о записи в обработчик из потока, который не вызвал Looper.prepare ().Я пытался добавить Looper.prepare () и Looper.loop () в различные части моей деятельности и потока безрезультатно.Я попытался использовать таймер вместо run () + sleep ().

Позже вместо записи в обработчик потока я собираюсь вставить местоположение в очередь.Другой поток, который обрабатывает сокетные соединения, проверит пустоту очереди.Если у него есть элемент, он удалит его из очереди () и отправит.

Пожалуйста, дайте мне совет.

1 Ответ

1 голос
/ 10 декабря 2011

На всякий случай вы не узнали. Цикл должен быть вне времени, и вы должны повторно инициализировать myLocation перед каждым новым вызовом. Однако в этом случае таймер в классе MyLocation не позволит этому сработать. Так что, если вы удалите часть getLastLocation, она должна нормально работать в вашем сервисе. Я предполагаю, что если вы хотите отправлять местоположения на регулярной основе, вы, скорее, хотите быть точным, и вам все равно, займет ли это еще 30 секунд, так что в любом случае это неплохой подход. Однако вы можете захотеть что-то сделать (открыть префы), если возникают исключения, когда gps и сеть не включены

Удачи.

Looper.prepare();   

while(true) {
    myLocation = new MyLocatiom()
    myLocation.getLocation(this, locationResult);
    try {Thread.sleep(30000);} catch (InterruptedException e) {}

Looper.loop()
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...