Java IntentService将位置对象传递给UI
我正在组装一个测试位置抓取器,并决定使用intentservice获取位置,以便用户可以继续在UI上填写表单 此测试类未实现表单。我只是想让服务正常工作,并让它返回一个位置作为测试的一部分 我一直在检查internet,我决定使用处理程序和消息传回location对象 问题是我收到错误消息“正在向死线程上的处理程序发送消息”。我知道消息应该是不言自明的,但我看不出我的代码有什么问题 我的主要和唯一的活动代码如下Java IntentService将位置对象传递给UI,java,android,service,Java,Android,Service,我正在组装一个测试位置抓取器,并决定使用intentservice获取位置,以便用户可以继续在UI上填写表单 此测试类未实现表单。我只是想让服务正常工作,并让它返回一个位置作为测试的一部分 我一直在检查internet,我决定使用处理程序和消息传回location对象 问题是我收到错误消息“正在向死线程上的处理程序发送消息”。我知道消息应该是不言自明的,但我看不出我的代码有什么问题 我的主要和唯一的活动代码如下 package com.pengilley.locationmanagertest;
package com.pengilley.locationmanagertest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class LocationManagerTestService extends Activity{
EditText locationField;
Button askLocation;
Location location;
private final static String TAG = "LocationManagerTestService";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
locationField = (EditText)findViewById(R.id.locationtext);
askLocation = (Button)findViewById(R.id.button);
askLocation.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
getLocation(getApplicationContext());
};
});
}
private void getLocation(Context context){
Intent intent = new Intent(context, LocationTest.class);
startService(intent);
Log.d(TAG,"getLocation: service request sent");
}
final Handler handler = new Handler(){
public void handleMessage(Message msg){
Log.d(TAG,"handleMessage start");
//receive the message from our intentservice
Bundle bundle = msg.getData();
location = (Location)bundle.getParcelable("location");
CharSequence charseq = "Latitude: " + location.getLatitude() + " Longitude: " + location.getLongitude();
locationField.setText(charseq);
}
};
}
我的IntentService课程在这里
package com.pengilley.locationmanagertest;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class LocationTest extends IntentService{
LocationListener locationListener;
Location lastKnownLocation;
Location goodLocation;
LocationManager locationManager;
boolean gpsEnabled;
boolean networkEnabled;
float distanceBetween;
private final static String TAG = "LocationTest";
private final float MAX_DISTANCE_BETWEEN_LOCATIONS = 20;
public static boolean LOCATION_AVAILABLE = false;
private String fieldVal;
private final Handler handler = new Handler();
public LocationTest(){
super("Location test");
}
public void setLocationManager(Context context){
Log.d(TAG,"setLocationManager start");
//setup locationlistener
locationListener = new LocationListener(){
@Override
public void onLocationChanged(Location location) {
Log.d(TAG,"onLocationChanged start");
// TODO Auto-generated method stub
//update check this location against last know location.
//If both locations are close to each other we can stop listening and pass the new location to lResult
lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//if no location from gps try network
if(lastKnownLocation==null){
lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if(lastKnownLocation==null){
//use current location
goodLocation = location;
}else{
//check accuracy of current location
distanceBetween = location.distanceTo(lastKnownLocation);
if(distanceBetween <= MAX_DISTANCE_BETWEEN_LOCATIONS){
//good location
goodLocation = location;
}else if(lastKnownLocation.hasAccuracy()){
goodLocation = lastKnownLocation;
}
}
Log.d(TAG,"onLocationChanged: " + goodLocation.toString());
//put result into handler
Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putParcelable("location", goodLocation);
message.setData(bundle);
handler.sendMessage(message);
Log.d(TAG,"onLocationChanged: messag sent");
}
@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 arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
};
//get location manager
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
//check if network and gps are enabled
gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
//request location for providers which are enabled
if(gpsEnabled){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
};
if(networkEnabled){
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
}
public String getFieldVal(){
return fieldVal;
}
@Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG,"onHandleIntent start");
setLocationManager(this);
}
package com.pengilley.locationmanagertest;
导入android.app.IntentService;
导入android.content.Context;
导入android.content.Intent;
导入android.location.location;
导入android.location.LocationListener;
导入android.location.LocationManager;
导入android.os.Bundle;
导入android.os.Handler;
导入android.os.Message;
导入android.util.Log;
公共类LocationTest扩展了IntentService{
LocationListener LocationListener;
定位;
位置好位置;
地点经理地点经理;
布尔gpsEnabled;
布尔网络化;
浮动距离;
私有最终静态字符串TAG=“LocationTest”;
专用最终浮子位置之间的最大距离=20;
公共静态布尔位置_AVAILABLE=false;
私有字符串fieldVal;
私有最终处理程序=新处理程序();
公共场所测试(){
超级(“定位测试”);
}
公共void setLocationManager(上下文){
Log.d(标记“setLocationManager启动”);
//设置位置侦听器
locationListener=新locationListener(){
@凌驾
已更改位置上的公共无效(位置){
Log.d(标记“onLocationChanged start”);
//TODO自动生成的方法存根
//更新检查此位置与上次知道的位置。
//如果两个位置彼此接近,我们可以停止侦听,并将新位置传递给lResult
lastKnownLocation=locationManager.getLastKnownLocation(locationManager.GPS\U提供程序);
//如果没有来自gps的位置,请尝试网络
if(lastKnownLocation==null){
lastKnownLocation=locationManager.getLastKnownLocation(locationManager.NETWORK\u提供程序);
}
if(lastKnownLocation==null){
//使用当前位置
好位置=位置;
}否则{
//检查当前位置的准确性
distanceBetween=位置。distanceTo(lastKnownLocation);
如果(距离)
我决定使用intentservice获取位置,以便用户可以继续在UI上填写表单
这不是一个好主意。IntentService
在onHandleIntent()时关闭
完成,没有更多的工作要做。您当前的实现像筛子一样泄漏内存—您永远不会删除更新请求,每次调用IntentService
都会注册一个新的LocationListener
问题是,我收到了错误消息“向死线程上的处理程序发送消息”。我知道该消息应该是不言自明的,但我看不出我的代码有什么问题
onHandleIntent()
在后台线程上执行,该线程在您尝试使用它时早已消失。此外,因为您从未费心实现handleMessage()
在处理程序上
,消息
不会出现在任何地方,当然也不会出现在某个活动中。您好。我不明白为什么我的intentservice只有在我按下一次按钮时才会启动。不会在HandleIntent()上只有在找到一个位置后才关闭?或者我必须手动关闭它?我的主要活动中有一个handMessage事件,这不是接收我的消息的地方吗?@Stephen:“我不明白为什么我的intentservice只有在我按下按钮(我按了一次按钮)时才会启动多次调用。”--您可以按一次。您的用户可以按也可以不按。您的用户可能会连续按五次,而您却无法阻止他们。“onHandleIntent()是否只在找到位置后才会关闭?”--否。“我的主要活动中有一个handMessage事件,这不是接收我的邮件的地方吗?”--不,因为那不是你的处理程序的位置。谢谢你的回复Commonware。我应该解释一下,这个测试应用程序纯粹是一个让intentservice工作的测试。在我实际发布的应用程序中,我没有启动位置服务的按钮。对于处理程序,我无法理解的是,如果我的处理程序正在使用d并在一个线程中实例化,它如何与另一个线程交互?我认为这就是处理程序的要点…我是否必须创建一个单独的类来扩展处理程序,然后我的主线程和intentservice都可以访问它?@Stephen:“在我实际发布的应用程序中,我没有启动位置服务的按钮。”--啊,好的。“我是否必须创建一个单独的类来扩展处理程序,然后我的主线程和intentservice都可以访问它?”?"--任何需要数据的类都需要实例化和访问处理程序
。如果您试图将消息
传递给活动
,在服务
中拥有处理程序
是毫无意义的。您将需要活动
中的处理程序
,并传递Messenger
到服务
。你好,Commonware。谢谢