My problem is that when i rotate the GPS, then I can't stop the LocationServices.FusedLocationApi. This only happens after I have rotated the screen. If I dont change the orientation the start and stop works fine.
This should controll if it should update or not
private boolean mRequestingLocationUpdates;
Here is the values I want to save
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(REQUESTING_LOCATION_UPDATES_KEY, mRequestingLocationUpdates);
savedInstanceState.putBoolean(REQUESTING_SAVED_FIRSTTIME, isFirstTime);
savedInstanceState.putString(LAST_UPDATED_TIME_STRING_KEY, mLastUpdateTime);
super.onSaveInstanceState(savedInstanceState);
}
private void updateValuesFromBundle(Bundle savedInstanceState) {
Log.i(TAG, "Updating values from bundle");
if (savedInstanceState != null) {
if (savedInstanceState.keySet().contains(REQUESTING_LOCATION_UPDATES_KEY)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(REQUESTING_LOCATION_UPDATES_KEY);
if (mProgressBar != null) {
mProgressBar.setVisibility(View.VISIBLE);
}
if (lightsOn != null) {
lightsOn.setVisibility(View.VISIBLE);
}
}
if (savedInstanceState.keySet().contains(IS_FIRST_TIME_KEY)) {
isFirstTime = savedInstanceState.getBoolean(IS_FIRST_TIME_KEY);
}
// Update the value of mLastUpdateTime from the Bundle and update the UI.
if (savedInstanceState.keySet().contains(LAST_UPDATED_TIME_STRING_KEY)) {
mLastUpdateTime = savedInstanceState.getString(LAST_UPDATED_TIME_STRING_KEY);
}
}
}
START and STOP Location updates
protected void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
onCreate With buttons to controll the start and stop
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mainreal);
// Starting the gps and location updates
mStartTrackerButton = (Button) findViewById(R.id.buttonStart);
mStartTrackerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainReal.this, "START", Toast.LENGTH_SHORT).show();
// Set true, will generate a new date, and a new startpoint in database
isFirstTime = true;
if (mProgressBar != null) {
mProgressBar.setVisibility(View.VISIBLE);
}
if (lightsOn != null) {
lightsOn.setVisibility(View.VISIBLE);
}
mRequestingLocationUpdates = true;
startLocationUpdates();
}
});
// STOP the gps and location updates
mStopTrackerButton = (Button) findViewById(R.id.buttonStop);
mStopTrackerButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mProgressBar != null) {
mProgressBar.setVisibility(View.GONE);
}
if (lightsOn != null) {
lightsOn.setVisibility(View.GONE);
}
mRequestingLocationUpdates = false;
stopLocationUpdates();
}
});
// Setting up google api client
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(5 * 1000); // 2 seconds, in milliseconds
mRequestingLocationUpdates = false;
// Update values using data stored in the Bundle.
updateValuesFromBundle(savedInstanceState);
}
I don't exactly understand your question, but if you want to save something when the screen is rotated you could check for screen rotation, like this:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int orientation = newConfig.orientation;
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// Save something
} else (orientation == Configuration.ORIENTATION_LANDSCAPE) {
// Save something
}
}
Or if you just want to lock the screen altogther (which also might be useful), you could write that in your AndroidManifest.xml file, like so:
<activity
android:name="MainActivity"
android:screenOrientation="portrait"
android:configChanges="keyboardHidden|orientation|screenSize">
Hope it helps!
Needed to add this inside onPause(). Could have some explanation about it.
#Override
protected void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
Related
I have an app which obtains the users location and sends it to my Firebase Database which has a list of locations closest to the user. The location radius has been set to less than 50km(50000m). if there are no locations within that radius, I want an alert dialog to appear saying that there are no locations available. The locations will be updated as the app runs. The alert dialog should be shown every time the user tries to access the locations within the set radius. Can someone help me out on how to go about doing it? Any help will be greatly appreciated.
LActivity
public class LActivity extends AppCompatActivity implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "Location1";
private static final long INTERVAL = 1000 * 10;
private static final long FASTEST_INTERVAL = 1000 * 5;
;
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
public Location mCurrentLocation;
String mLastUpdateTime;
ViewPager viewPager;
ProgressDialog progressdialog;
protected void createLocationRequest() {
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressdialog = new ProgressDialog(this);
progressdialog.setMessage("Pending");
Runnable progressRunnable = new Runnable() {
#Override
public void run() {
progressdialog.cancel();
}
};
Handler pdcanceller = new Handler();
pdcanceller.postDelayed(progressRunnable,1500);
progressdialog.show();
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
setContentView(R.layout.activity_rape_location);
viewPager = (ViewPager) findViewById(R.id.viewpagerL);
viewPager.setAdapter(new RapeLocationPageAdapter(getSupportFragmentManager(),
LActivity.this));
}
public void getLocation(View view) {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 501);
} else {
mGoogleApiClient.connect();
}
progressdialog.show();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 501) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mGoogleApiClient.connect();
} else {
Toast.makeText(this, "Location permission denied. Please grant location permission to the app.", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onStart() {
super.onStart();
Log.d(TAG, "onStart fired ..............");
mGoogleApiClient.connect();
progressdialog.show();
}
#Override
public void onStop() {
super.onStop();
Log.d(TAG, "onStop fired ..............");
mGoogleApiClient.disconnect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
startLocationUpdates();
}
protected void startLocationUpdates() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED)
{
final AlertDialog builder = new AlertDialog.Builder(this).create();
builder.setMessage("Location has not been granted");
builder.setButton(AlertDialog.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
builder.dismiss();
}
});
builder.show();
return;
}
PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Log.d(TAG, "Location update started ..............: ");
progressdialog.show();
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
final AlertDialog builder = new AlertDialog.Builder(this).create();
builder.setMessage("If there are no locations near you, please contact the local police for immediate attention");
builder.setButton(AlertDialog.BUTTON_POSITIVE, "Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
builder.dismiss();
}
});
builder.show();
}
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
RapeLocation rapeLocation = (RapeLocation) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.viewpagerRape + ":" + viewPager.getCurrentItem());
rapeLocation.update(mCurrentLocation);
}
}
LActivityMain
public class LActivityMain extends Fragment {
RecyclerView recyclerView;
LocationsAdapter locationsAdapter;
ArrayList<LocationModel> locationModelArrayList = new ArrayList<LocationModel>();
ArrayList<LocationModel> filteredlocationModelArrayList = new ArrayList<LocationModel>();
protected DatabaseReference mDatabase;
LActivityMain locationActivityfin;
Button bnt1;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_locationmain, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
locationActivityfin = (LActivityMain) getActivity();
mDatabase = FirebaseDatabase.getInstance().getReference();
recyclerView = view.findViewById(R.id.rvLocations);
bnt1 = view.findViewById(R.id.locdone);
bnt1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().onBackPressed();
}
});
locationsAdapter = new LocationsAdapter(getActivity(), new OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
LatLng latLng = new LatLng(filteredlocationModelArrayList.get(position).getLatitude(),
filteredlocationModelArrayList.get(position).getLongitude());
String url = "http://maps.google.com/maps?saddr=" + locationActivityfin.mCurrentLocation.getLatitude() + "," + locationActivityfin.mCurrentLocation.getLongitude() + "&daddr=" + latLng.latitude + "," + latLng.longitude + "&mode=driving";
Intent intent = new Intent(android.content.Intent.ACTION_VIEW,
Uri.parse(url));
PackageManager packageManager = getActivity().getPackageManager();
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent);
} else {
if (getView() != null)
Snackbar.make(getView(), "Make sure Google Maps is installed to use this feature", Snackbar.LENGTH_LONG).show();
}
}
}, filteredlocationModelArrayList);
getDataFromServer();
//textView.setText(getArguments().getDouble("latitude") + ", " + getArguments().getDouble("longitude"));
}
public void update(Location location) {
// Toast.makeText(getActivity(), "updated", Toast.LENGTH_SHORT).show();
filteredlocationModelArrayList.clear();
for (LocationModel locationModel : locationModelArrayList) {
Location location1 = new Location("Loc");
location1.setLatitude(locationModel.getLatitude());
location1.setLongitude(locationModel.getLongitude());
if (location1.distanceTo(location) <= 50000 && filteredlocationModelArrayList.size() < 30) {
double distance = (double) (location1.distanceTo(location) / 1000);
try {
distance = round(distance, 2);
} catch (Exception e) {
}
locationModel.setDistance(distance);
filteredlocationModelArrayList.add(locationModel);
}
locationsAdapter.update(filteredlocationModelArrayList);
}
}
public double round(double value, int places) {
if (places <= 0) throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places, RoundingMode.HALF_UP);
return bd.doubleValue();
}
void getDataFromServer() {
mDatabase.child("ali").child("location221").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot dataChild : dataSnapshot.getChildren()) {
LocationModel locationModel = dataChild.getValue(LocationModel.class);
locationModelArrayList.add(locationModel);
}
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(locationsAdapter);
if (locationActivityRape.mCurrentLocation != null) {
update(locationActivityRape.mCurrentLocation);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
Assuming you have figured out how to tell that some resource is within some distance from the app, the next question is do you want this to update the app over its entire lifecycle or just at startup or resume.
For the former, as part of your app initialization you start up a timed task of some sort. You want this code to be off the UI thread, and it probably needs to use the network to do its job. The idea is that this task wakes up periodically and does whatever it needs to do to check for external resources.
As long as it finds some valid resource(s) it just goes back to sleep. If it finds no valid resources it then either invokes a callback method or raises an intent that your client code listens for to display a dialog, ring a bell, etc. Make sure you shut down this task when cleaning up your app, and make sure you can cancel the running state and/or it handles and uses timeouts.
If only once on startup just fire off an AsyncTask that gets some results, and then reports via its UI thread handler (or communicates back to the caller) so a dialog can be shown and perhaps the app closed (if these resources are critical to the app lifecycle).
Related Q&A: Timertask or Handler, AsyncTask Android example (But there are many others resources out there.)
I want to get location from background and submit it to server so which is the best option to do the same like Job scheduler or Service. and why ?. I also want to know about battery saved by job scheduler while continuously we make web apicall.
This is my implementation, I don't use Job Scheduler or Service because it's not necessary. I use the Application class so you will be able to get the location of user in all your app.
First, you need to create a LocationHelper class, that will do all the work for you:
public class LocationHelper implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final int REQUEST_LOCATION_PERMISSION = 0;
private static final int REQUEST_RESOLVE_ERROR = 1;
private static GoogleApiClient mGoogleApiClient;
private Fragment mFragment;
private final Activity mActivity;
private final Callback mCallback;
private Location mLastLocation;
private boolean mResolvingError;
private LocationRequest mLocationRequest;
private boolean mRegisterLocationUpdates;
public interface Callback {
void onLastLocation(Location userLocation);
}
public LocationHelper(Fragment fragment, Callback callback) {
this(fragment.getActivity(), callback);
mFragment = fragment;
}
public LocationHelper(Activity activity, Callback callback) {
mActivity = activity;
mCallback = callback;
mLocationRequest = new LocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
obtainLastLocation();
}
private void obtainLastLocation() {
// Verifies if user give us permission to obtain its suggestionLocationV2.
if (ActivityCompat.checkSelfPermission(mActivity,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(mActivity,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity,
Manifest.permission.ACCESS_COARSE_LOCATION)) {
// Show an explanation to the user why we need its suggestionLocationV2.
requestPermissionRationale();
} else {
requestPermission();
}
// We don't have user permission to get its geo suggestionLocationV2, abort mission.
return;
}
if (!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
return;
}
Location lastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (lastLocation != null) {
onLocationChanged(lastLocation);
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
mRegisterLocationUpdates = true;
}
}
#Override
public void onLocationChanged(Location location) {
if (location == null) return;
removeLocationUpdatesIfNeed();
mLastLocation = location;
DirectoryApp.getInstance().setLastLocation(mLastLocation);
if (mCallback != null) {
mCallback.onLastLocation(mLastLocation);
}
}
private void removeLocationUpdatesIfNeed() {
if (mRegisterLocationUpdates && mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mRegisterLocationUpdates = false;
}
}
private void requestPermission() {
// Lets ask suggestionLocationV2 permission to user.
if (mFragment != null) {
mFragment.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_LOCATION_PERMISSION);
} else {
ActivityCompat.requestPermissions(mActivity,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_LOCATION_PERMISSION);
}
}
private void requestPermissionRationale() {
new AlertDialog.Builder(mActivity)
.setMessage("We need the suggestionLocationV2 to provide you best results.")
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
requestPermission();
}
})
.show();
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult result) {
// If not already attempting to resolve an error.
if (!mResolvingError) {
if (result.hasResolution()) {
try {
mResolvingError = true;
result.startResolutionForResult(mActivity, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
} else {
GooglePlayServicesUtil.showErrorDialogFragment(result.getErrorCode(), mActivity,
null, REQUEST_RESOLVE_ERROR, null);
mResolvingError = true;
}
}
}
// The follow methods should be called in Activity or Fragment.
public void onStart() {
mGoogleApiClient.connect();
}
public void onStop() {
removeLocationUpdatesIfNeed();
mGoogleApiClient.disconnect();
}
public void onRequestPermissionResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode == REQUEST_LOCATION_PERMISSION
&& grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted. Uhull lets get its suggestionLocationV2 now.
obtainLastLocation();
}
}
}
Note that when the location is changed, we call the Application class to set the new location, so in your Application class you have to create the methods :
public class Application extends MultiDexApplication {
private static App instance;
private Location mLastLocation;
#Override
public void onCreate() {
super.onCreate();
instance = this;
}
public void setLastLocation(Location lastLocation) {
mLastLocation = lastLocation;
}
public Location getLastLocation() {
return mLastLocation;
}
And finally, when you have to use the location, on Fragment or Activity, just start and stop it using the right method`s.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationHelper = new LocationHelper(this, this);
}
#Override
public void onStart() {
super.onStart();
locationHelper.onStart();
}
#Override
public void onStop() {
super.onStop();
locationHelper.onStop();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
locationHelper.onRequestPermissionResult(requestCode, permissions, grantResults);
}
if you define "best option" as "most battery efficient way": try to minimize calls that activly connects the internet to read or transfer data.
Instead implement a broadcast receiver that tells your app that there is already internet-traffic going on. when you app receives the broadcast notification it can add ist own internet traffic. this way your app can avoid the battery overhead of connecting to the internet which is is very battery expensive.
For detail see "bundled tranfer" at https://developer.android.com/training/efficient-downloads/efficient-network-access.html
No bug, but the distance keeps changing when i click test button(not every 5s), so i dunno if my code really works well or not. It would be appreciated if you can tell whether there is some logical error or not.
here is my code.
The logic here is, when i have clicked start button, it will get the location, and then in every 5s, it will get a new location and calculate the distance and store it in an array. When i press test button, the total distance will be shown
public class MapsActivity extends BaseActivity /*implements LocationListener*/{
double totalDis=0;
double l;
int oxy =0;
TimeAnimator anim = new TimeAnimator();
private int isReset = 1;
private TextView textTimer;
private Button startButton;
private Button pauseButton;
private Button resetButton;
private long startTime = 0L;
private Handler myHandler = new Handler();
long timeInMillies = 0L;
long timeSwap = 0L;
long finalTime = 0L;
private String[] navMenuTitles;
private TypedArray navMenuIcons;
private GoogleMap mMap;
private Button testbtn;
double x;
double y;
double j;
double k;
float [] dis = new float[6];
TextView txt;
Location locationA;
Location locationB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items); // load
// titles
// from
// strings.xml
navMenuIcons = getResources()
.obtainTypedArray(R.array.nav_drawer_icons);// load icons from
// strings.xml
set(navMenuTitles, navMenuIcons);
textTimer = (TextView) findViewById(R.id.textTimer);
testbtn = (Button) findViewById(R.id.testbtn);
txt = (TextView) findViewById(R.id.textTest);
testbtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
for(int i=0;i<dis.length;i++){
totalDis+=dis[i];
}
txt.setText("dis = "+totalDis);
}
});
startButton = (Button) findViewById(R.id.btnStart);
startButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
startTime = SystemClock.uptimeMillis();
myHandler.postDelayed(updateTimerMethod, 0);
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Location locationA = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
x = locationA.getLatitude();
y = locationA.getLongitude();
anim.start();
anim.setTimeListener(new TimeAnimator.TimeListener() {
long time = 0;
#Override
public void onTimeUpdate(TimeAnimator timeAnimator, long t, long dt) {
time += dt;
if (time >= 5000) { // >= needed because this also might be not totally accurate...
time -= 5000; // keep the remainder (if there is) to correct the accuracy of next loop
// do stuff here (in every 5 seconds)
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Location locationB = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
j = locationB.getLatitude();
k = locationB.getLongitude();
Location.distanceBetween(x,y,j,k,dis);
x=j;
y=k;
}
}
});
}
});
pauseButton = (Button) findViewById(R.id.btnPause);
pauseButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
timeSwap += timeInMillies;
myHandler.removeCallbacks(updateTimerMethod);
}
});
resetButton = (Button) findViewById(R.id.btnReset);
resetButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
textTimer.setText("0:00:00");
timeSwap=0;
}
});
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.setMyLocationEnabled(true);
}
private Runnable updateTimerMethod = new Runnable() {
public void run() {
timeInMillies = SystemClock.uptimeMillis() - startTime;
finalTime = timeSwap + timeInMillies;
int seconds = (int) (finalTime / 1000);
int minutes = seconds / 60;
seconds = seconds % 60;
int milliseconds = (int) (finalTime % 1000);
textTimer.setText("" + minutes + ":"
+ String.format("%02d", seconds) + ":"
+ String.format("%03d", milliseconds));
myHandler.postDelayed(this, 0);
}
};
}
put these codes into yours as directed .
declair these veriables
LocationManager manager;
Button start_calculating, show;
boolean startcount_now = false;
double total_dist = 0;
Location last_loc = null;
import
import android.location.LocationListener;
and implement
LocationListener
then implement these methods
#Override
public void onLocationChanged(Location location) {
if (startcount_now == true) {
if (last_loc == null) {
last_loc = location;
} else {
total_dist += location.distanceTo(last_loc);
}
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
protected void onResume() {
super.onResume();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
return;
}
if (manager != null) {
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, this);
}
}
#Override
protected void onPause() {
super.onPause();
super.onResume();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
return;
}
if (manager != null) {
manager.removeUpdates(MainActivity.this);
}
}
in oncreate()
manager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
the listeners for the button (you add these into your own button used for this purpose)
start_calculating.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startcount_now = true;
}
});
show.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "total distancetravelled is " + total_dist, Toast.LENGTH_LONG).show();
}
});
add permission in menifest
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
the show button will show you the total distance in toast . you can use as you want it. the location fetching will be stopped when your app is in background. for the location fetching mechanism please read this.
let me know if this is what you want.
Your code is very very wrong.
Refer to Receiving Location updates page. That page leaves some stuff for you to implement, so I'll give you working example. You'll need to adapt it for your needs yourself.
#Override
public void onConnected(#Nullable final Bundle bundle) {
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onConnectionSuspended(final int i) {
}
#Override
public void onLocationChanged(final Location location) {
EventBus.getDefault().post(new LocationChangedEvent(location));
}
#Override
public void onConnectionFailed(#NonNull final ConnectionResult connectionResult) {
}
protected synchronized void buildGoogleApiClient() {
Logger.e(this, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
protected void startLocationUpdates() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
Utils.showPermissionRationaleDialog(MainActivity.this, R.string.permission_rationale_location,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION);
}
});
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION);
}
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
protected void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
"request_location_updates");
}
buildGoogleApiClient();
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
protected void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
I'm trying to get Google maps to start on the users current location. Right now it starts zoomed all the way out. I have the correct code for finding and animating the camera to the user's location but this code only works if I put it in a button and touch it on my own. How can I get it to move at the start of the activity?
I've been trying a lot of different things. this was one of them.
public class FindBar extends Activity implements ConnectionCallbacks,
OnConnectionFailedListener, LocationListener,
OnMyLocationButtonClickListener {
private GoogleMap mMap;
private LocationClient mLocationClient;
// Button test;
boolean locationClientConnected = false;
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
setUpMapIfNeeded();
setUpLocationClientIfNeeded();
mLocationClient.connect();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
if (mLocationClient != null) {
mLocationClient.disconnect();
Log.d("tag", "locationclient disconnected");
}
}
private void setUpMapIfNeeded() {
Log.d("tag", "entered set up map");
// Check if we were successful in obtaining the map.
if (mMap != null) {
mMap.setMyLocationEnabled(true);
mMap.setOnMyLocationButtonClickListener(this);
Log.d("tag", "map location set true and click listener set");
}
}
private void setUpLocationClientIfNeeded() {
if (mLocationClient == null) {
mLocationClient = new LocationClient(getApplicationContext(), this, // ConnectionCallbacks
this); // OnConnectionFailedListener
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// removes the title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.fragment_find_bar);
// Get a handle to the Map Fragment
mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
.getMap();
// test = (Button) findViewById(R.id.bTest);
// test.setOnClickListener(new OnClickListener() {
//
// #Override
// public void onClick(View v) {
// // TODO Auto-generated method stub
// moveCameraTo(mMap.getMyLocation());
// }
//
// });
moveCameraTo(mLocationClient.getLastLocation());
}
// Takes a Location and centers camera on that location
public void moveCameraTo(Location mLocation) {
Log.d("camera", "entered moveToCamera");
LatLng camPos = new LatLng(mLocation.getLatitude(),
mLocation.getLongitude());
Log.d("camera", "created camera position");
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(camPos, 15));
Log.d("camera", "moved camera");
}
#Override
public boolean onMyLocationButtonClick() {
// TODO Auto-generated method stub
return false;
}
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// TODO Auto-generated method stub
}
#Override
public void onConnected(Bundle connectionHint) {
// TODO Auto-generated method stub
Log.d("camera", "entered onConnected");
// moveCameraTo(mMap.getMyLocation());
locationClientConnected = true;
}
#Override
public void onDisconnected() {
// TODO Auto-generated method stub
}
}
this code comes pretty much out of the samples. If you get a non null location from getLastLocation() then plug that location into your setupmap method.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
// mMap = mMapFragment.getMap();
// // Check if we were successful in obtaining the map.
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map)).getMap();
// use the settings maptype
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
// Start Parsing the map
}
}
private void setUpMap() {
final View mapView = getSupportFragmentManager().findFragmentById(
R.id.map).getView();
if (mapView.getViewTreeObserver().isAlive()) {
mapView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
// We use the new method when supported
#SuppressLint("NewApi")
// We check which build version we are using.
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
mapView.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
} else {
mapView.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
}
//
// put your move code here replacing code below
// which moves the map.
//
if (currentCameraPosition != null) {
mMap.moveCamera(CameraUpdateFactory
.newCameraPosition(currentCameraPosition));
} else {
// else move to bounds of the map
if (bounds != null) {
mMap.moveCamera(CameraUpdateFactory
.newLatLngBounds(bounds, 50));
}
}
}
});
}
}
I am using the periodic location updates and wanted to know which part should be put in service so that even when the app is closed it keeps running. Here is the code
public class MainActivity extends FragmentActivity implements LocationListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener {
private LocationRequest mLocationRequest;
private LocationClient mLocationClient;
private TextView mLatLng;
private TextView mConnectionState;
private TextView mConnectionStatus;
SharedPreferences mPrefs;
SharedPreferences.Editor mEditor;
boolean mUpdatesRequested = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLatLng = (TextView) findViewById(R.id.lat_lng);
mConnectionState = (TextView) findViewById(R.id.text_connection_state);
mConnectionStatus = (TextView) findViewById(R.id.text_connection_status);
mLocationRequest = LocationRequest.create();
mLocationRequest
.setInterval(LocationUtils.UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest
.setFastestInterval(LocationUtils.FAST_INTERVAL_CEILING_IN_MILLISECONDS);
mUpdatesRequested = false;
mPrefs = getSharedPreferences(LocationUtils.SHARED_PREFERENCES,
Context.MODE_PRIVATE);
mEditor = mPrefs.edit();
mLocationClient = new LocationClient(this, this, this);
}
#Override
public void onStop() {
if (mLocationClient.isConnected()) {
stopPeriodicUpdates();
}
mLocationClient.disconnect();
super.onStop();
}
#Override
public void onPause() {
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED,
mUpdatesRequested);
mEditor.commit();
super.onPause();
}
#Override
public void onStart() {
super.onStart();
mLocationClient.connect();
}
#Override
public void onResume() {
super.onResume();
// If the app already has a setting for getting location updates, get it
if (mPrefs.contains(LocationUtils.KEY_UPDATES_REQUESTED)) {
mUpdatesRequested = mPrefs.getBoolean(
LocationUtils.KEY_UPDATES_REQUESTED, false);
// Otherwise, turn off location updates until requested
} else {
mEditor.putBoolean(LocationUtils.KEY_UPDATES_REQUESTED, false);
mEditor.commit();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
// Choose what to do based on the request code
switch (requestCode) {
// If the request code matches the code sent in onConnectionFailed
case LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST:
switch (resultCode) {
// If Google Play services resolved the problem
case Activity.RESULT_OK:
// Log the result
Log.d(LocationUtils.APPTAG, getString(R.string.resolved));
// Display the result
mConnectionState.setText(R.string.connected);
mConnectionStatus.setText(R.string.resolved);
break;
// If any other result was returned by Google Play services
default:
// Log the result
Log.d(LocationUtils.APPTAG, getString(R.string.no_resolution));
// Display the result
mConnectionState.setText(R.string.disconnected);
mConnectionStatus.setText(R.string.no_resolution);
break;
}
// If any other request code was received
default:
// Report that this Activity received an unknown requestCode
Log.d(LocationUtils.APPTAG,
getString(R.string.unknown_activity_request_code,
requestCode));
break;
}
}
private boolean servicesConnected() {
// Check that Google Play services is available
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d(LocationUtils.APPTAG,
getString(R.string.play_services_available));
// Continue
return true;
// Google Play services was not available for some reason
} else {
// Display an error dialog
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode,
this, 0);
if (dialog != null) {
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(dialog);
errorFragment.show(getFragmentManager(), LocationUtils.APPTAG);
}
return false;
}
}
public void getLocation(View v) {
if (servicesConnected()) {
Location currentLocation = mLocationClient.getLastLocation();
mLatLng.setText(LocationUtils.getLatLng(this, currentLocation));
}
}
public void startUpdates(View v) {
mUpdatesRequested = true;
if (servicesConnected()) {
startPeriodicUpdates();
}
}
public void stopUpdates(View v) {
mUpdatesRequested = false;
if (servicesConnected()) {
stopPeriodicUpdates();
}
}
#Override
public void onConnected(Bundle bundle) {
mConnectionStatus.setText(R.string.connected);
if (mUpdatesRequested) {
startPeriodicUpdates();
}
}
#Override
public void onDisconnected() {
mConnectionStatus.setText(R.string.disconnected);
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
/*
* Google Play services can resolve some errors it detects. If the error
* has a resolution, try sending an Intent to start a Google Play
* services activity that can resolve error.
*/
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(this,
LocationUtils.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.
showErrorDialog(connectionResult.getErrorCode());
}
}
#Override
public void onLocationChanged(Location location) {
mConnectionStatus.setText(R.string.location_updated);
mLatLng.setText(LocationUtils.getLatLng(this, location));
}
private void startPeriodicUpdates() {
mLocationClient.requestLocationUpdates(mLocationRequest, this);
mConnectionState.setText(R.string.location_requested);
}
private void stopPeriodicUpdates() {
mLocationClient.removeLocationUpdates(this);
mConnectionState.setText(R.string.location_updates_stopped);
}
private void showErrorDialog(int errorCode) {
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(errorCode,
this, LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
if (errorDialog != null) {
ErrorDialogFragment errorFragment = new ErrorDialogFragment();
errorFragment.setDialog(errorDialog);
errorFragment.show(getFragmentManager(), LocationUtils.APPTAG);
}
}
public static class ErrorDialogFragment extends DialogFragment {
private Dialog mDialog;
public ErrorDialogFragment() {
super();
mDialog = null;
}
public void setDialog(Dialog dialog) {
mDialog = dialog;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return mDialog;
}
}
}
#Override
public void onLocationChanged(Location location) {
}
is the callback which is called when the location changes. So, this should be put in your service so that it is able to receive the updates.