为什么我不能从我的 Activity 调用此服务?

Why can't I call this Service from my Activity?

我试过以两种不同的方式调用此服务,但似乎没有用。

第一种方式是:

startService(new Intent(getBaseContext(), LocationService.class));

为此我收到一条错误消息`

原因:`java.lang.IllegalStateException:GoogleApiClient 尚未连接。

然后我试了这个:

Intent serviceIntent = new Intent();
                serviceIntent.setAction("com.parseapp.eseen.eseen.service.LocationService");
                startService(serviceIntent);

它也没有用,相反绝对没有任何反应,logcat 中什么也没有显示。谁能帮忙? 这是完整的代码:

LocationService.class

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

// LogCat tag
private static final String TAG = LocationService.class.getSimpleName();

private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;

private Location mLastLocation;

// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;

// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;

private LocationRequest mLocationRequest;

// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
private static int DISPLACEMENT = 10; // 10 meters


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

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


}

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

    if (mGoogleApiClient != null) {
        mGoogleApiClient.connect();
        togglePeriodicLocationUpdates();
    }



    return START_NOT_STICKY;
}

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

protected void createLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(UPDATE_INTERVAL);
    mLocationRequest.setFastestInterval(FATEST_INTERVAL);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}

private void togglePeriodicLocationUpdates() {
    mGoogleApiClient.connect();

    if (!mRequestingLocationUpdates) {

        mRequestingLocationUpdates = true;

        startLocationUpdates();

        Log.d(TAG, "Periodic location updates started!");

    } else {

        mRequestingLocationUpdates = false;

        // Stopping the location updates
        stopLocationUpdates();

        Log.d(TAG, "Periodic location updates stopped!");
    }
}

protected void stopLocationUpdates() {
    LocationServices.FusedLocationApi.removeLocationUpdates(
            mGoogleApiClient, this);
}

protected void startLocationUpdates() {
    mGoogleApiClient.connect();
    LocationServices.FusedLocationApi.requestLocationUpdates(
            mGoogleApiClient, mLocationRequest, this);

}

@Override
public void onConnected(Bundle arg0) {
    createLocationRequest();
}

@Override
public void onConnectionSuspended(int arg0) {
    mGoogleApiClient.connect();
}

@Override
public void onConnectionFailed(ConnectionResult result) {
    Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
            + result.getErrorCode());
}

@Override
public void onLocationChanged(Location location) {
    // Assign the new location
    mLastLocation = location;

    Toast.makeText(getApplicationContext(), "Location changed!",
            Toast.LENGTH_SHORT).show();
}

@Override
public boolean stopService(Intent name) {
    return super.stopService(name);
}

SearchActivity.class

button = (Button)findViewById(R.id.buttonPressed);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent serviceIntent = new Intent();
            serviceIntent.setAction("com.parseapp.eseen.eseen.service.LocationService");
            startService(serviceIntent);
        }
    });

AndroidManifest.xml

<service android:name=".LocationService">

        <intent-filter>
            <action android:name=".LocationService"> </action>
        </intent-filter>

    </service>

   

你的包名com.parseapp.eseen.eseen 并且您尝试使用 com.parseapp.eseen.eseen.service.LocationService 作为操作进行调用,但您在清单中提到 .LocationService 这意味着您应该使用 com.parseapp.eseen.eseen.LocationService

调用

startLocationUpdates(); 您再次调用连接并在连接前请求 api 从 onConnected 方法请求位置更新 LocationServices.FusedLocationApi.requestLocationUpdates( mGoogleApiClient, mLocationRequest, 这个);

您第一次尝试使用 class 名称启动服务成功了:

startService(new Intent(getBaseContext(), LocationService.class));

异常发生在服务开始执行后。在 GoogleApi 连接成功之前,即在调用 onConnected() 之后,您的代码无法使用 LocationServices。您的代码在到达 startLocationUpdates() 之前多次调用 connect(),但不等待调用 onConnected()。该方法是您在建立连接并且可以使用 LocationServices 时收到的通知。

demo code 适用于 AsyncTask,而非服务,但提供了如何使用 CountDownLatch 完成连接处理的想法。

使用此代码启动服务

startService(new Intent(getBaseContext(), BackgroundLocationUpdate.class));

此止一

stopService(new Intent(getBaseContext(), BackgroundLocationUpdate.class));

这用于获取位置更新

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

    public static final String BROADCAST_ACTION = "Location Change";
    private static final int ONE_MINUTES = 1000 * 60;
    public LocationManager locationManager;
    public MyLocationListener listener;
    public Location previousBestLocation = null;
    /**
     * Provides the entry point to Google Play services.
     */
    protected GoogleApiClient mGoogleApiClient;

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


    }

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

    /**
     * Builds a GoogleApiClient. Uses the addApi() method to request the LocationServices API.
     */
    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

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

    /**
     * Determines whether one Location reading is better than the current Location fix
     *
     * @param location            The new Location that you want to evaluate
     * @param currentBestLocation The current Location fix, to which you want to compare the new one
     */
    protected boolean isBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return true;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > ONE_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -ONE_MINUTES;
        boolean isNewer = timeDelta > 0;

//         If it's been more than two minutes since the current location, use the new location
//         because the user has likely moved
        if (isSignificantlyNewer) {
            return true;
            // If the new location is more than two minutes older, it must be worse
        } else if (isSignificantlyOlder) {
            return false;
        }

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 300;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return true;
        } else if (isNewer && !isLessAccurate) {
            return true;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return true;
        }
        return false;
    }

    /**
     * Checks whether two providers are the same
     */
    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }

    @Override
    public void onDestroy() {
        // handler.removeCallbacks(sendUpdatesToUI);
        super.onDestroy();
        Log.v("STOP_SERVICE", "DONE");
        locationManager.removeUpdates(listener);
    }

    @Override
    public void onConnected(Bundle bundle) {
        // Provides a simple way of getting a device's location and is well suited for
        // applications that do not require a fine-grained location and that do not need location
        // updates. Gets the best and most recent location currently available, which may be null
        // in rare cases when a location is not available.
        previousBestLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    public class MyLocationListener implements LocationListener {
//Location changes fetch here
        public void onLocationChanged(final Location loc) {
            Log.i("LOCATIONCHANGE", "Location changed");
            if (loc != null) {
                if (isBetterLocation(loc, previousBestLocation)) {
                    loc.getLatitude();
                    loc.getLongitude();

                }
            }
        }

        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) {

        }
    }
}