【问题标题】:Making the WakefulIntentService wait for location callback to be called使 WakefulIntentService 等待位置回调被调用
【发布时间】:2013-06-06 15:16:53
【问题描述】:

我正在尝试构建一个应用程序,该应用程序具有每 X 分钟将当前位置发送到服务器的服务。

查看 SO 中的其他帖子,发现 commons-ware https://github.com/commonsguy/cwac-wakeful 中概述的方法效果最好。这里的 demo2 应用程序对我来说很好,它每 x 分钟向 Alarm.txt 写入一条消息。

我对“AppService.java”进行了以下修改,以便它尝试获取一个位置,而不是它作为示例程序所做的事情。

public class AppService extends WakefulIntentService {

private Context context;
    public AppService() {
       super("AppService");
    }

    @Override
    protected void doWakefulWork(Intent intent) {
    //    File log=new File(Environment.getExternalStorageDirectory(),
    //                      "AlarmLog.txt");
    //    
    //    try {
    //      BufferedWriter out=new BufferedWriter(new FileWriter(log.getAbsolutePath(),
    //                                                           log.exists()));
    //      
    //      out.write(new Date().toString());
    //      out.write("\n");
    //      out.close();
    //      Log.e("AppService", "wrote to log file");
    //    }
    //    catch (IOException e) {
    //      Log.e("AppService", "Exception appending to log file", e);
    //    }
      context = this.getApplicationContext();
      Log.e("AppService", "Attaempting to get location");
      new GetLocation(context).execute();
   }
}

我的 GetLocation.java 看起来像这样

public class GetLocation {

private LocationManager locationManager;
private LocationListener locationListener;
private Context context;

public GetLocation(Context context) {
    this.context = context;
}

public void execute() {
    locationManager = (LocationManager) context
            .getSystemService(Context.LOCATION_SERVICE);
    locationListener = new LocationListener() {

        @Override
        public void onLocationChanged(Location location) {
            new SendLocation2(location).execute();
            locationManager.removeUpdates(locationListener);
        }

        @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

        }
    };
    Log.e("AppService", "Registered to get location");
    locationManager.requestLocationUpdates(
            LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}

}

发送位置使用 apache http 客户端库将位置上传到服务器。

当我运行它时,我会在 logcat 中得到以下信息。

06-06 08:06:27.031: E/AppService(3161): Attaempting to get location
06-06 08:06:27.039: E/AppService(3161): Registered to get location


W/MessageQueue(3161): Handler (android.location.LocationManager$ListenerTransport$1)  {41855e68} sending message to a Handler on a dead thread
W/MessageQueue(3161): java.lang.RuntimeException: Handler (android.location.LocationManager$ListenerTransport$1) {41855e68} sending message to a Handler on a dead thread
W/MessageQueue(3161):   at android.os.MessageQueue.enqueueMessage(MessageQueue.java:294)
W/MessageQueue(3161):   at android.os.Handler.enqueueMessage(Handler.java:618)
W/MessageQueue(3161):   at android.os.Handler.sendMessageAtTime(Handler.java:587)
W/MessageQueue(3161):   at android.os.Handler.sendMessageDelayed(Handler.java:558)
W/MessageQueue(3161):   at android.os.Handler.sendMessage(Handler.java:495)
W/MessageQueue(3161):   at android.location.LocationManager$ListenerTransport.onLocationChanged(LocationManager.java:218)
W/MessageQueue(3161):   at android.location.ILocationListener$Stub.onTransact(ILocationListener.java:58)
W/MessageQueue(3161):   at android.os.Binder.execTransact(Binder.java:351)
W/MessageQueue(3161):   at dalvik.system.NativeStart.run(Native Method)

我看起来在位置管理器调用它的回调 onLocationChanged() 之前,该应用程序不会保持活动状态。我该如何解决这个问题?

【问题讨论】:

    标签: android locationmanager android-broadcast commonsware-cwac


    【解决方案1】:

    查看 SO 中的其他帖子,发现 commons-ware https://github.com/commonsguy/cwac-wakeful 中概述的方法效果最好。

    绝对不是。任何形式的 IntentService 都不适合您的用例。 IntentService 不能注册侦听器、fork 自己的线程,或者做任何会在onHandleIntent() 结束后继续运行的事情。一旦onHandleIntent() 返回,如果没有进一步的命令要处理,服务将关闭,这反过来可能导致您的进程被终止。

    对于需要注册侦听器的情况,请使用常规 Service,以及您自己托管的 WakeLock,其中控制服务何时关闭。

    【讨论】:

    • 您好 CommonsWare,LocationPoller 链接已失效 404。您是否删除了 LocationPoller 项目?如果不是,请告诉我正确的链接,如果是,那么是否有替代位置轮询的方法?和OP一样的情况。
    • @SharpEdge:“您是否删除了 LocationPoller 项目?” - 是的。感谢您指出;我已从答案中删除了该链接。 “位置轮询有替代方案吗?” -- 我还没找。
    • "对于需要注册侦听器的情况,请使用常规服务,使用您自己托管的 WakeLock,您可以在其中控制服务何时关闭" 所以我可以修改您的 Wakeful 并替换IntentService 和常规的 Service 处理其处置和超时等?
    • @SharpEdge: WakefulIntentService 针对不同的场景进行了优化。它不是一个好的起点,尽管它可能会给你一些实现思路。
    • 你能不能至少给我指出正确的方向?即使应用程序关闭,我也需要每 15 分钟向服务器发送一次位置。我的猜测是,如果设备处于睡眠状态,则在某些情况下,警报管理器也不会调用该服务。任何指针将不胜感激。
    猜你喜欢
    • 2021-01-25
    • 2013-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    • 2021-06-30
    • 2018-09-19
    • 1970-01-01
    相关资源
    最近更新 更多