I am trying to use FusedLocationApi with a pending intention to receive period location updates so that I can send data to some server for processing. Everything is working. However, there are cases where the transmission simply stops receiving. I will need to restart the service again in order to continue.
I already have the onStartCommand service to return START_STICKY, so even if the application is killed, it should start the service again. In addition, I also added a boot receiver with the bootloader turned on, so if the phone died and the user restarted the phone, it will restart my service.
So, everything is fine and working, but just at some point, everything just stops. I noticed several times that when it stops working, the last place I got was NULL (I log every location update and error messages throughout my project).
Any ideas that search engines just stop working?
PS there is no connection failure, because I put a message and connect to this function and do not call. And this is not an Internet failure, since I am registering it. Once the Internet is restored, it will continue as usual / expected.
Thanks.
This is the main activity:
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);
MyStatusHandler.init(getApplicationContext(), textView);
...;
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) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Intent i = new Intent(this, MySettingsActivity.class);
startActivity(i);
return true;
}
else if (id == R.id.action_about){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
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);
}
AlertDialog dialog = builder.create();
dialog.show();
return true;
}
return super.onOptionsItemSelected(item);
}
public boolean isSettingsEntered(){
boolean result = true;
if (MyStatusHandler.getEmailText().equals("") || MyStatusHandler.getPasswordText().equals("")){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Please ensure both email and password are entered in settings")
.setTitle("Email and/or Password not set")
.setCancelable(false)
.setPositiveButton("OK",null);
AlertDialog dialog = builder.create();
dialog.show();
result = false;
}
return result;
}
public void startService(View view) {
if (isSettingsEntered() && isLocationEnabled(getApplicationContext())) {
...;
startService(new Intent(this, BackgroundLocationService.class));
String msg = "Connecting ...";
MyStatusHandler.setStatusText(msg);
}
}
public void stopService(View view) {
if (isSettingsEntered() && isLocationEnabled(getApplicationContext())) {
...;
String msg = "Connecting ...";
MyStatusHandler.setStatusText(msg);
}
}
public static void ...(boolean isOptIn, Location location, boolean sendOptIn){
if (sendOptIn)
{
}
else{
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Constants.CONNECTION_FAILURE_RESOLUTION_REQUEST :
MyStatusHandler.logDataToFile("Connection Failure Resolution Request - Result Code: "+String.valueOf(resultCode));
switch (resultCode) {
case Activity.RESULT_OK :
MyStatusHandler.logDataToFile("Attempting to re-start service");
startService(new Intent(this, BackgroundLocationService.class));
break;
}
}
}
}
Here is the help desk:
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) {
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 {
connectionResult.startResolutionForResult(null, Constants.CONNECTION_FAILURE_RESOLUTION_REQUEST);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
} else {
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();
}
}
Here is the broadcast receiver:
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()) {
String msg = Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Log.d("debug", msg);
MyStatusHandler.logDataToFile("Location: "+msg);
MainActivity....(MyStatusHandler.getOptInStatus(), location, false);
}
if (location == null){
MyStatusHandler.logDataToFile("Location == NULL!");
}
}
}
I set the interval to 5 minutes and Fast to 2 minutes. NOTE. I removed some function calls and code for web service operations.
, , , - . , OptInStatus , NULL.
- .