How do I retrieve address components from Place API object? - android

I want my user to be able to pick an address. For my backend, I need to get the following info: street name, number, country and zip code.
I am using PlaceAutocompleteFragment fragment as mentioned here: https://developers.google.com/places/android-api/autocomplete.
When the user has selected a Place, I get the Place object as a result:
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
// Here I want to retrieve all the address details, such as
// street name, number, country etc. and send them to my backend
}
#Override
public void onError(Status status) {
//handle Error
}
});
However from the Place object I can only use place.getAddress() to get a "human readable" address line.
The iOs and JS documentations both show that you can retrieve the addressComponents(iOs) or address_components(JS) from the Place object which contains these fields (street, zipcode, etc.). However the Android documentation shows no such method for a Place object for retrieving the addressComponents.
Am I overlooking something? Is it possible that they provide this info fro iOs and JS but not for android? Or am I also maybe missing an ovious alternative?

You need to set the search parameters you want.
autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ADDRESS,Place.Field.LAT_LNG));

There is a getAddressComponents() in Place object.
Make sure to add "Place.Field.ADDRESS" in Fields list, onActivityResultresults data will have the components of the place, otherwise it will be null.
List<Place.Field> fieldList = Arrays.asList(Place.Field.ADDRESS,
Place.Field.ADDRESS_COMPONENTS,
Place.Field.LAT_LNG, Place.Field.NAME, Place.Field.UTC_OFFSET);
Intent intent = new Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY
, fieldList)
.build(context);

Related

Firebase Update Multiple Child value From Multiple Key for Specific Child Value

I have below firebase database Structure.I am saving mobile no as child name. What I need to do is first get the tBid value for each key having specific mobile no value equal to ok then add/deduct a number and then update tBid value for all key under b_ookk_node
I have tried below code so far but it is not working.How can I achieve this
final String mobile_no = singleToneClass.getInstance().getData();
mDatabasebook = FirebaseDatabase.getInstance().getReference().child("b_ookk_node");
Query ref_book = mDatabase.child(mobile_no).equalTo("ok");
ref_book.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChildren()) {
for (DataSnapshot datas: dataSnapshot.getChildren()) {
final int total_bid = Integer.parseInt(datas.child("tBid").getValue(String.class));
String t_bid = Integer.toString(total_bid - 1);
mDatabasebook.child("tBid").setValue(t_bid);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Assuming that b_ookk_node in your code matches the struck out node in your JSON screenshot, this code looks OK. But it'd require you to define an index for each mobile number, since an index can only be defined on a property of which you specify the name. Since I assume the phone numbers are user-entered data, defining an index for each of them isn't feasible
In short: your current data structure allows your to easily look up the mobile number of a push ID, but not the push ID for a mobile number. To allow the latter you'll need to set up an additional data structure, which looks like this:
"number_to_pushid_map": {
"096554885": {
"-LyON1kEn...sWpW": true
"-LyON1kEn...key2": true
}
}
In this structure you can then look up the push ID for a number that the user entered.
Also see:
Firebase query if child of child contains a value
Aside from that:
The if (dataSnapshot.hasChildren()) { in your code is not needed. If there are no child nodes, then dataSnapshot.getChildren() will already return an empty iterator, and the loop will never be entered.
Consider using a transaction for the updating of the bid, as right now two users updating the bid around the same time may end up overwriting each other's result.
Consider storing the tBid value as a number, instead of as a string, so that you don't have to constantly convert it back and forth.

Android - Automatically fill text fields of another app

I am implementing an Android app that is responsible for some data exchange with other services such as credentials. I then want to use that information to automatically fill in the input fields of other applications on the device such as Spotify.
Is there any way to fill the input fields of another app, like the username and password to remove the chore for the user to manually input it?
Also I noticed that at least on iOS, Spotify recognizes 1Password to be installed and displays a small icon next to the input fields with which I can fill the fields from the data stored in 1Password - how is this done as it seems to be another solution to my problem?
Thanks in advance
You might want to implement Autofill Service https://developer.android.com/guide/topics/text/autofill-services.html
There is a ready to use sample app which will get you started https://github.com/googlesamples/android-AutofillFramework
Android will invoke onFillRequest() method giving your service a chance to show autofill suggestions. Here is a sample code from above link:
#Override
public void onFillRequest(FillRequest request, CancellationSignal cancellationSignal, FillCallback callback) {
// Get the structure from the request
List<FillContext> context = request.getFillContexts();
AssistStructure structure = context.get(context.size() - 1).getStructure();
// Traverse the structure looking for nodes to fill out.
ParsedStructure parsedStructure = parseStructure(structure);
// Fetch user data that matches the fields.
UserData userData = fetchUserData(parsedStructure);
// Build the presentation of the datasets
RemoteViews usernamePresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
usernamePresentation.setTextViewText(android.R.id.text1, "my_username");
RemoteViews passwordPresentation = new RemoteViews(getPackageName(), android.R.layout.simple_list_item_1);
passwordPresentation.setTextViewText(android.R.id.text1, "Password for my_username");
// Add a dataset to the response
FillResponse fillResponse = new FillResponse.Builder()
.addDataset(new Dataset.Builder()
.setValue(parsedStructure.usernameId,
AutofillValue.forText(userData.username), usernamePresentation)
.setValue(parsedStructure.passwordId,
AutofillValue.forText(userData.password), passwordPresentation)
.build())
.build();
// If there are no errors, call onSuccess() and pass the response
callback.onSuccess(fillResponse);
}
class ParsedStructure {
AutofillId usernameId;
AutofillId passwordId;
}
class UserData {
String username;
String password;
}

Filtering RecyclerView item (City) after getting json API

So, my app has successfully
1) Identified user's location (GPS Coordinates)
2) Passed these coordinates to an API and retrieved location specific data with retrofit.
3) Populated data to Recyclerview.
4) Implemented search functionality for user to filter the recyclerview as desired. For example, user can search for "pizza" and shrink their results from the initial 300 to the 20 that contain the String "pizza".
Lastly, I want to give the user the ability to filter by City name. I want to provide the user with the list of Cities that are generated from the recycleview list. Of course, the list would change each time based on users initial search criteria. How can I get the City list, which is one of the item fields retrieved from the API?
The "city" filter can be done before, after, or in place of the other filter. in other words, if I can only do one, that's OK, then I would just do the "city" filter and not offer the wildcard filter.
Any help is appreciated, even if it is just a high level view of what needs to be done. I guess first and foremost, I need to know how to get that list. My limited knowledge of the nuts and bolts of how recyclerview actually works tells me this might not be available.
#Override
public void onResponse(Call<Api> call, Response<Api> response) {
Api api = response.body();
data = new ArrayList<>(Arrays.asList(api.getDetails()));
//get city string array
String[] sa_cities = new String[data.size()];
for (int i = 0; i < sa_cities.length; i++) {
sa_cities[i] = data.get(i).getLocation();
}
adapter = new DataAdapter(data);
recyclerView.setAdapter(adapter);
#Override
public void onFailure(Call<Api> call, Throwable t) {
Log.d("Error",t.getMessage());
}

Android - Retrieving data from Firebase

I am developing an android application where older kids can pick up younger kids and walk to school. With the application the authenticated (email and password) younger kid can choose between three adresses to get picked up. As of right now my realtime database looks like this:
I want to retrieve the different addresses and the users who picked the addresses. I am thinking I have to use recyclerview to get the data, but I am unsure on if it is possible to do with my database structure.
Using the FirebaseUI database package makes it simple to bind data from the Firebase Realtime Database to your app's UI. Specifically using FirebaseUI with indexed data is applicable for your current database structure.
For example, you'd use something similar to:
// keyQuery - the Firebase location containing the list of keys to be found in dataRef
// dataRef - the Firebase location to watch for data changes. Each key found at
// keyRef's location represents a list item.
Query keyQuery = FirebaseDatabase.getInstance().getReference("/Addresses/Street 10/users");
DatabaseReference dataRef = FirebaseDatabase.getInstance().getReference("/User");
FirebaseRecyclerOptions<User> options = new FirebaseRecyclerOptions.Builder<User>()
.setIndexedQuery(keyQuery, dataRef, User.class)
.build();
Where your User class is:
public class User {
private String username;
public User() {}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
// ...
}
You can then use the above created options variable to create a FirebaseRecyclerAdapter instance and then call startListening() on it*.
Using FirebaseUI in this way will automatically handle matching the keys under /Addresses/Street 10/users to the /User node.
* Version 2.x of FirebaseUI uses FirebaseIndexRecyclerAdapter instead and starts listening automatically so doesn't require a startListening() call. The above example is applicable for version 3.0, see FirebaseUI 3.0 upgrade guide.
Following on from my previous answer, this one should accommodate your requirement to create a list of all addresses and their associated users, which may be closer to what you're looking for.
Again you can use the FirebaseUI database package to simplify the RecyclerView creation.
You'll need to start denormalizing your data, so your data structure should also include usernames in the addresses node:
{
"Addresses" : {
"Street 10" : {
"name" : "Street 10",
"users" : {
"VAzdMWafK6cyhmJnOI4br5xiQg93" : "John"
}
}
},
"User" : {
"VAzdMWafK6cyhmJnOI4br5xiQg93" : {
"username" : "John",
"address" : "Street 10"
}
}
}
Note: you only need to add user IDs to their chosen address (and remove the node if they change selection), so don't use "VAzdMWafK6cyhmJnOI4br5xiQg93" : false for addresses the user has not selected as this could cause confusion.
Then you can use:
Query query = FirebaseDatabase.getInstance().getReference("/Addresses");
FirebaseRecyclerOptions<Address> options = new FirebaseRecyclerOptions.Builder<Address>()
.setQuery(query, Address.class)
.build();
Where Address is something like:
public class Address {
private String name;
private Map<String, String> users;
public Address() {}
public Map<String, String> getUsers() {
return this.users;
}
// ...
}
And create a FirebaseRecyclerAdapter instance from the options variable. Then when binding the viewholder in the adapter, you can access the users map to list each user that has selected this address, without the need to load the entire User object unnecessarily.
This pattern is called denormalization and is the suggested approach when using NoSQL databases (like Firebase Realtime Database). The main downside to this is data duplication: so for example, when a user changes their selected address, you'll need to change:
The address value under the user, and
the users list under the address.
Likewise, if a user is allowed to change their username, you'll need to update the username under their chosen address as well as in the user's node.
For details on dealing with this, see this answer which explains a number of methods (although the examples are in JavaScript, the premise still applies).

Updating a row in parse table using the object Id of the current device

Hi I am trying to update the location of the current device into the parse database using the objectId of this device.
ParseQuery innerQuery = new ParseQuery("_Installation");
innerQuery.whereEqualTo("objectId", ParseInstallation.getCurrentInstallation());//current phone
ParseQuery<PhoneFinder> query = ParseQuery.getQuery(PhoneFinder.class);
query.whereMatchesQuery("identification", innerQuery);
query.findInBackground(new FindCallback<PhoneFinder>() {
#Override
public void done(List<PhoneFinder> list, ParseException e) {
for (PhoneFinder loc : list)
{
loc.setLocation(geoPoint);
loc.saveInBackground();
}
}
});
If I use the objectId explicitly is works fine.
Any suggestions?
You haven't said what's wrong with the code you posted (that is, exactly what it does wrong) but I'm going to guess innerQuery doesn't return any rows. If that is the case, this information from the API docs may help:
Note: We only allow the following types of queries for installations:
query.get(objectId)
query.whereEqualTo("installationId", value)
query.whereMatchesKeyInQuery("installationId", keyInQuery, query)
whereEqualTo("objectId",value) isn't on that list, so that is probably why it's not working. Also, ParseInstallation.getQuery is the best way to get a query to use for installations.

Categories

Resources