Android 如何在需要时发送服务器上设备的位置

Android 如何在需要时发送服务器上设备的位置,android,service,push-notification,Android,Service,Push Notification,我正在开发一个应用程序,其中我需要设备的当前lat和long。 获取lat/long的时间范围将由服务器决定。每当需要获取lat/lang时,服务器将发送通知。当设备收到来自的通知时 服务器,同时设备将其位置发送到服务器 某些条件: 即使设备没有gps,我也需要lat/long 如果用户没有触摸或单击通知,那么我也想获取 lat/long,即即使设备处于睡眠模式 我也不想一整天都在运行后台服务 它消耗设备的电池 我肯定会建议在这里使用谷歌云消息。这样做的好处是,一旦设备运行了你的应用程序,你就

我正在开发一个应用程序,其中我需要设备的当前lat和long。 获取lat/long的时间范围将由服务器决定。每当需要获取lat/lang时,服务器将发送通知。当设备收到来自的通知时 服务器,同时设备将其位置发送到服务器

某些条件:

  • 即使设备没有gps,我也需要lat/long

  • 如果用户没有触摸或单击通知,那么我也想获取 lat/long,即即使设备处于睡眠模式

  • 我也不想一整天都在运行后台服务 它消耗设备的电池


我肯定会建议在这里使用
谷歌云消息。这样做的好处是,一旦设备运行了你的应用程序,你就可以让它根据
GCM
注册,你可以向他们发送一些消息,让他们将坐标注册到你的数据库中

这种方法需要您实现一些服务器(例如,使用PHP的web服务器)并让用户与其通信,因此流程如下:

  • 您的服务器向所有已注册的设备发送广播消息,告诉它们必须根据
    GCM
    服务注册

  • 设备获取消息,您实现
    BroadcastReceiver
    来获取纬度和经度并将其发送到远程服务器,比如
    http://www.mysuperserver.com/getlonglat.php
    ,通过
    POST
    请求

  • 您的服务器接受这两个参数,您可以保存它们或执行任何需要的操作

  • 如果您想采用这种方法,以下是您必须遵循的步骤:

  • 去。使用您的Google帐户,注册一个新项目。这将为您提供API密钥和发件人ID

  • 您需要在
    GCM
    中针对您的项目注册设备。您可以通过在项目中导入
    Google Play Services
    来实现这一点,完成后,执行类似的操作:

    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
    final String regid = gcm.register("YOUR_SENDER_ID");
    
  • 此时,
    GCM
    服务器已经知道该用户已在您的项目中注册了whithin,并给了他一个
    regid

  • 下一步是通知您自己的远程服务器,用户已经这样做了,并将已提供的
    regid
    保存在某个地方,以便您以后可以向他们发送消息。因此,在客户端,对发送
    regid
    的服务器发出
    httppost
    请求,并使用如下方式处理它:

    $regid = $_POST['regid'];
    
    if (($regId) && ($ipAddr))
      sql_query("INSERT INTO gcm_subscribers(regid) VALUES($regid')");
    
  • 完成后,您就知道谁已经针对您的数据库进行了注册。您可以
    选择所有用户并向他们发送一个信号,将其坐标发回给您。在下面的示例中,参数首先是注册ID数组,其次是要发送的消息(例如,
    $messageData=“sendmeyyourcoords!”

  • 进入客户端后,只需处理该
    GCM
    消息,并在远程服务器上向另一个
    URL
    发送另一条
    POST
    ,然后将
    经度和
    纬度传递给它。为了处理这些信息,我在下面添加了一些链接

  • 在没有GPS的情况下获取坐标似乎没有太多的解决方案,但有一些解决方案。这将是一个例子:

    关于这方面的更多信息:

    • 参考

    • (西班牙语)

      • 以下是我所做的

      • 使用Google Play services融合位置提供程序获取和存储位置,如下所述

      • 我会避免设置服务,相反,您应该触发警报,请求最后可用的位置。这进一步节省了电池,因为该应用程序不会去寻找vale的位置,而是使用其他应用程序最近可能请求的位置。我认为收到的答复相当准确。。 那就这样做吧

        public class LocationReceiver extends BroadcastReceiver {
        // Restart service every 30 seconds
        private static final long REPEAT_TIME = 1000 * 60 * 5;
        private static final long REPEAT_DAILY = 1000 * 60 * 60 * 24;
        @Override
        public void onReceive(Context context, Intent intent) 
        {
            Log.v("TEST", "Service loaded at start");
            AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.SECOND, 0);
        
            Intent i = new Intent(context, ServiceStartReceiver.class);
            PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,PendingIntent.FLAG_CANCEL_CURRENT);
            service.setInexactRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), REPEAT_TIME, pending);
        
        }
        }
        
      • 由于您没有提到您需要实时更新,我认为您可以将所有数据转储到临时sqlite数据库中

      • 创建一个接收器来监听网络中的变化,当通过wifi时,只需将所有数据发送到您的服务器。通过仅在累积了一定数量的条目或以一定的周期间隔发送,您可以更聪明一点

      • 或者,服务器可以通过GCM通知向应用程序发送ping,这也可以触发向服务器发送数据。是一个描述向应用程序发送GCM消息的精彩教程

      • 最后介绍了一些非常有趣的定位策略。您可以根据用户活动或某些其他上下文确定何时触发位置保存


      • 希望这有帮助。

        您的ans很有用,但与我的要求不完全相符。
        public class LocationReceiver extends BroadcastReceiver {
        // Restart service every 30 seconds
        private static final long REPEAT_TIME = 1000 * 60 * 5;
        private static final long REPEAT_DAILY = 1000 * 60 * 60 * 24;
        @Override
        public void onReceive(Context context, Intent intent) 
        {
            Log.v("TEST", "Service loaded at start");
            AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.SECOND, 0);
        
            Intent i = new Intent(context, ServiceStartReceiver.class);
            PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,PendingIntent.FLAG_CANCEL_CURRENT);
            service.setInexactRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), REPEAT_TIME, pending);
        
        }
        }