For some reason it only updates the textviews when the app hits onPause, like when I hit the home button, or multitasking button. Can someone help me figure out why that is?
MainActivity.java:
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private String lat, lon;
private TextView longTextView, latTextView;
LocationService locationService = new LocationService(this);
private Intent intentService;
private PendingIntent pendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
latTextView = (TextView) findViewById(R.id.latitude_textview);
longTextView = (TextView) findViewById(R.id.longitude_textview);
}
#Override
protected void onStart() {
super.onStart();
locationService.buildGoogleApiClient();
locationService.apiConnect();
if (latTextView != null && longTextView != null) {
latTextView.setText( locationService.getLat());
longTextView.setText( locationService.getLon());
Toast.makeText(getApplicationContext(), " Actually got location", Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(getApplicationContext(), "The shit was null fam", Toast.LENGTH_LONG)
.show();
}
}
#Override
protected void onStop() {
super.onStop();
locationService.apiDisconnect();
}
}
LocationService.java:
import android.Manifest;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import static com.google.android.gms.wearable.DataMap.TAG;
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
// ============================================================= Variables
Context context;
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private String lat, lon;
final static String[] LOCATION_PERMISSIONS = {Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long UPDATE_FASTEST_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
public static boolean isEnded = false;
public static Boolean requestingLocationUpdates;
protected String lastUpdateTime;
final int GOOGLEAPI_REQUEST_CODE = 24;
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
// ============================================================= Constructor
public LocationService(Context context) {
this.context = context;
}
// ============================================================= Getters / Setters
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
// ============================================================= Methods
synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
public void apiConnect() {
mGoogleApiClient.connect();
}
public void apiDisconnect() {
mGoogleApiClient.disconnect();
}
void updateUI() {
}
// ============================================================= Implemented Location Methods
#Override
public void onLocationChanged(Location location) {
setLat(String.valueOf(location.getLatitude()));
setLon(String.valueOf(location.getLongitude()));
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); // Sets Location to update every second
mLocationRequest.setFastestInterval(UPDATE_FASTEST_INTERVAL_IN_MILLISECONDS); // The fastest location can update is every half-second
startLocationUpdates();
// TODO come back to this to see whats up
/* mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);*/
if (mLastLocation != null) {
setLat(String.valueOf(mLastLocation.getLatitude()));
setLon(String.valueOf(mLastLocation.getLongitude()));
}
}
#Override
public void onConnectionSuspended(int i) {
}
protected void startLocationUpdates() {
/*if (!requestingLocationUpdates) {
requestingLocationUpdates = true;*/
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context, LOCATION_PERMISSIONS, GOOGLEAPI_REQUEST_CODE);
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
Log.i(TAG, " startLocationUpdates===");
isEnded = true;
//}
}
// ============================================================= Implemented Service Methods
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Within {#code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
Log.d("LOC", "Service init...");
isEnded = false;
requestingLocationUpdates = false;
lastUpdateTime = "";
buildGoogleApiClient();
if (mGoogleApiClient.isConnected() && requestingLocationUpdates) {
startLocationUpdates();
}
return Service.START_REDELIVER_INTENT;
}
}
The reason why you are not getting the location updated in textview is because your code doesn't have a way for the service to communicate back to the activity.
If you want to obtain location only when the activity is in foreground don't use Service and please look into this google's example for obtaining location and updating on a TextView using fused location provider.
I am not sure why you are using a Service.Use Service only when you want to continuously fetch the location even when the app is running background.
For this use any one of the method mentioned here to inform the activity that a new location has been obtained.LocalBroadcast would be your best bet. Anyway explore the best possible solution that suits your usecase in the previous link.
Related
I have an android service and I'd like to do the following:
When clicking a button, I start this service, the toast in the onCreate() method always appears but after that I cannot see the longitude-latitude popping up. My main goal is to use this longitude-latitude couple in more activities.
How can I achieve this?
I implemented GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location .LocationListener because I had to wait 20-30 seconds to get the coordinates. The following code works in an activity, but not as a service.
Thanks!
EDITED:
package com.si.ou;
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class FullAutoService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location
.LocationListener {
private static final int PERMISSION_REQUEST_ACCESS_FINE_LOCATION = 100;
private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
String loki;
#Override
public void onCreate() {
createLocationRequest();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Toast.makeText(this, "service started....", Toast.LENGTH_SHORT).show();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void startLocationUpdates() {
//noinspection MissingPermission
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission
.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat
.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
mLocationRequest, this);
}
private void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
private boolean checkPermissions() {
return ContextCompat.checkSelfPermission(this, android.Manifest.permission
.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (checkPermissions() && mGoogleApiClient.isConnected()) startLocationUpdates();
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
Double lati = location.getLatitude();
Double longi = location.getLongitude();
loki = String.valueOf(lati) + ":" + String.valueOf(longi);
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), loki, Toast.LENGTH_SHORT).show();
}
});
}
}
It is because you are working on Service.
Try this:
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
getString(R.string.string_id),
Toast.LENGTH_SHORT).show();
}
});
Any UI component can't be accessed from background thread.
If need be arise use handler and sen msg to UI thread and update UI components.
Sorry for the long title but couldn't resume it more, basicly i implemented the googlefusedlocation api as a service, i need the service to run on background and update the location, this service starts on my app running (atm i am not requesting the user if he want to share location because i have no idea how ti implement it with a service).
My service:
package com.example.afcosta.inesctec.pt.android.services;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
public class GoogleLocation extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private static final String TAG = "BOOMBOOMTESTGPS";
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 0;
private LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 0;
private static final float LOCATION_DISTANCE = 0f;
private int updatePriority;
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private final IBinder mBinder = new LocalBinder();
private Intent intent;
private String provider;
Context context;
Location mLastLocation;
public class LocalBinder extends Binder {
public GoogleLocation getServerInstance() {
return GoogleLocation.this;
}
}
public Location getLocation() {
Log.d("IMHERE", "HELLO");
return mLastLocation;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
context = getApplicationContext();
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
Log.e(TAG, "onCreate");
initializeLocationManager();
if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
this.updatePriority = LocationRequest.PRIORITY_HIGH_ACCURACY;
} else if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
this.updatePriority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
} else {
this.updatePriority = LocationRequest.PRIORITY_HIGH_ACCURACY;
}
this.buildGoogleApiClient();
this.createLocationRequest();
this.googleApiClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) ==
PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(this.googleApiClient, this.locationRequest,this);
} else {
ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
mLastLocation = location;
}
#Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
this.googleApiClient.unregisterConnectionCallbacks(this);
this.googleApiClient.unregisterConnectionFailedListener(this);
this.googleApiClient.disconnect();
this.mLastLocation = null;
}
private void initializeLocationManager() {
Log.e(TAG, "initializeLocationManager");
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
private synchronized void buildGoogleApiClient() {
this.googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
private void createLocationRequest() {
this.locationRequest = new LocationRequest();
this.locationRequest.setInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
this.locationRequest.setPriority(updatePriority);
}
then on my camera i access the getLocation method that is inside my service, it gives me the last location, i just display the way i acces the service if you guys ask, but i just remember that i had a solution before(i used locationListener and not google one) and i could get the location, failled sometimes thats why i tried to change.
public void onServiceConnected(ComponentName name, IBinder service) {
mBounded = true;
GoogleLocation.LocalBinder mLocalBinder = (GoogleLocation.LocalBinder)service;
mlocation = mLocalBinder.getServerInstance();
location = mlocation.getLocation();
Log.d("localizacao",location.toString());
}
Now i get:
lat:null
lon:0.0
alt:0.0
Strange, why is that happening?
Thanks
I am using the Google Play Services to find the current location.
But it is not going in any of the callback functions. Google API client cannot be connected.
Here is my code of the LocationUtil class:
package com.steporganization.util;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
/**
* Created by Yogesh on 26-07-2015.
*/
public class LocationUtil implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,LocationListener{
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private final static String TAG="LocationUtil_Yogesh";
private GoogleApiClient client;
private Location location;
private boolean isClientConnected=false;
private Activity baseActivity;
private Context context;
private boolean isPlayServicesAvailable()
{
int resultCode= GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
if (resultCode!= ConnectionResult.SUCCESS)
{
if(GooglePlayServicesUtil.isUserRecoverableError(resultCode))
{
GooglePlayServicesUtil.getErrorDialog(resultCode,baseActivity,PLAY_SERVICES_RESOLUTION_REQUEST).show();
return false;
}
else
{
Toast.makeText(context,
"This device is not supported.", Toast.LENGTH_LONG)
.show();
return false;
}
}
return true;
}
private synchronized void buildGoogleAPiClient()
{
client=new GoogleApiClient.Builder(context).
addConnectionCallbacks(this).addOnConnectionFailedListener(this).
addApi(LocationServices.API).build();
}
private Location getLocation()
{
Location lastLocation;
lastLocation= LocationServices.FusedLocationApi.getLastLocation(client);
if(lastLocation==null)
{
//check for location
//requestlocation update until some location is acquired or timeout of 10 seconds
Long initialTime= System.currentTimeMillis();
Long finalTime=System.currentTimeMillis();
createLocationRequest();
while(this.location==null || finalTime-initialTime<20000)
{
finalTime=System.currentTimeMillis();
}
if(this.location==null)
{
Log.d(TAG,"Unable to fetch location");
LocationServices.FusedLocationApi.removeLocationUpdates(client,this);
return null;
}
else
LocationServices.FusedLocationApi.removeLocationUpdates(client,this);
return this.location;
}
else
return lastLocation;
}
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG,"onConnected Called");
isClientConnected=true;
location=getLocation();
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG,"onConnection suspended Called");
client.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG,"onConnection Failed Called");
Log.d(TAG, "Error Code: " + connectionResult.getErrorCode());
}
protected void createLocationRequest()
{
LocationRequest locationRequest=new LocationRequest().
setInterval(1000).setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(client, locationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
this.location=location;
}
public Location getUserCurrentLocation(Activity activity,Context context)
{
this.baseActivity=activity;
this.context=context;
if(isPlayServicesAvailable())
{
Log.d(TAG, "play services available");
buildGoogleAPiClient();
if(client!=null)
{
client.connect();
}
else
{
Log.d(TAG,"Cleint null");
}
while(isClientConnected!=true)
{
Log.d(TAG,"connecting API client");
}
return this.location;
}
else {
Log.d(TAG, "play service not available");
return null;
}
}
}
In another activity, I am creating an object of this class and calling getUserCurrentLocation(this,getApplicationContext()) function.
Can anybody suggest me what I am doing wrong here?
Also, it is not correct code, but my point is why it is not reaching inside any callback functions so that I can modify my logic as per my requirements.
Also, I found a similar question, but it has not been answered yet.
I've developed a simple weather app, but there is too much code in my WeatherActivity and two responsibilities for one class(handling weather JSON, and retrieving location info using googleapiclient). I tried to get the code that handles location out of the WeatherActivity class, but as I try to get any location in the onCreate method, it usually results in null, probably because it's not enough time to be updated. Is there any way to get users location outside of the activity? Or if you have another suggestion that might help in that situation?
I have been looking for a solution to have an object to handle the current location but I didn't find anything.
So I did it this way but it's a little bit tricky.
Hope it helps you.
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
/**
* This class uses GoogleApiClient to track location changes.
* In order to connect the GoogleApiClient correctly, this class must be instanciated in onCreate callback.
*/
public class Locator implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = "Locator";
private Activity activity;
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private static final long UPDATE_INTERVAL = 60 * 1000;
private static final long FASTEST_UPDATE_INTERVAL = 10 * 1000;
private static final int LOCATION_REQUEST = 1;
private static boolean locationPermissionRequested = false;
private static boolean locationPermissionGranted = false;
private Location location;
/**
* Default constructor. Ex. Locator locator = new Locator(getActivity());
*
* #param activity The activity to instanciate from.
*/
public Locator(Activity activity) {
this.activity = activity;
if (activity != null) {
googleApiClient = new GoogleApiClient.Builder(activity)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
locationRequest = new LocationRequest();
locationRequest.setInterval(UPDATE_INTERVAL);
locationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL);
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
googleApiClient.connect();
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
requestLocation();
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onLocationChanged(Location location) {
this.location = location;
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
/**
* Requests the current location to the GoogleApiClient.
* NB: If device os is Marshmallow or higher, il will also ask permission to acces location services.
*/
private void requestLocation() {
if (googleApiClient.isConnected()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
locationPermissionGranted = ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
if (!locationPermissionGranted) {
if (!locationPermissionRequested) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, LOCATION_REQUEST);
locationPermissionRequested = true;
requestLocation();
}
}
} else {
locationPermissionGranted = true;
}
if (locationPermissionGranted) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
} else {
}
}
}
/**
* Requests the current location et gets.
*
* #return The location.
*/
public Location getLocation() {
requestLocation();
return location;
}
/**
* Stops updating the location. (save battery power).
*/
public void removeUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
}
}
I'm a beginner of android programming then sorry if this question could seem silly but I need to understand how to update the view from a class that it is not an activity or a fragment. I have created a class that fetch data from the Google Play services API. I need to redirect this data to the fragment. which are the common software design patterns to achieve it?
This is the code but unfortunately it doesn't work
TodayFragment
package com.salvo.weather.android.fragment;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.salvo.weather.android.R;
import com.salvo.weather.android.app.VolleyCallback;
import com.salvo.weather.android.entity.CurrentWeatherEntity;
import com.salvo.weather.android.geolocation.CurrentGeolocation;
/**
* A simple {#link Fragment} subclass.
*/
public class TodayFragment extends Fragment {
private static final String TAG = TodayFragment.class.getSimpleName();
private CurrentGeolocation mCurrentGeolocation;
public TodayFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_today, container, false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCurrentGeolocation = CurrentGeolocation.get(getActivity());
}
#Override
public void onStart() {
super.onStart();
mCurrentGeolocation.getmGoogleApiClient().connect();
renderView();
}
#Override
public void onPause() {
super.onPause();
if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
mCurrentGeolocation.stopLocationUpdates();
}
}
#Override
public void onResume() {
super.onResume();
if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
mCurrentGeolocation.startLocationUpdates();
}
}
#Override
public void onStop() {
super.onStop();
if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
mCurrentGeolocation.stopLocationUpdates();
}
}
public void renderView() {
// check if googleApiClient is connected
if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
mCurrentGeolocation.getmCurrentWeatherRequest().loadData(new VolleyCallback() {
#Override
public void onSuccess(CurrentWeatherEntity currentWeatherEntity) {
Log.i(TAG, currentWeatherEntity.getmCity());
}
});
}
}
}
CurrentGeolocation
package com.salvo.weather.android.geolocation;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.salvo.weather.android.app.VolleyCallback;
import com.salvo.weather.android.client.request.CurrentWeatherRequest;
import com.salvo.weather.android.entity.CurrentGeolocationEntity;
import com.salvo.weather.android.entity.CurrentWeatherEntity;
/**
* Created by mazzy on 30/05/15.
*/
public class CurrentGeolocation
implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
private static final String TAG = CurrentGeolocation.class.getSimpleName();
// SETTING CONSTANTS FOR THE LOCATION
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000; //ms
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
private static CurrentGeolocation sCurrentGeolocation;
private boolean mRequestingLocationUpdates;
private Context mAppContext;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private CurrentGeolocationEntity mCurrentGeolocationEntity;
private CurrentWeatherRequest mCurrentWeatherRequest;
public static CurrentGeolocation get(Context appContext) {
if (sCurrentGeolocation == null) {
sCurrentGeolocation = new CurrentGeolocation(appContext.getApplicationContext());
}
return sCurrentGeolocation;
}
private CurrentGeolocation(Context appContext) {
mAppContext = appContext;
mRequestingLocationUpdates = true;
mCurrentGeolocationEntity = new CurrentGeolocationEntity();
mCurrentWeatherRequest = CurrentWeatherRequest.get(appContext);
buildGoogleApiClient();
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected to GoggleApiClient");
if (mCurrentGeolocationEntity.getmLastLocation() == null) {
mCurrentGeolocationEntity.setmLastLocation(LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient));
mCurrentWeatherRequest.setmCurrentGeolocationEntity(mCurrentGeolocationEntity);
}
if (mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onConnectionSuspended(int i) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: error " + connectionResult.getErrorCode());
}
#Override
public void onLocationChanged(Location location) {
// update the location
mCurrentGeolocationEntity.setmLastLocation(location);
}
public GoogleApiClient getmGoogleApiClient() {
return mGoogleApiClient;
}
public void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
public void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
public CurrentWeatherRequest getmCurrentWeatherRequest() {
return mCurrentWeatherRequest;
}
private synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building Google Api Client");
mGoogleApiClient = new GoogleApiClient.Builder(mAppContext)
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
}
You must create a Listener.
TodayFragment
package com.salvo.weather.android.fragment;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.salvo.weather.android.R;
import com.salvo.weather.android.app.VolleyCallback;
import com.salvo.weather.android.entity.CurrentWeatherEntity;
import com.salvo.weather.android.geolocation.CurrentGeolocation;
/**
* A simple {#link Fragment} subclass.
*/
public class TodayFragment extends Fragment implements CurrentGeoloaction.OnUpdateListener {
private static final String TAG = TodayFragment.class.getSimpleName();
private CurrentGeolocation mCurrentGeolocation;
public TodayFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_today, container, false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCurrentGeolocation = CurrentGeolocation.get(getActivity());
mCurrentGeolocation.setOnUpdateListener(this);
}
#Override
public void onStart() {
super.onStart();
mCurrentGeolocation.getmGoogleApiClient().connect();
renderView();
}
#Override
public void onPause() {
super.onPause();
if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
mCurrentGeolocation.stopLocationUpdates();
}
}
#Override
public void onResume() {
super.onResume();
if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
mCurrentGeolocation.startLocationUpdates();
}
}
#Override
public void onStop() {
super.onStop();
if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
mCurrentGeolocation.stopLocationUpdates();
}
}
#Override
public void onUpdate() {
renderView();
}
public void renderView() {
// check if googleApiClient is connected
if (mCurrentGeolocation.getmGoogleApiClient().isConnected()) {
mCurrentGeolocation.getmCurrentWeatherRequest().loadData(new VolleyCallback() {
#Override
public void onSuccess(CurrentWeatherEntity currentWeatherEntity) {
Log.i(TAG, currentWeatherEntity.getmCity());
}
});
}
}
}
CurrentGeolocation
package com.salvo.weather.android.geolocation;
import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.salvo.weather.android.app.VolleyCallback;
import com.salvo.weather.android.client.request.CurrentWeatherRequest;
import com.salvo.weather.android.entity.CurrentGeolocationEntity;
import com.salvo.weather.android.entity.CurrentWeatherEntity;
/**
* Created by mazzy on 30/05/15.
*/
public class CurrentGeolocation
implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener {
private static final String TAG = CurrentGeolocation.class.getSimpleName();
// SETTING CONSTANTS FOR THE LOCATION
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000; //ms
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
private static CurrentGeolocation sCurrentGeolocation;
private boolean mRequestingLocationUpdates;
private Context mAppContext;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private CurrentGeolocationEntity mCurrentGeolocationEntity;
private CurrentWeatherRequest mCurrentWeatherRequest;
private OnUpdateListener mOnUpdateListener;
public interface OnUpdateListener {
public void onUpdate();
}
public void setOnUpdateListener(Fragment todayFragment) {
this.mOnUpdateListener = (OnUpdateListener) todayFragment;
}
public static CurrentGeolocation get(Context appContext) {
if (sCurrentGeolocation == null) {
sCurrentGeolocation = new CurrentGeolocation(appContext.getApplicationContext());
}
return sCurrentGeolocation;
}
private CurrentGeolocation(Context appContext) {
mAppContext = appContext;
mRequestingLocationUpdates = true;
mCurrentGeolocationEntity = new CurrentGeolocationEntity();
mCurrentWeatherRequest = CurrentWeatherRequest.get(appContext);
buildGoogleApiClient();
}
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected to GoggleApiClient");
if (mCurrentGeolocationEntity.getmLastLocation() == null) {
mCurrentGeolocationEntity.setmLastLocation(LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient));
mCurrentWeatherRequest.setmCurrentGeolocationEntity(mCurrentGeolocationEntity);
}
if (mRequestingLocationUpdates) {
startLocationUpdates();
mOnUpdateListener.onUpdate();
}
}
#Override
public void onConnectionSuspended(int i) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: error " + connectionResult.getErrorCode());
}
#Override
public void onLocationChanged(Location location) {
// update the location
mCurrentGeolocationEntity.setmLastLocation(location);
}
public GoogleApiClient getmGoogleApiClient() {
return mGoogleApiClient;
}
public void startLocationUpdates() {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
public void stopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
public CurrentWeatherRequest getmCurrentWeatherRequest() {
return mCurrentWeatherRequest;
}
private synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building Google Api Client");
mGoogleApiClient = new GoogleApiClient.Builder(mAppContext)
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.build();
createLocationRequest();
}
private void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
}