【问题标题】:Using LocationManager.addGpsStatusListener with Android from JNI causes nothing to happen将 LocationManager.addGpsStatusListener 与来自 JNI 的 Android 一起使用不会导致任何事情发生
【发布时间】:2013-11-26 10:42:47
【问题描述】:

我有一个奇怪的问题,我无法理解。我可以使用 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() 调用时,所有这些都可以正常工作......但是,(这应该是我首先提到的事情之一),在我的主 Activity 中有一个单独的函数调用上述 LocationManager 方法并实例化相关对象。 我通过 JNI 从本机代码调用方法

在创建 Activity 一段时间后使用 JNI 调用该方法。

【问题讨论】:

  • 呃,抱歉,我自己从未与 JNI 合作过。如果您不将 WorkerThread 的循环器传递给 LocationUpdates,您可以尝试是否有任何不同。还要使这个方法真正被调用的舒尔(即使用日志)。但是,您还应该包含您的 C 代码以供下一个阅读。也许您的错误是在您的本机代码中完成的。
  • 原来是线程问题。我已经在自己的回答中解释了我的理解。

标签: java android gps


【解决方案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 确实有效。我想如果您移动手机,您将收到位置修复。

【讨论】:

  • 我意识到它也适用于我在 onCreate() 中调用的方法。请查看我更新的问题...抱歉没有提及其他详细信息(在我尝试了您的代码之前,我认为它们不相关)。
【解决方案2】:

看来我需要从主线程调用 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); 
       }
    });
 }

【讨论】:

  • 很好,也许它可以帮助其他读者解决同样的问题。总是最好自己找到问题。
猜你喜欢
  • 2017-06-15
  • 1970-01-01
  • 2019-08-04
  • 2020-04-19
  • 2011-09-19
  • 2019-09-19
  • 2014-01-28
  • 2019-08-18
  • 1970-01-01
相关资源
最近更新 更多