从服务访问android位置?

时间:2013-02-22 12:15:28

标签: android android-service android-location

我遇到了从服务启动的线程请求位置更新的问题。

我的应用程序需要从后台服务获取位置更新(没有任何UI线程)。我将解释我的申请结构。

  1. 它有一个由Boot Receiver启动的服务。
  2. onStartCommand()服务中,它启动一个调度程序线程。
  3. 调度程序线程请求位置更新。
  4. 问题是调度程序调用{​​{1}}时 它说locationMgr.requestLocationUpdates() 我已经看到其他人遇到类似的问题,但无法找到任何解决方案。我听说我们可以直接从服务中调用以获得位置更新而没有任何问题,但由于我无法找到一种睡眠服务的方式(如调度程序线程),我想我需要一个单独的线程。

    请解释为什么会这样? android是否需要UI线程来请求位置?通过改变我的应用程序结构有没有解决方案?

4 个答案:

答案 0 :(得分:2)

Looper是轮询Message的/ Runnable(通过该线程上的Handler发布的线程队列)的线程队列的原因。 UI线程默认有一个。对于自定义线程,您需要在启动线程之前进行设置。

As mentioned in the example:

  

用于为线程运行消息循环的类。默认情况下的线程   没有与之关联的消息循环;创建一个,打电话   prepare()在运行循环的线程中,然后循环()到   让它处理消息,直到循环停止。

现在,RequestLocationUpdates()需要一种机制来为您的线程提供更新,但您的线程没有Looper轮询。

考虑将RequestLocationUpdates()及其相应的removeUpdates()移至服务主题。很可能是服务开始和停止的地方。

答案 1 :(得分:1)

发生的原因是:getLooper连接到上下文的UI,但服务是ackground进程不直接连接到UI。所以你得到了错误。

您的问题的解决方案:

1)将位置类放在其他包中。 2)导入该包名称。 3)在包中使用一个回调接口。 4)使用Service组件中的接口实例。 5)它会工作!!

答案 2 :(得分:1)

我已经用过这个并且工作正常:获取服务中的位置

此处的服务类:

public class MyService extends Service {

    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();

    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        super.onStart(intent, startId);

        // start location manager
        LocationDetermined objLocationDetemined = new LocationDetermined(this);
        objLocationDetemined.getlocation(this);
        objLocationDetemined.getRecentKnownLocation(this);

    }

位置类:

public class LocationDetermined implements OnInitListener {

    String TAG = "LocationDeterminedClass";
private static LocationManager locationManager;
double Lat = 0.0;
double Long = 0.0;
GeoPoint geoPoint;
private Toast mToast;
Context appContext;
static MyLocationListener locationListener;

    public LocationDetermined(Context context) {
        this.appContext = context;

    }

    public MyLocationListener getlocation(Context appContext) {

        locationManager = (LocationManager) appContext
                .getSystemService(Context.LOCATION_SERVICE);
        locationListener = new MyLocationListener();
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
        String provider = locationManager.getBestProvider(criteria, true);

        Log.d(TAG, "------provider------" + provider);


        if (provider != null && locationManager.isProviderEnabled(provider)) {
            locationManager.requestLocationUpdates(provider, 0, 0,
                    locationListener);
        } else {
            Toast.makeText(appContext, "No provider available to get loctaion",
                    2000).show();
        }
        return locationListener;
    }



    private class MyLocationListener implements LocationListener {

        public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub

        }

        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub

        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO Auto-generated method stub

        }

        public void onLocationChanged(final Location argLocation) {
            // TODO Auto-generated method stub
            if (argLocation != null) {
                Lat = argLocation.getLatitude();
                Long = argLocation.getLongitude();

                Log.e("OnLocationChanged:", "lat:" + Lat + "  long:" + Long);

                Log.d("service gps", "lat" + argLocation.getLatitude() + "-"
                        + argLocation.getLongitude());

                Constant.mLatitude = argLocation.getLatitude();
                Constant.mLongitude = argLocation.getLongitude();               
            }
        }
    }

    public GeoPoint getRecentKnownLocation(Context appContext) {
        Location locGps = locationManager
                .getLastKnownLocation(LocationManager.GPS_PROVIDER);
        Location locNet = locationManager
                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

        Location locPassive = locationManager
                .getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
        if (locGps != null) {
            Lat = locGps.getLatitude();
            Long = locGps.getLongitude();

            Constant.mLatitude = locGps.getLatitude();
            Constant.mLongitude = locGps.getLongitude();

            geoPoint = new GeoPoint((int) (Lat * 1000000),
                    (int) (Long * 1000000));
            return geoPoint;

        } else if (locNet != null) {
            Lat = locNet.getLatitude();
            Long = locNet.getLongitude();

            Constant.mLatitude = locNet.getLatitude();
            Constant.mLongitude = locNet.getLongitude();

            geoPoint = new GeoPoint((int) (Lat * 1000000),
                    (int) (Long * 1000000));
            return geoPoint;

        }
        return geoPoint;
    }

    private void fetchedSavedLocationDetail(Context mContext) {

    }

    @Override
    public void onInit(int status) {
        // TODO Auto-generated method stub

    }

    public static void removeLocationListener() {

        locationManager.removeUpdates(locationListener);
    }

}

我在Constants类中使用这些变量来存储位置 public static double mLatitude = 0.0,mLongitude = 0.0;

启动服务 startService(new Intent(this,MyService.class));

答案 3 :(得分:0)

我已经使用处理程序修复了它。

  1. 我创建了一个处理程序。
  2. 我将服务代码放在handleMessage()
  3. 创建一个线程,以所需的时间间隔(while循环)向处理程序发送空消息。
  4. 因此,当处理程序收到空消息时,它会运行包含实际调度程序循环的handleMessage()