Android Location Object Always Null - java

I'm simply trying to write a method that returns Latitude and Longitude. I have an activity with a button and two text fields. The java class I am using extends AppCompatActivity and implements LocationListener When the button is pressed the following method is pressed:
public void startGPS(View view)
{
// Here is the code to handle permissions - you should not need to edit this.
if ( Build.VERSION.SDK_INT >= 23 &&
ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION }, TAKE_PHOTO_PERMISSION);
}
Location location = locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 5000, 0, this);
}
Later on I try to print out my location in my onLocationChanged method but it was causing the app to crash. I ran it through the debugger and found that the location was always null.
I tried to this solution but it didn't work. Other examples are calling the function in onResume but I really need this to be in startGPS method.
Also, is there a chance that the error is just with my device? I'm running it on a Nexus 7 which doesn't seem to have any problems when I run Google Maps.

If are trying to return the GPS Coordinates after pressing a button that chances are you don't already have an existing GPS location stored. You should be using requestLocationUpdates and not getLastKnownLocation.
locationManager.requestLocationUpdate(LocationManager.NETWORK_PROVIDER, 5000, 0, locationListener)
When you use requestLocationUpdate it will automatically call onLocationChanged for you so you don't need to call it in your code.
You can substitute LocationManager.NETWORK_PROVIDERfor LocationManager.GPS_PROVIDER but as long as you have a WiFi connection you should be able to get coordinates.

If you are trying to use this inside try switching GPS_PROVIDER to NETWORK_PROVIDER; this will work anywhere that the phone has service.

Because Android doesn't track location when no app is requesting it, in order to save battery. GetLastKnownLocation will almost always return null. If you want an assured non-null response, use requestLocationUpdates or requestSingleLocation. Both of those are asynchronous though, so they will call a callback when a location is found (actually figuring out a location can take from a few seconds to a minute or two, depending on the type of location provider, atmospheric conditions, line of sight issues, etc. If using GPS and inside it could actually never occur.)

Related

Android - app goes to launcher after calling CAPTURE_IMAGE intent and taking picture (doesn't return to the fragment)

So I have a Fragment that calls the following method which launches the camera:
private void launchCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
And I expect to receive the picture data in this method in my fragment:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (!(resultCode == RESULT_OK)) return;
if (requestCode == REQUEST_IMAGE_CAPTURE || requestCode == REQUEST_GALLERY_IMAGE) {
Uri imageURI = data.getData();
// do something
}
}
However, after I take a picture and confirm it, the app goes to my launcher. After setting breakpoints in the onActivityResult method, the app never even reaches this method before crashing. I've granted made sure to grant all permissions in both the manifest and at runtime.
There are also no outputs to Logcat with this crash, both in the app logs and the device logs. I have also tested on both my device (Moto G5 Plus) & Pixel XL API 26 emulator; both have the same result.
I think you need to call super.onActivityResult().
The fragment is the one making the startActivityForResult() call, but the activity gets the first shot at handling the result so you need to implement super.onActivityResult() to make the fragment handle the result.
the app immediately crashes to my launcher
No, the camera app immediately brings up the launcher. Apparently, the developers of this camera app wrote it to bring up the home screen when the user is done taking the picture. This is a bug, of course, but there is little that you can do about it.
Use ACTION_IMAGE_CAPTURE when you would like a picture but do not mind if you do not get it, due to bugs in some of the hundreds of camera apps that you are integrating with. Otherwise, use a camera library (Fotoapparat, CameraKit-Android, etc.) to take the picture directly in your own app.
Also, and FWIW, ACTION_IMAGE_CAPTURE does not return a Uri, so your onActivityResult() code will not work anyway. Given your particular ACTION_IMAGE_CAPTURE Intent configuration, in onActivityResult(), data.getParcelableExtra("data") will return a Bitmap representing a thumbnail-sized image.
I believe this is yet another manifestation of the Android: Activity getting Destroyed after calling Camera Intent.
The bottom line is, the system restarts your app from scratch and your activity is created but has a chance to restore its state.
So you must implement onRestoreInstanceState(). I am not sure you can guarantee that the fragment will be ready to receive onActiviyResult() timely, so to be in the safe side, I prefer to handle the captured image in activity itself.
So this issue was actually because of an intent flag I had attached to the activity. My activity was started using the NO_HISTORY intent flag, which apparently prevented it from being recreated when returned from a startActivityForResult call.

Null pointer exception when checking for permission with android.content.Context.checkPermission

I need to check for permissions before querying the Android calendar for events.
To do it, Android studio is warning that I need to follow a check before querying.
The auto generated code is this piece:
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
System.out.println("NO ACCESS TO CALENDAR!! Abort mission, abort mission!!");
}
When trying to run it, I get this error:
Attempt to invoke virtual method 'int
android.content.Context.checkPermission(java.lang.String, int, int)'
on a null object reference
So it is clear that something is null at this point, and I tried to get the context of the app with a different way, but it's still the same error.
Other thing I tried was this code, which is supposed to handle the targets lower than Android 6:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CALENDAR},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
Still get the same error, can anybody help me with this?
it's a separate class, controller: public class DummyData extends Activity { .... }
That is not going to work.
Never extend Activity unless it is a real activity, one that you will register in the manifest.
Never create an instance of an Activity via a constructor (e.g., the new DummyData() that you have somewhere in your code). Use startActivity() to display an activity that you have registered in the manifest.
As it stands, while your DummyData class may work from a compilation standpoint, it will not work at runtime. An Activity needs to be instantiated by the framework, and that is not the case with your DummyData.
Pass a real Context object to checkSelfPermission(), and pass a real Activity object to requestPermissions(). In this case, "real" means "handed to you from the framework".
Use (Activity)mContext instead of this.
if(ContextCompat.checkSelfPermission((Activity)mContext,Manifest.permission.READ_CALENDAR)!=PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions((Activity) mContext, new String[]{Manifest.permission.READ_CALENDAR},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}
You have to write the right activity at the position "this"
main problem in activity.
Try to write the code in MainActivity and test.
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CALENDAR},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}

Wait onLocationChanged(Location location)

I need to get current location, and after that - do next code. How can i wait while this method has finished? onLocationChanged is called automatically that why i have problem. Do someone has any ideas how to do itmore correct?
I make it very stupid, in OnLocationChanged() i call onResume(), but it is so bad idea.
#Override
public void onLocationChanged(Location location) {
final Location loc = location;
Log.d("myLogs", "OnChange2");
Log.d("myLogs", "2" + loc.getLatitude() + "," + loc.getLongitude());
myLat = loc.getLatitude();
myLong = location.getLongitude();
onResume();
}
You might want to use AsyncTask for that. See Android find GPS location once, show loading dialog for the answers. Basically in onPreExecute you can start dialog( it starts before the doInBackground is called). It means you are waiting till the time you can location and showing the dialog. Then in doInBackground you can get the location. After that finishes onPostExecute is called. You can stop is from inside onPostExecute. You can check if the location is not null and then call some other function from inside onPostExecute also if you want.
This might be one way. You can learn a basic example from AsyncTask Android example . You can also start by reading the documentation here and read How to Get GPS Location Using AsyncTask? .
Some other similar helpful questions:
Wait for current location - GPS - Android Dev
getting location instantly in android
Hope this helps.
I realize the OP has accepted the above answer but I have a feeling the OP wanted a more simple answer.
I am assuming the OP has an android application with an Activity. I declared mine like this:
public class HelloAndroidActivity extends Activity implements LocationListener {
The OP was confused as to how the lifecycle methods worked and when work should be done. My Resume and Pause methods would look like this:
#Override
protected void onPause() {
((LocationManager)getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
super.onPause();
}
#Override
protected void onResume() {
((LocationManager)getSystemService(Context.LOCATION_SERVICE)).requestLocationUpdates(LocationManager.GPS_PROVIDER, 5 * 1000, 1, this);
super.onResume();
}
Notice that my onResume asks that I be notified when there are location updates and the onPause method asks that I no longer be notified. You should be careful to not ask for updates at a time interval smaller then you really need or you will drain your battery.
Since the activity implements LocationListener my onLocationChanged method looks like this:
#Override
public void onLocationChanged(Location location) {
// Update the location fields
((EditText)findViewById(R.id.latField)).setText(Double.toString(location.getLatitude()));
((EditText)findViewById(R.id.longField)).setText(Double.toString(location.getLongitude()));
}
This simply takes the new location and updates some text EditText fields that I have in my activity. The only other thing I needed to do was to add the GPS permission to my manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
So if I were asking how to start out using the location manager and the location service this would be how I would begin. I'm not trying to take anything away from the accepted answer, I just think there was a fundamental misunderstanding about what to do in onResume and in the onLocationMethodChanged methods.

Getting Coordinates From Button Press Not Working

I am pretty new to Android Development, and I've tried to make a method in my Android Application, where you press the button and get coordinates (Longitude and Latitude). But the program stops working on the emulator when I press the button.
I am probably just doing something wrong here. Looking through the Callstack didn't help me. It was simply too cluttered with...a lot of useless information.
How do I fix this?
public void onLocateByGMapButtonClick() {
LocationManager mloc = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
List<String> providers = mloc.getAllProviders();
Location loc = new Location(providers.get(0));
double loTude = loc.getLongitude();
double laTude = loc.getLatitude();
String newCoords = loTude + "," + laTude;
location.setText(newCoords);
Toast.makeText(this.getBaseContext(),"Location have been updated!",5);
}
The reason you application is crashing is probably because you are receiving a null pointer exception.
You have to understand that a GPS fix is not an immediate process, it might take time and in this time you don't have a location to work on unless you use the getLaskKnownLocation method (which maybe return null as well).
So what you need to to is or use:
Location loc = lm.getLastKnownLocation(provider);
or implement a LocationListener that will fire as soon as a new location update arrives.
Tutorial: http://www.vogella.com/articles/AndroidLocationAPI/article.html

How does really work the requestLocationUpdates of LocationManager in Android?

Working with the Location Manager in Android, nce you first call the requestLocationUpdates, the value you pass it to select the refresh time can be changed?
Let me explain. Here we have what I'm doing (and works perfect):
(...)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPSrefresh, GPSminDistance, locationListener);
(...)
public void onLocationChanged(Location location) {
// Do what you want to do
}
If, after some time, I change the value of GPSrefresh, Is it going to affect to the locationUpdates? Is it always checking the value of GPSrefresh or it just did it the first time it was called?
Thank you very much.
you are passing values to a method requestLocationUpdates of LocationManager calss and then updateing that value..so it will not affect the previous method call..
Like,
String tmp="Mango";
Fruits.add(tmp);
tmp="Apple";
in above only Mango will be added..to add Apple you will have to call Fruits.add(tmp) again,
Same way..IF you cange value of GPSRefresh you will need to call the method requestLocationUpdates again with the new updated parameters.

Categories