如何在需要时将设备位置发送到服务器

7
我正在开发一个应用程序,需要获取设备的当前纬度和经度。获取纬度/经度的时间框架由服务器决定。当服务器要求获取纬度/经度时,会发送通知给设备。设备在接到通知的同时,将其位置发送给服务器。
一些条件如下:
- 即使设备没有GPS,我也希望能够获取纬度/经度。 - 如果用户不触摸或点击通知,我仍然希望获取纬度/经度,即使设备处于睡眠模式。 - 我也不想为整天运行后台服务,因为这会消耗设备的电量。
2个回答

21

我会强烈建议在这里使用 Google Cloud Messaging。这样做的好处是,一旦设备运行您的应用程序,您可以使其注册到 GCM 并向它们发送一条消息,让他们将自己的坐标注册到您的数据库中。

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

  1. 您的服务器向所有已注册的设备发送广播消息,告诉它们需要注册到 GCM 服务。

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

  3. 您的服务器获取两个参数后,对其进行保存或进行其他必要的操作。

如果您想采用这种方法,请按照以下步骤进行:

  1. 前往 https://console.developers.google.com。使用您的 Google 帐户注册一个新项目。这将为您提供一个 API 密钥和一个 Sender ID。

  2. 您需要使设备在 GCM 中注册到您的项目中。您可以通过将 Google Play Services 导入您的项目中来实现这一点,然后执行类似于以下内容的操作:

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

  4. 下一步是通知您自己的远程服务器该用户已完成注册,并在某个地方保存它所获得的regid,以便稍后发送消息。因此,在客户端上,使用HTTP POST请求针对您的服务器发送该regid,并使用类似以下方式处理它:

  5. $regid = $_POST['regid'];
    
    if (($regId) && ($ipAddr))
      sql_query("INSERT INTO gcm_subscribers(regid) VALUES($regid')");
    
  6. 完成后,您就知道已经在您的数据库中注册的用户。您可以SELECT所有用户并发送信号要求他们将其坐标发送回您。在下面的示例中,参数将是首先是注册ID的数组,其次是要发送的消息(例如, $messageData = "sendMeYourCoords!")。

  7. function sendNotification($registrationIdsArray, $messageData) {
      $apiKey = "YOUR_API_KEY";
    
      $headers = array("Content-Type:" . "application/json", "Authorization:" . "key=" . $apiKey);
      $data = array(
        'data' => $messageData,
        'registration_ids' => $registrationIdsArray
      );
    
      $ch = curl_init();
    
      curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
      curl_setopt( $ch, CURLOPT_URL, "https://android.googleapis.com/gcm/send" );
      curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0 );
      curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
      curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
      curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode($data) );
    
      $response = curl_exec($ch);
      curl_close($ch);
    
      return $response;
    }
    
  8. 在客户端中,只需处理GCM消息并向远程服务器上的另一个URL发送另一个POST,并将longitudelatitude传递给它。为了处理这些消息,我在下面包含了一些链接。

如果不使用GPS获取坐标,似乎并没有太多解决方案,但还是有一些的。以下是一个示例:如何在Android中不使用GPS获取纬度经度值?

更多相关内容:


你的答案很有用,但并不完全符合我的要求。 - Pankaj Arora

0

这是我所做的。

  1. 使用Google Play服务融合位置提供程序获取和存储位置,如此处所述here

  2. 我建议避免设置一个服务,而是应该触发一个请求最后可用位置的闹钟。这进一步节省电池,因为应用程序不会寻找位置值,而是使用其他应用程序可能最近请求的位置。在我看来,接收到的响应相当准确。因此,可以像这样做:

    public class LocationReceiver extends BroadcastReceiver {
    // 每30秒重启服务
    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);
    
    }
    }
    
  3. 由于您没有提到您想要实时更新,我认为您可以将所有数据转储到临时SQLite数据库中。

  4. 创建一个接收器以侦听网络中的更改,当通过wifi时,只需将所有数据发送到您的服务器。在执行此操作时,您可以更加聪明,仅在积累了一定数量的条目或在周期性间隔时发送。

  5. 或者,服务器可以通过GCM mnotification向应用程序发送ping,这也可以触发将数据发送到您的服务器。this是一个惊人的教程,描述了向应用程序发送GCM消息。

  6. 最后,here提到了一些非常有趣的位置策略。您可以根据用户活动或其他上下文选择何时触发位置保存。

希望这能有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接