以下是我遇到的错误
11-03 03:03:02.380: W/dalvikvm(1381): threadid=9: thread exiting with uncaught exception (group=0x40015560)
11-03 03:03:02.400: E/AndroidRuntime(1381): FATAL EXCEPTION: Timer-0
11-03 03:03:02.400: E/AndroidRuntime(1381): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
11-03 03:03:02.400: E/AndroidRuntime(1381): at android.os.Handler.<init>(Handler.java:121)
11-03 03:03:02.400: E/AndroidRuntime(1381): at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:173)
11-03 03:03:02.400: E/AndroidRuntime(1381): at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:173)
11-03 03:03:02.400: E/AndroidRuntime(1381): at android.location.LocationManager._requestLocationUpdates(LocationManager.java:579)
11-03 03:03:02.400: E/AndroidRuntime(1381): at android.location.LocationManager.requestLocationUpdates(LocationManager.java:446)
11-03 03:03:02.400: E/AndroidRuntime(1381): at com.colinlgray.MyService$1.run(MyService.java:84)
11-03 03:03:02.400: E/AndroidRuntime(1381): at java.util.Timer$TimerImpl.run(Timer.java:284)
这是我的服务,我正在尝试使用其中的计时器来更新我计划用于发送到网络服务器的GPS位置
package com.colinlgray;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
import java.util.Timer;
import java.util.TimerTask;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import com.google.android.maps.GeoPoint;
import android.content.Context;
public class MyService extends Service{
int counter = 0;
static final int UPDATE_INTERVAL = 1000;
private Timer timer = new Timer();
GeoPoint geopoint;
private LocationManager lm;
private LocationListener locationListener;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
doSomethingRepeatedly();
return START_STICKY;
}
private void doSomethingRepeatedly() {
timer.scheduleAtFixedRate( new TimerTask() {
public void run() {
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
class MyLocationListener implements LocationListener{
public void onLocationChanged(Location location) {
geopoint = new GeoPoint(
(int) (location.getLatitude() * 1E6),
(int) (location.getLongitude() * 1E6));
double latitude = location.getLatitude();
double longitude = location.getLatitude();
double altitude = location.getAltitude();
double accuracy = location.getAccuracy();
Log.d("LONGITUDE", String.valueOf(longitude));
Log.d("LATITTUDE", String.valueOf(latitude));
}
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
}
locationListener= new MyLocationListener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
}
}, 0, UPDATE_INTERVAL);
}
@Override
public void onDestroy() {
super.onDestroy();
if (timer != null){
timer.cancel();
}
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
我会感激任何帮助或建议。感谢
答案 0 :(得分:2)
我遇到了同样的问题。 我已经解决了从Timer中执行locationrequestupdates的问题,并在Timer I的run方法中将纬度和经度发送到Web服务器。
其他可能的解决方案是不使用计时器。随着
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
您可以告诉新的更新位置和“onLocationChanged(位置位置)”之间的minTime,您可以发送新的位置。
答案 1 :(得分:1)
从UI线程调用Async任务。任何未调用Looper.prepare()的线程都会导致此问题。
我今天遇到了同样的问题所以发布我的工作,看看这是否是最好的解决方案。
首先在你的代码中不要在运行
中执行此操作lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
而是将其移动到重复启动函数dosomething。 e.g。
public void dosomethingrepeatedly()
{
final Myclass x = new Myclass();
..........
public void run()
{
x.somefunction()
}
}
替代方法: 找出currentThread
Thread.currentThread().getClass();
如果它是Timer的一个实例,你可以调用Looper.prepare(); 设置一个标志,以便只调用一次Looper.prepare。 e.g。
boolean looperCalled=false;
...
...
...
public void dorepeatedly()
{
....
....
public void run()
{
if(Thread.currentThread().getName().equals(java.util.Timer$TimerImpl)
{
if(looperCalled){//do nothing}
else {Looper.prepare(); looperCalled=true;}
}
}
}