Android:requestLocationUpdates 抛出异常

发布于 2024-11-28 07:23:02 字数 6074 浏览 1 评论 0原文

我试图通过 Android 中的 GPS 定期获取用户位置并将数据发送到远程数据库,但出现异常: Can't create handler inside thread that has not Called Looper.prepare().

检索位置的方法位于远程服务中,并且非常基本:

private void dumpLocationLog() {
        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Looper.myLooper().prepare();
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,this);
        retrieveUserId();
        sendData(user_id);
    }

我尝试调用 Looper.myLooper().prepare(); ,但它仍然不起作用。 我想我必须在这里实现一个 Looper,但我不知道如何实现,因为我还是 Android 新手。

这是我的服务的完整代码:

public class LocationLoggingService extends Service {
    String latString, lngString;
    Double latitude, longitude;
    Date durationDate;
    String user_id;
    public String username;

    private Handler serviceHandler;
    private Task myTask = new Task();

    @Override
    public IBinder onBind(Intent i) {
        Log.d(getClass().getSimpleName(), "onBind()");
        username = i.getStringExtra("username");
        return myRemoteLocationServiceStub;
    }

    private IMyRemoteLocationLoggingService.Stub myRemoteLocationServiceStub = new IMyRemoteLocationLoggingService.Stub() {
        public void dumpLocationLog() throws RemoteException {
            LocationLoggingService.this.dumpLocationLog();
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(getClass().getSimpleName(), "onCreate()");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        serviceHandler.removeCallbacks(myTask);
        serviceHandler = null;
        Log.d(getClass().getSimpleName(), "onDestroy()");
    }

    @Override
    public void onStart(Intent intent, int startId) {
        username = intent.getStringExtra("username");
        super.onStart(intent, startId);
        serviceHandler = new Handler();
        serviceHandler.postDelayed(myTask, 1000L);
        Log.d(getClass().getSimpleName(), "onStart()");
    }

    class Task implements Runnable {
        public void run() {
            try {
                myRemoteLocationServiceStub.dumpLocationLog();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            serviceHandler.postDelayed(this, 5000L);
            Log.i(getClass().getSimpleName(), "Calling the dumpLocationLog");
        }
    }

    public void retrieveUserId() {
        ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
        postParameters.add(new BasicNameValuePair("username", username));
        String response = null;
        try {
            response = CustomHttpClient.executeHttpPost(
                    "http://10.0.2.2/science/getUserId.php", postParameters);
            String res = response.toString();
            res = res.replaceAll("\\s+", "");
            if (!res.equals("0")) {
                Log.d(getClass().getSimpleName(),
                        "Successfully retrieved user_id");
                user_id = res;
            } else {
                Log.d(getClass().getSimpleName(), "Error retrieving user_id");
            }
        } catch (Exception e) {
        }
    }

    private void sendData(String user_id) {
        ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
        postParameters.add(new BasicNameValuePair("user_id", user_id));
        postParameters.add(new BasicNameValuePair("latitude", latString));
        postParameters.add(new BasicNameValuePair("longitude", lngString));
        String response = null;
        try {
            response = CustomHttpClient.executeHttpPost(
                    "http://10.0.2.2/science/sendLocationData.php",
                    postParameters);
            String res = response.toString();
            res = res.replaceAll("\\s+", "");
            if (res.equals("1")) {
                Log.d(getClass().getSimpleName(), "Insertado en DB!");
            } else {
                Log.d(getClass().getSimpleName(), "Error insertando en la DB");
            }
        } catch (Exception e) {
        }
    }

    LocationListener myLocationListener = new LocationListener () {
        @Override
        public void onLocationChanged(Location location) {
            if (location != null) {
                android.os.Debug.waitForDebugger();
                latitude = location.getLatitude();
                longitude = location.getLongitude();
                latString = Double.toString(latitude);
                lngString = Double.toString(longitude);
                Log.d("Location: ", getClass().getSimpleName());
                Log.d(latString, getClass().getSimpleName());
                Log.d(lngString, getClass().getSimpleName());
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

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

        }
    };

    private void dumpLocationLog() {
        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, myLocationListener);
        retrieveUserId();
        sendData(user_id);
    }

    public static String create_datestring(String timestring)
            throws java.text.ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
                Locale.US);
        Date dt = null;
        Calendar c = Calendar.getInstance();
        try {
            dt = sdf.parse("2011-03-01 17:55:15");
            c.setTime(dt);
            System.out.println(c.getTimeInMillis());
            System.out.println(dt.toString());
        } catch (ParseException e) {
            System.err.println("There's an error in the Date!");
        }
        return dt.toString();
    }
}

非常感谢!

I'm trying to get periodically the user position via GPS in Android and send the data to a remote DB, but I get the exception: Can't create handler inside thread that has not called Looper.prepare().

The method that retrieves the position is in a remote service, and it's pretty basic:

private void dumpLocationLog() {
        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        Looper.myLooper().prepare();
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,this);
        retrieveUserId();
        sendData(user_id);
    }

I tried calling Looper.myLooper().prepare(); but it still does not work.
I guess I have to implement a Looper here but I don't know how as I'm still pretty newbie with Android.

This is the full code of my service:

public class LocationLoggingService extends Service {
    String latString, lngString;
    Double latitude, longitude;
    Date durationDate;
    String user_id;
    public String username;

    private Handler serviceHandler;
    private Task myTask = new Task();

    @Override
    public IBinder onBind(Intent i) {
        Log.d(getClass().getSimpleName(), "onBind()");
        username = i.getStringExtra("username");
        return myRemoteLocationServiceStub;
    }

    private IMyRemoteLocationLoggingService.Stub myRemoteLocationServiceStub = new IMyRemoteLocationLoggingService.Stub() {
        public void dumpLocationLog() throws RemoteException {
            LocationLoggingService.this.dumpLocationLog();
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(getClass().getSimpleName(), "onCreate()");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        serviceHandler.removeCallbacks(myTask);
        serviceHandler = null;
        Log.d(getClass().getSimpleName(), "onDestroy()");
    }

    @Override
    public void onStart(Intent intent, int startId) {
        username = intent.getStringExtra("username");
        super.onStart(intent, startId);
        serviceHandler = new Handler();
        serviceHandler.postDelayed(myTask, 1000L);
        Log.d(getClass().getSimpleName(), "onStart()");
    }

    class Task implements Runnable {
        public void run() {
            try {
                myRemoteLocationServiceStub.dumpLocationLog();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            serviceHandler.postDelayed(this, 5000L);
            Log.i(getClass().getSimpleName(), "Calling the dumpLocationLog");
        }
    }

    public void retrieveUserId() {
        ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
        postParameters.add(new BasicNameValuePair("username", username));
        String response = null;
        try {
            response = CustomHttpClient.executeHttpPost(
                    "http://10.0.2.2/science/getUserId.php", postParameters);
            String res = response.toString();
            res = res.replaceAll("\\s+", "");
            if (!res.equals("0")) {
                Log.d(getClass().getSimpleName(),
                        "Successfully retrieved user_id");
                user_id = res;
            } else {
                Log.d(getClass().getSimpleName(), "Error retrieving user_id");
            }
        } catch (Exception e) {
        }
    }

    private void sendData(String user_id) {
        ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
        postParameters.add(new BasicNameValuePair("user_id", user_id));
        postParameters.add(new BasicNameValuePair("latitude", latString));
        postParameters.add(new BasicNameValuePair("longitude", lngString));
        String response = null;
        try {
            response = CustomHttpClient.executeHttpPost(
                    "http://10.0.2.2/science/sendLocationData.php",
                    postParameters);
            String res = response.toString();
            res = res.replaceAll("\\s+", "");
            if (res.equals("1")) {
                Log.d(getClass().getSimpleName(), "Insertado en DB!");
            } else {
                Log.d(getClass().getSimpleName(), "Error insertando en la DB");
            }
        } catch (Exception e) {
        }
    }

    LocationListener myLocationListener = new LocationListener () {
        @Override
        public void onLocationChanged(Location location) {
            if (location != null) {
                android.os.Debug.waitForDebugger();
                latitude = location.getLatitude();
                longitude = location.getLongitude();
                latString = Double.toString(latitude);
                lngString = Double.toString(longitude);
                Log.d("Location: ", getClass().getSimpleName());
                Log.d(latString, getClass().getSimpleName());
                Log.d(lngString, getClass().getSimpleName());
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

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

        }
    };

    private void dumpLocationLog() {
        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, myLocationListener);
        retrieveUserId();
        sendData(user_id);
    }

    public static String create_datestring(String timestring)
            throws java.text.ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
                Locale.US);
        Date dt = null;
        Calendar c = Calendar.getInstance();
        try {
            dt = sdf.parse("2011-03-01 17:55:15");
            c.setTime(dt);
            System.out.println(c.getTimeInMillis());
            System.out.println(dt.toString());
        } catch (ParseException e) {
            System.err.println("There's an error in the Date!");
        }
        return dt.toString();
    }
}

Thanks a lot in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一萌ing 2024-12-05 07:23:03

我建议你做的是

class DumpLocationLog extends Thread
{
    public void run()
    {
        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,/* FIXME this */);
        retrieveUserId();
        sendData(user_id);
    }
}

然后,从你调用 dumpLocationLog() 的任何地方,使用 runOnUiThread(new DumpLocationLog()) 代替。

What I was suggesting you do was

class DumpLocationLog extends Thread
{
    public void run()
    {
        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,/* FIXME this */);
        retrieveUserId();
        sendData(user_id);
    }
}

Then, from wherever you had been calling dumpLocationLog(), use runOnUiThread(new DumpLocationLog()) instead.

帅冕 2024-12-05 07:23:03

您可以使用这种方法:


DumpLocationLog 类扩展了 Thread
{
公共无效运行()
{
Looper.prepare();
mLooper = Looper.myLooper();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,mLooper);
检索用户 ID();
发送数据(user_id);
Looper.loop();
}
公共无效停止()
{
mLooper.quit();
}
}

You can use this approach:


class DumpLocationLog extends Thread
{
public void run()
{
Looper.prepare();
mLooper = Looper.myLooper();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f ,mLooper);
retrieveUserId();
sendData(user_id);
Looper.loop();
}
public void stop()
{
mLooper.quit();
}
}

败给现实 2024-12-05 07:23:02

使用消息循环程序的正确方法在其文档中进行了描述,其中包含代码示例此处< /a>

The proper way to use the message looper is described in its doc with a code sample here

浮云落日 2024-12-05 07:23:02

最后的解决方案是:

Class LoggingService.java (这是我的服务):

private void dumpLocationLog() {
        new DumpLocationLog(context, latString, lngString).start();
        Log.d(latString, getClass().getSimpleName());
        Log.d(lngString, getClass().getSimpleName());
        retrieveUserId();
        sendData(user_id);
    }

然后在 DumpLocationLog.java 中:

public class DumpLocationLog extends Thread {
    LocationManager lm;
    LocationHelper loc;
    String latString, lngString = null;

    public DumpLocationLog(Context context, String latString, String lngString) {
        loc = new LocationHelper();
        lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
    }

    public void run() {
        Looper.prepare();
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, loc);
        Looper.loop();
    }
}

然后最后是 LocationListener 接口的 LocationHelper:

public class LocationHelper implements LocationListener {
    public String latString, lngString;
    public Double latitude, longitude;

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            LocationLoggingService.latString = Double.toString(latitude);
            LocationLoggingService.lngString = Double.toString(longitude);
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

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

    }
}

它的工作原理就像一个魅力,但我已经意识到,当侦听位置时,它正在创建线程不停地运行并且永远不会关闭前面的线程;我的意思是,每次它检查位置时,都会创建一个新线程,X 分钟后,就会有数百个线程。

有人知道为什么吗?

Well finally the solution is:

Class LoggingService.java (this is my service):

private void dumpLocationLog() {
        new DumpLocationLog(context, latString, lngString).start();
        Log.d(latString, getClass().getSimpleName());
        Log.d(lngString, getClass().getSimpleName());
        retrieveUserId();
        sendData(user_id);
    }

Then in DumpLocationLog.java:

public class DumpLocationLog extends Thread {
    LocationManager lm;
    LocationHelper loc;
    String latString, lngString = null;

    public DumpLocationLog(Context context, String latString, String lngString) {
        loc = new LocationHelper();
        lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
    }

    public void run() {
        Looper.prepare();
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L, 500.0f, loc);
        Looper.loop();
    }
}

Then finally the LocationHelper for the LocationListener interface:

public class LocationHelper implements LocationListener {
    public String latString, lngString;
    public Double latitude, longitude;

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            LocationLoggingService.latString = Double.toString(latitude);
            LocationLoggingService.lngString = Double.toString(longitude);
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

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

    }
}

It works like a charm but I have realized, that when listening for locations, it's creating threads non-stop and never closing the former ones; I mean that every time it checks for location, it creates a new thread and after X minutes, there are hundreds of threads.

Anybody knows why?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文