使用来自JNI的Android的LocationManager.addGpsStatusListener不会导致任何事情发生

时间:2013-11-26 10:42:48

标签: java android gps

我有一个奇怪的问题,我很难理解。我可以使用LocationManager及其requestLocationUpdates方法来接收位置更新。我有一个实现LocationListener的简单类:

  public class PrisLocationListener implements LocationListener
  {
     @Override
     public void onLocationChanged(Location location)
     { ... }

     @Override
     public void onStatusChanged(String provider, int status, Bundle extras)
     { ... }

     @Override
     public void onProviderEnabled(String provider)
     { ... }

     @Override
     public void onProviderDisabled(String provider)
     { ... }
  }

我在Activity中使用此类,为它创建一个单独的线程:

    // create seperate thread for location callbacks
    mPrisLocationListener = new PrisLocationListener();
    mLocationHandlerThread = new HandlerThread("LocationHandlerThread");
    mLocationHandlerThread.start();

然后将其传递给LocationManager:

    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,
                                            mPrisLocationListener,
                                            mLocationHandlerThread.getLooper());

以上按预期工作,我可以获得设备的GPS位置。

我还想要GPS状态信息(卫星计数,TTFF等),所以我创建了另一个实现GpsStatus.Listener的类:

  public class PrisGpsListener implements GpsStatus.Listener
  {
     @Override
     public void onGpsStatusChanged(int event)
     { ... }
  }

当我尝试使用上述课程时,麻烦就开始了。在我的Activity和LocationListener的同一点,我初始化GpsListener的一个实例并将其传递给LocationManager:

    mPrisGpsListener = new PrisGpsListener();
    if(!mLocationManager.addGpsStatusListener(mPrisGpsListener))   {
       Log.i("Activity: ","addGpsStatusListener failed"); // doesn't fail, addGpsStatusListener returns true
    }
    // LocationManager.requestLocationUpdates called after addGpsStatusListener

问题是,如果我添加' addGpsStatusListener'调用我的代码,没有任何关于位置服务的事情。也就是说,我不仅没有从GpsListener获得任何状态更新,而且我也不能获得正常的位置更新。当调用相关函数时,Logcat根本没有向我显示任何内容。

奇怪的是requestLocationUpdates本身工作正常,但调用addGpsStatusListener使混乱失败。我不知道在这里尝试什么,所以任何建议都会受到赞赏。


编辑:

正如Rafael指出的那样,当从Activity :: onCreate()调用时,所有这一切都可以正常工作......但是,(这应该是我提到的第一件事之一),那里有一个单独的函数main调用上述LocationManager方法并实例化相关对象的Activity。 我从本机代码通过JNI

调用该方法

在创建Activity之后的某个时间使用JNI调用该方法。

2 个答案:

答案 0 :(得分:1)

刚试过这个:

public class TestActivity extends Activity {

private LocationManager mLocationManager;
private PrisLocationListener mLocationListener;
private PrisGpsListener mGpsListener;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);

    PrisLocationListener locationListener = new PrisLocationListener();
    HandlerThread t = new HandlerThread("LocationHandlerThread");
    t.start();

    mLocationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener, t.getLooper());

    mGpsListener = new PrisGpsListener();
    mLocationManager.addGpsStatusListener(mGpsListener);

}

@Override
protected void onPause() {
    super.onPause();
    mLocationManager.removeUpdates(mLocationListener);
    mLocationManager.removeGpsStatusListener(mGpsListener);
}

public static class PrisLocationListener implements LocationListener{

    private static final String TAG = PrisLocationListener.class.getSimpleName();

    @Override
    public void onLocationChanged(Location arg0) {
        Log.d(TAG, "onLocationChanged: loc=" + arg0);
    }

    @Override
    public void onProviderDisabled(String provider) {
        Log.d(TAG, "onProviderDisabled: provider=" + provider);

    }

    @Override
    public void onProviderEnabled(String provider) {
        Log.d(TAG, "onProviderEnabled: provider=" + provider);
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        Log.d(TAG, "onStatusChanged: provider=" + provider + ", status=" + status + ", extras=" + extras);
    }

}

public static class PrisGpsListener implements GpsStatus.Listener{

    private static final String TAG = PrisGpsListener.class.getSimpleName();

    @Override
    public void onGpsStatusChanged(int event) {
        Log.d(TAG, "onGpsStatusChanged: event=" + event);
    }

}

}

我的日志输出

  

11-26 12:03:58.707:D / PrisGpsListener(24412):onGpsStatusChanged:event = 1   11-26 12:04:00.199:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:01.199:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:02.199:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:03.207:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:04.207:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:05.199:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:06.199:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:07.191:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:08.207:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:09.215:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:10.207:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:11.207:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:12.207:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:13.215:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:14.223:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4   11-26 12:04:15.223:D / PrisGpsListener(24412):onGpsStatusChanged:event = 4

所以GpsStatus.Listener实际上正在发挥作用。如果移动手机,我想你会收到位置修复。

答案 1 :(得分:0)

似乎我需要从主线程调用LocationManager.addGpsStatusListener(...)。使用Runnable封闭调用可以解决问题:

 public void someFunctionCalledWithJNI()
 {
    this.runOnUiThread(new Runnable()   {
       public void run()   {
          if(!mLocationManager.addGpsStatusListener(mPrisGpsListener))   {
             Log.i("Activity: ","addGpsStatusListener failed");
          }
       }
    });
 }

同样的事情适用于LocationManager.requestLocationUpdates,但会抛出一个异常,明确告诉你:“无法在未调用Looper.prepare()的线程内创建Handler”,所以我为它创建了一个单独的HandlerThread

您也可以将两者都放在主线程上:

 public void someFunctionCalledWithJNI()
 {
    this.runOnUiThread(new Runnable()   {
       public void run()   {
          if(!mLocationManager.addGpsStatusListener(mPrisGpsListener))   {
             Log.i("Activity: ","addGpsStatusListener failed");
          }
          mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,mPrisLocationListener); 
       }
    });
 }