JavaScript ब्रिज API
Contacts
पढ़ना, खोजना, चुनना और लिखना - पिकर को कोई अनुमति नहीं चाहिए।
addContact ब्रिज#
window.WebToApk.addContact(requestId: String, contactJson: String)
सिस्टम पिकर (कोई अनुमति नहीं चाहिए) और नया contact लिखना (WRITE_CONTACTS)। पढ़ने वाला हिस्सा - सूची और खोज - ऊपर के Contacts समूह में है।
इसका वर्णन अलग से नहीं, बल्कि इसके समूह Contacts: चुनें और जोड़ें में किया गया है।
उदाहरण
Contacts ऐप खोले बिना, नया contact सीधे फ़ोन की एड्रेस बुक में सेव करता है।
लौटाता है: अभी कुछ नहीं। जवाब सफलता पर detail = { requestId, ok: true, id: '123' } के साथ appmint:contacts इवेंट (और window.onAppMintContacts) है, सेव विफल होने पर { requestId, ok: false, id: null }, या { requestId, error }। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Edit Contacts चालू करें; यूज़र से पहली कॉल पर अनुमति माँगी जाती है।
ग्राहक सेव करें। Contact JSON स्ट्रिंग के रूप में दिया जाता है।
function saveCustomer(name, phone, email) {
if (!(window.WebToApk && window.WebToApk.addContact)) return;
var id = 'add-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error === 'not_enabled') { showMessage('Turn on Edit Contacts when you build'); return; }
if (e.detail.error) { showMessage('Not saved: ' + e.detail.error); return; }
showMessage(e.detail.ok ? 'Saved to contacts' : 'Could not save the contact');
});
WebToApk.addContact(id, JSON.stringify({
displayName: name,
phones: [{ number: phone, type: 'mobile' }], // type: mobile | home | work
emails: [email]
}));
}छोटा रूप। एकल वैल्यू भी स्वीकार की जाती हैं: { name: 'Ali', phone: '+911234567890', email: '[email protected]' }.
बिज़नेस कार्ड पेज पर "Save to contacts" बटन, छोटे रूप और Promise के साथ:
function addOne(contact) {
return new Promise(function (resolve, reject) {
var id = 'card-' + Date.now() + '-' + Math.random().toString(36).slice(2);
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error) reject(new Error(e.detail.error));
else if (!e.detail.ok) reject(new Error('save_failed'));
else resolve(e.detail.id);
});
WebToApk.addContact(id, JSON.stringify(contact));
});
}
document.getElementById('save-card').addEventListener('click', function () {
if (!(window.WebToApk && window.WebToApk.addContact)) return;
addOne({ name: 'Priya Sharma', phone: '+919876543210', email: '[email protected]' })
.then(function () { showMessage('Priya is in your contacts now'); })
.catch(function (err) {
showMessage(err.message === 'permission_denied' ? 'Allow Contacts to save this card.' : 'Not saved: ' + err.message);
});
});टीम की सूची एक-एक व्यक्ति करके इम्पोर्ट करें, काम और घर के नंबरों के साथ, और बताएँ कि कितने सेव हुए:
async function importTeam(team) { // [{ name, work, home, email }]
if (!(window.WebToApk && window.WebToApk.addContact)) return;
var saved = 0;
for (var i = 0; i < team.length; i++) {
var m = team[i];
try {
await addOne({ // addOne() from the example above
displayName: m.name,
phones: [{ number: m.work, type: 'work' }, { number: m.home, type: 'home' }],
emails: m.email ? [m.email] : []
});
saved++;
} catch (err) {
if (err.message === 'not_enabled' || err.message === 'permission_denied') break; // the rest would fail too
}
}
showMessage(saved + ' of ' + team.length + ' saved');
}ध्यान दें: त्रुटियाँ: not_enabled, permission_denied। लौटाया गया id नए raw-contact की id है। home या work के अलावा कोई फ़ोन type mobile के रूप में सेव होता है। Contact डिवाइस पर सेव होता है (कोई अकाउंट नहीं)। Contacts लिखना संवेदनशील अनुमति है: आपकी Play Store लिस्टिंग को इसे Data safety फ़ॉर्म और प्राइवेसी पॉलिसी में बताना होगा।
getContact ब्रिज#
window.WebToApk.getContact(requestId: String, contactId: String)
सब कुछ async है: cursor रीड हज़ारों पंक्तियों के हो सकते हैं, और ब्लॉक करने वाला @JavascriptInterface रिटर्न उन्हें JS थ्रेड पर चलाएगा - यानी ANR। नतीजे `appmint:contacts` / window.onAppMintContacts({requestId,...}) के रूप में आते हैं। requestId: एक STRING दें ('pick-' + Date.now())। सादा NUMBER भी चलता है - ब्रिज उसे double से गुज़ारता है ("1.787491234567E12"), और हर जवाब उसे वापस सही रूप में बदल देता है (BridgeRequestId), इसलिए `res.requestId === Date.now()` दोनों तरह से सख़्ती से true निकलता है। WebToApk.listContacts(id, limit, offset) WebToApk.searchContacts(id, query, limit) WebToApk.getContact(id, contactId) WebToApk.pickContact(id) <- कोई अनुमति नहीं चाहिए (सिस्टम पिकर) WebToApk.addContact(id, json) <- Contacts-write अनुमति चाहिए
इसका वर्णन अलग से नहीं, बल्कि इसके समूह Contacts में किया गया है।
उदाहरण
एक contact को उसकी id से दोबारा पढ़ता है (listContacts से मिली id या searchContacts).
लौटाता है: अभी कुछ नहीं। जवाब detail = { requestId, contact: { id, displayName, photoUri, phones: [{ number, type }], emails: [...] } } के साथ appmint:contacts इवेंट (और window.onAppMintContacts) है। उस contact के अब मौजूद न होने पर contact null होता है। विफलता पर: { requestId, error }। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Contacts चालू करें।
सेव किया हुआ contact रीफ़्रेश करें, इवेंट लिसनर की जगह पेज हुक से।
var pendingId = '';
window.onAppMintContacts = function (detail) {
if (detail.requestId !== pendingId) return;
if (detail.error) { showMessage('Could not read the contact: ' + detail.error); return; }
if (!detail.contact) { showMessage('This contact was deleted.'); return; }
var c = detail.contact;
document.getElementById('name').textContent = c.displayName;
document.getElementById('phones').textContent =
c.phones.map(function (p) { return p.type + ': ' + p.number; }).join(', ');
document.getElementById('emails').textContent = c.emails.join(', ');
};
function openContact(contactId) {
if (!(window.WebToApk && window.WebToApk.getContact)) return;
pendingId = 'one-' + Date.now();
WebToApk.getContact(pendingId, String(contactId));
}पसंदीदा contact ids की सेव सूची रीफ़्रेश करें और जो तब से फ़ोन से हट गए हों उन्हें हटाएँ:
function getOne(contactId) {
return new Promise(function (resolve, reject) {
var id = 'fav-' + contactId + '-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error) reject(new Error(e.detail.error)); else resolve(e.detail.contact);
});
WebToApk.getContact(id, String(contactId));
});
}
async function loadFavourites() {
if (!(window.WebToApk && window.WebToApk.getContact)) return;
var ids = JSON.parse(localStorage.getItem('favIds') || '[]');
var people = [];
for (var i = 0; i < ids.length; i++) {
var c = await getOne(ids[i]);
if (c) people.push(c); // null = deleted from the phone
}
localStorage.setItem('favIds', JSON.stringify(people.map(function (c) { return c.id; })));
renderFavourites(people);
}जाँचें कि आपके ऐप में किसी ग्राहक के लिए सेव किया नंबर अब भी उसके contact कार्ड पर है या नहीं:
function checkStoredNumber(customer) { // { contactId, phone }
if (!(window.WebToApk && window.WebToApk.getContact)) return;
var id = 'check-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error) { showMessage('Could not check: ' + e.detail.error); return; }
if (!e.detail.contact) { showMessage('This customer is no longer in your contacts.'); return; }
var digits = function (s) { return String(s).replace(/\D/g, ''); };
var still = e.detail.contact.phones.some(function (p) {
return digits(p.number).slice(-10) === digits(customer.phone).slice(-10);
});
if (!still) showMessage('The number for ' + e.detail.contact.displayName + ' has changed.');
});
WebToApk.getContact(id, String(customer.contactId));
}ध्यान दें: window.onAppMintContacts को हर contacts जवाब मिलता है (सूची, खोज, चुनाव, जोड़ना), इसलिए हमेशा requestId जाँचें। आप इसे या addEventListener('appmint:contacts', ...) इस्तेमाल कर सकते हैं - दोनों चलते हैं। त्रुटियाँ: not_enabled, permission_denied, foreign_origin। pickContact से मिली id फ़ोन-पंक्ति की id है, contact की id नहीं, इसलिए यह यहाँ काम नहीं करती। Contacts निजी डेटा है: आपकी Play Store लिस्टिंग को इसे Data safety फ़ॉर्म और प्राइवेसी पॉलिसी में बताना होगा।
listContacts ब्रिज#
window.WebToApk.listContacts(requestId: String, limit: Int, offset: Int)
सब कुछ async है: cursor रीड हज़ारों पंक्तियों के हो सकते हैं, और ब्लॉक करने वाला @JavascriptInterface रिटर्न उन्हें JS थ्रेड पर चलाएगा - यानी ANR। नतीजे `appmint:contacts` / window.onAppMintContacts({requestId,...}) के रूप में आते हैं। requestId: एक STRING दें ('pick-' + Date.now())। सादा NUMBER भी चलता है - ब्रिज उसे double से गुज़ारता है ("1.787491234567E12"), और हर जवाब उसे वापस सही रूप में बदल देता है (BridgeRequestId), इसलिए `res.requestId === Date.now()` दोनों तरह से सख़्ती से true निकलता है। WebToApk.listContacts(id, limit, offset) WebToApk.searchContacts(id, query, limit) WebToApk.getContact(id, contactId) WebToApk.pickContact(id) <- कोई अनुमति नहीं चाहिए (सिस्टम पिकर) WebToApk.addContact(id, json) <- Contacts-write अनुमति चाहिए
इसका वर्णन अलग से नहीं, बल्कि इसके समूह Contacts में किया गया है।
उदाहरण
फ़ोन की एड्रेस बुक पेज-दर-पेज पढ़ता है, नाम के हिसाब से A से Z क्रम में।
लौटाता है: अभी कुछ नहीं। जवाब बाद में detail = { requestId, contacts: [{ id, displayName, photoUri, phones: [{ number, type }], emails: ['[email protected]'] }] } के साथ appmint:contacts इवेंट (और window.onAppMintContacts) के रूप में आता है, या { requestId, error }। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Contacts चालू करें; यूज़र से पहली कॉल पर अनुमति माँगी जाती है।
पहले 100 contacts लोड करें। जवाब को अपने requestId.
function loadContacts() {
if (!(window.WebToApk && window.WebToApk.listContacts)) {
showMessage('Contacts work only inside the app.');
return;
}
var id = 'contacts-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return; // another call's answer
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error) { showMessage('Could not read contacts: ' + e.detail.error); return; }
var list = document.getElementById('list');
list.innerHTML = '';
e.detail.contacts.forEach(function (c) {
var li = document.createElement('li');
var num = c.phones.length ? c.phones[0].number + ' (' + c.phones[0].type + ')' : '';
li.textContent = c.displayName + ' ' + num;
list.appendChild(li);
});
});
WebToApk.listContacts(id, 100, 0); // limit 100, start at 0
}अगला पेज। जो नंबर आपके पास पहले से है वह इस रूप में दें offset: WebToApk.listContacts(id, 100, 100).
पूरी एड्रेस बुक 500 के पेजों में तब तक लोड करें जब तक कोई छोटा पेज न बताए कि आप अंत तक पहुँच गए:
function listPage(limit, offset) {
return new Promise(function (resolve, reject) {
var id = 'page-' + offset + '-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error) reject(new Error(e.detail.error));
else resolve(e.detail.contacts);
});
WebToApk.listContacts(id, limit, offset);
});
}
async function loadEveryContact() {
if (!(window.WebToApk && window.WebToApk.listContacts)) return [];
var all = [];
while (true) {
var page = await listPage(500, all.length);
all = all.concat(page);
if (page.length < 500) return all; // last page
}
}सिर्फ़ मोबाइल नंबरों से "Invite friends" सूची बनाएँ, और पढ़ना मना होने पर यूज़र को बताएँ कि क्या करना है:
function showInviteList() {
if (!(window.WebToApk && window.WebToApk.listContacts)) return;
var id = 'invite-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error === 'permission_denied') { showMessage('Allow Contacts to invite friends.'); return; }
if (e.detail.error) { showMessage('Contacts are not available: ' + e.detail.error); return; }
var mobiles = [];
e.detail.contacts.forEach(function (c) {
c.phones.forEach(function (p) {
if (p.type === 'mobile') mobiles.push({ name: c.displayName, number: p.number });
});
});
renderInviteList(mobiles); // your own list UI
});
WebToApk.listContacts(id, 500, 0);
}ध्यान दें: limit को 1-2000 के बीच रखा जाता है। त्रुटियाँ: not_enabled (बिल्ड के समय Contacts बंद था), permission_denied (यूज़र ने मना किया), foreign_origin (ऐसे पेज से कॉल जो आपके ऐप का अपना नहीं है)। फ़ोन type है home, mobile, work, main, work_fax, home_fax या other। photoUri एक content:// पता है, ऐसा इमेज URL नहीं जिसे पेज लोड कर सके। यूज़र से सिर्फ़ एक व्यक्ति चुनवाने के लिए इसकी जगह pickContact इस्तेमाल करें - उसे कोई अनुमति नहीं चाहिए। Contacts निजी डेटा है: आपकी Play Store लिस्टिंग को इसे Data safety फ़ॉर्म और प्राइवेसी पॉलिसी में बताना होगा।
pickContact ब्रिज#
window.WebToApk.pickContact(requestId: String)
सिस्टम कॉन्टैक्ट पिकर - इसे कोई अनुमति नहीं चाहिए, और जब भी पेज को बस यूज़र से एक व्यक्ति चुनवाना हो तो यही सही विकल्प है। यह contact टेबल से नहीं, PHONE टेबल से चुनता है: पिकर सिर्फ़ उसी पंक्ति को पढ़ने की अनुमति देता है जो वह लौटाता है, इसलिए फ़ोन पंक्ति चुनने से ही READ_CONTACTS के बिना नंबर पढ़ा जा सकता है। सिर्फ़ contact चुनने पर नाम वाली पंक्ति मिलती, नंबर नहीं, और उससे नंबर पढ़ने के लिए वही अनुमति चाहिए होती जिससे यह तरीका बचाता है।
उदाहरण
Android का अपना contact पिकर खोलता है ताकि यूज़र एक फ़ोन नंबर चुने। कोई अनुमति नहीं चाहिए।
लौटाता है: अभी कुछ नहीं। जवाब detail = { requestId, contact: { id, displayName, photoUri, phones: [{ number, type: 'picked' }], emails: [] } } के साथ appmint:contacts इवेंट (और window.onAppMintContacts) है। अगर यूज़र पिकर बंद कर दे: { requestId, error: 'cancelled' }। ज़रूरत: कुछ नहीं - कोई बिल्ड स्विच नहीं, कोई अनुमति प्रॉम्प्ट नहीं।
चुने हुए व्यक्ति से फ़ॉर्म भरें।
function chooseContact() {
if (!(window.WebToApk && window.WebToApk.pickContact)) {
showMessage('Open this page in the app to pick a contact.');
return;
}
var id = 'pick-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error === 'cancelled') return; // user closed the picker
if (e.detail.error) { showMessage('Could not open contacts'); return; }
if (!e.detail.contact) { showMessage('Could not read that contact'); return; }
var c = e.detail.contact;
document.getElementById('name').value = c.displayName;
document.getElementById('phone').value = c.phones.length ? c.phones[0].number : '';
});
WebToApk.pickContact(id);
}आपातकालीन contacts की छोटी सूची रखें। id नहीं, नाम और नंबर सेव करें, ताकि सूची एड्रेस बुक पर निर्भर न रहे:
function pickOne() {
return new Promise(function (resolve, reject) {
var id = 'sos-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error === 'cancelled') resolve(null);
else if (e.detail.error) reject(new Error(e.detail.error));
else resolve(e.detail.contact);
});
WebToApk.pickContact(id);
});
}
document.getElementById('add-sos').addEventListener('click', async function () {
if (!(window.WebToApk && window.WebToApk.pickContact)) return;
var c = await pickOne();
if (!c || !c.phones.length) return; // closed, or nothing readable
var list = JSON.parse(localStorage.getItem('sos') || '[]');
list.push({ name: c.displayName, number: c.phones[0].number });
localStorage.setItem('sos', JSON.stringify(list));
renderSosList(list);
});पिकर खुला होने पर बटन बंद रखें, और फ़ोन में contacts ऐप न हो तो टाइप करने वाले फ़ील्ड दिखाएँ:
var pickBtn = document.getElementById('pick');
pickBtn.addEventListener('click', function () {
if (!(window.WebToApk && window.WebToApk.pickContact)) { showManualEntry(); return; }
var id = 'recipient-' + Date.now();
pickBtn.disabled = true; // one picker at a time
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
pickBtn.disabled = false;
if (e.detail.error === 'no_picker') { showManualEntry(); return; }
if (e.detail.error) return; // 'cancelled'
if (e.detail.contact && e.detail.contact.phones.length) {
document.getElementById('to').value = e.detail.contact.phones[0].number;
}
});
WebToApk.pickContact(id);
});ध्यान दें: आपको नाम और वह ONE नंबर मिलता है जिस पर यूज़र ने टैप किया - कभी ईमेल नहीं, बाकी बुक नहीं। emails हमेशा खाली रहता है। त्रुटियाँ: cancelled, no_picker (फ़ोन में कोई contacts ऐप नहीं)। चुनने के बाद पढ़ना विफल हो तो contact null होता है। क्योंकि यूज़र के चुनाव के बिना कुछ नहीं पढ़ा जाता, फ़ोन नंबर पाने का Play-अनुकूल तरीका यही है; जब सिर्फ़ एक व्यक्ति चाहिए तो listContacts की जगह इसे अपनाएँ। AI से बने ऐप और Google AI Studio इम्पोर्ट के लिए बिल्ड आपका कोड स्कैन करता है; pickContact( कॉल से Contacts टिक नहीं होता - सिर्फ़ listContacts, searchContacts और getContact से होता है - इसलिए पिकर contacts-पढ़ने की कोई अनुमति नहीं जोड़ता।
searchContacts ब्रिज#
window.WebToApk.searchContacts(requestId: String, query: String, limit: Int)
सब कुछ async है: cursor रीड हज़ारों पंक्तियों के हो सकते हैं, और ब्लॉक करने वाला @JavascriptInterface रिटर्न उन्हें JS थ्रेड पर चलाएगा - यानी ANR। नतीजे `appmint:contacts` / window.onAppMintContacts({requestId,...}) के रूप में आते हैं। requestId: एक STRING दें ('pick-' + Date.now())। सादा NUMBER भी चलता है - ब्रिज उसे double से गुज़ारता है ("1.787491234567E12"), और हर जवाब उसे वापस सही रूप में बदल देता है (BridgeRequestId), इसलिए `res.requestId === Date.now()` दोनों तरह से सख़्ती से true निकलता है। WebToApk.listContacts(id, limit, offset) WebToApk.searchContacts(id, query, limit) WebToApk.getContact(id, contactId) WebToApk.pickContact(id) <- कोई अनुमति नहीं चाहिए (सिस्टम पिकर) WebToApk.addContact(id, json) <- Contacts-write अनुमति चाहिए
इसका वर्णन अलग से नहीं, बल्कि इसके समूह Contacts में किया गया है।
उदाहरण
ऐसे contacts खोजता है जिनका नाम खोज शब्द से मेल खाता है, पूरी एड्रेस बुक लोड किए बिना।
लौटाता है: अभी कुछ नहीं। जवाब detail = { requestId, contacts: [...] } के साथ appmint:contacts इवेंट (और window.onAppMintContacts) है - वही contact रूप जो listContacts में है - या { requestId, error }। ज़रूरत: बिल्ड करते समय चरण 4 (Access) में Contacts चालू करें; यूज़र से पहली कॉल पर अनुमति माँगी जाती है।
यूज़र के टाइप करते ही खोजें। सिर्फ़ आख़िरी खोज का जवाब दिखाया जाता है।
var lastSearchId = '';
function searchPeople(word) {
if (!(window.WebToApk && window.WebToApk.searchContacts)) return;
lastSearchId = 'search-' + Date.now();
WebToApk.searchContacts(lastSearchId, word, 20); // at most 20 results
}
window.addEventListener('appmint:contacts', function (e) {
if (!e.detail || e.detail.requestId !== lastSearchId) return; // old or other request
if (e.detail.error) { showMessage('Search failed: ' + e.detail.error); return; }
var names = e.detail.contacts.map(function (c) {
return c.displayName + (c.phones.length ? ' - ' + c.phones[0].number : '');
});
document.getElementById('results').textContent = names.join('\n') || 'No match';
});
document.getElementById('q').addEventListener('input', function (e) {
searchPeople(e.target.value);
});खोज को Promise में लपेटें और यूज़र के टाइप करना रोकने तक रुकें, ताकि तेज़ टाइपिंग हर कुंजी पर खोज शुरू न करे:
function searchOnce(word, limit) {
return new Promise(function (resolve, reject) {
var id = 'find-' + Date.now() + '-' + Math.random().toString(36).slice(2);
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error) reject(new Error(e.detail.error)); else resolve(e.detail.contacts);
});
WebToApk.searchContacts(id, word, limit);
});
}
var timer = null;
document.getElementById('q').addEventListener('input', function (e) {
clearTimeout(timer);
var word = e.target.value.trim();
timer = setTimeout(function () {
if (!(window.WebToApk && window.WebToApk.searchContacts) || !word) return;
searchOnce(word, 10)
.then(function (people) { renderSuggestions(people); })
.catch(function (err) { showMessage('Search failed: ' + err.message); });
}, 300);
});जब टाइप किया गया नाम ऐसे एक व्यक्ति से मेल खाए जिसका ईमेल है, तब एड्रेस बुक से ईमेल बॉक्स भरें:
function suggestEmail(name) {
if (!(window.WebToApk && window.WebToApk.searchContacts) || name.length < 2) return;
var id = 'email-' + Date.now();
window.addEventListener('appmint:contacts', function handler(e) {
if (!e.detail || e.detail.requestId !== id) return;
window.removeEventListener('appmint:contacts', handler);
if (e.detail.error) return; // leave the box for the user to type
var withEmail = e.detail.contacts.filter(function (c) { return c.emails.length > 0; });
if (withEmail.length === 1) {
document.getElementById('email').value = withEmail[0].emails[0];
}
});
WebToApk.searchContacts(id, name, 5);
}
document.getElementById('name').addEventListener('change', function (e) {
suggestEmail(e.target.value.trim());
});ध्यान दें: खाली खोज शब्द सूची की शुरुआत से contacts लौटाता है (listContacts की तरह)। limit को 1-2000 के बीच रखा जाता है और कोई offset नहीं है। त्रुटियाँ: not_enabled, permission_denied, foreign_origin। Contacts निजी डेटा है: आपकी Play Store लिस्टिंग को इसे Data safety फ़ॉर्म और प्राइवेसी पॉलिसी में बताना होगा।