我想每15分钟将位置更新发布到服务器,即使应用未在前台运行 [英] i want to post location updates every 15mins to server even when the app is not running in the foreground

查看:79
本文介绍了我想每15分钟将位置更新发布到服务器,即使应用未在前台运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望从Android手机到服务器的时间间隔每15分钟将位置更新发送到服务器。是服务还是警报管理器是最佳选择。

I want the location updates to be sent to the server every 15mins to time interval from android phone to the server.Is the service or the alarm manager is the best option.

如果我启动一项服务,是否可以启动asynctask将位置发布到服务器??

If i start a service,can i start an asynctask to post locations to the server.?

这是我使用的代码:

    @Override
    public void onStart(Intent intent, int startId) {
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        listener = new MyLocationListener();
        locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, 4000, 0, listener);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
                4000, 0, listener);
    }




    public class MyLocationListener implements LocationListener {

        public void onLocationChanged(final Location loc) {
            Log.i("**************************************", "Location changed");
            if (isBetterLocation(loc, previousBestLocation)) {
                loc.getLatitude();
                loc.getLongitude();

//              
//              intent.putExtra("Latitude", loc.getLatitude());
//              intent.putExtra("Longitude", loc.getLongitude());
//              intent.putExtra("Provider", loc.getProvider());
//              
//              sendBroadcast(intent);

            }
        }

        public void onProviderDisabled(String provider) {
            Toast.makeText(getApplicationContext(), "Gps Disabled",
                    Toast.LENGTH_SHORT).show();
        }

        public void onProviderEnabled(String provider) {
            Toast.makeText(getApplicationContext(), "Gps Enabled",
                    Toast.LENGTH_SHORT).show();
        }
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

    }
}

我不知道如何每隔十五分钟运行一次服务后台。.
我想开始当我获得新的位置更新时,aysnctask是服务还是警报管理器是最佳选择。
如果我启动服务,是否可以启动asynctask将位置发布到服务器。?

I dont know how to run the service background every fifteen minutes of interval.. I want to start an aysnctask when i get fresh location updates.Is the service or the alarm manager is the best option. If i start a service,can i start an asynctask to post locations to the server.?

推荐答案

更新的答案

旧答案不适用于定位M或更高版本的应用,因为静态连接接收器将不再接收广播

Old answer will not work for apps targeting M or higher, because static connectivity receiver will no longer receive broadcasts.

现在,最好的选择是 FusedLocationApi ,它是Google Play服务的一部分。

Now, the best option is a FusedLocationApi, which is a part of Google Play Services.

compile 'com.google.android.gms:play-services-location:[version_here]'

创建一个IntentService处理位置更新

Create an IntentService handling location updates

/**
 * Handles location updates from FusedLocationProvider
 */
public final class LocationUpdateService extends IntentService {

    private static final String TAG = "LocationUpdateService";

    public static final String ACTION_HANDLE_LOCATION = "ACTION_HANDLE_LOCATION";

    public LocationUpdateService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(final Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (action != null) {
                switch (action) {
                    case ACTION_HANDLE_LOCATION:
                        onActionHandleLocation(intent);
                        break;

                    default:
                        Log.w(TAG, "onHandleIntent(), unhandled action: " + action);
                        break;
                }
            }
        }
    }

    private void onActionHandleLocation(@NonNull final Intent intent) {
        if (!LocationResult.hasResult(intent)) {
            Log.w(TAG, "No location result in supplied intent");
            return;
        }

        final LocationResult locationResult = LocationResult.extractResult(intent);
        if (locationResult == null) {
            Log.w(TAG, "LocationResult is null in supplied intent");
            return;
        }

        // TODO send to server using a blocking request.
        // Remember that this is the background thread already
    }
}

不要忘记将其添加到清单应用程序标记中

Don't forget to add it to Manifest application tag

<service android:name=".LocationUpdateService"/>

请求位置权限,连接GoogleApiClient,您现在可以执行以下操作

Request location permission, connect GoogleApiClient, and you now may do the following

@NonNull
private static PendingIntent createLocationServiceIntent(@NonNull final Context context) {
    final Intent intent = new Intent(context, LocationUpdateService.class);
    intent.setAction(LocationUpdateService.ACTION_HANDLE_LOCATION);

    return PendingIntent.getService(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}

public static void scheduleLocationUpdates(@NonNull final Context context,
        @NonNull final GoogleApiClient googleApiClient) {
    // Make sure you have permission, request if necessary
    if (googleApiClient.isConnected() &&
            ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
            // ACCESS_COARSE_LOCATION, depending on what you want
            == PackageManager.PERMISSION_GRANTED) {

        LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient,
                LocationRequest.create().setInterval(AlarmManager.INTERVAL_FIFTEEN_MINUTES),
                createLocationServiceIntent(context));
    }
}

public static void unscheduleLocationUpdates(@NonNull final Context context,
        @NonNull final GoogleApiClient googleApiClient) {
    if (googleApiClient.isConnected()) {
        LocationServices.FusedLocationApi
                .removeLocationUpdates(googleApiClient, createLocationServiceIntent(context));
    }
}

旧答案

AsyncTask用于较短的后台操作,主要是在UI中等待时。您最好使用服务启动: //developer.android.com/reference/android/os/PowerManager.WakeLock.html rel = nofollow noreferrer> WakeLock 。但请注意,您每 15分钟。当设备未连接到网络时,考虑不安排警报。

AsyncTask is intended for short background operations, mostly when you are waiting in UI. You should better start a Service with WakeLock in this case. But be aware that you will likely drain a battery doing so every 15 minutes. Consider not scheduling Alarms when device is not connected to network.

1)注册静态 BroadcastReceiver 中的noreferrer>监视设备是否已连接。
针对android sdk中网络事件的意图动作

2)当设备连接到互联网并且允许位置时,启动一个服务,该服务将保留WakeLock,侦听一个位置更新,取消注册位置更新,将位置发送给服务器,安排 AlarmManager ,释放WakeLock并校准stopSelf();如果位置更新未到,请考虑超时。如果超时,则注销位置更新,注册下一个警报,释放WakeLock并调用stopSelf。

2) When device gets connected to the internet and locations are allowed, start a Service that will hold WakeLock, listen for one location update, unregisters location updates, sends location to server, schedules AlarmManager, releases WakeLock and cals stopSelf(); Consider a timeout if location updates are not comming. If timeout reached, unregister location updates, register next Alarm, release WakeLock and call stopSelf.

3)如果接收器的网络断开,则取消所有警报并停止服务

3) If you receive network disconnected in a Receiver, cancel all Alarms and stop Service if running.

根据要求执行步骤2的代码示例

public final class ConnectivityReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        final AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        final PendingIntent wakeupIntent = PendingIntent.getService(context, 0,
                new Intent(context, LocationUpdaterService.class), PendingIntent.FLAG_UPDATE_CURRENT);

        final boolean hasNetwork = !intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
        if (hasNetwork) {
            // start service now for doing once
            context.startService(new Intent(context, LocationUpdaterService.class));

            // schedule service for every 15 minutes
            alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                    SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_FIFTEEN_MINUTES,
                    AlarmManager.INTERVAL_FIFTEEN_MINUTES, wakeupIntent);
        } else {
            alarmManager.cancel(wakeupIntent);
        }
    }

}

public  final class LocationUpdaterService extends Service implements LocationListener {

    private enum State {
        IDLE, WORKING;
    }



    private static State state;

    private LocationManager locationManager;
    private WakeLock wakeLock;

    static {
        state = State.IDLE;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "LocationUpdaterService");
    }


    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (state == State.IDLE) {
            state = State.WORKING;
            this.wakeLock.acquire();
            // register location updates, not gonna code it you know

        }
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        state = State.IDLE;
        if (this.wakeLock.isHeld()) {
            this.wakeLock.release();
        }
    }

    private void sendToServer(Location location) {
        // send to server in background thread. you might want to start AsyncTask here
    }

    private void onSendingFinished() {
        // call this after sending finished to stop the service
        this.stopSelf(); //stopSelf will call onDestroy and the WakeLock releases.
        //Be sure to call this after everything is done (handle exceptions and other stuff) so you release a wakeLock
        //or you will end up draining battery like hell
    }

    @Override
    public void onLocationChanged(Location location) {
        locationManager.removeUpdates(this); // you will want to listen for updates only once
        sendToServer(location);
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

}

这篇关于我想每15分钟将位置更新发布到服务器,即使应用未在前台运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆