Am I missing something on retrieving GPS Current Location? - java

I recently began developing an app, and I've spent the last few days working on the GPS part to obtain the user's address.
The issue is that if I run the app in Android Studio Emulator and change the address on the map, it appears correctly on a Toast and in the String variable I created to store the address, as shown in the screenshot below, but if I build the APK and run it on a Smartphone, the Toast does not appear and the String variable remains empty.
Is there something in my code that I'm forgetting? I'll paste the code for someone to review below.
public class FragmentT1_Agora extends Fragment {
View view;
LocationManager locationManager;
String moradaAtual; // Current Address
private Button btEnviar;
public FragmentT1_Agora() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_t1_agora, container, false);
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 100);
}
locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 3, mLocationListener);
return view;
}
private final LocationListener mLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
Toast.makeText(getContext(), "" + location.getLatitude() + "," + location.getLongitude(), Toast.LENGTH_LONG).show();
try {
Geocoder geocoder = new Geocoder(getContext(), Locale.getDefault());
List<Address> moradas = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);
moradaAtual = moradas.get(0).getAddressLine(0);
Toast.makeText(getContext(), "Morada: " + moradaAtual, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
}
I've left out the code that isn't related to the GPS.
Screenshot:

Related

Problem in getting location in android studio

I tried to get a latitude and longitude and the address of the current location.
When I tried in the emulator it worked..but when I tried to use my smartphone it was not working.
I have added the location permissions in the manifest.
Please help me with a solution.
The emulator I have used is Pixel 4a API 30.
I can't find where I have gone wrong.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView_location = findViewById(R.id.text_location);
button_location = findViewById(R.id.button_location);
//Runtime permissions
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{
Manifest.permission.ACCESS_FINE_LOCATION
},100);
}
button_location.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//create method
getLocation();
}
});
}
#SuppressLint("MissingPermission")
private void getLocation() {
try {
locationManager = (LocationManager) getApplicationContext().getSystemService(LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,5,MainActivity.this);
}catch (Exception e){
e.printStackTrace();
}
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(this, ""+location.getLatitude()+","+location.getLongitude(), Toast.LENGTH_SHORT).show();
try {
Geocoder geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
List<Address> addresses = geocoder.getFromLocation(location.getLatitude(),location.getLongitude(),1);
String address = addresses.get(0).getAddressLine(0);
textView_location.setText(address);
}catch (Exception e){
e.printStackTrace();
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}

Android duplicates activity when minimized, then maximized

I have google searched this with no success and seams very strange to me.
I am building a simple GPS app that send co-ordinates with HttpRequest, though I have noticed when minimising the UI then maximising, It runs a duplicate of the same activity. and doubles up on HttpRequest's
private LocationManager locationManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gps);
processExtraData();
}
private void processExtraData() {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(this);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10000, 5, this);
}
#Override
public void onLocationChanged(Location location) {
Bundle extras = getIntent().getExtras();
String driver_id = extras.getString("driverid");
String msg = "Driver:" + driver_id + "\nCurrent Location:\nLatitude: " + location.getLatitude()
+ "\nLongitude: " + location.getLongitude();
new HttpRequestTask(
new HttpRequest("https://www.autoflora.net/driver/gps.php?user_id=" + driver_id + "&latlong=" + location.getLatitude() + "*" + location.getLongitude(), HttpRequest.POST, "{ \"some\": \"data\" }"),
new HttpRequest.Handler() {
#Override
public void response(HttpResponse response) {
if (response.code == 200) {
Log.d(this.getClass().toString(), "Request successful!");
} else {
Log.e(this.getClass().toString(), "Request unsuccessful: " + response);
}
}
}).execute();
String s = calc.getText().toString();
calc.setText(s + "1")
TextView driver = (TextView) findViewById(R.id.driver);
driver.setText("" + driver_id);
TextView Longitude = (TextView) findViewById(R.id.longitude);
// Getting reference to TextView tv_latitude
TextView Latitude = (TextView) findViewById(R.id.latitude);
// Setting Current Longitude
Longitude.setText("Longitude:" + location.getLongitude());
// Setting Current Latitude
Latitude.setText("Latitude:" + location.getLatitude());
// Toast.makeText(getBaseContext(), msg, Toast.LENGTH_LONG).show();
}
noticed when minimising the UI then maximising
There's neither minimising nor maximizing of UI on Android. You apparently start the activity again via launcher (this is most likely your maximizing thing) which creates new instance of you activity. If you want just single instance allowed no matter what, you must set system so by using android:launchMode in declaration of activity in your manifest file. See docs here for possible options.
#Override
public void onStart() {
super.onStart();
Toast.makeText(getBaseContext(), "start", Toast.LENGTH_LONG).show();
locationManager.removeUpdates(this);
}
#Override
public void onResume() {
super.onResume();
Toast.makeText(getBaseContext(), "resume", Toast.LENGTH_LONG).show();
locationcheck(); // checks permissions
}
#Override
public void onPause() {
super.onPause();
Toast.makeText(getBaseContext(), "pause", Toast.LENGTH_LONG).show();
}
#Override
public void onStop() {
super.onStop();
// locationManager.removeUpdates(this);
Toast.makeText(getBaseContext(), "stop", Toast.LENGTH_LONG).show();
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getBaseContext(), "destroy", Toast.LENGTH_LONG).show();
locationManager.removeUpdates(this);
finish();
}
Seems to have fixed it..

Current location shows on emulator but not on phone

I am setting up my map to track my location. Right at the start I want it to detect my Lat and Long and show where I am and update the marker location when I move.
When I test this on GenyMotion emulator and input my own positions, it works and shows updated location accordingly. But when I test it on a mobile device, I do not get any marker and get the "Location null" Toast message.
Since it is the first time on the device, there is probably no last known location. Thus wanting to make sure, I took the device and moved a distance (probably 50 meters or so back n forth) and still nothing updated on the device.
public class TrackMapsActivity extends FragmentActivity implements OnMapReadyCallback, LocationListener {
private GoogleMap mMap;
LocationManager locationManager;
Location location;
String provider;
Double lat, lng;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_track_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
provider = locationManager.getBestProvider(new Criteria(), false);
try {
//Get last known user location
location = locationManager.getLastKnownLocation(provider);
if(location != null){
Toast.makeText(TrackMapsActivity.this, "Location NOT null", Toast.LENGTH_SHORT).show();
onLocationChanged(location);
}
else {
Toast.makeText(TrackMapsActivity.this, "Location null", Toast.LENGTH_SHORT).show();
}
}
catch (SecurityException e){
e.printStackTrace();
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
}
#Override
protected void onResume() {
super.onResume();
try {
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
catch (SecurityException e){
e.printStackTrace();
}
}
#Override
protected void onPause() {
super.onPause();
try {
locationManager.removeUpdates(this);
}
catch (SecurityException e){
e.printStackTrace();
}
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(TrackMapsActivity.this, "You Moved", Toast.LENGTH_SHORT).show();
lat = location.getLatitude();
lng = location.getLongitude();
LatLng yourLocation = new LatLng(lat, lng);
if(mMap != null) {
mMap.clear();
mMap.addMarker(new MarkerOptions().position(yourLocation).title("Your Location"));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(yourLocation, 10));
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
do you put the permission for using the gps :)
The main permissions you need are
android.permission.ACCESS_COARSE_LOCATION or
android.permission.ACCESS_FINE_LOCATION.

locationManager.isProviderEnabled is not working with Genymortion emulator

I am new to JAVA and I have to create an app that plot a route between where I am (found by GPS) and some pre-specified destination. I followed online tutorials such as http://androidexample.com/GPS_Basic__-__Android_Example/index.php?view=article_discription&aid=68&aaid=93 to learn how to read my own location.
I want my app to act differently when the GPS is turned on and off. To read the GPS status I used an LocationManager object as line below:
boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
I can manually turn the GPS off in Genymortion emulator by right clicking the GPS tab. The picture below shows how I turned on the GPS.
However, my app always say either isGPSEnabled = true all the time or isGPSEnabled = false all the time even though I change the GPS status. Can anyone tells me what I am missing? I attached most of my code below if that helps.
public class MapDisplayActivity extends Activity implements LocationListener {
private MapDisplayFragment fragment;
private DrawerLayout sideDrawerMenu;
private ListView sideDrawerMenuList;
private LocationManager locationManager;
private boolean isGPSEnabled;
private final static String LOG_TAG = "MapDisplayActivity";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.side_drawer_menu);
// some codes come here...
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (isGPSEnabled) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
5000, // 5 sec
10, this);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#Override
public void onLocationChanged(Location location) {
if (isGPSEnabled) {
String str = "Latitude: " +
location.getLatitude()
+ "Longitude: " + location.getLongitude();
Toast.makeText(getBaseContext(), str, Toast.LENGTH_LONG).show();
}else{
gpsLatlon = null;
}
}
#Override
public void onProviderDisabled(String provider) {
Toast.makeText(getBaseContext(), "Gps turned off ", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(getBaseContext(), "Gps turned on ", Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
// ~~~~~~~~~~ to imeplement LocationListener ~~~~~~~~~~~~~~
private class SideDrawerClickListener implements ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
selectItem(position);
}
}
// some more methods definitions....
}
It looks like you just need to set the isGPSEnabled flag in the callbacks:
#Override
public void onProviderDisabled(String provider) {
if(provider.equals(LocationManager.GPS_PROVIDER)){
isGPSEnabled = false;
}
Toast.makeText(getBaseContext(), "Gps turned off ", Toast.LENGTH_LONG).show();
}
#Override
public void onProviderEnabled(String provider) {
if(provider.equals(LocationManager.GPS_PROVIDER)){
isGPSEnabled = true;
}
Toast.makeText(getBaseContext(), "Gps turned on ", Toast.LENGTH_LONG).show();
}
One thing to note is that these callbacks will only be called if you currently have the Activity registered as a location listener.
So, as you have it now, only the onProviderDisabled() callback will be called if the Activity starts with GPS on and then GPS is disabled with the Activity still running.
One way to go would be to register for NETWORK_PROVIDER callbacks when GPS is disabled.
That way you would still have a location listener registered, and you would get the onProviderEnabled() callback for GPS. At that point you could unregister for NETWORK callbacks and register for GPS callbacks.

Android - EBADF (Bad file number) OnClickInfoMarker

I have searched related issues but can't find it. I create an InfoWindowMarker which shows Picture, Name and Address. Then i create OnInfoWindowClickListener that will showing Latitude and Longitude of selected Marker. But when i click the Info Window i got this error message.
Logcat:
com.xxxxxxxx.xxxxxxxxxx E/Zygote﹕ Zygote: error closing descriptor
libcore.io.ErrnoException: close failed: EBADF (Bad file number)
at libcore.io.Posix.close(Native Method)
at libcore.io.BlockGuardOs.close(BlockGuardOs.java:75)
at com.android.internal.os.ZygoteInit.closeServerSocket(ZygoteInit.java:221)
at com.android.internal.os.ZygoteConnection.handleChildProc(ZygoteConnection.java:879)
at com.android.internal.os.ZygoteConnection.runOnce(ZygoteConnection.java:242)
at com.android.internal.os.ZygoteInit.runSelectLoop(ZygoteInit.java:713)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:649)
at dalvik.system.NativeStart.main(Native Method)
InfoWindowAdapter:
public GoogleMap.InfoWindowAdapter CustomMarkerInfo = new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker marker) {
ViewGroup viewGroup = (ViewGroup)getLayoutInflater().inflate(R.layout.custom_info_window, null);
ImageView ivRow = (ImageView)viewGroup.findViewById(R.id.ivRowImage);
TextView locationName = (TextView)viewGroup.findViewById(R.id.tvRowTitle);
TextView locationAddress = (TextView)viewGroup.findViewById(R.id.tvRowTitle2);
Bitmap locationImage;
locationName.setText(marker.getTitle());
locationAddress.setText(marker.getSnippet());
URL imageURL;
try {
imageURL = new URL(markerInfo.get(marker.getId()));
locationImage = BitmapFactory.decodeStream(imageURL.openConnection().getInputStream());
ivRow.setImageBitmap(locationImage);
}catch (Exception e){
e.printStackTrace();
}
return viewGroup;
}
#Override
public View getInfoContents(Marker marker) {return null;}
};
OnInfoWindowClickListener:
private GoogleMap.OnInfoWindowClickListener onInfoWindowClickListener = new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
LatLng myLatLng = myLatLng();
Toast.makeText(getApplicationContext(),myLatLng.toString(),Toast.LENGTH_LONG).show();
}
};
private final LocationListener locationListener = new LocationListener() {
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
#Override
public void onLocationChanged(Location newLocation) {
}
};
private LatLng myLatLng(){
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
String provider;
Location location;
LatLng myLatLng = null;
if(locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
provider = LocationManager.GPS_PROVIDER;
Toast.makeText(getApplicationContext(),"GPS tidak aktif.",Toast.LENGTH_LONG).show();
}else if(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
provider = LocationManager.NETWORK_PROVIDER;
}else{
provider = LocationManager.PASSIVE_PROVIDER;
}
if(locationManager.getLastKnownLocation(provider) == null){
locationManager.requestLocationUpdates(provider,2000,10,locationListener);
location = locationManager.getLastKnownLocation(provider);
if(location == null){
Toast.makeText(getApplicationContext(),"Tidak dapat menemukan lokasi saat ini, coba lagi.",Toast.LENGTH_LONG).show();
}else{
location = locationManager.getLastKnownLocation(provider);
myLatLng = new LatLng(location.getLatitude(),location.getLongitude());
}
}else{
location = locationManager.getLastKnownLocation(provider);
myLatLng = new LatLng(location.getLatitude(),location.getLongitude());
}
return myLatLng == null ? myLatLng() : myLatLng;
}
Thanks for any solution.
Update: Markers created from loaded JSON. If it is could causing this issue.
This might be a threading issue. Your viewGroup is returned before your image is load from the URL. An easy way to solve the problem is to use the third party image loading library Picasso.
Sample code:
ImageView imageView = (ImageView)myContentsView.findViewById(R.id.ivRowImage);
if (not_first_time_showing_info_window) {
Picasso.with(getApplicationContext()).load("YOUR_IMG_URL").into(imageView);
} else { // if it's the first time, load the image with the callback set
not_first_time_showing_info_window=true;
Picasso.with(getApplicationContext()).load("YOUR_IMG_URL").into(imageView,new InfoWindowRefresher(marker));
}
And then you can have a private helper method to make sure the asynchronous shown in the first click:
private class InfoWindowRefresher implements Callback {
private Marker markerToRefresh;
private InfoWindowRefresher(Marker markerToRefresh) {
this.markerToRefresh = markerToRefresh;
}
#Override
public void onSuccess() {
markerToRefresh.showInfoWindow();
}
#Override
public void onError() {}
}
You can refer to this GitHub page for complete implementation: https://github.com/jbj88817/GoogleMap-InfoWindow-android/blob/master/app/src/main/java/com/bjiang/map_ex/MainActivity.java
If you really want to do it with ImageLoader, you can check out this post: http://androidfreakers.blogspot.com/2013/08/display-custom-info-window-with.html
(But it is more complicated compared to using Picasso to load from URL)

Categories