i am developing an app like "whatsapp" for which i want display contacts on my content (between header and footer) from my android phone so what can i do that task?
i tried this but it doesnt work.
function displayContact1() {
alert('Clicked');
var options = new ContactFindOptions();
options.filter="";
options.multiple=true;
var filter = [ "displayName", "phoneNumbers", "photos" ];
navigator.contacts.find(filter, displayContact, onContactError, options);
var myContacts = new Object();
// Default image path for the profile image
var defaultImagePath = $("#defaultImagePath").attr('src');
for (var i=0; i<contacts.length; i++)
{
if( contacts[i].phoneNumbers == null )
continue;
// Checks for the image
var img = contacts[i].photos != null ? contacts[i].photos[0].value : defaultImagePath;
if(contacts[i].phoneNumbers.length)
for (var j=0; j<contacts[i].phoneNumbers.length; j++)
{
var pNumber = contacts[i].phoneNumbers[j].value;
var name = contacts[i].displayName != null ? contacts[i].displayName: "No name";
// To sort the names based on the starting letter
// Stores the names in that array
var index = name.substring(0,1).toUpperCase();
if (typeof myContacts[index] == 'undefined')
{
myContacts[index] = new Array();
}
// cuts the large names
if( name.length > 35 )
{
name = name.substr(0,35)+"...";
}
// Push every details into an array.
myContacts[index].push({"name":name, "pNumber": pNumber, "img": img} );
}
}
var arrayKeys = new Array();
for (var key in myContacts )
{
arrayKeys.push( key );
}
// Sorts the array based on the key A, B , C etc
arrayKeys = arrayKeys.sort();
for( i = 0 ; i < arrayKeys.length ; i++ )
{
var records = myContacts[ arrayKeys[i] ];
$("#contacts").append ("<li class='letter-head'>"+ arrayKeys[i]+"</li>");
// Sort each names
records = records.sort( sortNames );
for( var r_key in records )
{
$("#contacts").append ( "<li><img src='"+ records[r_key].img+"' /> <span class='contact-name'>"+records[r_key].name + "</span><span class='contact-number'>" + records[r_key].pNumber + "</span></li>");
}
}
hide_loader();
$('.addressBook').effect("slide", {direction: "right"}, 500);
}
function sortNames(a, b )
{
return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;
}
Please look up the Android Developer Site before asking next time.
Google can help here too.
There's a "Contact Managet" Sample from Google or THIS one.
Here's how you read the contact data: LINK
Here's how you create a custom listview: LINK
Here's a tutorial for a whole contacts list: LINK
Related
Im decoding a json and transforming it in a variable of type map [string , List < LatLng>] and trying to retun it as the code of this function, howevwer im unable to save it as a map in the variable _polyFinal:
static getPoligoni() async {
http.Response _response = await http.get('$api/posizione/poligoni',
headers: {'Authorization': '${dataController.tokenBearer.value}'});
if (_response.statusCode == 200) {
Map<String, dynamic> _json = jsonDecode(_response.body);
var _poly = Map.from(_json["Poligoni"]).map(
(k, v) {
return MapEntry<String, List<String>>(
k,
List<String>.from(
v.map((x) => x),
),
);
},
);
List<String> _verticiRaw;
List<LatLng> _vertici = [];
Map<String, List<LatLng>> _polyFinal = {};
for (String key in _poly.keys) {
// print(_verticiRaw);
_verticiRaw?.clear();
_verticiRaw = _poly[key];
for (int i = 0; i < _verticiRaw.length; i++) {
print(i);
var _posVirgola = _verticiRaw[i].indexOf(',');
String posx, posy;
posx = _verticiRaw[i].substring(0, _posVirgola);
posy = _verticiRaw[i].substring(_posVirgola + 1);
var lat = double.tryParse(posx);
var lon = double.tryParse(posy);
_vertici.add(LatLng(lat, lon));
}
print(key);
print(_vertici);
_polyFinal.putIfAbsent(key, () => _vertici);
_vertici?.clear();
}
dataController.showLoadingStatus(false);
// print(_polyFinal);
// return _polyFinal;
If I try to print the polyFinal variable at the end of the cycle i get an empty map, And if I print the variable during the cycle every key-value pair get transformed in the following
key --> last vertici value
I tried to chek the values of both key and vertici and they are different every time the cycle is run.
Any help understanding this behavior is greatly appreciated,
Best Regards.
Resolved by putting
_polyFinal.putIfAbsent(key, () => _vertici.toList());
Maybe _vertici is just a pointer and not the value itself.
In Phonegap I try to fetch the contact list from phone.I need just name and phone number , its taking around 40 seconds to fetch all the result.I add the plugin in config.xml .In my phone I have around only 400 contacts. But when I alert the length of contact in index.html it says that 1351 list.I don't know where I am wrong.I think some optimization is needed while fetching name and number from phone.
advance Thanks...:)
Config.xml
<feature name="Contacts">
<param name="android-package" value="org.apache.cordova.contacts.ContactManager" />
</feature>
index.html
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
var options = new ContactFindOptions();
options.filter="";
options.multiple=true;
filter = ["displayName", "phoneNumbers"];
navigator.contacts.find(filter, onSuccess, onError, options);
}
var cSort = function(a, b) {
aName = a.displayName ;
bName = b.displayName ;
return aName < bName ? -1 : (aName == bName ? 0 : 1);
};
function onSuccess(contacts) {
contacts = contacts.sort(cSort);
alert("length " + contacts.length );
var i =0;
for (var i = 0; i < contacts.length; i++)
{
console.log("Display Name = " + contacts[i].displayName);
if(contacts[i].displayName != null)
{
if( contacts[i].phoneNumbers == null )
continue;
else if(contacts[i].phoneNumbers.length)
{
for (var j=0; j<contacts[i].phoneNumbers.length; j++)
{
$('#contact_list').append('<li> Name:'+contacts[i].displayName+'</li>');
$('#contact_list').append('<li> Number:'+contacts[i].phoneNumbers[j].value+'</li><br><br>');
}
$('#contact_list').listview('refresh');
}
}
}
}
function onError(contactError) {
alert('onError!');
}
</script>
Change your code from:
{
for (var j=0; j<contacts[i].phoneNumbers.length; j++)
{
$('#contact_list').append('<li> Name:'+contacts[i].displayName+'</li>');
$('#contact_list').append('<li> Number:'+contacts[i].phoneNumbers[j].value+'</li><br><br>');
}
$('#contact_list').listview('refresh');
}
To:
{
var finalList = '';
listEntryPoint = $('#contact_list');
for (var j=0; j<contacts[i].phoneNumbers.length; j++)
{
finalList += '<li> Name:'+contacts[i].displayName+'</li>' + '<li> Number:'+contacts[i].phoneNumbers[j].value+'</li><br><br>';
}
listEntryPoint.append(finalList);
listEntryPoint.listview('refresh');
}
#BINIL S, you have a very expensive Jquery call:
$('#contact_list').append(...);
Change to:
listEntryPoint = $('#contact_list');
move that outside of the loop and assign it to a variable, that should help. You can also NOT insert the new entries one at at time. You CAN make the one large list before you insert into HTML. Like this,
finalList += '<li> Name:'+contacts[i].displayName+'</li>' + '<li> Number:'+contacts[i].phoneNumbers[j].value+'</li><br><br>';
After loop is done,
listEntryPoint.append(finalList);
That should help - Jesse
I am working on android application in phonegap-3.1.0
I want to use phone contacts in my application, So I have refer this Document.
Successfully installed the plugins for contacts
When I remove saved contact(save from javascript code), It alerts Removal Success
But when I go into the contacts, it is still not removed from here,
Every time I try, it saves the contact but not not removed since alerts like Removal Success,
What should I Do...
SO I need help on it, Why the contact can't be remove
I have created an app for contacts insert and delete
You can fork on github-> xxbinxx/phoneGap-ContactsApp-Android. you can definitely solve your issue after it.
I have used contact ID's for the deletion purpose.
Here's the short code...
var app ={
/********************SOME OTHER CODE*************************/
openContacts: function() {
app.initialize();
var options = new ContactFindOptions();
options.filter = "";
options.multiple = true;
var fields = ["*"]; //"*" will return all contact fields
navigator.contacts.find(fields, app.onSuccess, app.onError, options);
},
// Write contacts in DOM
onSuccess: function(contacts) {
var li = '';
$.each(contacts, function(key, value) {
if (value.name) {
$.each(value.name, function(key, value) {
if (key === 'formatted') {
name = value;
}
});
}
if (value.note) {
note = value.note;
}
if (value.id) {
id = value.id;
}
console.log("id : " + id + "-> name : " + name + " -> note : " + note);
li += '<li style="text-decoration:none;"><b>Name</b>: ' + name + '<div class="removeIcon pullRight" onclick="app.removeThisContact(\'' + id + '\',\'' + name + '\')"> </div><br><b> Note:</b> ' + note + '</li>';
}); // NOTICE the ID is passed as PARAMETER to remove specific contact.
$("#contact").html(li);
},
onError: function(contactError) {
alert('onError!' + contactError.code);
},
removeThisContact: function(id, name) {
console.log("removing contact : " + name);
options = new ContactFindOptions(); // find the contact to delete
options.filter.id = id;
options.multiple = "true";
var fields = ["displayName", "name"]; // you can take any..
navigator.contacts.find(fields, deleteThis, app.onError, options);
function deleteThis(contacts) {
var contact = contacts.pop();
// logging things to troubleshoot.
console.log('inside deleteThisContact: parameter passed: '+ contacts);
console.log("popped out:" +contact);
contact.remove(function() {
$('#status-area')
.flash_message({
text: 'Contact Removed!',
how: 'append'
});
app.openContacts();
}, null);
},
deleteAllTheContacts: function() {
var deleteContact = function(contacts) {
console.log("length = " + contacts.length);
// No contacts left, stop saving
if (contacts.length == 0) {
console.log("All contacts removed");
return;
}
var contact = contacts.pop();
contact.remove(function() {
deleteContact(contacts);
}, null);
};
navigator.contacts.find(["*"], deleteContact, app.onError, {
"multiple": true
});
},
/********************SOME OTHER CODE*************************/
}
$.fn.flash_message = function(options) {
//flash your message
}
Hope this will help you. :)
Using phonegap, I can get/filter a single contact from contact list. But how to update (add/remove) phone number field. Please help. Thanks alot.
Lets say 1 got a contact name John Smith with 2 phone number [('Home', '1111'), ('Work', '2222')].
When I try to remove the 'Work' number, just keep the 'Home' one. First get the contact, try to remove all number, then add the 'Home' number but I always get both 3 numbers [('Home', '1111'), ('Work', '2222'), ('Home', '1111')]
Weir that if I try to remove all number, then add nothing, it really remove all the number from contact ?
Here is my code
var phoneNumbers = [];
for (...){
phoneNum = {
type: ...,
value: ...,
pref: false
};
phoneNumbers.push(phoneNum);
}
contact = contacts_list[index]; //get the contact need to edit
//try to remove all current phone number
if (contact.phoneNumbers){
for (var i = 0; i < contact.phoneNumbers.length; i++){
delete contact.phoneNumbers[i];
//contact.phoneNumbers[i] = null; //i try this too
//contact.phoneNumbers[i] = []; //i try this too
}
}
//set new phone number
contact.phoneNumbers = phoneNumbers;
contact.save(...)
I also try create a new contact with only 1 number [('Home', '1111')], set id and rawId as same as i contact object I need to update, then save(). But i still get the same result [('Home', '1111'), ('Work', '2222'), ('Home', '1111')]
var contact = navigator.contacts.create();
var phoneNumbers = [];
phoneNumbers[0] = new ContactField('Home', '1111', false);
contact.phoneNumbers = phoneNumbers;
contact.id = ...
contact.rawId = ...
contact.save(...);
this also
contact = contacts_list[index]; //get the contact need to edit
//try to remove all current phone number
if (contact.phoneNumbers){
for (var i = 0; i < contact.phoneNumbers.length; i++){
delete contact.phoneNumbers[i];
//contact.phoneNumbers[i] = null; //i try this too
//contact.phoneNumbers[i] = []; //i try this too
}
}
var phoneNumbers = [];
phoneNumbers[0] = new ContactField('Home', '1111', false);
contact.phoneNumbers = phoneNumbers;
contact.save(...)
In the contact plugin of cordova, you can save the contact passing the original contact id, it will update the contact details in the database.
Here is an example:
//Set the options for finding conact
var options = new ContactFindOptions();
options.filter = 'Bob'; //name that you want to search
options.multiple = false;
var fields = ["id","displayName", "phoneNumbers"];
navigator.contacts.find(fields, sucessUpdate, onError, options);
function sucessUpdate(contacts) {
var contact = contacts[0]; //found contact array must be one as we disabled multiple false
// Change the contact details
contact.phoneNumbers[0].value = "999999999";
contact.name = 'Bob';
contact.displayName = 'Mr. Bob';
contact.nickname = 'Boby'; // specify both to support all devices
// Call the "save" function on the object
contact.save(function(saveSuccess) {
alert("Contact successful update");
}, function(saveError){
alert("Error when updating");
});
}
function onError(contactError)
{
alert("Error = " + contactError.code);
}
I have been using Parse to retrieve a data for a list view. Unfortunately they limit requests to 100 by default to a 1000 max. I have well over that 1000 max in my class. I found a link on the web which shows a way to do it on iOS but how would you do it on Android? Web Link
I am currently adding all the data into a arraylist in a loop until all items are complete (100) then adding them to the list
I have figured out how to achieve my goal:
Declare Global Variable
private static List<ParseObject>allObjects = new ArrayList<ParseObject>();
Create Query
final ParseQuery parseQuery = new ParseQuery("Objects");
parseQuery.setLimit(1000);
parseQuery.findInBackground(getAllObjects());
Callback for Query
int skip=0;
FindCallback getAllObjects(){
return new FindCallback(){
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
allObjects.addAll(objects);
int limit =1000;
if (objects.size() == limit){
skip = skip + limit;
ParseQuery query = new ParseQuery("Objects");
query.setSkip(skip);
query.setLimit(limit);
query.findInBackground(getAllObjects());
}
//We have a full PokeDex
else {
//USE FULL DATA AS INTENDED
}
}
};
}
Here is a JavaScript version without promises..
These are the global variables (collections are not required, just a bad habit of mine)..
///create a collection of cool things and instantiate it (globally)
var CoolCollection = Parse.Collection.extend({
model: CoolThing
}), coolCollection = new CoolCollection();
This is the "looping" function that gets your results..
//recursive call, initial loopCount is 0 (we haven't looped yet)
function getAllRecords(loopCount){
///set your record limit
var limit = 1000;
///create your eggstra-special query
new Parse.Query(CoolThings)
.limit(limit)
.skip(limit * loopCount) //<-important
.find({
success: function (results) {
if(results.length > 0){
//we do stuff in here like "add items to a collection of cool things"
for(var j=0; j < results.length; j++){
coolCollection.add(results[j]);
}
loopCount++; //<--increment our loop because we are not done
getAllRecords(loopCount); //<--recurse
}
else
{
//our query has run out of steam, this else{} will be called one time only
coolCollection.each(function(coolThing){
//do something awesome with each of your cool things
});
}
},
error: function (error) {
//badness with the find
}
});
}
This is how you call it (or you could do it other ways):
getAllRecords(0);
IMPORTANT None of the answers here are useful if you are using open
source parse server then it does limit 100 rows by default but you can
put any value in query,limit(100000) //WORKS
No need for recursive
calls just put the limit to number of rows you want.
https://github.com/parse-community/parse-server/issues/5383
JAVA
So after 5 years, 4 months the above answer of #SquiresSquire needed some changes to make it work for me, and I would like to share it with you.
private static List<ParseObject>allObjects = new ArrayList<ParseObject>();
ParseQuery<ParseObject> parseQuery = new ParseQuery<ParseObject>("CLASSNAME");
parseQuery.setLimit(1000);
parseQuery.findInBackground(getAllObjects());
FindCallback <ParseObject> getAllObjects() {
return new FindCallback <ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
allObjects.addAll(objects);
int limit = 1000;
if (objects.size() == limit) {
skip = skip + limit;
ParseQuery query = new ParseQuery("CLASSNAME");
query.setSkip(skip);
query.setLimit(limit);
query.findInBackground(getAllObjects());
}
//We have a full PokeDex
else {
//USE FULL DATA AS INTENDED
}
}
}
};
In C# I use this recursion:
private static async Task GetAll(int count = 0, int limit = 1000)
{
if (count * limit != list.Count) return;
var res = await ParseObject.GetQuery("Row").Limit(limit).Skip(list.Count).FindAsync();
res.ToList().ForEach(x => list.Add(x));
await GetAll(++count);
}
JS version:
function getAll(list) {
new Parse.Query(Row).limit(1000).skip(list.length).find().then(function (result) {
list = list.concat(result);
if (result.length != 1000) {
//do here something with the list...
return;
}
getAll(list);
});
}
Usage: GetAll() in C#, and getAll([]) in JS.
I store all rows from the class Rowin the list. In each request I get 1000 rows and skip the current size of the list. Recursion stops when the current number of exported rows is different from the expected.
**EDIT : Below answer is redundant because open source parse server doesn't put any limit on max rows to be fetched
//instead of var result = await query.find();
query.limit(99999999999);//Any value greater then max rows you want
var result = await query.find();**
Original answer:
Javascript / Cloud Code
Here's a clean way working for all queries
async function fetchAllIgnoringLimit(query,result) {
const limit = 1000;
query.limit(limit);
query.skip(result.length);
const results = await query.find();
result = result.concat(results)
if(results.length === limit) {
return await fetchAllIgnoringLimit(query,result );
} else {
return result;
}
}
And here's how to use it
var GameScore = Parse.Object.extend("GameScore");
var query = new Parse.Query(GameScore);
//instead of var result = await query.find();
var result = await fetchAllIgnoringLimit(query,new Array());
console.log("got "+result.length+" rows")
YAS (Yet Another Solution!) Using async() and await() in javascript.
async parseFetchAll(collected = []) {
let query = new Parse.Query(GameScore);
const limit = 1000;
query.limit(limit);
query.skip(collected.length);
const results = await query.find();
if(results.length === limit) {
return await parseFetchAll([ ...collected, ...results ]);
} else {
return collected.concat(results);
}
}
A Swift 3 Example:
var users = [String] ()
var payments = [String] ()
///set your record limit
let limit = 29
//recursive call, initial loopCount is 0 (we haven't looped yet)
func loadAllPaymentDetails(_ loopCount: Int){
///create your NEW eggstra-special query
let paymentsQuery = Payments.query()
paymentsQuery?.limit = limit
paymentsQuery?.skip = limit*loopCount
paymentsQuery?.findObjectsInBackground(block: { (objects, error) in
if let objects = objects {
//print(#file.getClass()," ",#function," loopcount: ",loopCount," #ReturnedObjects: ", objects.count)
if objects.count > 0 {
//print(#function, " no. of objects :", objects.count)
for paymentsObject in objects {
let user = paymentsObject[Utils.name] as! String
let amount = paymentsObject[Utils.amount] as! String
self.users.append(user)
self.payments.append(amount)
}
//recurse our loop with increment because we are not done
self.loadAllPaymentDetails(loopCount + 1); //<--recurse
}else {
//our query has run out of steam, this else{} will be called one time only
//if the Table had been initially empty, lets inform the user:
if self.users.count == 1 {
Utils.createAlert(self, title: "No Payment has been made yet", message: "Please Encourage Users to make some Payments", buttonTitle: "Ok")
}else {
self.tableView.reloadData()
}
}
}else if error != nil {
print(error!)
}else {
print("Unknown Error")
}
})
}
adapted from #deLux_247's example above.
You could achieve this using CloudCode... Make a custom function you can call that will enumerate the entire collection and build a response from that but a wiser choice would be to paginate your requests, and fetch the records 1000 (or even less) at a time, adding them into your list dynamically as required.
GENERIC VERSION For SWIFT 4:
Warning: this is not tested!
An attempt to adapt nyxee's answer to be usable for any query:
func getAllRecords(for query: PFQuery<PFObject>, then doThis: #escaping (_ objects: [PFObject]?, _ error: Error?)->Void) {
let limit = 1000
var objectArray : [PFObject] = []
query.limit = limit
func recursiveQuery(_ loopCount: Int = 0){
query.skip = limit * loopCount
query.findObjectsInBackground(block: { (objects, error) in
if let objects = objects {
objectArray.append(contentsOf: objects)
if objects.count == limit {
recursiveQuery(loopCount + 1)
} else {
doThis(objectArray, error)
}
} else {
doThis(objects, error)
}
})
}
recursiveQuery()
}
Here's my solution for C# .NET
List<ParseObject> allObjects = new List<ParseObject>();
ParseQuery<ParseObject> query1 = ParseObject.GetQuery("Class");
int totalctr = await query1.CountAsync()
for (int i = 0; i <= totalctr / 1000; i++)
{
ParseQuery<ParseObject> query2 = ParseObject.GetQuery("Class").Skip(i * 1000).Limit(1000);
IEnumerable<ParseObject> ibatch = await query2.FindAsync();
allObjects.AddRange(ibatch);
}