2015-06-24 54 views
1

我試過用兩種不同的方式調用這個服務,但它似乎沒有工作。爲什麼我不能從我的活動中調用此服務?

第一種方式是:

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> 
+0

我可以知道你的包名請 – praveen

+0

' package =「com.parseapp.eseen.eseen」' – Ivan

+0

可能是這個鏈接支持你解決它:http://stackoverflow.com/questions/29343922/googleapiclient-is-throwing-googleapiclient-is-not-connected-yet-after-onconne –

回答

1

你開始使用類名服務第一次嘗試的工作:

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

異常發生後,該服務開始執行。在GoogleApi連接成功後,即在調用onConnected()之後,您的代碼才能使用LocationServices。在獲取startLocationUpdates()之前,您的代碼會多次調用connect(),但不會等待onConnected()被調用。該方法是您在建立連接並使用LocationServices時收到的通知。

這個demo code是用於AsyncTask,而不是服務,但給出瞭如何使用CountDownLatch完成連接處理的想法。

+0

那麼在onStartCommand中是否需要檢查一下GoogleApi是否成功,然後再移動到startLocationUpdates? – Ivan

+0

你有什麼機會嗎?我有一個問題。 – Ivan

+0

@Ivan你有問題嗎? –

0

你包的名字com.parseapp.eseen.eseen 和你tryng使用com.parseapp.eseen.eseen.service.LocationService爲行動電話,但你在清單提到.LocationService是手段你應該打電話使用com.parseapp.eseen.eseen.LocationService

in startLocationUpdates();您呼叫重新連接,從連接 請求locationupdates之前請求API onConnected方法 LocationServices.FusedLocationApi.requestLocationUpdates( mGoogleApiClient,mLocationRequest,這一點);

+0

讓我如果仍然有任何問題 – praveen

+0

我試着將它改爲'com.parseapp.eseen.eseen.LocationService',但它仍然沒有做任何事情。當我點擊按鈕絕對沒有什麼新的logcat出現。 – Ivan

+0

哪一行是非法狀態異常 – praveen

1

使用此代碼來啓動服務

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

     } 
    } 
} 
+0

對於我正在工作的應用程序,如果新位置從最後一個位置改變了約10米,我需要更頻繁地更新約5-10秒的時間。 – Ivan

+0

然後,只需將時間從60秒改爲您的需求即可。但請記住,這將導致電池排水更新的位置,所以不建議這麼頻繁。 –

+0

@Ankit爲什麼包含與GoogleApiClient相關的代碼?不需要使用LocationManager,並且從不製作connect()請求,因此buildGoogleApiClient()和連接回調沒有任何用處。 –

相關問題