我希望从Android手机到服务器每15分钟到服务器发送一次位置更新。这是服务或报警管理器是最好的选择。
如果我启动服务,我是否可以启动asynctask将位置发布到服务器。?
这是我使用的代码:
@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) {
}
}
}
我不知道如何每15分钟间隔运行服务后台.. 当我获得新的位置更新时,我想启动一个aysnctask.Is服务或警报管理器是最好的选择。 如果我启动服务,我可以启动asynctask将位置发布到服务器。?
答案 0 :(得分:10)
更新回答
旧答案不适用于针对M或更高级别的应用,因为静态连接接收器will no longer receive broadcasts。
现在,最佳选择是FusedLocationApi
,它是Google Play服务的一部分。
compile 'com.google.android.gms:play-services-location:[version_here]'
创建处理位置更新的IntentService
/**
* 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
}
}
不要忘记将其添加到Manifest应用程序标记
<service android:name=".LocationUpdateService"/>
请求位置权限,连接GoogleApiClient,您现在可以执行以下操作
@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中等待时。在这种情况下,您最好使用Service开始WakeLock。但请注意,每隔15 minutes,您可能会耗尽电池电量。当设备未连接到网络时,请考虑不安排警报。
1)注册静态BroadcastReceiver in Manifest以监控设备是否已连接。 Intent action for network events in android sdk
2)当设备连接到互联网并且允许位置时,启动将保存WakeLock的服务,侦听一个位置更新,取消注册位置更新,将位置发送到服务器,安排AlarmManager,释放WakeLock和cals stopSelf();如果没有进行位置更新,请考虑超时。如果达到超时,取消注册位置更新,注册下一个警报,释放WakeLock并调用stopSelf。
3)如果您在Receiver中接收网络已断开连接,请取消所有警报并在运行时停止服务。
按要求执行第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) {
}
}
答案 1 :(得分:0)
是的,您可以每隔15分钟为接收器安排警报,并触发可启动AsyncTask并发布位置更新的服务