2013-02-22 49 views
1

我从服务启动的线程请求位置更新时遇到问题。从服务中访问android位置?

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

  1. 它具有由启动接收器启动的服务。
  2. 在服务的onStartCommand()中,它启动一个调度程序线程。
  3. 调度程序线程请求位置更新。

问题是,当调度呼叫locationMgr.requestLocationUpdates() 它说:Can't create handler inside thread that has not called Looper.prepare() 我已经看到了其他类似的问题,但无法找到任何解决方案。我听说我们可以直接从服务调用获取位置更新没有任何问题,但因为我无法找到睡眠服务的方式(如调度程序线程),我想我需要一个单独的线程。

请解释为什么会发生这种情况? android是否需要UI线程来请求位置?有改变我的应用程序结构的解决方案吗?

回答

1

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

分辨率为您的问题:

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

2

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

As mentioned in the example:

类。线程默认为 没有与它们相关的消息循环;创建一个,在要运行循环的线程中调用 prepare(),然后循环()到 让它处理消息,直到循环停止。

现在,RequestLocationUpdates()需要某种机制来提供更新你的线程,但你的线程没有Looper投票。

考虑将RequestLocationUpdates()及其对应的removeUpdates()设置为服务线程。最有可能在服务启动和停止的地方。

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); 

    } 

Location类在这里:

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); 
    } 

} 

我在常量使用这些变量类来存储位置 公共静态双mLatitude = 0.0,mLongitude = 0.0;

启动服务 startService(新意图(这一点,MyService.class));

0

我已经用处理程序固定它。

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