[英]How to periodically update the location to Firebase Realtime database?
[英]receiving location update periodically
我正在编写一个应用程序,每5秒获取一次位置。 我收到此错误。 java.lang.RuntimeException:无法在尚未调用Looper.prepare()的线程内创建处理程序。 我已经搜索了此错误代码。 许多人说需要创建runOnUiThread()。 但是,即使我注释掉editTextShowLocation,这意味着在输出到ui时,也会发生相同的错误。
非常感谢您急需的帮助。 谢谢。
下面是我的代码:
package com.example.celine.telemetryloop;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
private EditText editTextShowLocation;
private Button buttonGetLocation;
private LocationManager locManager;
private LocationListener locListener = new MyLocationListener();
private boolean gps_enabled = false;
private boolean network_enabled = false;
String TAG = "App";
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextShowLocation = (EditText) findViewById(R.id.editTextShowLocation);
locManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
Thread rcvLocationThread = new Thread(new RcvLocation());
rcvLocationThread.start();
}
class RcvLocation implements Runnable {
public void run() {
try {
gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
}
// don't start listeners if no provider is enabled
if (!gps_enabled && !network_enabled) {
Log.d(TAG, "Not Enabled!"); //to enable it for user.
}
if (gps_enabled) {
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
}
if (network_enabled) {
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyLocationListener extends Handler implements LocationListener {
@Override
public void onLocationChanged(Location location) {
Log.d(TAG, "2");
if (location != null) {
// This needs to stop getting the location data and save the battery power.
//locManager.removeUpdates(locListener);
String londitude = "Londitude: " + location.getLongitude();
String latitude = "Latitude: " + location.getLatitude();
String altitiude = "Altitiude: " + location.getAltitude();
String accuracy = "Accuracy: " + location.getAccuracy();
String time = "Time: " + location.getTime();
editTextShowLocation.setText(londitude + "\n" + latitude + "\n" + altitiude + "\n" + accuracy + "\n" + time);
}
}
@Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
}
该错误实际上说明了该怎么做:尚未在线程内调用Looper.prepare()
。 请参阅此SO答案: https : //stackoverflow.com/a/16886486/798406
基本上说必须将Looper.prepare()
放在Runnable
的run()方法内。 但是,您应该避免使用Thread.sleep。 相反,您可以使用其他处理程序并在5秒后发布延迟的消息:
private class Poller implements Runnable {
/**
* {@inheritDoc}
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
// Do something
long pollingDelay = 5000;
mHandler.postDelayed(this, pollingDelay);
}
}
// Start the handler
mPollingRunnable = new Poller();
mHandler.post(mPollingRunnable);
首先,您错误地考虑了位置API-不需要每5秒轮询一次更新。 您告诉LocationManager您想听更新,并且每次发生更新时都会告诉您有关更新的信息。 如果您告诉它将更新限制为每5秒一次,它将忽略或延迟更新以满足您的要求,但是如果每隔五秒钟要求更新一次,则如果没有任何更新,则不会更频繁地为您提供更新。
其次,您编写的代码实际上不会每五秒钟执行任何操作。 您启动的Thread
仅注册更新,等待五秒钟,然后退出-没有循环发生。 幸运的是,除了不必要的额外线程和五秒钟的延迟外,这实际上是使用位置API的正确方法。
最后,对于您的实际问题:出现RuntimeException的原因是,您给LocationManager提供了一个LocationListener,并告诉它(在不经意间)在rcvLocationThread
上执行其回调方法。 Looper
是用作消息泵的类。 Looper
在Thread
之上运行,并执行Handler
赋予它们的工作。 Handler
在Looper
的顶部运行,并接收消息和/或Runnable
,并且Looper
通过Handler
的队列进行抽水并执行每个传入的项目。
如果在调用requestLocationUpdates
时未指定Looper
,则LocationManager假定您正在从 Looper
线程进行调用,并尝试使LocationListener
方法调用返回到同一线程。 由于您的线程上没有正在运行的Looper
(在这种情况下也不应该),因此它实际上无法使回调入队,并引发异常。
所以你会怎么做? 摆脱所有的Thread
废话了,把你已经得到了你的一切RcvLocation.run()
方法来代替你的new Thread(...).start()
在结束onCreate
。 此外,您MyLocationListener
类不需要扩展Handler
-只要有它实现LocationListener
,你会没事的。 回调将在主线程(已经有自己的Looper
)上执行。 这很好,因为您正在修改视图( 必须在主线程中完成),并且由于您不执行任何长时间运行的处理操作而显得很安全。
public class MainActivity extends Activity {
... // variables and such
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editTextShowLocation = (EditText) findViewById(R.id.editTextShowLocation);
locManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
setupLocationUpdates();
}
private void setupLocationUpdates() {
try {
gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) { /* tsk tsk, empty catch block */ }
try {
network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) { /* tsk tsk, empty catch block */ }
// don't start listeners if no provider is enabled
if (!gps_enabled && !network_enabled) {
Log.d(TAG, "Not Enabled!"); //to enable it for user.
}
if (gps_enabled) {
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
}
if (network_enabled) {
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
}
}
class MyLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
// do your stuff
}
// all the other required callback methods
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.