1
+ package com .example .placesdemo ;
2
+
3
+ import android .content .Intent ;
4
+ import android .content .res .Resources ;
5
+ import android .os .Bundle ;
6
+ import android .util .Log ;
7
+ import android .view .View ;
8
+ import android .view .ViewStub ;
9
+ import android .widget .Button ;
10
+ import android .widget .EditText ;
11
+
12
+ import androidx .annotation .Nullable ;
13
+ import androidx .appcompat .app .AppCompatActivity ;
14
+
15
+ import com .example .placesdemo .model .AutocompleteEditText ;
16
+ import com .google .android .gms .common .api .Status ;
17
+ import com .google .android .gms .maps .CameraUpdateFactory ;
18
+ import com .google .android .gms .maps .GoogleMap ;
19
+ import com .google .android .gms .maps .GoogleMapOptions ;
20
+ import com .google .android .gms .maps .OnMapReadyCallback ;
21
+ import com .google .android .gms .maps .SupportMapFragment ;
22
+ import com .google .android .gms .maps .model .LatLng ;
23
+ import com .google .android .gms .maps .model .MapStyleOptions ;
24
+ import com .google .android .gms .maps .model .Marker ;
25
+ import com .google .android .gms .maps .model .MarkerOptions ;
26
+ import com .google .android .libraries .places .api .Places ;
27
+ import com .google .android .libraries .places .api .model .AddressComponent ;
28
+ import com .google .android .libraries .places .api .model .AddressComponents ;
29
+ import com .google .android .libraries .places .api .model .Place ;
30
+ import com .google .android .libraries .places .api .net .PlacesClient ;
31
+ import com .google .android .libraries .places .widget .Autocomplete ;
32
+ import com .google .android .libraries .places .widget .AutocompleteActivity ;
33
+ import com .google .android .libraries .places .widget .model .AutocompleteActivityMode ;
34
+
35
+ import java .util .Arrays ;
36
+ import java .util .List ;
37
+
38
+ /**
39
+ * Activity for using Place Autocomplete to assist filling out an address form.
40
+ */
41
+ @ SuppressWarnings ("FieldCanBeLocal" )
42
+ public class AutocompleteAddressActivity extends AppCompatActivity implements OnMapReadyCallback {
43
+
44
+ private static final String TAG = "ADDRESS_AUTOCOMPLETE" ;
45
+ private static final String MAP_FRAGMENT_TAG = "MAP" ;
46
+ private static final int AUTOCOMPLETE_REQUEST_CODE = 23487 ;
47
+ private AutocompleteEditText address1Field ;
48
+ private EditText address2Field ;
49
+ private EditText cityField ;
50
+ private EditText stateField ;
51
+ private EditText postalField ;
52
+ private EditText countryField ;
53
+ private LatLng coordinates ;
54
+ private SupportMapFragment mapFragment ;
55
+ private GoogleMap map ;
56
+ private Marker marker ;
57
+ private PlacesClient placesClient ;
58
+ private View mapPanel ;
59
+
60
+ @ Override
61
+ protected void onCreate (Bundle savedInstanceState ) {
62
+ super .onCreate (savedInstanceState );
63
+
64
+ // Use whatever theme was set from the MainActivity - some of these colors (e.g primary color)
65
+ // will get picked up by the AutocompleteActivity.
66
+ int theme = getIntent ().getIntExtra (MainActivity .THEME_RES_ID_EXTRA , 0 );
67
+ if (theme != 0 ) {
68
+ setTheme (theme );
69
+ }
70
+
71
+ setContentView (R .layout .autocomplete_address_activity );
72
+
73
+ // Retrieve a PlacesClient (previously initialized - see MainActivity)
74
+ placesClient = Places .createClient (this );
75
+
76
+ address1Field = findViewById (R .id .autocomplete_address1 );
77
+ address2Field = findViewById (R .id .autocomplete_address2 );
78
+ cityField = findViewById (R .id .autocomplete_city );
79
+ stateField = findViewById (R .id .autocomplete_state );
80
+ postalField = findViewById (R .id .autocomplete_postal );
81
+ countryField = findViewById (R .id .autocomplete_country );
82
+
83
+ // Attach an Autocomplete intent to the Address 1 EditText field
84
+ address1Field .setOnClickListener (v -> startAutocompleteIntent ());
85
+
86
+ // Reset the form
87
+ Button resetButton = findViewById (R .id .autocomplete_reset_button );
88
+ resetButton .setOnClickListener (v -> clearForm ());
89
+ }
90
+
91
+ private void startAutocompleteIntent () {
92
+ // Set the fields to specify which types of place data to
93
+ // return after the user has made a selection.
94
+ List <Place .Field > fields = Arrays .asList (Place .Field .ADDRESS_COMPONENTS ,
95
+ Place .Field .LAT_LNG , Place .Field .VIEWPORT );
96
+
97
+ // Start the autocomplete intent.
98
+ Intent intent = new Autocomplete .IntentBuilder (AutocompleteActivityMode .OVERLAY , fields )
99
+ .build (this );
100
+ startActivityForResult (intent , AUTOCOMPLETE_REQUEST_CODE );
101
+ }
102
+
103
+ @ Override
104
+ protected void onActivityResult (int requestCode , int resultCode , @ Nullable Intent data ) {
105
+ if (requestCode == AUTOCOMPLETE_REQUEST_CODE ) {
106
+ if (resultCode == RESULT_OK ) {
107
+ Place place = Autocomplete .getPlaceFromIntent (data );
108
+ Log .i (TAG , "Place: " + place .getAddressComponents ());
109
+
110
+ fillInAddress (place );
111
+
112
+ } else if (resultCode == AutocompleteActivity .RESULT_ERROR ) {
113
+ // TODO: Handle the error.
114
+ Status status = Autocomplete .getStatusFromIntent (data );
115
+ Log .i (TAG , status .getStatusMessage ());
116
+ } else if (resultCode == RESULT_CANCELED ) {
117
+ // The user canceled the operation.
118
+ }
119
+ return ;
120
+ }
121
+ super .onActivityResult (requestCode , resultCode , data );
122
+ }
123
+
124
+ @ Override
125
+ public void onMapReady (GoogleMap googleMap ) {
126
+ map = googleMap ;
127
+ try {
128
+ // Customise the styling of the base map using a JSON object defined
129
+ // in a string resource.
130
+ boolean success = map .setMapStyle (
131
+ MapStyleOptions .loadRawResourceStyle (this , R .raw .style_json ));
132
+
133
+ if (!success ) {
134
+ Log .e (TAG , "Style parsing failed." );
135
+ }
136
+ } catch (Resources .NotFoundException e ) {
137
+ Log .e (TAG , "Can't find style. Error: " , e );
138
+ }
139
+ map .moveCamera (CameraUpdateFactory .newLatLngZoom (coordinates , 15f ));
140
+ marker = map .addMarker (new MarkerOptions ().position (coordinates ));
141
+ }
142
+
143
+ private void fillInAddress (Place place ) {
144
+ AddressComponents components = place .getAddressComponents ();
145
+ StringBuilder address1 = new StringBuilder ();
146
+ StringBuilder postcode = new StringBuilder ();
147
+
148
+ // Get each component of the address from the place details,
149
+ // and then fill-in the corresponding field on the form.
150
+ // Possible AddressComponent types are documented at https://goo.gle/32SJPM1
151
+ if (components != null ) {
152
+ for (AddressComponent component : components .asList ()) {
153
+ String type = component .getTypes ().get (0 );
154
+ switch (type ) {
155
+ case "street_number" : {
156
+ address1 .insert (0 , component .getName ());
157
+ break ;
158
+ }
159
+
160
+ case "route" : {
161
+ address1 .append (" " );
162
+ address1 .append (component .getShortName ());
163
+ break ;
164
+ }
165
+
166
+ case "postal_code" : {
167
+ postcode .insert (0 , component .getName ());
168
+ break ;
169
+ }
170
+
171
+ case "postal_code_suffix" : {
172
+ postcode .append ("-" ).append (component .getName ());
173
+ break ;
174
+ }
175
+
176
+ case "locality" :
177
+ cityField .setText (component .getName ());
178
+ break ;
179
+
180
+ case "administrative_area_level_1" : {
181
+ stateField .setText (component .getShortName ());
182
+ break ;
183
+ }
184
+
185
+ case "country" :
186
+ countryField .setText (component .getName ());
187
+ break ;
188
+ }
189
+ }
190
+ }
191
+
192
+ address1Field .setText (address1 .toString ());
193
+ postalField .setText (postcode .toString ());
194
+
195
+ // After filling the form with address components from the Autocomplete
196
+ // prediction, set cursor focus on the second address line to encourage
197
+ // entry of sub-premise information such as apartment, unit, or floor number.
198
+ address2Field .requestFocus ();
199
+
200
+ // Add a map for visual confirmation of the address
201
+ showMap (place );
202
+ }
203
+
204
+ private void showMap (Place place ) {
205
+ coordinates = place .getLatLng ();
206
+
207
+ // It isn't possible to set a fragment's id programmatically so we set a tag instead and
208
+ // search for it using that.
209
+ mapFragment = (SupportMapFragment )
210
+ getSupportFragmentManager ().findFragmentByTag (MAP_FRAGMENT_TAG );
211
+
212
+ // We only create a fragment if it doesn't already exist.
213
+ if (mapFragment == null ) {
214
+ mapPanel = ((ViewStub ) findViewById (R .id .stub_map )).inflate ();
215
+ GoogleMapOptions mapOptions = new GoogleMapOptions ();
216
+ mapOptions .mapToolbarEnabled (false );
217
+
218
+ // To programmatically add the map, we first create a SupportMapFragment.
219
+ mapFragment = SupportMapFragment .newInstance (mapOptions );
220
+
221
+ // Then we add it using a FragmentTransaction.
222
+ getSupportFragmentManager ()
223
+ .beginTransaction ()
224
+ .add (R .id .confirmation_map , mapFragment , MAP_FRAGMENT_TAG )
225
+ .commit ();
226
+ mapFragment .getMapAsync (this );
227
+ } else {
228
+ updateMap (coordinates );
229
+ }
230
+ }
231
+
232
+ private void updateMap (LatLng latLng ) {
233
+ marker .setPosition (latLng );
234
+ map .moveCamera (CameraUpdateFactory .newLatLngZoom (latLng , 15f ));
235
+ if (mapPanel .getVisibility () == View .GONE ) {
236
+ mapPanel .setVisibility (View .VISIBLE );
237
+ }
238
+ }
239
+
240
+ private void clearForm () {
241
+ address1Field .setText ("" );
242
+ address2Field .getText ().clear ();
243
+ cityField .getText ().clear ();
244
+ stateField .getText ().clear ();
245
+ postalField .getText ().clear ();
246
+ countryField .getText ().clear ();
247
+ if (mapPanel != null ) {
248
+ mapPanel .setVisibility (View .GONE );
249
+ }
250
+ address1Field .requestFocus ();
251
+ }
252
+ }
0 commit comments