繁体   English   中英

定期接收位置更新

[英]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是用作消息泵的类。 LooperThread之上运行,并执行Handler赋予它们的工作。 HandlerLooper的顶部运行,并接收消息和/或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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM