I am trying to display contact list in autoCompleteTextView so far I have successfully achieved that but I need to use the contact_id related to name how Should I bind id with name?
I have used hashmap to store the contact list.
here is my code to get contact and add them to hashmap
Cursor cursor_number=getActivity().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null);
if(cursor_number!=null){
if (cursor_number.moveToFirst()){
do{
contact_id=cursor_number.getString(cursor_number.getColumnIndex(ContactsContract.Data._ID));
if(Integer.parseInt(cursor_number.getString(cursor_number.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)))>0) {
Cursor cursor_number1 = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.Data.CONTACT_ID + " = ? ", new String[]{contact_id}, null);
if (cursor_number1 != null) {
while (cursor_number1.moveToNext()) {
String name=cursor_number1.getString(cursor_number1.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
String id=contact_id;
HashMap<String, String> contact_data=new HashMap<String, String>();
contact_data.put(id,name);
}
cursor_number1.close();
}
}
}
while (cursor_number.moveToNext());
cursor_number.close();
}
}
and this is how i'm adding adapter to autoComplete textView
autoCompleteTextView =(AutoCompleteTextView) this.getActivity().findViewById(R.id.act_network_auto_search);
autoCompleteTextView.setThreshold(2);
checkContacts();
Collection<String> collection=contact_data.values();
String[] array= collection.toArray(new String[collection.size()]);
adapter = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_dropdown_item_1line,array);
autoCompleteTextView.setAdapter(adapter);
How should I get the id associated with name
any help would be great!
Update :
LinkedHashMap<String, String> contact_data=new LinkedHashMap<String, String>();
contact_data.put(id,name);
Check this example AutocompleteTextView
If it is compulsary for you to use key valu pair than
I will sugest use LinkedHashMap insted of Hasmap because hashmap do not have ordering.
you can put data in linkedhasmap same as hashmap like follows
LinkedHashMap<String,String> lH = new LinkedHashMap<String,String>();
lH.put(id,name);
while in your auto complete text view do folowing
autoCompleteTextView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View arg1, int pos,
long id) {
String key = (new ArrayList<String>(lH.keySet())).get(pos);
you will have your id in key
}
});
also you can make above efficient by just initializing lH.keySet out of listner
also look at this
http://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html
for LinkedHashMap
you can get id from contact_data ,if you are sure the names are uniqe
public String getIdByName(String name) {
for (Entry<String,String> entry : contact_data.entrySet()) {
if (name.equals(value, entry.getValue())) {
return entry.getKey();
}
}
return null;
}
check this answer too
Related
I'm developing an app:
In my realtime database I have this structure
But some keys have the same data and it's a duplicate like this:
In my Android Studio project I code this function but only retrieve the data but no check the duplicates:
private void deleteIfAreDuplicateData() {
List<Order> orderList = new ArrayList<>();
FirebaseDatabase.getInstance().getReference(Common.ORDER_REF)
.orderByKey()
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
ArrayList<Object> numeroDeOrden = new ArrayList<>();
String datos;
String pagoFinal, tiempo, idUsuario, nombreUsuario;
boolean exists = false;
for (DataSnapshot orderSnapshot : dataSnapshot.getChildren()) {
Map<String, Object> model = (Map<String, Object>) orderSnapshot.getValue();
pagoFinal = String.valueOf(orderSnapshot.child("finalPayment").getValue());
tiempo = String.valueOf(orderSnapshot.child("orderTime").getValue());
idUsuario = String.valueOf(orderSnapshot.child("userId").getValue());
nombreUsuario = String.valueOf(orderSnapshot.child("userName").getValue());
datos = (String) orderSnapshot.getKey();
numeroDeOrden.add(datos);
for (int i = 0; i < numeroDeOrden.size(); i++) {
if (model.get("finalPayment").equals(pagoFinal) && model.get("orderTime").equals(tiempo)) {
exists = true;
}
}
}
if(exists)
{
Toast.makeText(getContext(), "Tienes ordenes repetidas ", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
How can I check for duplicate in the database and when I have the duplicates remove only one of the 2 values (?)
If you want to prevent duplicate values, use those values as the keys for the data. So in your case, if you want the combination of all property values to be unique, combine all of those values into a single string and use that as your key.
You'll want to remove or encode any characters that are not allowed in keys, so ., $, [, ], #, and /, from the key.
In addition, if the key becomes longer than the maximum key length of 768 characters, you'll want to reduce it down to size too with a hash function or by simply truncating the string. See my answer here for some more info on that: Firebase Error: First argument has a key path longer than 768 Bytes
You can have a list of your model saved in your activity (or typically in ViewModel as a static member):
pubic static List<Map<String, Object>> modelList;
Then for each change in data you can add only the new data to the model by checking if exists using contains() method:
for (DataSnapshot orderSnapshot : dataSnapshot.getChildren()) {
Map<String, Object> model = (Map<String, Object>) orderSnapshot.getValue();
if (!modelList.contains(model)) {
modelList.add(model);
// Add your rest of code for the incoming new/change of data
}
}
I have a custom adapter with a listview. I query the items from SQL Server and display them as a list using my listview. I have item click listener on my list view in order to get the item position.
public void getData() {
String query = "SELECT * FROM Table";
List<Map<String, String>> data = new ArrayList<>();
data = filterData(query);
adapter = new ContactListAdapter(this, data, R.layout.items, from, to);
listView.setAdapter(adapter);
listView.invalidateViews();
listView.setOnItemClickListener((adapterView, view, i, l) -> {
HashMap<String, String> retreive = (HashMap<String, String>) adapterView.getAdapter().getItem(i);
callerID = retreive.get("CallerDetailID");
.
.
});
}
I store the values using hashmap strings in a list as follows.
// filter the contact details from sql server
List<Map<String, String>> filterData(String query) {
List<Map<String, String>> contact_details = new ArrayList<>();
try {
connect = connectionClass.CONN(); // Connect to database
Statement stmt = connect.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
Map<String, String> datanum = new HashMap<>();
datanum.put("CallerDetailID", rs.getString("CallerID"));
.
.
.
contact_details.add(datanum);
}
} catch (Exception e) {
e.printStackTrace();
}
return contact_details;
}
I am aware that I can get the items to the position by clicking on it (since I already use setOnItemClickListener). But my question here is how can I scroll to the newly added item's position in my list view, without clicking the item?
Once I get the position of the item, I can use one of the following methods in the listview to scroll.
listView.smoothScrollToPosition();
listView.smoothScrollToPosition();
listView.smoothScrollToPositionFromTop();
Is it possible to get the item's to position without clicking on the item in the listview? Any ideas folks.
To achieve the behaviour you need to add a property to scroll listview automatically.
android:transcriptMode="alwaysScroll"
You just have to call notifyDataSetChanged() and your list will be auto scrolled.
how to merge the list of values to the same Key in hashmap?
if I use the above logic I'm getting below result as an output
{Adam=[[Subject, ComputerScience], [Subject, ComputerScience]]}
But I have to merge like the below result, is it possible to append the list of values to the same key?
{Adam=[Subject, ComputerScience,Subject, ComputerScience]}
public class DemoMap {
public static void main(String[] args) {
HashMap<String, ArrayList<String>> tmeMap = new HashMap<>();
HashMap<String, ArrayList<Object>> mngrMap = new HashMap<>();
ArrayList<Object> emailcontent = new ArrayList<>();
ArrayList<String> mngrList1 = new ArrayList<>();
mngrList1.add("Jay");
mngrList1.add("Aaron");
tmeMap.put("Adam", mngrList1);
//Adam is Senior Manager who has the list of managers under him
emailcontent.add("Subject");
emailcontent.add("ComputerScience");
mngrMap.put("Jay", emailcontent);
mngrMap.put("Aaron", emailcontent);
//Each manager will have the email content
ArrayList<Object> collectionOfManagerContent = new ArrayList<>();
for (Map.Entry<String,ArrayList<Object>> emailEntry : mngrMap.entrySet()) {
collectionOfManagerContent.add(emailEntry.getValue());
}
//our Target is to show the manager's content to Senior Project manager
HashMap<String, ArrayList<Object>> tmeEmailMap1 = new HashMap<>();
for (Map.Entry<String,ArrayList<String>> emailEntry : tmeMap.entrySet()) {
emailEntry.getValue();
tmeEmailMap1.put(emailEntry.getKey(), collectionOfManagerContent);
}
System.out.println(tmeEmailMap1.toString());
}
}
Use addAll() to add all elements of ArrayList into another ArrayList
for (Map.Entry<String,ArrayList<Object>> emailEntry : mngrMap.entrySet()) {
collectionOfManagerContent.addAll(emailEntry.getValue());
}
I'm trying to migrate an old project to Retrofit library and this project has quite tricky API. So I have a query template like this:
#GET(value = "products/search")
Single<ProductSearchResponse> productSearch();
And I have to add some parameters here of following template:
filter[attributeId]=attributeValueId
For example:
products/search?filter[1]=10&filter[1]=11&filter[2]=20&filter[2]=21
That's how API works and I can't change it. I know that we can pass a list as a parameter, like this:
#Query("filter") List<Integer> attributeValueIds
But how can I also set parameter's name dynamically?
You can use an arrayList! Something like the code below.
#GET(value = "products/search")
Single<ProductSearchResponse> productSearch(
#Query("status") List<Integer> status
);
ArrayList<Integer> queryStatus = new ArrayList<>();
queryStatus.add(0);
queryStatus.add(1);
queryStatus.add(2);
productService.productSearch(queryStatus);
Your url will be like that -> {url}?status=0&status=1&status=2
Thanks to the link, posted by #ILLIA DEREVIANKO (https://github.com/square/retrofit/issues/1324), I've managed to solve the problem with this class:
public class ProxyRetrofitQueryMap extends HashMap<String, Object> {
public ProxyRetrofitQueryMap(Map<String, Object> m) {
super(m);
}
#Override
public Set<Entry<String, Object>> entrySet() {
Set<Entry<String, Object>> originSet = super.entrySet();
Set<Entry<String, Object>> newSet = new HashSet<>();
for (Entry<String, Object> entry : originSet) {
String entryKey = entry.getKey();
if (entryKey == null) {
throw new IllegalArgumentException("Query map contained null key.");
}
Object entryValue = entry.getValue();
if (entryValue == null) {
throw new IllegalArgumentException(
"Query map contained null value for key '" + entryKey + "'.");
}
else if(entryValue instanceof List) {
for(Object arrayValue:(List)entryValue) {
if (arrayValue != null) { // Skip null values
Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, arrayValue);
newSet.add(newEntry);
}
}
}
else {
Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, entryValue);
newSet.add(newEntry);
}
}
return newSet;
}
}
With this we can just use a map, where key is a unique parameter name and value is a List of Strings, that are values for this parameter. Something like this:
ProxyRetrofitQueryMap map = new ProxyRetrofitQueryMap();
List<String> values1 = new ArrayList<>();
values1.add("10");
values1.add("11");
map.put("filter[1]", values1);
List<String> values2 = new ArrayList<>();
values1.add("20");
values1.add("21");
map.put("filter[2]", values2);
You can use #QueryMap annotation like this:
public interface NewsService() {
#GET("/news")
Call<List<News>> getNews(
#QueryMap Map<String, String> options
);
}
Map<String, String> data = new HashMap<>();
data.put("author", "Marcus");
data.put("page", String.valueOf(2));
...
newsService.getNews(data);
More details: https://futurestud.io/tutorials/retrofit-2-add-multiple-query-parameter-with-querymap
I'm trying to insert some data into my firebase but encountered the following error, the 2nd data is missing. Here are the code:
Firebase.setAndroidContext(this);
Button btnSave = (Button) findViewById(R.id.btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
//Creating firebase object
Firebase ref = new Firebase(Config.FIREBASE_URL);
//Getting values to store
String name = mName.getText().toString().trim();
String address = mAddress.getText().toString().trim();
String latlng = mLatLng.getText().toString().trim();
//Creating Person object
FM_Spots spots = new FM_Spots();
//Adding values
spots.setName(name);
spots.setAddress(address);
spots.setLatLng(latlng);
//Storing values to firebase
//ref.child("FM_Spots").setValue(spots);
Firebase newRef = ref.child("FM_Spots").push();
newRef.setValue(spots);
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage().toString(), Toast.LENGTH_SHORT).show();
}
}
});
}
I only have 2 fields which are name and the address is having data from the last field (latlng). Please advise, thank you.
-sea-
When you said "2nd data" you meant that the second field of the writable object is missing, right?
If so, you can use updateChildren(Map map) method instead of setValue() to specify fields you want to write directly:
newRef.updateChildren(convertFMSpotsToMap(spots));
where convertFMSpotsToMap() is something like this:
private static Map<String, Object> convertFMSpotsToMap(#NonNull FM_Spots spots) {
HashMap<String, Object> map = new HashMap<>();
map.put("name", spots.getName());
map.put("address", spots.getAddress());
return map;
}