Служба FoxyLocationApi Background Location перестает получать обновления случайно

Я пытаюсь использовать FusedLocationApi с ожиданием намерения получить обновления местоположения периода, чтобы я мог отправить данные на какой-либо сервер для обработки. Все работает. Однако есть несколько случаев, когда трансляция просто прекращает прием. Мне нужно будет снова перезапустить службу, чтобы она продолжалась.

У меня уже есть служба onStartCommand для возврата START_STICKY, поэтому, даже если приложение будет убито, он должен снова запустить службу. Кроме того, я также добавил загрузочный приемник с включенным загрузчиком, поэтому, если телефон умер и пользователь перезапустил телефон, он перезапустит мою службу.

Кажется, все прекрасно и работает, но в какой-то момент все просто прекращается. Я заметил несколько раз, что, когда он перестает работать, последнее место, которое я получил, было NULL (я регистрирую каждое обновление местоположения и сообщения об ошибках в течение всего моего проекта).

Любые идеи, почему службы поиска просто перестают работать?

PS нет сбоя соединения, потому что я помещаю сообщение и подключаюсь к этой функции, и он не вызывается. И это не интернет-выход, так как я регистрирую это. Как только интернет будет восстановлен, он будет продолжаться как обычно / ожидается.

Благодарю.

Это основная деятельность:

public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayShowHomeEnabled(false); actionBar.setDisplayShowTitleEnabled(false); if (findViewById(android.R.id.home) != null) { findViewById(android.R.id.home).setVisibility(View.GONE); } LayoutInflater inflator = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflator.inflate(R.layout.header_logo, null); ActionBar.LayoutParams params = new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT, Gravity.CENTER); actionBar.setDisplayShowCustomEnabled(true); actionBar.setCustomView(view, params); } setContentView(R.layout.activity_main); TextView textView = (TextView) findViewById(R.id.status_text); // init preferences and status handler MyStatusHandler.init(getApplicationContext(), textView); // init web service call class ...; // check for location services if (!isLocationEnabled(getApplicationContext())){ String msg = "Location services not turned on"; MyStatusHandler.setStatusText(msg); } } public static boolean isLocationEnabled(Context context) { int locationMode = 0; String locationProviders; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){ try { locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } return locationMode != Settings.Secure.LOCATION_MODE_OFF; }else{ locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED); return !TextUtils.isEmpty(locationProviders); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { // create new intent activity for the settings page Intent i = new Intent(this, MySettingsActivity.class); startActivity(i); return true; } else if (id == R.id.action_about){ // 1. Instantiate an AlertDialog.Builder with its constructor AlertDialog.Builder builder = new AlertDialog.Builder(this); // 2. Chain together various setter methods to set the dialog characteristics if (Constants.DEBUG_BUILD == true) { builder.setMessage("v." + MyStatusHandler.getReleaseVersionNum() + " dev Build: " + MyStatusHandler.getDevVersionNum()) .setTitle("About") .setCancelable(false) .setPositiveButton("OK", null); } else{ builder.setMessage("v." + MyStatusHandler.getReleaseVersionNum()) .setTitle("About") .setCancelable(false) .setPositiveButton("OK", null); } // 3. Get the AlertDialog from create() AlertDialog dialog = builder.create(); // show it dialog.show(); return true; } return super.onOptionsItemSelected(item); } // check email entered public boolean isSettingsEntered(){ boolean result = true; if (MyStatusHandler.getEmailText().equals("") || MyStatusHandler.getPasswordText().equals("")){ // 1. Instantiate an AlertDialog.Builder with its constructor AlertDialog.Builder builder = new AlertDialog.Builder(this); // 2. Chain together various setter methods to set the dialog characteristics builder.setMessage("Please ensure both email and password are entered in settings") .setTitle("Email and/or Password not set") .setCancelable(false) .setPositiveButton("OK",null); // 3. Get the AlertDialog from create() AlertDialog dialog = builder.create(); // show it dialog.show(); result = false; } return result; } /** Called when the user clicks the Opt in button */ public void startService(View view) { // Do something in response to button if (isSettingsEntered() && isLocationEnabled(getApplicationContext())) { // send opt in to web service ...; // start service startService(new Intent(this, BackgroundLocationService.class)); // update status text String msg = "Connecting ..."; MyStatusHandler.setStatusText(msg); } } /** Called when the user clicks the Opt out button */ public void stopService(View view) { // Do something in response to button if (isSettingsEntered() && isLocationEnabled(getApplicationContext())) { // send OptOut to web service ...; // update status text String msg = "Connecting ..."; MyStatusHandler.setStatusText(msg); } } public static void ...(boolean isOptIn, Location location, boolean sendOptIn){ if (sendOptIn) { // send opt in via async task } else{ // send location via async task } } // Handle results returned to the FragmentActivity by Google Play services @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Decide what to do based on the original request code switch (requestCode) { case Constants.CONNECTION_FAILURE_RESOLUTION_REQUEST : // log the error MyStatusHandler.logDataToFile("Connection Failure Resolution Request - Result Code: "+String.valueOf(resultCode)); // If the result code is Activity.RESULT_OK, try to connect again switch (resultCode) { case Activity.RESULT_OK : // Try the request again MyStatusHandler.logDataToFile("Attempting to re-start service"); // start service startService(new Intent(this, BackgroundLocationService.class)); break; } } } } 

Вот справочная служба:

 public class BackgroundLocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { public static final String TAG = BackgroundLocationService.class.getSimpleName(); private GoogleApiClient mGoogleApiClient; private boolean mInProgress; private LocationRequest mLocationRequest; 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) { super.onStartCommand(intent, flags, startId); if(mGoogleApiClient.isConnected() || mInProgress) return START_STICKY; if(!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting() && !mInProgress) { mInProgress = true; mGoogleApiClient.connect(); } return START_STICKY; } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onConnected(Bundle bundle) { mLocationRequest = LocationRequest.create() .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) .setFastestInterval(Constants.FASTEST_INTERVAL) .setInterval(Constants.UPDATE_INTERVAL); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(this, MyLocationHandler.class), PendingIntent.FLAG_CANCEL_CURRENT); if (mGoogleApiClient.isConnected()) { LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, pendingIntent); } else{ MyStatusHandler.setStatusText("Google Client Failed"); } } @Override public void onConnectionSuspended(int i) { } @Override public void onLocationChanged(Location location) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { mInProgress = false; if (connectionResult.hasResolution()) { try { // Start an Activity that tries to resolve the error connectionResult.startResolutionForResult(null, Constants.CONNECTION_FAILURE_RESOLUTION_REQUEST); // * Thrown if Google Play services canceled the original // * PendingIntent } catch (IntentSender.SendIntentException e) { // Log the error e.printStackTrace(); } } else { //* If no resolution is available, display a dialog to the // * user with the error. Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode()); MyStatusHandler.setStatusText("Location services connection failed with code " + connectionResult.getErrorCode()); } } @Override public void onDestroy(){ mInProgress = false; if (mGoogleApiClient.isConnected()) { LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); mGoogleApiClient.disconnect(); } super.onDestroy(); } } 

Вот радиовещательный приемник:

 public class MyLocationHandler extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Location location = intent.getParcelableExtra(FusedLocationProviderApi.KEY_LOCATION_CHANGED); if (location != null && MyStatusHandler.getOptInStatus()) { // debug messages String msg = Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude()); Log.d("debug", msg); // log location to file MyStatusHandler.logDataToFile("Location: "+msg); // send Location to web service MainActivity....(MyStatusHandler.getOptInStatus(), location, false); } if (location == null){ MyStatusHandler.logDataToFile("Location == NULL!"); } } } 

Я установил интервал 5 минут, а Fast – 2 минуты. ПРИМЕЧАНИЕ. Я удалил некоторые вызовы функций и код для операций веб-сервиса

Все работает, и я получаю обновления, как ожидалось, но в какой-то момент вещательный приемник ничего не получает. Когда я проверяю журналы, OptInStatus не изменяется, и последнее переданное местоположение местоположения было равно NULL.

Другие части моего кода для вызова веб-службы и обработки сообщений о статусе не касаются запросов на обслуживание или местоположение.