I am practicing Android for internship and I have been able to write a class that handles the geolocation for me trying to find the best location and I keep updating things whenever onLocationChanged is called.
Now I need to use my location to put Markers on a GoogleMaps I could obviously change the onLocationChanged method from my class handling geolocation but I would love to extract the action I need to do outside of the class because in the future I might need my current location to perform a lot of different things.
package com.example.soueuls.swipe;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
public class GeoLocation {
private final Context context;
private final LocationManager locationManager;
private Location currentLocation;
private int updateLimit = 0;
private long timeLimit = 0;
public GeoLocation(Context context) {
this.context = context;
this.locationManager = (LocationManager)this.context.getSystemService(Context.LOCATION_SERVICE);
this.currentLocation = this.locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (this.currentLocation == null) {
this.currentLocation = this.locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
}
private LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location newLocation) {
if (isBetterLocation(GeoLocation.this.currentLocation, newLocation)) {
GeoLocation.this.currentLocation = newLocation;
}
if (--GeoLocation.this.updateLimit == 0) {
GeoLocation.this.stopLocationUpdate();
} else if (System.currentTimeMillis() / 1000 > GeoLocation.this.timeLimit) {
GeoLocation.this.stopLocationUpdate();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
private boolean isBetterLocation(Location currentLocation, Location newLocation) {
if (currentLocation == null) {
return true;
}
int twoMinutes = 1000 * 60 * 2;
long timeDelta = newLocation.getTime() - currentLocation.getTime();
int accuracyDelta = (int) (newLocation.getAccuracy() - currentLocation.getAccuracy());
boolean isSignificantlyNewer = timeDelta > twoMinutes;
boolean isSignificantlyOlder = timeDelta < -twoMinutes;
boolean isNewer = timeDelta > 0;
if (isSignificantlyNewer) {
return true;
} else if (isSignificantlyOlder) {
return false;
}
boolean isMoreAccurate = accuracyDelta < 0;
boolean isLessAccurate = accuracyDelta > 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
boolean isFromSameProvider = isSameProvider(currentLocation.getProvider(), newLocation.getProvider());
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
} else {
return false;
}
}
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
public void setUpdateLimit(int limit) {
this.updateLimit = limit;
}
public void setTimeLimit(long limit) {
this.timeLimit = System.currentTimeMillis() / 1000 + limit;
}
public void setLocationUpdate(String provider, int minTimeInterval, int minDistance) {
this.locationManager.requestLocationUpdates(provider, minTimeInterval, minDistance, this.locationListener);
}
public void stopLocationUpdate() {
this.locationManager.removeUpdates(this.locationListener);
}
public Location getCurrentLocation() {
return this.currentLocation;
}
}
Here is GeoLocation class I would still need to update this.currentLocation each time onLocationChanged is called.
But I would like to be able to detect whenever onLocationChanged iscalled to perform update inside my activity which is outside this class.
How could I do it ?
EDIT :
Inside the onResume method of the activity I am trying to listen I do
GeolocationListener locationListener = new GeolocationAdapter() {
#Override
public void onLocationChanged(Location newLocation) {
System.out.println("OHOHOH");
displayWeatherInformation(weatherCache, geoLocation.getCurrentLocation());
}
};
use listeners
you add the interface to your Geolocation class
public class GeoLocation {
add your listeners
// listeners
private List<LocationListener> listeners = new ArrayList<LocationListener>();
public void addListener(LocationListener l){
listeners.add(l);
}
public void removeListener(LocationListener l){
listeners.remove(l);
}
then inside your private LocationListener locationListener = new LocationListener() you put
#Override
public void onLocationChanged(Location newLocation) {
if (isBetterLocation(GeoLocation.this.currentLocation, newLocation)) {
GeoLocation.this.currentLocation = newLocation;
for(LocationListener l:listeners){
l.onLocationChanged(newLocation);
}
}
... the rest of the code
then any class can register to receive updates on your Geolocation class
edit:
declare your activity like this:
public class MyActivity extends Activity implements LocationListener{
#Override
public void onResume(){
geoLocation.addListener(this);
}
#Override
public void onPause(){
geoLocation.removeListener(this);
}
#Override
public void onLocationChanged(Location newLocation) {
}
}
You can use observer pattern-the activity registers itself in onResume() with the GeoLocation class to receive updates and in onPause() unregisters itself.
There are lot of material on net to learn observer pattern-http://en.wikipedia.org/wiki/Observer_pattern
Related
I have an application which uses the accelerometer, but only occasionally under rare circumstances. I'd like to preserve battery by having it disabled by default and only turn it on when needed.
Only thing I've found is setting configurations when initializing the app from this site
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.useCompass = false;
config.useAccelerometer = false;
MyGame myGame = new MyGame(new AndroidPlatform(this, config));
initialize(myGame , config);
}
But I can't find a way to enable/disable it while the app is running. Anyone have an idea?
EDIT:
In the above example AndroidPlatform is implementing a Platform interface in the core project. I tried out Zoe's idea of passing the config to platform implementation and changing it follows:
#Override
public void enableAccelerometer(boolean enable) {
config.useCompass = enable;
config.useAccelerometer = enable;
}
and then in the core project when the accelerometer should be enabled:
private void startInclineMonitoring() {
System.out.println("Before:");
System.out.println(Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer));
System.out.println(Gdx.input.isPeripheralAvailable(Input.Peripheral.Compass));
platform.enableAccelerometer(true);
System.out.println("After:");
System.out.println(Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer));
System.out.println(Gdx.input.isPeripheralAvailable(Input.Peripheral.Compass));
}
Unfortunately this outputs:
I/System.out: Before:
I/System.out: false
I/System.out: false
I/System.out: After:
I/System.out: false
I/System.out: false
So, no luck there.
It seems like there's no easy way to do this as of today, but I ended up doing my own (Android) motion sensor implementation. I thought I'd share it for future visitors:
This assumes you have your platform interface and platform specific implementation as explained in this wiki.
First these methods are added to the interface:
public interface Platform {
public void startMotionSensors(PlatformCallback<float[]> callback);
public void stopMotionSensors();
}
And in the android implementation:
public class AndroidPlatform implements Platform {
private Activity activity;
private MotionSensor motionSensor;
private Handler handler;
public AndroidPlatform(Activity activity) {
this.activity = activity;
this.motionSensor = new MotionSensor(activity);
this.handler = new Handler();
}
#Override
public void startMotionSensors(final PlatformCallback<float[]> callback) {
handler.post(new Runnable() {
#Override
public void run() {
motionSensor.start(callback);
}
});
}
#Override
public void stopMotionSensors() {
handler.post(new Runnable() {
#Override
public void run() {
motionSensor.stop();
}
});
}
}
The MotionSensor class:
public class MotionSensor implements SensorEventListener {
private Activity activity;
private SensorManager sensorManager;
private float[] gravity = new float[3];
private float[] geomag = new float[3];
private float[] rotationMatrix = new float[16];
private float[] inclinationMatrix = new float[16];
private PlatformCallback<float[]> callback;
public MotionSensor(Activity activity) {
this.activity = activity;
}
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
gravity = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
geomag = event.values.clone();
break;
}
if (gravity != null && geomag != null) {
boolean success = SensorManager.getRotationMatrix(rotationMatrix,
inclinationMatrix, gravity, geomag);
if (success) {
notifyCallback(new Result(), rotationMatrix);
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private void notifyCallback(Result result, float[] rotationMatrix) {
callback.callback(result, rotationMatrix);
}
public void start(PlatformCallback<float[]> callback) {
this.callback = callback;
sensorManager = (SensorManager) activity.getSystemService(Activity.SENSOR_SERVICE);
if (sensorManager != null) {
boolean accelerometerSupport = sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
boolean magneticFieldSupport = sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_UI);
if (!accelerometerSupport || !magneticFieldSupport) {
sensorManager.unregisterListener(this);
notifyCallback(new Result(Result.STATE.FAILED, "Not supported"), null);
}
} else {
notifyCallback(new Result(Result.STATE.FAILED, "Not supported"), null);
}
}
public void stop() {
if (sensorManager != null) {
sensorManager.unregisterListener(this);
}
}
}
And the PlaformCallback class:
public abstract class PlatformCallback<T> {
public void callback(final Result result, final T t) {
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
doCallback(result, t);
}
});
}
protected abstract void doCallback(Result result, T t);
}
In the core project you can now simply turn on and off your motion sensors:
private void startMotionSensor() {
platform.startMotionSensors(new PlatformCallback<float[]>() {
#Override
protected void doCallback(Result result, float[] rotationMatrix) {
if (result.ok()) {
// Do what you want with the rotation matrix
}
}
});
}
public void stopMotionSensor() {
platform.stopMotionSensors();
}
I am new in using background service and retrofit library, i am getting no error, by debugging my app i come to know that its getting coordinates but not sending to server(in background service)
Any help will appreciated, thanks in advance, happy coding!
GPS Service
public class LocationUpdaterService extends Service
{
public static final int TWO_MINUTES = 120000; // 120 seconds
public static Boolean isRunning = false;
public LocationManager mLocationManager;
public LocationUpdaterListener mLocationListener;
public Location previousBestLocation = null;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mLocationListener = new LocationUpdaterListener();
super.onCreate();
}
Handler mHandler = new Handler();
Runnable mHandlerTask = new Runnable(){
#Override
public void run() {
if (!isRunning) {
startListening();
}
mHandler.postDelayed(mHandlerTask, TWO_MINUTES);
}
};
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mHandlerTask.run();
return START_STICKY;
}
#Override
public void onDestroy() {
stopListening();
mHandler.removeCallbacks(mHandlerTask);
super.onDestroy();
}
private void startListening() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER))
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListener);
if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER))
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
}
isRunning = true;
}
private void stopListening() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationManager.removeUpdates(mLocationListener);
}
isRunning = false;
}
public class LocationUpdaterListener implements LocationListener
{
#Override
public void onLocationChanged(Location location) {
if (isBetterLocation(location, previousBestLocation)) {
previousBestLocation = location;
try {
// Script to post location data to server..
Call<Update> loginCall;
String deviceKey;
deviceKey = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
loginCall = MyApplication.getInstance().getAPI().update(deviceKey,String.valueOf(location.getLatitude()),String.valueOf(location.getLongitude()));
loginCall.enqueue(new Callback<Update>() {
#Override
public void onResponse(Call<Update> call, Response<Update> response) {
if(response.getClass() != null)
{
}
}
#Override
public void onFailure(Call<Update> call, Throwable t) {
}
});
}
catch (Exception e) {
e.printStackTrace();
}
finally {
stopListening();
}
}
}
#Override
public void onProviderDisabled(String provider) {
stopListening();
}
#Override
public void onProviderEnabled(String provider) { }
#Override
public void onStatusChanged(String provider, int status, Bundle extras) { }
}
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(), currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
My Application
import android.app.Application;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MyApplication extends Application {
private API api;
private OkHttpClient client;
private static MyApplication sInstance;
#Override
public void onCreate() {
super.onCreate();
sInstance = this;
configureAPI();
}
private void configureAPI() {
client = new OkHttpClient.Builder()
.connectTimeout(80, TimeUnit.SECONDS)
.writeTimeout(300, TimeUnit.SECONDS)
.readTimeout(80, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Server.API_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
api = retrofit.create(API.class);
}
public API getAPI() {
return api;
}
public static MyApplication getInstance() {
return sInstance;
}
}
API
public interface API {
#FormUrlEncoded
#POST("updateLocation")
Call<Update> update(#Query("token") String token, #Query("lat") String latitude, #Field("long") String longitude);
}
Server
public class Server {
public static final String API_URL = "http://192.168.146.2:8090/";
public static final String REG_API_URL = "http://192.168.120.2:8090/";
public static final String SndMsg_API_URL = "http://192.168.120.2:8090/";
}
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent serviceIntent = new Intent(getApplicationContext(), LocationUpdaterService.class);
startService(serviceIntent);
}
}
Your code looks pretty good. There are few things those might be causing problems. please check those.
First of all make sure compiler is going inside the "OnLocationChanged()" method.
Second thing make sure your web-service call method is of "Update" type. Because you are using "Update". It can be "Post".
Third thing is print the response in "OnFailure()" method, maybe it is going to failure.
I hope you will find the problem by checking these scenarios.
I am working on a simple GeoFence Service. I am not using the GeofencingApi because I am working with a jni bridge and making the library available would be to much overhead for my project.
So my Problem now is, that the LocationManager is not removing Updates after I am calling removeUpdates. I don't understand why. My code is as follows:
public class GeoFenceService extends Service {
public GeoFenceService() { Log.v("GeoFenceService","GeoFenceService init"); }
public static LocationManager mlocManager;
public static LocationListener mlocListener;
public void updateLocationAndCheckGeoFences() {
Log.d("GeoFenceService","Updating Location");
GeoFenceService.mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
GeoFenceService.mlocListener = new MyLocationListener();
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
String bestProvider = GeoFenceService.mlocManager.getBestProvider(criteria, true);
GeoFenceService.mlocManager.requestLocationUpdates(bestProvider, 0, 0, GeoFenceService.mlocListener);
//Location loc = mlocManager.getLastKnownLocation(bestProvider);
//checkGeoFences4(loc);
}
public void checkGeoFences4(Location locCurrent) {
Log.d("GeoFenceService","Checking GeoFence for Location:"
+locCurrent.getLatitude()+"/"+locCurrent.getLongitude());
for (Voucher voucher : listVouchers) {
Location locVoucher = new Location("Voucher");
locVoucher.setLatitude(voucher.dblLat);
locVoucher.setLongitude(voucher.dblLon);
float distance = locCurrent.distanceTo(locVoucher);
Log.d("GeoFenceService","\tGeoFence for Voucher"+voucher.strText+" Distance:"+distance);
if (distance < voucher.dblRadius) {
showNotification(voucher.strText,voucher.intEntryId);
}
}
}
public class MyLocationListener implements LocationListener
{
#Override
public void onLocationChanged(Location loc)
{
try {
checkGeoFences4(loc);
try {
GeoFenceService.mlocManager.removeUpdates(GeoFenceService.mlocListener);
Log.d("GeoFenceService","Location Update suspended");
} catch(Exception e) {
Log.e("GeoFenceService","Failed to suspend Location Update"+e.getMessage());
}
} catch (Exception e) { }
}
#Override
public void onProviderDisabled(String provider)
{
}
#Override
public void onProviderEnabled(String provider)
{
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
}
//Stuff for class GeoFenceService (simplyfied)
private final int UPDATE_INTERVAL = 15 * 60 * 1000;
private Timer timer = new Timer();
public void onCreate() { Log.d("GeoFenceService","GeoFenceService created"); }
public void onDestroy() { if (timer != null) { timer.cancel(); } }
public int onStartCommand(Intent intent, int flags, int startid) {
Log.d("GeoFenceService","GeoFenceService started");
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
updateLocationAndCheckGeoFences();
}
}, 0, UPDATE_INTERVAL);
return START_STICKY;
}
}
While updateLocationAndCheckGeoFences is succesfully starting the Location Updates removing them is not working.
The Log continuely logging:
D/GeoFenceService( 9953): Checking GeoFence for Location:♣♣.♣♣♣♣♣♣♣♣♣♣♣♣♣♣/♣♣.♣♣♣♣♣♣♣♣♣♣♣♣♣♣
D/GeoFenceService( 9953): GeoFence for VoucherRestaurant ♣♣♣♣: GUTSCHEIN jetzt einlösen Distance:315341.0
D/GeoFenceService( 9953): Location Update suspended
I hope someone can help me,
thanks in advance
how can I associate a method to home button of smartphone? I want that checking this botton my Android app does a specific method. I read that to disable home button there is the method:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
but it isn't useful for me. How can I solve this problem?
Use this code:
HomeWatcher mHomeWatcher = new HomeWatcher(this);
mHomeWatcher.setOnHomePressedListener(new OnHomePressedListener() {
#Override
public void onHomePressed() {
// do something here...
}
#Override
public void onHomeLongPressed() {
}
});
mHomeWatcher.startWatch();
HomeWatcher:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
public class HomeWatcher {
static final String TAG = "hg";
private Context mContext;
private IntentFilter mFilter;
private OnHomePressedListener mListener;
private InnerRecevier mRecevier;
public HomeWatcher(Context context) {
mContext = context;
mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
}
public void setOnHomePressedListener(OnHomePressedListener listener) {
mListener = listener;
mRecevier = new InnerRecevier();
}
public void startWatch() {
if (mRecevier != null) {
mContext.registerReceiver(mRecevier, mFilter);
}
}
public void stopWatch() {
if (mRecevier != null) {
mContext.unregisterReceiver(mRecevier);
}
}
class InnerRecevier extends BroadcastReceiver {
final String SYSTEM_DIALOG_REASON_KEY = "reason";
final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (reason != null) {
Log.e(TAG, "action:" + action + ",reason:" + reason);
if (mListener != null) {
if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
mListener.onHomePressed();
} else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
mListener.onHomeLongPressed();
}
}
}
}
}
}
}
OnHomePressedListener:
public interface OnHomePressedListener {
public void onHomePressed();
public void onHomeLongPressed();
}
Try overriding onKeyDown as such:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_HOME)
// do what you need
}
Use This Code For only HomeWtcher class this one is better.
public class HomeWatcher {
static final String TAG = "hg";
private Context mContext;
private IntentFilter mFilter;
private OnHomePressedListener mListener;
private InnerReceiver mReceiver;
public HomeWatcher(Context context) {
mContext = context;
mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
}
public void setOnHomePressedListener(OnHomePressedListener listener) {
mListener = listener;
mReceiver = new InnerReceiver();
}
public void startWatch() {
if (mReceiver != null) {
mContext.registerReceiver(mReceiver, mFilter);
}
}
public void stopWatch() {
if (mReceiver != null) {
mContext.unregisterReceiver(mReceiver);
}
}
class InnerReceiver extends BroadcastReceiver {
final String SYSTEM_DIALOG_REASON_KEY = "reason";
final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
if (reason != null) {
Log.e(TAG, "action:" + action + ",reason:" + reason);
if (mListener != null) {
if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
mListener.onHomePressed();
} else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
mListener.onHomeLongPressed();
}
}
}
}
}
}
}
I have a problem with Location variable in my Android app. On this screen GPSLocation works fine, but when I change screen to gpsLocation.getLastKnownLocation() this method always returns null.
First Screen:
public class MainActivity extends ActionBarActivity {
private TextView text;
private GPSLocation gpsLocation;
private Location targetLocation;
private EditText editLatitude;
private EditText editLongitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView)findViewById(R.id.textView);
gpsLocation = new GPSLocation(this);
editLatitude = (EditText)findViewById(R.id.editDlugosc);
editLongitude = (EditText)findViewById(R.id.editSzerokosc);
targetLocation = new Location("Bosch");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void click_rozpocznij(View view) {
targetLocation=gpsLocation.getLastKnownLocation();
text.setText("Your location: \n" + gpsLocation.getLatitude() + "\n" + gpsLocation.getLongitude());
}
public void click_end(View view)
{
gpsLocation.stopUsingGPS();
text.setText("Your location:");
}
public void click_pointer(View view) {
if(targetLocation !=null) {
Intent nextScreen = new Intent(getApplicationContext(), Pointer.class);
nextScreen.putExtra("location", targetLocation);
startActivity(nextScreen);
}
else
{
targetLocation.setLongitude(0);
targetLocation.setLatitude(0);
Intent nextScreen = new Intent(getApplicationContext(), Pointer.class);
nextScreen.putExtra("location", targetLocation);
startActivity(nextScreen);
}
}
public void click_show(View view) {
gpsLocation.getLastKnownLocation();
text.setText("Your location: \n" + gpsLocation.getLatitude() + "\n" + gpsLocation.getLongitude());
}
public void click_SaveTarget(View view) {
if(targetLocation !=null)
{
try{
targetLocation.setLatitude(Double.parseDouble(editLatitude.getText().toString()));
targetLocation.setLongitude(Double.parseDouble(editLongitude.getText().toString()));
}
catch(Exception e)
{
targetLocation.setLatitude(0);
targetLocation.setLongitude(0);
editLatitude.setText("0");
editLongitude.setText("0");
}
}
}
Second Screen:
public class Pointer extends ActionBarActivity implements SensorEventListener{
private Location cel;
private TextView textLocation;
private TextView textDistance;
private TextView textAngle;
private TextView textAccuracy;
private ImageView obrazek;
private SensorManager sensorManager;
private float[] lastCompass= new float[3];
private float[] lastAccelero = new float[3];
private float[] orientation = new float[3];
private boolean lastCompassSet = false;
private boolean lastAcceleroSet = false;
private float[] rotation = new float[9];
private float degree = 0f;
private Sensor compass;
private Sensor accelerometer;
private GPSLocation gpsLocation;
private Location locationFirst;
private Location locationNow;
private GeomagneticField magneticField;
private float azimuthDegress;
private float azimuthCel;
private Long timeStart;
private Long timeEnd;
private void sprawdzPolozenie()
{
if (gpsLocation.location.distanceTo(locationFirst) > 10000)
{
magneticField = new GeomagneticField(Double.valueOf(gpsLocation.getLatitude()).floatValue(),Double.valueOf(gpsLocation.getLongitude()).floatValue(),Double.valueOf(gpsLocation.getAltitude()).floatValue(),System.currentTimeMillis());
locationFirst = gpsLocation.getLastKnownLocation();
}
SensorManager.getRotationMatrix(rotation,null,lastAccelero,lastCompass);
SensorManager.getOrientation(rotation,orientation);
float azimuthRadians = orientation[0];
azimuthDegress = (float)(Math.toDegrees(azimuthRadians));
azimuthDegress += magneticField.getDeclination();
azimuthCel= locationNow.bearingTo(cel);
azimuthDegress=azimuthDegress-azimuthCel;
RotateAnimation ra = new RotateAnimation(degree,-azimuthDegress, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
ra.setDuration(400);
ra.setFillAfter(true);
obrazek.startAnimation(ra);
degree=-azimuthDegress;
}
#Override
public void onSensorChanged(SensorEvent event) {
locationNow=gpsLocation.getLastKnownLocation();
if(locationNow!=null) {
if (event.sensor == compass) {
/*event.values[0]=lastCompass[0];
event.values[1]=lastCompass[1];
event.values[2]=lastCompass[2];*/
System.arraycopy(event.values, 0, lastCompass, 0, event.values.length);
lastCompassSet = true;
} else if (event.sensor == accelerometer) {
/*event.values[0]=lastAccelero[0];
event.values[1]=lastAccelero[1];
event.values[2]=lastAccelero[2];*/
System.arraycopy(event.values, 0, lastAccelero, 0, event.values.length);
lastAcceleroSet = true;
}
if (lastCompassSet) {
timeStart = System.currentTimeMillis();
if (timeStart > timeEnd + 500) {
sprawdzPolozenie();
timeEnd = timeStart;
}
}
textDistance.setText("Distanse: " + locationNow.distanceTo(cel));
textAccuracy.setText("Accuracy: " + locationNow.getAccuracy());
textAngle.setText("Angle: " + azimuthDegress);
}
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
sensorManager.registerListener(this, compass, SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause(){
super.onPause();
sensorManager.unregisterListener(this,accelerometer);
sensorManager.unregisterListener(this,compass);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gpsLocation = new GPSLocation(this);
locationFirst = new Location("Bosch");
locationNow = new Location("Bosch");
cel = new Location("Bosch");
locationNow=gpsLocation.getLastKnownLocation();
locationFirst= gpsLocation.getLastKnownLocation();
setContentView(R.layout.activity_wskaznik);
timeEnd =System.currentTimeMillis();
sensorManager = (SensorManager)this.getSystemService(Context.SENSOR_SERVICE);
compass = sensorManager.getDefaultSensor(TYPE_MAGNETIC_FIELD);
accelerometer = sensorManager.getDefaultSensor(TYPE_ACCELEROMETER);
obrazek =(ImageView)findViewById(R.id.wskaznik_imageView);
textLocation = (TextView)findViewById(R.id.wskaznikTekstCel);
textDistance = (TextView)findViewById(R.id.wskaznikTekstOdleglosc);
textAngle = (TextView)findViewById(R.id.wskaznikTekstKat);
textAccuracy =(TextView)findViewById(R.id.wskaznikTekstDokladnosc);
Bundle extras = getIntent().getExtras();
magneticField = new GeomagneticField(Double.valueOf(gpsLocation.getLatitude()).floatValue(),Double.valueOf(gpsLocation.getLongitude()).floatValue(),Double.valueOf(gpsLocation.getAltitude()).floatValue(),System.currentTimeMillis());
if(extras!=null)
{
cel = (Location)extras.get("location");
}
textLocation.setText(cel.getLatitude() + "," + cel.getLongitude());
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void click_wroc(View view) {
finish();
}
GPSLocation itself:
public class GPSLocation extends Service implements LocationListener {
private final Context mContext;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
public boolean canGetLocation = false;
//czas i dystans pomiedzy pomiarami
private static final long MIN_DISTANCE = 10;
private static final long MIN_TIME = 1000 * 60 * 1;
double latitude;
double longitude;
double altitude;
public Location location;
protected LocationManager locationManager;
public GPSLocation(Context context)
{
this.mContext = context;
getLocation();
}
public void requestLocation() {
//network
if (isNetworkEnabled)
{
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME, MIN_DISTANCE, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
altitude = location.getAltitude();
}
}
//gps
if(isGPSEnabled)
{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME, MIN_DISTANCE, this);
if(locationManager != null)
{
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
if(location!=null)
{
latitude=location.getLatitude();
longitude=location.getLongitude();
altitude = location.getAltitude();
}
}
}
public Location getLastKnownLocation()
{
try
{
isGPSEnabled=locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled=locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(!isGPSEnabled && !isNetworkEnabled)
{
this.canGetLocation=false;
this.showSettingsAlert();
}
else
{
requestLocation();
}
}
catch (Exception e)
{
e.printStackTrace();
}
return location;
}
public Location getLocation()
{
try
{
locationManager=(LocationManager)mContext.getSystemService(LOCATION_SERVICE);
isGPSEnabled=locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled=locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(!isGPSEnabled && !isNetworkEnabled)
{
this.canGetLocation=false;
this.showSettingsAlert();
}
else
{
this.canGetLocation=true;
requestLocation();
}
}
catch (Exception e)
{
e.printStackTrace();
}
return location;
}
public double getLatitude()
{
if(location!=null)
{
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude()
{
if(location!=null)
{
latitude = location.getLatitude();
}
return longitude;
}
public double getAltitude(){
if(location!=null)
{
latitude=location.getAltitude();
}
return altitude;
}
public void showSettingsAlert()
{
AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
alertDialog.setTitle("Przejdź do ustawień");
alertDialog.setMessage("Lokalizacja wyłączona");
// On pressing Settings button
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
mContext.startActivity(intent);
}
});
// on pressing cancel button
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
public void stopUsingGPS()
{
if(locationManager!=null)
{
locationManager.removeUpdates(GPSLocation.this);
}
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
I ran your Pointer Activity code in isolation, and it worked fine for me.
It looks like your main issue is how you're passing the Location through the Intent to the Pointer Activity from MainActivity.
Location implements Parcelable, so you can pass it though the Intent as you are already doing, and retrieve it like this:
if(extras!=null)
{
//cel = (Location)extras.get("location"); //this is not correct
cel = (Location) extras.getParcelable("location");
}
if (cel != null){
textLocation.setText(cel.getLatitude() + "," + cel.getLongitude());
}
Documentation: http://developer.android.com/reference/android/os/Bundle.html#getParcelable(java.lang.String)
http://developer.android.com/reference/android/location/Location.html
Sory for everyone who wanted help me for problem. I solved this by myself.
Problem was in GPSLocation class. I had to add new constructor at start and change way of getting location from locationManager
public GPSLocation(Context context)
{
this.mContext = context;
location = new Location("Bosch");
getLocation();
}
When I use this code location stay nullpointer.
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
But creating copy of location from locationManager solved problem.
location = new Location(locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
Maybe locationManager is creating data of location only not Location itself and that was causing creating nullpointer.