如何从 Android 服务访问 GPS?

How do I access GPS from Android Service?

我正在尝试从后台服务获取位置信息。我使用以下代码从 Activity 启动服务。

Intent serviceIntent = new Intent(this, LocationService.class);
startService(serviceIntent);

这是我的服务代码。

public class LocationService extends Service {

    private Thread t;
    Looper threadLooper = null;

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

        Log.i("Imp", "Inside service.");

        new LooperThread().start();

        return Service.START_NOT_STICKY;
    }

    private void logLocation(String lat, String lng){

        //write to database.
    }

    class LooperThread extends Thread {


        public void run() {
            Log.i("Imp", "inside thread");
            Looper.prepare();

            Context context = getApplicationContext();
            String svcName = Context.LOCATION_SERVICE;
            LocationManager locationManager = (LocationManager) context.getSystemService(svcName);

            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            criteria.setPowerRequirement(Criteria.POWER_HIGH);
            criteria.setAltitudeRequired(false);
            criteria.setBearingRequired(false);
            criteria.setSpeedRequired(false);
            criteria.setCostAllowed(false);

            Log.i("Imp", "Regestring event.");
            locationManager.requestSingleUpdate(criteria, locationListener, Looper.myLooper());
            Log.i("Imp",  "event reg.");

            Looper.loop();
            stopSelf();


        }
    }

    final LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            Log.i("Imp",  "Inside event");
            if(location != null){
                String lat = Double.toString(location.getLatitude());
                String lng = Double.toString(location.getLongitude());
                Log.i("Imp",  "Lat " + lat);
                Log.i("Imp",  "lng " + lng);

                logLocation(lat, lng);
            }
        }

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

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };
}

最初我使用得到错误,因为我为 Looper 对象传递了 null 参数。但是在传递了 looper 对象之后,我没有得到任何错误,但我什至没有得到任何坐标。

我每次 运行 代码时都会收到 event reg. 消息,但由于某种原因它从不调用监听器。

PS :我 运行 在我的 phone 上而不是模拟器上编写代码。

可能您还没有在清单文件中注册该服务。 所有服务都必须由清单文件中的元素表示。任何未在此处声明的内容都不会被系统看到,并且永远不会 运行.

<service android:enabled=["true" | "false"] android:exported=["true" | "false"] android:icon="drawable resource" android:isolatedProcess=["true" | "false"] android:label="string resource" android:name="string" android:permission="string" android:process="string" > </service>

Ref Source

推荐的方法是使用 Google 播放服务中的位置 API。

添加 google 播放服务依赖。

compile 'com.google.android.gms:play-services:+'

以及以下代码。

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

public class FusedLocationProvider implements
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener,
        com.google.android.gms.location.LocationListener,
        ArchitectViewHolderInterface.ILocationProvider {

    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private LocationListener listener;
    private String TAG = "FusedLocationProvider";

    public FusedLocationProvider(Context ctx, LocationListener locationListener){

        mGoogleApiClient = new GoogleApiClient.Builder(ctx)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        mGoogleApiClient.connect();

        Log.i(TAG, "Connecting...");

        this.listener = locationListener;
    }

    @Override
    public void onConnected(Bundle bundle) {

        Log.i(TAG, "onConnected");

        mLocationRequest = LocationRequest.create();
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setInterval(1000); // Update location every second

        try{
            if(mGoogleApiClient.isConnected()) {

                Log.i(TAG, "requestLocationUpdates");
                LocationServices.FusedLocationApi.requestLocationUpdates(
                        mGoogleApiClient, mLocationRequest, this);
            }
        }catch (SecurityException se){
            Log.i(TAG, se.toString());
        }catch (Exception e){
            Log.i(TAG, e.toString());
        }

    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "onConnectionSuspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.i(TAG, "onConnectionFailed");
    }

    @Override
    public void onLocationChanged(Location recentLoc) {
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

        StrictMode.setThreadPolicy(policy);

        Log.i(TAG, Double.toString(recentLoc.getLongitude()));

        listener.onLocationChanged(recentLoc);
    }


    public void onPause() {
        Log.i(TAG, "onPause");
        if(mGoogleApiClient.isConnected()) {

            Log.i(TAG, "removeLocationUpdates");
            LocationServices.FusedLocationApi.removeLocationUpdates(
                    mGoogleApiClient, this);
        }
    }

    @Override
    public void onResume() {
        Log.i(TAG, "onResume");
        try{
            if(mGoogleApiClient.isConnected()){

                Log.i(TAG, "requestLocationUpdates");
                LocationServices.FusedLocationApi.requestLocationUpdates(
                        mGoogleApiClient, mLocationRequest, this);
            }

        }catch (SecurityException se){
            Log.i(TAG, se.toString());
        }catch (Exception e){
            Log.i(TAG, e.toString());
        }
    }


    public void onStop(){
        Log.i(TAG, "onStop");
        if(mGoogleApiClient.isConnected()) {

            Log.i(TAG, "disconnect");
            mGoogleApiClient.disconnect();
        }
    }
}

以及 android 清单文件中的以下权限。

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_GPS" />