How to send location of the device on server when

2019-01-08 18:25发布

问题:

I am developing a application in which i need current lat and long of the device. Time frame to get the lat/long will be decided by the server. Server will send notification whenever lat/lang is required to be fetched. When device get notified from the server,at the same time device send its location to server.

Some conditions:

  • I want lat/long even if device don't have gps

  • if user doesn't touch or click the notification,then also i want to fetch lat/long, i.e. even if the device is in sleep mode.

  • Also i don't want to run a background service for the whole day as it consumes battery of the device.

回答1:

I would definitely suggest using Google Cloud Messaging here. This has the benefit that once a device runs your app, you can make it register against GCM and you can send them some message that would make them register their coordinates into your database.

This approach would need that you have to implement some server (for instance, a web server with PHP) and make the users communicate with it, so the flow would be:

  1. Your server sends a broadcast message to all registered devices telling them they have to register against the GCM service.

  2. The devices get the message, and you implement the BroadcastReceiver to get both latitude and longitude and send it to your remote server, say http://www.mysuperserver.com/getlonglat.php, via a POST request.

  3. Your server takes both parameters and you save them or do whatever you need.

If you want to follow this approach, this are the steps you have to follow:

  1. Go to https://console.developers.google.com. With your Google account, register a new project. This will provide you an API key and a Sender ID.

  2. You'll need to make the device register against your project in GCM. You can achieve this by importing Google Play Services within your project, and once done, do something alike to this:

    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
    final String regid = gcm.register("YOUR_SENDER_ID");
    
  3. At this time, the GCM server already knows that this user has registered whithin your project and has given him a regid.

  4. The next step is informing your own remote server that the user has done so, and save somewhere the regid that it has been given, so you can later send them messages. So in the client side, make a HTTP POST request against your server sending that regid and process it with somethat like this:

    $regid = $_POST['regid'];
    
    if (($regId) && ($ipAddr))
      sql_query("INSERT INTO gcm_subscribers(regid) VALUES($regid')");
    
  5. Once done, you know who have already registered against your database. You can SELECT all the users and send them a signal to send you back their coordinates. In the following example, the parameters would be, firstly, an array of registration IDs and secondly the message to send (for instance, $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;
    }
    
  6. Once in your client, just process that GCM message and make another POST to another URL on your remote server and pass it the longitude and latitude. To process the messages I'm including a few links below.

And for getting the coordinates without GPS seems there aren't too much solutions, but there are some. This would be an example: How to get Latitute Longitude value without using GPS in Android?

More about this:

  • Reference on Google Cloud Messaging

  • Android Push Notifications using Google Cloud Messaging GCM - Android Example

  • Google Cloud Messaging using PHP

  • Connection between PHP (server) and Android (client) Using HTTP and JSON

  • Notificaciones Push Android: Google Cloud Messaging (GCM). Implementación Cliente (Nueva Versión) (spanish)



回答2:

Here is what i did.

  1. Fetch and store locations using the Google Play services fused location provider as described herehere

  2. I would avoid setting up a service instead you should trigger an alarm that requests for last available location. This further saves battery as the app does not go looking for a location vale but uses what other apps might have recently requested. In my opinion the received response is fairly accurate.. so do something like this

    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);
    
    }
    }
    
  3. Since you have not mentioned that you want the updates in real time i think you can just dump all data in a temp sqlite database.

  4. Create a receiver to listen for changes in network and when over wifi simply send all data to your server. You can be a bit more smart while doing this by sending only when certain number of entries have accumulated or at a periodic interval.

  5. Alternatively the server can send a ping to the app via a GCM mnotification which can also trigger sending of data to your server.this is an amazing tutorial to describe sending GCM messages to the app.

  6. Finally some very interesting location strategies are mentioned here. You can pic when to trigger your location save based on user activity or some other context.

Hope this helps.