android更新位置,即使应用程序在后台

时间:2017-06-18 18:34:14

标签: android location background-process android-geofence

我有一个使用Google地图地理围栏的应用。 (每当用户穿过围栏时,它会触发一个处理事件的PendingIntent

问题是,我似乎无法让我的应用程序在后台更新位置。

我目前的代码如下所示

protected void createLocationRequest() {
        LocationRequest mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(this, "user permissions have blocked the app from getting location updates", Toast.LENGTH_SHORT).show();
            return;
        }
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

在我的活动中,使用更改侦听器。

@Override
    public void onLocationChanged(Location location) {
        Toast.makeText(this, "testing message, at location " + location, Toast.LENGTH_SHORT).show();
    }

当应用程序位于前台时,我正在获取位置更新,正如OnLocationChanged和我的地理围栏都被正确触发所显示的那样。但是当应用程序在后台时,我的地理围栏在我进入应用程序之前不会被触发。

我甚至不需要回电,只是为了让手机检查它的当前位置。

任何方式在后台获取位置更新?

2 个答案:

答案 0 :(得分:2)

可能重复

快速回答(现在在办公室)

  1. Best way to get user GPS location in background in android
  2. Continuous location updates in background
  3. 我目前正在查看代码,如果通过,我会更新此答案。

答案 1 :(得分:0)

每当应用程序在后台运行时,它都会消耗设备某些有限的资源,例如RAM。这会导致用户体验受损,尤其是在用户使用资源密集型应用程序(例如玩游戏或观看视频)的情况下。为了改善用户体验, Android 8.0(API级别26 )对在后台运行时应用可以执行的操作施加了限制。

  • 您可以使用前台服务和通知渠道在后台进行位置更新,它将在Api级别26之上和之下完美运行。
  • 我已经开发了以下代码,并且在我这方面工作正常。

    希望对您有帮助

(1)请在代码的下面放置项目的 Manifest.xml 文件

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application>
<service
        android:name="com.yourpackagename.location.LocationTracker"
        android:stopWithTask="true"
        />
</application>

(2)在 app.gradle 文件

implementation 'com.google.android.gms:play-services-location:16.0.0'

(2)请在您的项目中的服务类代码行下放置,可以将位置结果(纬度,经度)保存在共享首选项或静态变量中,也可以在需要时绑定服务

public class LocationTracker extends Service implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {

private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
private static int DISPLACEMENT = 0;

private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest mLocationRequest;
private SettingsClient mSettingsClient;
private LocationSettingsRequest mLocationSettingsRequest;
private LocationCallback mLocationCallback;

private String TAG = LocationTracker.class.getSimpleName();
private GoogleApiClient mGoogleApiClient;

private final int NOTIFICATION_ID = 9083150;
private final String CHANNEL_ID = "test123";
private final String CHANNEL_ID_NAME = "test123";

@Override
public void onCreate() {
    super.onCreate();
    try {
        if (Build.VERSION.SDK_INT >= 26) {
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID_NAME,
                    NotificationManager.IMPORTANCE_HIGH);
            channel.setSound(null, null);
            channel.setShowBadge(false);
            NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
            notificationManager.deleteNotificationChannel(Constant.CHANNEL_ID);
            notificationManager.createNotificationChannel(channel);

            Notification notification = createNotification(getApplicationContext(),Constant.CHANNEL_ID,0);
            if (notification == null) {
                notification = new NotificationCompat.Builder(this, Constant.CHANNEL_ID).build();
            }
            startForeground(NOTIFICATION_ID, notification);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private Notification createNotification(Context context, String channelid,int type) {
    try {
        return new NotificationCompat.Builder(context,channelid)
                .setContentText("TEST")
                .setOnlyAlertOnce(true)
                .setOngoing(true)
                .setPriority(NotificationCompat.PRIORITY_HIGH)
                .setSmallIcon(R.mipmap.ic_launcher)
                .build();

    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}


public void setLocationUpdateCallback() {
    try {
        mLocationCallback = null;
        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
                Logger.i(TAG, "locationResult ==== " + locationResult);
                //You can put location in sharedpreferences or static varibale and can use in app where need
            }

            @Override
            public void onLocationAvailability(LocationAvailability locationAvailability) {
                super.onLocationAvailability(locationAvailability);
            }
        };
    }catch (Exception e){
        e.printStackTrace();
    }
}

private void init() {
    try {
        setLocationUpdateCallback();
        buildGoogleApiClient();
        mFusedLocationClient = null;
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        mSettingsClient = LocationServices.getSettingsClient(this);

        mLocationRequest = null;
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(DISPLACEMENT);

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);
        mLocationSettingsRequest = null;
        mLocationSettingsRequest = builder.build();

    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

protected synchronized void buildGoogleApiClient() {
    try {
        mGoogleApiClient = null;
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API).build();

        mGoogleApiClient.connect();
    } catch (Exception e) {
        e.printStackTrace();
    }
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    init();
    return START_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
    throw new UnsupportedOperationException("Not yet implemented");
}

@Override
public void onConnected(@Nullable Bundle bundle) {
    startLocationUpdates();
}

public void requestingLocationUpdates() {
    try {
        mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                mLocationCallback, Looper.myLooper());
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

protected void startLocationUpdates() {
    try {
        if (mGoogleApiClient != null) {
            mSettingsClient
                    .checkLocationSettings(
                            mLocationSettingsRequest)
                    .addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
                        @SuppressLint("MissingPermission")
                        @Override
                        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                            Log.e(TAG, "LocationSettingsStatusCodes onSuccess");
                            requestingLocationUpdates();
                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            int statusCode = ((ApiException) e).getStatusCode();
                            switch (statusCode) {
                                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                                    Log.e(TAG, "LocationSettingsStatusCodes.RESOLUTION_REQUIRED");
                                    requestingLocationUpdates();
                                    break;
                                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                                    Log.e(TAG, "LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE");
                            }
                        }
                    });
        }

    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

@Override
public void onDestroy() {
    WakeLocker.releasePartialLock();
    super.onDestroy();
}

@Override
public void onTaskRemoved(Intent rootIntent) {
    super.onTaskRemoved(rootIntent);
}

public void stopLocationService(Context context) {        
    try {      
        stopForeground(true);
        stopSelf();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static void startLocationService(Context context) {
    try {
        Intent intent = new Intent(context, LocationTracker.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            ContextCompat.startForegroundService(context, intent);
        } else {
            context.startService(intent);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}