0

I am creating simple Location / Interval Training app for runners. In my main activity (MapsActivity) I am creating object of another class I have created (GPSImplementation). It is getting current location and calculates a few things for a runner (speed, distance traveled etc.). Then I have created another activity "SettingsActivity" where the user can change some settings. During changing settings I don't want to stop the data income for the main activity (runner can change some options during the training, I don't want to reset data and I want them to be still gathered during changing options, for example distance should be continously added). So I thought I will pass the class object I have created (gps) to another activity with a "Parcelable" method. When I've added it, the program refused to open SettingsActivity. It closes itself automaticly with a lot of mistakes. Am I using Parcelable wrong? The app on the beginning works well, It's showing location data etc. Only when I try to enter Settings (through onSettingsClick method) it crashes.

MapsActivity (Main Activity):

public class MapsActivity extends AppCompatActivity {

private TextView tvDistanceOverall;
private TextView tvTime;
private TextView tvTimeOverall;
private TextView tvSpeed;
private TextView tvSpeedOverall;
private GPSImplementation gps;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);

    gps = new GPSImplementation(this);

    tvDistanceOverall = (TextView) findViewById(R.id.textViewDistance);
    tvSpeed = (TextView) findViewById(R.id.textViewSpeed);
    tvSpeedOverall = (TextView) findViewById(R.id.textViewSpeedOverall);
    tvTime = (TextView) findViewById(R.id.textViewTime);
    tvTimeOverall = (TextView) findViewById(R.id.textViewTimeOverall);


}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_menu, menu);
    return true;
}

public void onExitClose(MenuItem item) {
    System.exit(0);
}

public void onSettingsClick(MenuItem item) {
    Intent settingsIntent = new Intent(this, SettingsActivity.class);
    settingsIntent.putExtra("GPS", (Parcelable) gps);
    startActivity(settingsIntent);
}

public void onProgramClick(MenuItem item) {
}

public void fillingData() {
    tvDistanceOverall.setText("Overall Distance: " + Double.toString(gps.getOverallDistance()));
    tvDistanceOverall.invalidate();
    if (gps.getDistance() != 0 && gps.getTime() != 0) {
        double tempo = gps.getTime() / gps.getDistance() * 100 / 6;
        double speed = gps.getDistance() / gps.getTime() * 3.6;
        gps.setOverallDistance(gps.getOverallDistance()+gps.getDistance());
        tvSpeed.setText("Tempo: " + String.format("%.2f", tempo));
        tvSpeed.invalidate();
        tvSpeedOverall.setText("Speed km/h: " + String.format("%.2f", speed));
        tvSpeedOverall.invalidate();
    } else {
        tvSpeed.setText("Tempo: 0,00");
        tvSpeed.invalidate();
        tvSpeedOverall.setText("Speed km/h: 0,00");
        tvSpeedOverall.invalidate();
    }
    tvTime.setText("Time: " + Double.toString(gps.getTime()));
    tvTime.invalidate();
    tvTimeOverall.setText("Time Overall: " + Double.toString(gps.getTimeOverall()));
    tvTimeOverall.invalidate();
}

@Override
public void onStart(){
    gps.getmGoogleApiClient().connect();
    super.onStart();

}

@Override
public void onResume(){
    super.onResume();
    fillingData();
}

SettingsActivity:

public class SettingsActivity extends AppCompatActivity {


private GPSImplementation gps;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent i = getIntent();
    Parcelable myParcelableObject = i.getParcelableExtra("GPS");
    gps = (GPSImplementation) myParcelableObject;
    setContentView(R.layout.activity_settings);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_menu, menu);
    return true;
}

public void onExitClose(MenuItem item) {
    System.exit(0);
}

public void onSettingsClick(MenuItem item) {
}

public void onProgramClick(MenuItem item){
    Intent programIntent = new Intent(this, MapsActivity.class);
    startActivity(programIntent);
}

GPSImplementation (Location tracking class):

public class GPSImplementation implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, LocationListener {

private Context context;
private TextView tvDistanceOverall;
private TextView tvTime;
private TextView tvTimeOverall;
private TextView tvSpeed;
private TextView tvSpeedOverall;
private double startTime;
private double endTime;
private double overallDistance;
private double timeOverall;
private double distance;
private double time;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location mLastLocation;
private Location myCurrentLocation;
private boolean mRequestingLocationUpdates;

public GPSImplementation(Context c) {
    this.context=c;
    mGoogleApiClient = new GoogleApiClient.Builder(context)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
    timeOverall = overallDistance = distance = time = 0;
    mRequestingLocationUpdates = true;
    mLocationRequest = new LocationRequest();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(3000);
    mLocationRequest.setFastestInterval(1000);

    tvDistanceOverall = (TextView) ((Activity)context).findViewById(R.id.textViewDistance);
    tvSpeed = (TextView) ((Activity)context).findViewById(R.id.textViewSpeed);
    tvSpeedOverall = (TextView) ((Activity)context).findViewById(R.id.textViewSpeedOverall);
    tvTime = (TextView) ((Activity)context).findViewById(R.id.textViewTime);
    tvTimeOverall = (TextView) ((Activity)context).findViewById(R.id.textViewTimeOverall);
}


public Context getContext() {
    return context;
}

public void setContext(Context context) {
    this.context = context;
}

public double getStartTime() {
    return startTime;
}

public void setStartTime(double startTime) {
    this.startTime = startTime;
}

public double getEndTime() {
    return endTime;
}

public void setEndTime(double endTime) {
    this.endTime = endTime;
}

public double getOverallDistance() {
    return overallDistance;
}

public void setOverallDistance(double overallDistance) {
    this.overallDistance = overallDistance;
}

public double getTimeOverall() {
    return timeOverall;
}

public void setTimeOverall(double timeOverall) {
    this.timeOverall = timeOverall;
}

public double getDistance() {
    return distance;
}

public void setDistance(double distance) {
    this.distance = distance;
}

public double getTime() {
    return time;
}

public void setTime(double time) {
    this.time = time;
}

public GoogleApiClient getmGoogleApiClient() {
    return mGoogleApiClient;
}

public void setmGoogleApiClient(GoogleApiClient mGoogleApiClient) {
    this.mGoogleApiClient = mGoogleApiClient;
}

public LocationRequest getmLocationRequest() {
    return mLocationRequest;
}

public void setmLocationRequest(LocationRequest mLocationRequest) {
    this.mLocationRequest = mLocationRequest;
}

public Location getmLastLocation() {
    return mLastLocation;
}

public void setmLastLocation(Location mLastLocation) {
    this.mLastLocation = mLastLocation;
}

public Location getMyCurrentLocation() {
    return myCurrentLocation;
}

public void setMyCurrentLocation(Location myCurrentLocation) {
    this.myCurrentLocation = myCurrentLocation;
}

public boolean ismRequestingLocationUpdates() {
    return mRequestingLocationUpdates;
}

public void setmRequestingLocationUpdates(boolean mRequestingLocationUpdates) {
    this.mRequestingLocationUpdates = mRequestingLocationUpdates;
}


@Override
public void onLocationChanged(Location location) {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    myCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
    endTime = SystemClock.elapsedRealtime();
    distance = getDistance(mLastLocation.getLatitude(), mLastLocation.getLongitude(), myCurrentLocation.getLatitude(), myCurrentLocation.getLongitude());
    time = (endTime - startTime) / 1000;
    startTime = endTime;
    timeOverall += time;
    mLastLocation = myCurrentLocation;
    fillingData();
}


@Override
public void onConnected(@Nullable Bundle bundle) {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
            mGoogleApiClient);

    if (mRequestingLocationUpdates) {
        startTime = SystemClock.elapsedRealtime();
        startLocationUpdates();
    }
}

private void startLocationUpdates() {
    if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
private double getDistance(double lat1, double lon1, double lat2, double lon2) {
    double latA = Math.toRadians(lat1);
    double lonA = Math.toRadians(lon1);
    double latB = Math.toRadians(lat2);
    double lonB = Math.toRadians(lon2);
    double cosAng = (Math.cos(latA) * Math.cos(latB) * Math.cos(lonB - lonA)) +
            (Math.sin(latA) * Math.sin(latB));
    double ang = Math.acos(cosAng);
    double dist = ang * 6371;
    return dist;
}

private void fillingData() {
    tvDistanceOverall.setText("Overall Distance: " + Double.toString(overallDistance));
    tvDistanceOverall.invalidate();
    if (distance != 0 && time != 0) {
        double tempo = time / distance * 100 / 6;
        double speed = distance / time * 3.6;
        overallDistance+=distance;
        tvSpeed.setText("Tempo: " + String.format("%.2f", tempo));
        tvSpeed.invalidate();
        tvSpeedOverall.setText("Speed km/h: " + String.format("%.2f", speed));
        tvSpeedOverall.invalidate();
    } else {
        tvSpeed.setText("Tempo: 0,00");
        tvSpeed.invalidate();
        tvSpeedOverall.setText("Speed km/h: 0,00");
        tvSpeedOverall.invalidate();
    }
    tvTime.setText("Time: " + Double.toString(time));
    tvTime.invalidate();
    tvTimeOverall.setText("Time Overall: " + Double.toString(timeOverall));
    tvTimeOverall.invalidate();
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}
Łukasz
  • 3
  • 3
  • "Am I using Parcelable wrong?" -- yes, insofar as you cannot pass an activity as a `Parcelable`. – CommonsWare Apr 30 '17 at 22:26
  • Maybe it would be easier to have an activity collecting the data and fragments to do the UI. That way the activity would remain active and you can pass data from the activity to the fragments. – nasch May 01 '17 at 00:32

0 Answers0