【问题标题】:How to send location of the device on server when needed需要时如何在服务器上发送设备的位置
【发布时间】:2014-04-25 12:50:48
【问题描述】:
我正在开发一个应用程序,其中我需要设备的当前纬度和经度。
获取纬度/经度的时间范围将由服务器决定。每当需要获取 lat/lang 时,服务器都会发送通知。当设备收到通知时
服务器,同时设备将其位置发送给服务器。
一些条件:
【问题讨论】:
标签:
android
service
push-notification
【解决方案1】:
我肯定会建议在这里使用Google Cloud Messaging。这样做的好处是,一旦设备运行您的应用程序,您可以使其注册到 GCM,并且您可以向他们发送一些消息,让他们将其坐标注册到您的数据库中。
这种方法需要你必须实现一些服务器(例如,使用 PHP 的 Web 服务器)并让用户与之通信,所以流程是:
您的服务器向所有已注册的设备发送一条广播消息,告诉它们必须注册GCM 服务。
-
设备收到消息,您实现 BroadcastReceiver 以获取纬度和经度,然后通过 POST 请求将其发送到您的远程服务器,例如 http://www.mysuperserver.com/getlonglat.php。
您的服务器接受这两个参数,然后您保存它们或执行任何您需要的操作。
如果您想遵循这种方法,您必须遵循以下步骤:
转到https://console.developers.google.com。使用您的 Google 帐户注册一个新项目。这将为您提供 API 密钥和发件人 ID。
-
您需要在GCM 中针对您的项目注册设备。您可以通过在项目中导入Google Play Services 来实现这一点,一旦完成,请执行类似的操作:
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
final String regid = gcm.register("YOUR_SENDER_ID");
此时,GCM 服务器已经知道该用户已在您的项目中注册并给了他一个regid。
-
下一步是通知您自己的远程服务器用户已这样做,并将已提供的regid 保存在某处,以便您以后可以向他们发送消息。因此,在客户端,对发送 regid 的服务器发出 HTTP POST 请求,并使用以下方式处理它:
$regid = $_POST['regid'];
if (($regId) && ($ipAddr))
sql_query("INSERT INTO gcm_subscribers(regid) VALUES($regid')");
-
一旦完成,您就知道谁已经在您的数据库中注册了。您可以SELECT所有用户并向他们发送信号,将他们的坐标发回给您。在以下示例中,参数首先是一组注册 ID,其次是要发送的消息(例如,$messageData = "sendMeYourCoords!")。
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;
}
在您的客户端中,只需处理该 GCM 消息,然后将另一个 POST 发送到您的远程服务器上的另一个 URL,并将 longitude 和 latitude 传递给它。为了处理这些消息,我在下面添加了一些链接。
对于没有 GPS 的情况下获取坐标似乎没有太多解决方案,但有一些解决方案。这就是一个例子:How to get Latitute Longitude value without using GPS in Android?
更多信息:
【解决方案2】:
这就是我所做的。
使用此处所述的 Google Play 服务融合位置提供程序获取和存储位置here
-
我会避免设置服务,而是您应该触发警报,请求最后一个可用位置。这进一步节省了电池电量,因为该应用程序不会寻找位置值,而是使用其他应用程序最近可能请求的内容。在我看来,收到的回复是相当准确的..
所以做这样的事情
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 mnotification 向应用发送 ping,这也可以触发向您的服务器发送数据。this 是一个很棒的教程,用于描述向应用发送 GCM 消息。
最后提到了一些非常有趣的定位策略here。您可以根据用户活动或其他上下文确定何时触发您的位置保存。
希望这会有所帮助。