Ücretsiz APK oluştur

JavaScript köprü API'si

KiΕiler

Okuma, arama, seΓ§me ve yazma. SeΓ§ici hiΓ§bir izin gerektirmez.

navigator.contacts web standardı#

navigator.contacts.select(properties, options) — Contact Picker

Örnek

Standart KiΕi SeΓ§ici API'si: telefonun kendi kiΕi seΓ§icisi aΓ§Δ±lΔ±r ve sayfa yalnΔ±zca kullanΔ±cΔ±nΔ±n seΓ§tiΔi kiΕiyi alΔ±r; kiΕiler izni gerekmez.

DΓΆner deΔer: bir dizi iΓ§eren Promise: [{ name: [string], tel: [string] }] ya da kullanΔ±cΔ± seΓ§iciyi kapatΔ±rsa []. Gerekenler: aΓ§Δ±lacak bir Εey yok; bir dokunuΕtan Γ§aΔΔ±rΔ±n (kullanΔ±cΔ± hareketi gerekir, aksi halde SecurityError).

document.getElementById('pick').addEventListener('click', async () => {
  if (!('contacts' in navigator)) { showManualEntry(); return; }
  const props = await navigator.contacts.getProperties();   // ['name', 'tel']
  const [person] = await navigator.contacts.select(props, { multiple: false });
  if (!person) return;                                       // closed without choosing
  document.getElementById('name').value = person.name[0] || '';
  document.getElementById('phone').value = person.tel[0] || '';
});

"GΓΆnderilecek kiΕi" kutusunu yalnΔ±zca numarayla doldurun ve seΓ§icinin reddedebileceΔi her durum iΓ§in bir mesaj gΓΆsterin:

document.getElementById('choose-number').addEventListener('click', async () => {
  if (!('contacts' in navigator)) return;
  try {
    const [person] = await navigator.contacts.select(['tel']);
    if (person && person.tel.length) document.getElementById('to').value = person.tel[0];
  } catch (err) {
    if (err.name === 'InvalidStateError') showMessage('The contact picker is already open or not available.');
    else if (err.name === 'SecurityError') showMessage('Tap the button to choose a contact.');
    else showMessage('Could not pick a contact: ' + err.message);
  }
});

Bir misafir listesini her dokunuΕta bir kiΕi ekleyerek oluΕturun (her seΓ§imde bir kiΕi) ve listede zaten bulunan bir numarayΔ± atlayΔ±n:

const guests = [];

document.getElementById('add-guest').addEventListener('click', async () => {
  if (!('contacts' in navigator)) { showManualEntry(); return; }
  const [person] = await navigator.contacts.select(['name', 'tel']);
  if (!person || !person.tel.length) return;   // closed, or no number

  const number = person.tel[0];
  if (guests.some((g) => g.number === number)) { showMessage('Already invited'); return; }
  guests.push({ name: person.name[0] || number, number });
  renderGuests(guests);
});

Notlar: uygulama name ve tel deΔerlerini destekler; yani kullanΔ±cΔ±nΔ±n dokunduΔu numara. email, address ve icon tam kiΕiler izni gerektirir; bu yΓΌzden sunulmaz ve bunlarΔ± istemek TypeError ile reddedilir. Her seΓ§imde bir kiΕi (multiple kabul edilir ama Android seΓ§icisi bir kiΕi dΓΆndΓΌrΓΌr). YalnΔ±zca ΓΌst sayfada Γ§alΔ±ΕΔ±r. TΓΌm kiΕileri listelemek veya aramak iΓ§in WebToApk.listContacts kullanΔ±n (KiΕiler anahtarΔ± gerekir).

addContact köprü#

window.WebToApk.addContact(requestId: String, contactJson: String)

Sistem seΓ§icisi (izin gerekmez) ve yeni bir kiΕi yazma (WRITE_CONTACTS). Okuma tarafΔ± olan listeleme ve arama, yukarΔ±daki KiΕiler grubunun altΔ±ndadΔ±r.

Kendi baΕΔ±na deΔil, grubuyla birlikte anlatΔ±lΔ±r: KiΕiler: seΓ§me ve ekleme.

Örnek

Yeni bir kiΕiyi KiΕiler uygulamasΔ±nΔ± aΓ§madan doΔrudan telefonun rehberine kaydeder.

DΓΆner deΔer: Δ°Εlem artΔ±k hiΓ§bir Εey dΓΆndΓΌrmez. YanΔ±t, baΕarΔ±da detail = { requestId, ok: true, id: '123' } ile, kayΔ±t baΕarΔ±sΔ±z olduΔunda { requestId, ok: false, id: null } ile ya da { requestId, error } ile gelen appmint:contacts olayΔ±dΔ±r (ve window.onAppMintContacts). Gerekenler: derleme yaparken AdΔ±m 4'te (EriΕim) KiΕileri DΓΌzenle seΓ§eneΔini aΓ§Δ±n; ilk Γ§aΔrΔ±da kullanΔ±cΔ±dan izin istenir.

Bir mΓΌΕteriyi kaydedin. KiΕi bir JSON dizesi olarak iletilir.

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]
  }));
}

KΔ±sa biΓ§im. Tek deΔerler de kabul edilir: { name: 'Ali', phone: '+911234567890', email: '[email protected]' }.

Bir kartvizit sayfasΔ±nda, kΔ±sa biΓ§imi ve bir Promise kullanan "KiΕilere kaydet" dΓΌΔmesi:

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);
    });
});

Bir ekip listesini kiΕi kiΕi, iΕ ve ev numaralarΔ±yla iΓ§e aktarΔ±n ve kaΓ§ kiΕinin kaydedildiΔini bildirin:

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');
}

Notlar: Hatalar: not_enabled, permission_denied. DΓΆnen id, yeni ham kiΕi kimliΔidir. home veya work dΔ±ΕΔ±ndaki bir telefon type deΔeri mobile olarak kaydedilir. KiΕi cihaza kaydedilir (hesap yok). KiΕi yazmak hassas bir izindir: Play Store sayfanΔ±z bunu Veri gΓΌvenliΔi formunda ve gizlilik politikasΔ±nda belirtmelidir.

getContact köprü#

window.WebToApk.getContact(requestId: String, contactId: String)

Hepsi asenkron: imleΓ§ okumalarΔ± binlerce satΔ±r olabilir ve engelleyici bir @JavascriptInterface dΓΆnΓΌΕΓΌ bunu JS iΕ parΓ§acΔ±ΔΔ±nda Γ§alΔ±ΕtΔ±rΔ±rdΔ±; bu da ANR demektir. SonuΓ§lar `appmint:contacts` / window.onAppMintContacts({requestId,...}) olarak gelir. requestId: bir STRING verin ('pick-' + Date.now()). Ham bir SAYI da Γ§alΔ±ΕΔ±r; kΓΆprΓΌ onu bir double ΓΌzerinden dΓΆnΓΌΕtΓΌrΓΌr ("1.787491234567E12") ve her yanΔ±t onu yeniden asΔ±l haline getirir (BridgeRequestId), bΓΆylece `res.requestId === Date.now()` katΔ± karΕΔ±laΕtΔ±rmasΔ± her iki durumda da doΔru Γ§Δ±kar. WebToApk.listContacts(id, limit, offset) WebToApk.searchContacts(id, query, limit) WebToApk.getContact(id, contactId) WebToApk.pickContact(id) <- Δ°zin GEREKMEZ (sistem seΓ§icisi) WebToApk.addContact(id, json) <- KiΕiler yazma izni gerekir

Kendi baΕΔ±na deΔil, grubuyla birlikte anlatΔ±lΔ±r: KiΕiler.

Örnek

Bir kiΕiyi id deΔeriyle yeniden okur (listContacts iΓ§inden gelen id veya searchContacts).

DΓΆner deΔer: Δ°Εlem artΔ±k hiΓ§bir Εey dΓΆndΓΌrmez. YanΔ±t, detail = { requestId, contact: { id, displayName, photoUri, phones: [{ number, type }], emails: [...] } } ile birlikte appmint:contacts olayΔ±dΔ±r (ve window.onAppMintContacts). Kiεi artΔ±k yoksa contact, null olur. Hata durumunda: { requestId, error }. Gerekenler: derleme yaparken AdΔ±m 4'te (EriΕim) KiΕiler seΓ§eneΔini aΓ§Δ±n.

Olay dinleyicisi yerine sayfa kancasΔ±nΔ± kullanarak kayΔ±tlΔ± bir kiΕiyi yenileyin.

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));
}

KayΔ±tlΔ± bir favori kiΕi kimliΔi listesini yenileyin ve o zamandan beri telefondan silinenleri dΓΌΕΓΌrΓΌn:

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);
}

UygulamanΔ±zΔ±n bir mΓΌΕteri iΓ§in sakladΔ±ΔΔ± numaranΔ±n hΓ’lΓ’ kiΕi kartΔ±nda olup olmadΔ±ΔΔ±nΔ± kontrol edin:

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));
}

Notlar: window.onAppMintContacts her kiΕiler yanΔ±tΔ±nΔ± alΔ±r (liste, arama, seΓ§me, ekleme); bu yΓΌzden her zaman requestId deΔerini kontrol edin. Onu ya da addEventListener('appmint:contacts', ...) kullanabilirsiniz; ikisi de tetiklenir. Hatalar: not_enabled, permission_denied, foreign_origin. pickContact iΓ§inden gelen id, bir kiΕi kimliΔi deΔil telefon satΔ±rΔ± kimliΔidir; bu yΓΌzden burada iΕe yaramaz. KiΕiler kiΕisel veridir: Play Store sayfanΔ±z bunu Veri gΓΌvenliΔi formunda ve gizlilik politikasΔ±nda belirtmelidir.

listContacts köprü#

window.WebToApk.listContacts(requestId: String, limit: Int, offset: Int)

Hepsi asenkron: imleΓ§ okumalarΔ± binlerce satΔ±r olabilir ve engelleyici bir @JavascriptInterface dΓΆnΓΌΕΓΌ bunu JS iΕ parΓ§acΔ±ΔΔ±nda Γ§alΔ±ΕtΔ±rΔ±rdΔ±; bu da ANR demektir. SonuΓ§lar `appmint:contacts` / window.onAppMintContacts({requestId,...}) olarak gelir. requestId: bir STRING verin ('pick-' + Date.now()). Ham bir SAYI da Γ§alΔ±ΕΔ±r; kΓΆprΓΌ onu bir double ΓΌzerinden dΓΆnΓΌΕtΓΌrΓΌr ("1.787491234567E12") ve her yanΔ±t onu yeniden asΔ±l haline getirir (BridgeRequestId), bΓΆylece `res.requestId === Date.now()` katΔ± karΕΔ±laΕtΔ±rmasΔ± her iki durumda da doΔru Γ§Δ±kar. WebToApk.listContacts(id, limit, offset) WebToApk.searchContacts(id, query, limit) WebToApk.getContact(id, contactId) WebToApk.pickContact(id) <- Δ°zin GEREKMEZ (sistem seΓ§icisi) WebToApk.addContact(id, json) <- KiΕiler yazma izni gerekir

Kendi baΕΔ±na deΔil, grubuyla birlikte anlatΔ±lΔ±r: KiΕiler.

Örnek

Telefonun rehberini sayfa sayfa, ada gΓΆre A'dan Z'ye sΔ±ralΔ± okur.

DΓΆner deΔer: Δ°Εlem artΔ±k hiΓ§bir Εey dΓΆndΓΌrmez. YanΔ±t daha sonra detail = { requestId, contacts: [{ id, displayName, photoUri, phones: [{ number, type }], emails: ['[email protected]'] }] } ile birlikte appmint:contacts olayΔ± olarak (ve window.onAppMintContacts) ya da { requestId, error } olarak gelir. Gerekenler: derleme yaparken AdΔ±m 4'te (EriΕim) KiΕiler seΓ§eneΔini aΓ§Δ±n; ilk Γ§aΔrΔ±da kullanΔ±cΔ±dan izin istenir.

Δ°lk 100 kiΕiyi yΓΌkleyin. YanΔ±tΔ± kendi 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
}

Sonraki sayfa. Elinizdeki sayΔ±yΔ± Εu olarak verin: offset: WebToApk.listContacts(id, 100, 100).

KΔ±sa bir sayfa sonuna ulaΕtΔ±ΔΔ±nΔ±zΔ± sΓΆyleyene kadar tΓΌm rehberi 500'lΓΌk sayfalar halinde yΓΌkleyin:

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
  }
}

YalnΔ±zca cep numaralarΔ±ndan bir "ArkadaΕlarΔ± davet et" listesi oluΕturun ve okuma reddedildiΔinde kullanΔ±cΔ±ya ne yapacaΔΔ±nΔ± sΓΆyleyin:

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);
}

Notlar: limit deΔeri 1-2000 aralΔ±ΔΔ±na sΔ±nΔ±rlanΔ±r. Hatalar: not_enabled (derleme sΔ±rasΔ±nda KiΕiler kapalΔ±ydΔ±), permission_denied (kullanΔ±cΔ± HayΔ±r dedi), foreign_origin (uygulamanΔ±zΔ±n kendi sayfasΔ± olmayan bir sayfadan Γ§aΔrΔ±ldΔ±). Telefon type deΔeri home, mobile, work, main, work_fax, home_fax veya other olur. photoUri, bir content:// adresidir; sayfanΔ±n yΓΌkleyebileceΔi bir gΓΆrsel URL'si deΔildir. KullanΔ±cΔ±nΔ±n yalnΔ±zca bir kiΕi seΓ§mesini istiyorsanΔ±z bunun yerine pickContact kullanΔ±n; izin gerektirmez. KiΕiler kiΕisel veridir: Play Store sayfanΔ±z bunu Veri gΓΌvenliΔi formunda ve gizlilik politikasΔ±nda belirtmelidir.

pickContact köprü#

window.WebToApk.pickContact(requestId: String)

Sistem kişi seçici - İZİN GEREKTİRMEZ ve sayfanın yalnızca kullanıcının bir kişi seçmesini istediği her durumda doğru seçimdir. Kişi tablosundan değil TELEFON tablosundan seçer: seçici yalnızca döndürdüğü satıra okuma erişimi verir, bu yüzden bir telefon satırı seçmek numarayı READ_CONTACTS olmadan okunabilir kılar. Çıplak bir kişi seçmek adı olan ama numarası olmayan bir satır döndürür ve numarayı ondan okumak, bu yöntemin kaçındığı izni gerektirir.

Örnek

Android'in kendi kiΕi seΓ§icisini aΓ§ar; kullanΔ±cΔ± bir telefon numarasΔ± seΓ§er. Δ°zin gerekmez.

DΓΆner deΔer: Δ°Εlem artΔ±k hiΓ§bir Εey dΓΆndΓΌrmez. YanΔ±t, detail = { requestId, contact: { id, displayName, photoUri, phones: [{ number, type: 'picked' }], emails: [] } } ile birlikte appmint:contacts olayΔ±dΔ±r (ve window.onAppMintContacts). KullanΔ±cΔ± seΓ§iciyi kapatΔ±rsa: { requestId, error: 'cancelled' }. Gerekenler: hiΓ§bir Εey; derleme anahtarΔ± yok, izin isteΔi yok.

Bir formu seΓ§ilen kiΕiyle doldurun.

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);
}

KΔ±sa bir acil durum kiΕileri listesi tutun. id deΔil, ad ve numarayΔ± kaydedin; bΓΆylece liste rehbere baΔlΔ± kalmaz:

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);
});

SeΓ§ici aΓ§Δ±kken dΓΌΔmeyi devre dΔ±ΕΔ± bΔ±rakΔ±n ve telefonda kiΕiler uygulamasΔ± yoksa yazΔ±m alanlarΔ±nΔ± gΓΆsterin:

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);
});

Notlar: AdΔ± ve kullanΔ±cΔ±nΔ±n dokunduΔu TEK numarayΔ± alΔ±rsΔ±nΔ±z; e-postalarΔ± ve rehberin geri kalanΔ±nΔ± asla. emails her zaman boΕtur. Hatalar: cancelled, no_picker (telefonda kiΕiler uygulamasΔ± yok). SeΓ§imden sonra okuma baΕarΔ±sΔ±z olursa contact deΔeri null olur. KullanΔ±cΔ±nΔ±n seΓ§imi olmadan hiΓ§bir Εey okunmadΔ±ΔΔ± iΓ§in bu, Play'e uygun biΓ§imde telefon numarasΔ± almanΔ±n yoludur; yalnΔ±zca bir kiΕiye ihtiyacΔ±nΔ±z olduΔunda listContacts yerine bunu tercih edin. Yapay zekΓ’yla oluΕturulan uygulamalarda ve Google AI Studio iΓ§e aktarmalarΔ±nda derleme kodunuzu tarar; pickContact( Γ§aΔrΔ±sΔ± KiΕiler seΓ§eneΔini iΕaretlemez, yalnΔ±zca listContacts, searchContacts ve getContact iΕaretler; bu yΓΌzden seΓ§ici kiΕi okuma izni eklemez.

searchContacts köprü#

window.WebToApk.searchContacts(requestId: String, query: String, limit: Int)

Hepsi asenkron: imleΓ§ okumalarΔ± binlerce satΔ±r olabilir ve engelleyici bir @JavascriptInterface dΓΆnΓΌΕΓΌ bunu JS iΕ parΓ§acΔ±ΔΔ±nda Γ§alΔ±ΕtΔ±rΔ±rdΔ±; bu da ANR demektir. SonuΓ§lar `appmint:contacts` / window.onAppMintContacts({requestId,...}) olarak gelir. requestId: bir STRING verin ('pick-' + Date.now()). Ham bir SAYI da Γ§alΔ±ΕΔ±r; kΓΆprΓΌ onu bir double ΓΌzerinden dΓΆnΓΌΕtΓΌrΓΌr ("1.787491234567E12") ve her yanΔ±t onu yeniden asΔ±l haline getirir (BridgeRequestId), bΓΆylece `res.requestId === Date.now()` katΔ± karΕΔ±laΕtΔ±rmasΔ± her iki durumda da doΔru Γ§Δ±kar. WebToApk.listContacts(id, limit, offset) WebToApk.searchContacts(id, query, limit) WebToApk.getContact(id, contactId) WebToApk.pickContact(id) <- Δ°zin GEREKMEZ (sistem seΓ§icisi) WebToApk.addContact(id, json) <- KiΕiler yazma izni gerekir

Kendi baΕΔ±na deΔil, grubuyla birlikte anlatΔ±lΔ±r: KiΕiler.

Örnek

TΓΌm rehberi yΓΌklemeden, adΔ± bir arama sΓΆzcΓΌΔΓΌyle eΕleΕen kiΕileri bulur.

DΓΆner deΔer: Δ°Εlem artΔ±k hiΓ§bir Εey dΓΆndΓΌrmez. YanΔ±t, detail = { requestId, contacts: [...] } ile birlikte appmint:contacts olayΔ±dΔ±r (ve window.onAppMintContacts); listContacts ile aynΔ± kiΕi yapΔ±sΔ± ya da { requestId, error }. Gerekenler: derleme yaparken AdΔ±m 4'te (EriΕim) KiΕiler seΓ§eneΔini aΓ§Δ±n; ilk Γ§aΔrΔ±da kullanΔ±cΔ±dan izin istenir.

KullanΔ±cΔ± yazdΔ±kΓ§a arayΔ±n. YalnΔ±zca en son aramanΔ±n yanΔ±tΔ± gΓΆsterilir.

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);
});

AramayΔ± bir Promise iΓ§ine alΔ±n ve kullanΔ±cΔ± yazmayΔ± bΔ±rakana kadar bekleyin; bΓΆylece hΔ±zlΔ± yazΔ±m her tuΕ iΓ§in bir arama baΕlatmaz:

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);
});

YazΔ±lan ad e-postasΔ± olan tek bir kiΕiyle eΕleΕtiΔinde e-posta kutusunu rehberden doldurun:

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());
});

Notlar: BoΕ bir arama sΓΆzcΓΌΔΓΌ, listenin baΕΔ±ndan kiΕileri dΓΆndΓΌrΓΌr (listContacts gibi). limit 1-2000 aralΔ±ΔΔ±na sΔ±nΔ±rlanΔ±r ve ofset yoktur. Hatalar: not_enabled, permission_denied, foreign_origin. KiΕiler kiΕisel veridir: Play Store sayfanΔ±z bunu Veri gΓΌvenliΔi formunda ve gizlilik politikasΔ±nda belirtmelidir.

Her belge derlemesinde uygulama çalışma zamanından ve örnek dosyalarından oluşturulur. Markdown olarak okuyun · Tüm aileler.

22.10.2026 tarihinde yayınlanan köprüyle karşılaştırılarak kontrol edildi.