-->

安卓:requestLocationUpdates抛出异常(Android: requestLoca

2019-10-16 13:23发布

我想,定期获得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();
    }
}

非常感谢提前!

Answer 1:

使用弯针消息的正确方法在其文档与一个代码示例描述在这里



Answer 2:

那么最终的解决办法是:

类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();
    }
}

然后最后LocationHelper了LocationListener的界面:

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分钟后,有数百个线程。

任何人都知道这是为什么?



Answer 3:

我是建议你做的是

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(新DumpLocationLog())来代替。



Answer 4:

您可以使用此方法:

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(); } }



文章来源: Android: requestLocationUpdates throws exception