The following code is from a Google maps activity to find a particular location on user input.It works fine but crashes when there is no persistent internet connection.Please help me fix this problem.
The MainActivity.java class looks like this:
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.io.IOException;
import java.util.List;
public class MainActivity
extends FragmentActivity {
GoogleMap googleMap;
MarkerOptions markerOptions;
LatLng latLng;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
// Getting a reference to the map
googleMap = supportMapFragment.getMap();
// Getting reference to btn_find of the layout activity_main
Button btn_find = (Button) findViewById(R.id.btn_find);
// Defining button click event listener for the find button
OnClickListener findClickListener = new OnClickListener() {
#Override
public void onClick(View v) {
EditText etLocation = (EditText) findViewById(R.id.et_location);
// Getting user input location
String location = etLocation.getText().toString();
if (location != null && !location.equals("")) {
new GeocoderTask().execute(location);
}
}
};
// Setting button click event listener for the find button
btn_find.setOnClickListener(findClickListener);
}
// An AsyncTask class for accessing the GeoCoding Web Service
private class GeocoderTask
extends AsyncTask<String, Void, List<Address>> {
#Override
protected List<Address> doInBackground(String... locationName) {
// Creating an instance of Geocoder class
Geocoder geocoder = new Geocoder(getBaseContext());
List<Address> addresses = null;
try {
// Getting a maximum of 3 Address that matches the input text
addresses = geocoder.getFromLocationName(locationName[0], 3);
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses) {
if (addresses == null || addresses.size() == 0) {
Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();
}
// Clears all the existing markers on the map
googleMap.clear();
// Adding Markers on Google Map for each matching address
for (int i = 0; i < addresses.size(); i++) {
Address address = (Address) addresses.get(i);
// Creating an instance of GeoPoint, to display in Google Map
latLng = new LatLng(address.getLatitude(), address.getLongitude());
String addressText = String.format("%s, %s", address.getMaxAddressLineIndex() > 0 ? address.getAddressLine(0) : "", address.getCountryName());
markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
googleMap.addMarker(markerOptions);
// Locate the first location
if (i == 0) {
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
}
}
}
}
}
And this is my crash report:
02-25 17:17:42.157 4312-4312/aravindaby.myapp123 E/test: Exception
02-25 17:17:42.157 4312-4312/aravindaby.myapp123 E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NullPointerException
at aravindaby.myapp123.MainActivity$GeocoderTask.onPostExecute(MainActivity.java:100)
at aravindaby.myapp123.MainActivity$GeocoderTask.onPostExecute(MainActivity.java:72)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4793)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:808)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:575)
at dalvik.system.NativeStart.main(Native Method)
In the case of no internet connection, address is null. So after showing Toast message, you should return the control.
if(addresses==null || addresses.size()==0){
Toast.makeText(getBaseContext(), "No Location found", Toast.LENGTH_SHORT).show();
return;
}
Related
Process crashed while executing mainTest(ru.myitschool.lab23.InstrumentedTestGeo):
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:190)
at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:174)
at android.content.Context.obtainStyledAttributes(Context.java:809)
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:852)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:819)
at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:640)
at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:261)
at ru.myitschool.lab23.MainActivity.(MainActivity.java:26)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1273)
at androidx.test.runner.MonitoringInstrumentation.newActivity(MonitoringInstrumentation.java:866)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3901)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4201)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2438)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
It is my "homework" and I should to do location provider, but I have minimum 1 problem and my teacher is at
holidays(
MainActivity:
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.location.Address;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.location.Geocoder;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
private FusedLocationProviderClient mFusedLocationClient;
TextView text_longitude = findViewById(R.id.text_longitude),
text_accuracy = findViewById(R.id.text_accuracy), text_address = findViewById(R.id.text_address);
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#SuppressLint("Range")
public void getLoc(View v) {
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;
}
mFusedLocationClient.getLastLocation().addOnSuccessListener(this, location -> {
if (location != null) {
text_longitude.setText(String.valueOf(location.getLatitude()));
text_accuracy.setText(String.valueOf(location.getAccuracy()));
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
try {
text_address.setText((CharSequence) geocoder.getFromLocation(location.getLatitude(), location.getAccuracy(), 1));
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
In this line
TextView text_longitude = findViewById(R.id.text_longitude);
You are trying to assign the variables to the widgets from the layout with findViewById() before actually inflating the Activity's UI.
The proper way is firstly to declare them
private TextView textLongitude;
private TextView textAccuracy;
private TextView textAddress;
and assign later in onCreate() after setContentView(R.layout.activity_main); instruction.
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textLongitude = findViewById(R.id.text_longitude);
textAccuracy = findViewById(R.id.text_accuracy);
textAddress = findViewById(R.id.text_address);
}
My problem is: When I'm trying to move around in the map or zoom in & out it immediately return to my current location. Also when I search for location, new marker added at the searched location but immediately goes back to my current location.
I searched for solution but found nothing.. I hope somebody can figure it out
package com.hitman.locationrevision;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationRequest;
import android.os.Bundle;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.hitman.locationrevision.databinding.ActivityMapsBinding;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
LocationManager locationManager;
LocationListener locationListener;
>function for current location information
public void locationInfo(Location location,String title){
if(location != null) {
LatLng currentLocation = new LatLng(location.getLatitude(), location.getLongitude());
mMap.clear();
mMap.addMarker(new MarkerOptions().position(currentLocation).title(title));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLocation,10));
}
}
>function to request permission from user
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_FINE_LOCATION)==PackageManager.PERMISSION_GRANTED){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
Location lastLocation=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
locationInfo(lastLocation,"Your lastLocation");
}
}
}
private GoogleMap mMap;
private ActivityMapsBinding binding;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMapsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// 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);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
Intent intent=getIntent();
locationManager=(LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener=new LocationListener() {
#Override
public void onLocationChanged(#NonNull Location location) {
locationInfo(location,"Your Location");
}
};
>code to ask permission and check permission from user
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}else{
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,locationListener);
>code to find the last location and update the last location
Location
lastLocation=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
locationInfo(lastLocation,"Your lastlocation");
}
}
}
Its because you have move camera when your location update. You just need to put condition whether its user call or not to see current location.
Here is the line, this will alway move camera and display your current location
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLocation,10));
You can do like this, whenever user required to see current location then change fromUser = true and then make to false back. Just like happen in Google Map when you click on location button.
var fromUser = false;
if(fromUser){
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLocation,10));
fromUser = false;
}
Use this code for get current location.this method only get one time
of user location.inside OnLocationResult callback handle your location
logic
private void getCurrentLocation(){
LocationRequest locationRequest = new LocationRequest();
FusedLocationProviderClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setMaxWaitTime(1000);
locationRequest.setFastestInterval(500);
locationRequest.setInterval(500);
fusedLocationProviderClient.requestLocationUpdates(locationRequest, new LocationCallback() {
#Override
public void onLocationResult( LocationResult locationResult) {
if(locationResult.getLocations().size() != 0){
Location location = locationResult.getLocations().get(0);
LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude());
//handle current user location logic
FusedLocationProviderClient.removeLocationUpdates(this);
}
}
}, Looper.getMainLooper());
}
I encountered error inflating class fragment when I tried to mark the location (lat and longitude from SQL) onto the google map for the android java app. In MapsActivity.java, it is already using onCreate, not onCreateView. Do I have to change it or is there any way I can solve the error?
MapsActivity.java
package com.example.paddy_disease_tracker;
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import com.example.paddy_disease_tracker.databinding.ActivityMapsBinding;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
String query;
Statement st;
ResultSet rs;
Toast toast;
String disease;
float lat,lon;
private GoogleMap mMap;
private ActivityMapsBinding binding;
LatLng centerLocation,place;
Connection connect;
ArrayList<LatLng> places=new ArrayList<LatLng>();
ArrayList<String> dis=new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMapsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// 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);
centerLocation=new LatLng(6.0,101);
try {
ConnectionHelper connectionHelper = new ConnectionHelper();
connect = connectionHelper.connectionclass();
if (connect != null) {
query = "Select * from Disease";
st = connect.createStatement();
rs = st.executeQuery(query);
while (rs.next()) {
disease=rs.getString(3);
lat=rs.getFloat(4);
lon=rs.getFloat(5);
places.add(new LatLng(lat,lon));
dis.add(disease);
}
} else {
toast=Toast.makeText(getApplicationContext(),"Check Connection",Toast.LENGTH_LONG);
toast.show();
}
}catch(Exception e){
toast=Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_LONG);
toast.show();
}
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
enableMyLocation();
// Add a marker in Sydney and move the camera
for(int i=0; i<places.size();i++){
mMap.addMarker(new MarkerOptions().position(places.get(i)).title(dis.get(i)+" found"));
}
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(centerLocation,6));
}
private void enableMyLocation() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
if (mMap != null) {
mMap.setMyLocationEnabled(true);
}
} else {
String []perms={"android.permission.ACCESS_FINE_LOCATION"};
// Permission to access the location is missing. Show rationale and request permission
ActivityCompat.requestPermissions(this,perms,200);
}
}
}
Hi I posted a question concerning the same topic a while ago, after following your advices I can feel that I'm getting closed to solving my problem. The App does is now crashing as I click on the button with the following error message in the monitor:
FATAL EXCEPTION: main
Process: com.example.apple.myapp1, PID: 10081
java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.example.apple.myapp1.MainActivity$1.onClick(MainActivity.java:62)
MainActivity.java
package com.example.apple.myapp1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Locale;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;
public class MainActivity extends Activity {
double lats, lons;
Geocoder geocoder;
double lat = lats;
double lon = lons;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnGetLocation = (Button) findViewById(R.id.button1);
btnGetLocation.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ProgressDialog mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setMessage("Fetching location...");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.show();
geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(lat, lon, 1);
} catch (IOException e) {
e.printStackTrace();
}
if (addresses != null) {
String address = addresses.get(0).getAddressLine(0);
String city = addresses.get(0).getLocality();
String state = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalCode = addresses.get(0).getPostalCode();
String knownName = addresses.get(0).getFeatureName();
mProgressDialog.dismiss();
TextView cellText = (TextView) findViewById(R.id.cellText);
cellText.setText(address);
} else {
mProgressDialog.dismiss();
TextView cellText = (TextView) findViewById(R.id.cellText);
cellText.setText("Error");
}
}
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Please click the button below to get your location" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me" />
<TextView
android:id="#+id/cellText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
<TextView
android:id="#+id/lacationText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />
</LinearLayout>
in the condition if (addresses != null) { } you should also check for the length of the addresses, since there might be 0.
if (addresses != null && addresses.size() > 0) {
String address = addresses.get(0).getAddressLine(0);
String city = addresses.get(0).getLocality();
String state = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalCode = addresses.get(0).getPostalCode();
String knownName = addresses.get(0).getFeatureName();
mProgressDialog.dismiss();
TextView cellText = (TextView) findViewById(R.id.cellText);
cellText.setText(address);
} else {
mProgressDialog.dismiss();
TextView cellText = (TextView) findViewById(R.id.cellText);
cellText.setText("Error");
}
if it wasn't able to find at least one address you should consider showing the user an empty state.
It also seems like you forgot to initialize your latitude and longitude before calling addresses = geocoder.getFromLocation(lat, lon, 1);
To properly initialize this, do the following:
Location location = intent.getParcelableExtra(__YOUR_PACKAGE_NAME__ + ".LOCATION_DATA_EXTRA");
lat = location.getLatitude();
lon = location.getLongitude();
If you need any more help check out this page from android. It should hold all information you need.
EDIT:
I kind of assumed you we're further in the process, but it seems you have only tried to get the location of a latLong position, which you have never obtained. To achieve obtaining the address you will have to have the user's lcoation first.
Again, the page mentioned above should explain everything you need to obtain the location, but make sure of the following:
1. Have the permission to access the user's location (for Android 6+ use Runtime permissions)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.gms.location.sample.locationupdates" >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
</manifest>
2. Get an instance of the GoogleApi and ave your activity implement some callbacks
For the Callbacks
public class YourActivity extends AppCompatActivity implements
ConnectionCallbacks, OnConnectionFailedListener
Then in your OnCreate() create an instance of GoogleApiClient.
protected GoogleApiClient mGoogleApiClient;
public void onCreate(Bundle savedInstanceState) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
3. Obtain the location from the GoogleApiClient
Do this by implementing the callbacks properly.
/**
* Represents a geographical location.
*/
protected Location mLastLocation;
#Override
public void onConnected(Bundle connectionHint) {
// Gets the best and most recent location currently available, which may be null
// in rare cases when a location is not available.
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
// Determine whether a Geocoder is available.
if (!Geocoder.isPresent()) {
Toast.makeText(this, "no geocoder available", Toast.LENGTH_LONG).show();
return;
}
}
}
4. Now obtain the lat long and try to obtain the address as attempted before.
lat = mLastLocation.getLatitude();
lon = mLastLocation.getLongitude();
geocoder = new Geocoder(MainActivity.this, Locale.getDefault());
List<Address> addresses = null;
try {
addresses = geocoder.getFromLocation(lat, lon, 1);
} catch (IOException e) {
e.printStackTrace();
}
This should be enough to obtain the actual adress of the device and ask the geocoder for the addresses. I altered the example a bit to simplify for this question. Google's example handles fetching the address a bit more clean. Note that you will also have to disconnect the GoogleApi when stopping your activity and such. Again I recommend reading the entire Tutorial page. You can find en example of their implementation on this page on GitHub
I am not able to figure out why i am getting null pointer exception everytime i am running the app.This android app finds the place and marks it on the map using geocoding.But i have not succeded in doing so and not getting to know where is the mistake.Please help!
The main activity code is as follows:
package com.dutt.rishabh.locator;
import android.location.Address;
import android.location.Geocoder;
import android.os.AsyncTask;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import java.io.IOException;
import java.util.List;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
EditText x;
Button bfind;
String location;
MarkerOptions markerOptions;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_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);
bfind=(Button)findViewById(R.id.bfind);
View.OnClickListener findClickListener =new View.OnClickListener() {
#Override
public void onClick(View view) {
x=(EditText)findViewById(R.id.etsearch);
location=x.getText().toString();
if(location!=null || location.equals("")){
new GeocoderTask().execute(location);
}
}
};
bfind.setOnClickListener(findClickListener);
}
private class GeocoderTask extends AsyncTask<String, Void, List<Address>>{
#Override
protected List<Address> doInBackground(String... strings) {
Geocoder geocoder = new Geocoder(getBaseContext());
List<Address> addresses=null;
try {
addresses=geocoder.getFromLocationName(strings[0],3);
} catch (IOException e) {
e.printStackTrace();
}
return addresses;
}
#Override
protected void onPostExecute(List<Address> addresses){
if(addresses==null || addresses.size()==0){
Toast.makeText(getBaseContext(),"No location found",Toast.LENGTH_SHORT).show();
}
mMap.clear();
for(int i=0;i<addresses.size();i++){
Address address= addresses.get(i);
LatLng latLng=new LatLng(address.getLatitude(),address.getLongitude());
String addressText=String.format("%s,%s",address.getMaxAddressLineIndex()>0?address.getAddressLine(0):"",address.getCountryName());
markerOptions=new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title(addressText);
mMap.addMarker(markerOptions);
if(i==0){
mMap.animateCamera(CameraUpdateFactory.newLatLng(latLng));
}
}
}
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}
Please help and kindly mention my mistake so i can understand.
The following is the logcat :
07-26 15:02:02.264 30388-30388/com.dutt.rishabh.locator E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dutt.rishabh.locator, PID: 30388
java.lang.NullPointerException
at com.dutt.rishabh.locator.MapsActivity$GeocoderTask.onPostExecute(MapsActivity.java:75)
at com.dutt.rishabh.locator.MapsActivity$GeocoderTask.onPostExecute(MapsActivity.java:57)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5345)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:828)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:644)
at dalvik.system.NativeStart.main(Native Method)
Null check for addresses
for(int i=0;i<addresses.size();i++){
}
or add return
if(addresses==null || addresses.size()==0){
Toast.makeText(getBaseContext(),"No location found",Toast.LENGTH_SHORT).show();
return;
}
In your case the address list seems to be null. You can return code execution after showing the toast message.
if(addresses==null || addresses.size()==0){ // Line 71
Toast.makeText(getBaseContext(),"No location found",Toast.LENGTH_SHORT).show();
return;
}