Android,在熄屏状态下获取位置

标签 android service location android-gps

我使用带有融合 api 的启动服务,并直接在其上实现位置监听器。 即使在屏幕锁定时位置也会继续更新,但如果屏幕熄灭则停止。

那么,有没有什么办法可以确保在屏幕关闭时位置会不断更新呢?

我读了很多其他问题,但我真的不知道我错过了什么。

public class CLocationService extends Service implements GoogleApiClient.ConnectionCallbacks, LocationListener,
    GoogleApiClient.OnConnectionFailedListener {

private GoogleApiClient mGoogleApiClient;
private PowerManager.WakeLock mWakeLock;
private LocationRequest mLocationRequest;
// Flag that indicates if a request is underway.
private boolean mInProgress;

private Boolean servicesAvailable = false;

private boolean isStarted;

public static final int LOCATION_SERVICE_NOTIFICATION_ID = 4567654;

private void showNotification() {

    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    Notification notification = new Notification.Builder(this)
            .setContentTitle(getText(R.string.app_name))
            .setContentText("")
            .setSmallIcon(R.mipmap.ic_notification)
            .setContentIntent(pendingIntent)
            .setTicker("")
            .build();

    startForeground(LOCATION_SERVICE_NOTIFICATION_ID, notification);
}

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

@Override
public void onCreate() {
    super.onCreate();

    /*
     * Create a new location client, using the enclosing class to
     * handle callbacks.
     */
    setUpLocationClientIfNeeded();

    startLocationServices();
}

/*
 * Create a new location client, using the enclosing class to
 * handle callbacks.
 */
protected synchronized void buildGoogleApiClient() {
    this.mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
}

private boolean servicesConnected() {

    // Check that Google Play services is available
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

    // If Google Play services is available
    if (ConnectionResult.SUCCESS == resultCode) {

        return true;
    } else {

        return false;
    }
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    PowerManager mgr = (PowerManager) getSystemService(Context.POWER_SERVICE);

    /*
    WakeLock is reference counted so we don't want to create multiple WakeLocks. So do a check before initializing and acquiring.
    This will fix the "java.lang.Exception: WakeLock finalized while still held: MyWakeLock" error that you may find.
    */
    if (this.mWakeLock == null) { //**Added this
        this.mWakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
    }

    if (!this.mWakeLock.isHeld()) { //**Added this
        this.mWakeLock.acquire();
    }

    if (!servicesAvailable || mGoogleApiClient.isConnected() || mInProgress)
        return START_STICKY;

    setUpLocationClientIfNeeded();
    if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress) {
        mInProgress = true;
        mGoogleApiClient.connect();
    }

    return START_STICKY;
}

private void setUpLocationClientIfNeeded() {
    if (mGoogleApiClient == null)
        buildGoogleApiClient();
}

@Override
public void onDestroy() {

    stopLocationServices();

    super.onDestroy();
}

private void startLocationServices() {

    mInProgress = false;
    // Create the LocationRequest object
    mLocationRequest = LocationRequest.create();
    // Use high accuracy
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    // Set the update interval to 5 seconds
    mLocationRequest.setInterval(5000);
    // Set the fastest update interval to 1 second
    mLocationRequest.setFastestInterval(1000);
    mLocationRequest.setSmallestDisplacement(0);

    servicesAvailable = servicesConnected();
}

private void stopLocationServices() {

    // Turn off the request flag
    this.mInProgress = false;

    if (this.servicesAvailable && this.mGoogleApiClient != null) {
        this.mGoogleApiClient.unregisterConnectionCallbacks(this);
        this.mGoogleApiClient.unregisterConnectionFailedListener(this);
        this.mGoogleApiClient.disconnect();
        // Destroy the current location client
        this.mGoogleApiClient = null;
    }
    // Display the connection status
    // Toast.makeText(this, DateFormat.getDateTimeInstance().format(new Date()) + ":
    // Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();

    if (this.mWakeLock != null) {
        this.mWakeLock.release();
        this.mWakeLock = null;
    }
}

private void cancelNotification() {
    NotificationManager nMgr = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
    nMgr.cancel(LOCATION_SERVICE_NOTIFICATION_ID);
}

@Override
public void onLocationChanged(Location location) {
    // log the new location
}

@Override
public void onConnected(@Nullable Bundle bundle) {

    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        // TODO: Consider calling
        //    ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
        //                                          int[] grantResults)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.
        return;
    }
    LocationServices.FusedLocationApi.requestLocationUpdates(this.mGoogleApiClient,
            mLocationRequest, this); // This is the changed line.
}

@Override
public void onConnectionSuspended(int i) {

    // Turn off the request flag
    mInProgress = false;
    // Destroy the current location client
    mGoogleApiClient = null;
}

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

    mInProgress = false;

    /*
     * Google Play services can resolve some errors it detects.
     * If the error has a resolution, try sending an Intent to
     * start a Google Play services activity that can resolve
     * error.
     */
    if (connectionResult.hasResolution()) {

        // If no resolution is available, display an error dialog
    } else {

    }
}

最佳答案

我不确定我是否得到了你的答案,但由于你已经 9 天一无所获,我会给出一些建议。

我的应用正在执行您希望执行的操作。我使用长时间运行的启动服务来保持位置更新,即使在手机关闭时也是如此。

最有可能导致您的代码和我的代码之间出现不同行为的差异是 onStartCommand() 的返回。您正在返回 START_STICKY。这是类似这样的东西的推荐返回:

This mode makes sense for things that will be explicitly started and stopped to run for arbitrary periods of time, such as a service performing background music playback.

但是,我在 Intent 中发送我需要重新传送的信息,所以我返回 START_REDELIVER_INTENT。试试这个(即使您不需要重新传送任何数据)看看它是否能解决您的问题。

此外,我的实现中不需要 WakeLock。也许您的实现需要这个。你试过没有它吗?

编辑:最后,您使用的是哪种设备? link

关于Android,在熄屏状态下获取位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41965789/

相关文章:

android - Android 上的 Irrlicht 帧速率低

java - Sqlite - 降级

android - ListView 中的 ViewPager - 动态测量高度(WRAP_CONTENT 在适配器中膨胀)

unix - 从 C/C++ 应用程序启动 systemd 服务或调用 D-Bus 服务

java - 如何确定地理点(纬度,经度对)是否位于连接两个地理点的线上

Angular :类型 'go' 上不存在属性 'Location'

android - 单击微调器会出现 WindowManager$BadTokenException

可绑定(bind)的Android前台服务

java - 如果 Activity 被杀死,Service 会发生什么?

android - 未连接。调用 Connect 或等待 onConnected() 在 onConnected 内部调用异常?