Bardziej niezawodny sposób dodawania i edytowania kontaktów na Androidzie
Czas czytania: 6 min
Co się zmienia
Aplikacje kierowane na nadchodzącą wersję Androida nie będą już mogły bezpośrednio zapisywać kontaktów z uprawnieniem WRITE_CONTACTS. Zamiast tego możesz użyć standardowych intencji kontaktów (ACTION_INSERT, ACTION_EDIT i ACTION_INSERT_OR_EDIT). Pełną implementację referencyjną znajdziesz w przewodniku dla deweloperów na temat modyfikowania kontaktów za pomocą intencji.
Na urządzeniach z nadchodzącą wersją Androida te 3 intencje dotyczące kontaktów będą działać spójnie i nie będą wymagać żadnych uprawnień. Jeśli Twoja aplikacja jest kierowana na nadchodzącą wersję Androida lub nowszą i próbuje bezpośrednio zapisywać kontakty, te zapisy zostaną odrzucone i spowodują błąd SecurityException lub odmowę uprawnień. W przypadku niewielkiej liczby aplikacji, które wymagają szerokiego dostępu do tworzenia i modyfikowania kontaktów, w Androidzie 17 QPR2 (IV kwartał 2026 r.) pojawi się nowe specjalne uprawnienie dostępu do aplikacji: MANAGE_CONTACTS. Google Play publikuje dziś zaktualizowane wytyczne dotyczące dostępu do kontaktów, w tym MANAGE_CONTACTS.
Dlaczego to robimy
Obecnie, jeśli aplikacja musi zapisać choćby jeden kontakt, możesz poprosić o uprawnienie WRITE_CONTACTS. To uprawnienie zapewnia jednak szeroki dostęp, umożliwiając aplikacji wprowadzanie w tle zmian w kontaktach na całym urządzeniu, nawet bez interakcji użytkownika. Większość aplikacji nie potrzebuje tak szerokich uprawnień.
Chociaż istnieją alternatywne rozwiązania, otrzymaliśmy od Was informacje, że powinny być one bardziej ustandaryzowane w całym ekosystemie. Wcześniej intencje kontaktów działały inaczej na różnych urządzeniach. Niektóre edytory odrzuciły przekazane przez Ciebie dane, np. zdjęcie kontaktu. Na niektórych urządzeniach przycisk Wstecz zapisywał kontakt bez wiedzy użytkownika lub opcja „Utwórz nowy kontakt” była trudna do znalezienia. Dlatego poproszenie o zgodę było racjonalnym wyborem. Rozwiązujemy wszystkie te problemy w nadchodzącej wersji Androida i wymagamy, aby urządzenia z tą wersją spełniały te same standardy.
Co użyć zamiast tego
Dodawanie i edytowanie kontaktu: używanie intencji kontaktu
Gdy używasz tych intencji – ACTION_INSERT, ACTION_EDIT i ACTION_INSERT_OR_EDIT – system wykonuje najtrudniejsze zadania, prezentując przejrzysty, ustandaryzowany edytor kontaktów. Otwiera szybki formularz w formie półarkusza, w którym można dodawać nowe wpisy, lub umożliwia użytkownikowi łatwe wyszukiwanie i dodawanie informacji do istniejącego kontaktu. Użytkownicy mogą bez problemu rozwinąć ten widok do pełnoekranowego edytora, aby podać więcej szczegółów, a aplikacja nie musi mieć bezpośrednich uprawnień do zapisu. Poniżej znajdziesz wstępne makiety UX:
Ilustracja 1. Tworzenie nowego kontaktu *UX nie jest ostateczny*
Rysunek 2. Dodawanie informacji do istniejącego kontaktu *UX nie jest ostateczny*
Uwaga: różni producenci urządzeń mogą modyfikować interfejs użytkownika, aby dopasować go do stylu swojego systemu operacyjnego, ale działanie pozostanie takie samo.
Możesz jeszcze bardziej usprawnić proces tworzenia, przekazując wraz z intencją opcjonalne ładunki danych, czyli dodatki:
EXTRA_ACCOUNTsugeruje, na którym koncie zapisać kontakt, co jest przydatne, jeśli aplikacja synchronizuje kontakty. Ta funkcja była już dostępna, ale jej obsługa różniła się w zależności od urządzenia. Począwszy od nadchodzącej wersji Androida, obsługa będzie ustandaryzowana na wszystkich urządzeniach.EXTRA_PHOTO_URIprzekazuje zdjęcie, aby wstępnie wypełnić zdjęcie kontaktu. Edytor obsługuje uprawnienia do odczytu identyfikatora URI. Jest to nowa funkcja w nadchodzącej wersji Androida, która będzie obsługiwana w całym ekosystemie.
Przed: zapisywanie bezpośrednio za pomocą
// Requires android.permission.WRITE_CONTACTS fun saveContactDirectly(context: Context, name: String, phone: String, account: Account) { val ops = arrayListOf( ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, account.name) .build(), ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE ) .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name) .build(), ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) .withValue( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ) .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .build() ) context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops) }
| Po: otwarcie edytora kontaktów (nie są wymagane uprawnienia)
fun saveContactWithEditor( context: Context, name: String, phone: String, account: Account, photoUri: Uri ) { val intent = Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI).apply { putExtra(ContactsContract.Intents.Insert.NAME, name) putExtra(ContactsContract.Intents.Insert.PHONE, phone) // Suggest which account the contact is saved to putExtra(ContactsContract.Intents.Insert.EXTRA_ACCOUNT, account) // New in the upcoming Android release: pre-fill the contact photo putExtra(ContactsContract.Intents.Insert.EXTRA_PHOTO_URI, photoUri) clipData = ClipData.newRawUri("", photoUri) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } context.startActivity(intent) }
|
Przed: bezpośrednie aktualizowanie istniejącego kontaktu
// Requires android.permission.WRITE_CONTACTS fun addPhoneDirectly(context: Context, rawContactId: Long, phone: String) { val values = ContentValues().apply { put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId) put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) } context.contentResolver.insert(ContactsContract.Data.CONTENT_URI, values) } | Po: umożliwienie użytkownikowi wybrania kontaktu do zaktualizowania lub utworzenia nowego fun addPhoneWithEditor(context: Context, phone: String) { val intent = Intent(Intent.ACTION_INSERT_OR_EDIT).apply { type = ContactsContract.Contacts.CONTENT_ITEM_TYPE putExtra(ContactsContract.Intents.Insert.PHONE, phone) } context.startActivity(intent) } Jeśli wiesz już, który kontakt chcesz zaktualizować, użyj metody fun editKnownContact(context: Context, contactUri: Uri, phone: String) { val intent = Intent(Intent.ACTION_EDIT, contactUri).apply { putExtra(ContactsContract.Intents.Insert.PHONE, phone) } context.startActivity(intent) }
|
Wybieranie kontaktu: używanie selektora kontaktów
Jeśli chcesz tylko odczytywać kontakty wybrane przez użytkownika, użyj selektora kontaktów, który jest dostępny od Androida 17. Nie wymaga żadnych uprawnień.
Aplikacje do obsługi połączeń i komunikatory: korzystanie z katalogu osób
Niektóre aplikacje dodają do kontaktów działania „Zadzwoń przez…” lub „Wyślij wiadomość przez…”, aby użytkownicy mogli rozpocząć połączenie lub czat z poziomu aplikacji Telefon lub Kontakty. Jeśli Twoja aplikacja robi to obecnie przez zapisywanie dodatkowych wpisów w kontaktach użytkownika, przejdź na Katalog osób, który pojawi się w Androidzie QPR2 (IV kwartał 2026 r.). Jest to nowy katalog systemowy, w którym aplikacja publikuje informacje o tym, jak użytkownicy mogą się ze sobą kontaktować, bez edytowania kontaktów użytkownika.
Przykłady migracji aplikacji
Aby zobaczyć, jak te alternatywy działają w praktyce, zapoznaj się z kilkoma przykładami, jak różne typy aplikacji mogą podchodzić do dostępu do kontaktów:
| Przykładowy typ aplikacji (niewyłączny). | Zalecana ścieżka migracji |
| Aplikacje społecznościowe, do płatności P2P i wspólnych przejazdów | Jeśli aplikacja umożliwia użytkownikom znajdowanie znajomych, dzielenie rachunku lub udostępnianie stanu podróży, nie potrzebujesz dostępu do kontaktów. Używaj selektora kontaktów do jednorazowego wybierania kontaktów i uruchamiaj ACTION_INSERT z EXTRA_PHOTO_URI, gdy użytkownik kliknie „Zapisz w kontaktach” w profilu. |
| Skanery wizytówek i aplikacje do nawiązywania kontaktów podczas wydarzeń | Jeśli aplikacja skanuje identyfikator lub kod QR i zapisuje nowy kontakt albo dodaje służbowy numer telefonu do wpisu dotyczącego współpracownika, użyj ACTION_INSERT lub ACTION_INSERT_OR_EDIT. Ustandaryzowany edytor w formie połowy arkusza wstępnie wypełnia przeanalizowane pola (imię i nazwisko, firma, telefon, adres e-mail i zdjęcie), dzięki czemu użytkownik może je zweryfikować i zapisać jednym kliknięciem bez przyznawania uprawnień do działania w tle. |
| Aplikacje do połączeń VoIP i obsługi wiadomości | Zamiast prosić WRITE_CONTACTS o wstrzykiwanie niestandardowych wierszy „Zadzwoń do…” lub „Wyślij wiadomość do…” do książki adresowej użytkownika, opublikuj metadane dotyczące osiągalności w katalogu osób i użyj ACTION_INSERT, gdy użytkownicy dodają nowy kontakt z wątku czatu. |
| Aplikacje CRM i aplikacje do synchronizacji z chmurą dla firm | Jeśli aplikacja przeprowadza ciągłą, dwukierunkową synchronizację kontaktów w tle z kontem w chmurze lub kontem firmowym, gdzie wyświetlanie użytkownikowi interfejsu intencji dla każdego rekordu nie jest możliwe, aplikacja kwalifikuje się do zadeklarowania uprawnienia MANAGE_CONTACTS . |
Zmiany do sprawdzenia
- Niestandardowe typy danych nie są obsługiwane w edytorze. Jeśli przekażesz wiersze
Insert.DATAz typami MIME innymi niż standardowe typyContactsContract.CommonDataKinds, te typy MIME zostaną zignorowane przez edytor bez powiadomienia. SHOW_OR_CREATE_CONTACTnie jest obsługiwany przez edytor systemowy. Aplikacje do obsługi kontaktów, które są zainstalowane na urządzeniu, nadal mogą obsługiwać te dane. Aby zapewnić spójne działanie na różnych urządzeniach, użyjACTION_INSERT_OR_EDIT.- Domyślnie zapisywanie kończy się niepowodzeniem. Jeśli Twoja aplikacja będzie kierowana na nadchodzącą wersję Androida, każdy bezpośredni zapis bez
MANAGE_CONTACTSspowoduje błądSecurityException or permission denial. Sprawdź, czy tak jest.
Czy potrzebuję MANAGE_CONTACTS?
Raczej nie. Jeśli aplikacja zapisuje lub edytuje kontakty na prośbę użytkownika, powyższe intencje obejmują te działania bez konieczności uzyskiwania uprawnień i składania deklaracji w Konsoli Play.
MANAGE_CONTACTS jest przeznaczone dla aplikacji, których głównym celem jest zarządzanie kontaktami, gdy intencje nie wystarczają. Przykład:
| Twoja aplikacja… | Potrzebujesz MANAGE_CONTACTS? |
| Zapisuje kontakt z czatu, wizytówki lub zamówienia. | Nie,użyj ACTION_INSERT |
| Dodaje numer lub adres e-mail do istniejącego kontaktu. | Nie,użyj ACTION_INSERT_OR_EDIT lub ACTION_EDIT |
| Umożliwia użytkownikom wybieranie kontaktów, które chcą zaprosić, którym chcą coś udostępnić lub zapłacić. | Nie,użyj selektora kontaktów. |
| Dodaje do kontaktów działania związane z połączeniami lub wiadomościami. | Nie,użyj katalogu osób |
| ma własny ekran edycji kontaktów z logo marki. | Nie,sam niestandardowy interfejs nie wystarczy. |
| jest specjalną aplikacją do zarządzania kontaktami lub zastępującą dialer; | Prawdopodobnie tak |
| jest aplikacją do identyfikacji rozmówcy i ochrony przed spamem, która masowo aktualizuje wpisy w książce adresowej; | Prawdopodobnie tak |
| Synchronizuje kontakty z kontem firmowym lub kontem w chmurze w tle. | Prawdopodobnie tak |
| wykonuje zbiorcze tworzenie i przywracanie kopii zapasowej kontaktów lub przenoszenie danych z jednego telefonu na drugi. | Prawdopodobnie tak |
| ustawiać niestandardowe dzwonki dla poszczególnych kontaktów; | Prawdopodobnie tak |
Jak to działa:
MANAGE_CONTACTSto specjalne uprawnienie dostępu do aplikacji. Nie jest to okno środowiska wykonawczego. Użytkownicy mogą ją włączyć, wybierając Ustawienia > Specjalny dostęp do aplikacji > Zarządzaj kontaktami.
// Opens Settings > Apps > Special app access > Manage contacts val intent = Intent(Settings.ACTION_MANAGE_CONTACTS, Uri.fromParts("package", packageName, null)) context.startActivity(intent)
- Obejmuje odczytywanie, dodawanie, edytowanie i usuwanie kontaktów, kont oraz danych z katalogu osób. Nie musisz też prosić o
READ_CONTACTS. - Aby opublikować aplikację w Google Play z uprawnieniem
MANAGE_CONTACTS, prześlij w Konsoli Play deklarację wyjaśniającą, dlaczego intencje nie wystarczają do działania głównej funkcjonalności aplikacji.
Etapy migracji
- Znajdź zapisy kontaktów. Wyszukaj w kodzie ciągi
WRITE_CONTACTS,ContactsContract.RawContacts.CONTENT_URI,ContactsContract.Data.CONTENT_URIiapplyBatch(ContactsContract.AUTHORITY, …). - Zastąp każdy zapis wywołany przez użytkownika intencją:
ACTION_INSERTw przypadku nowych kontaktów orazACTION_EDITlubACTION_INSERT_OR_EDITw przypadku aktualizacji. - Używaj tylko standardowych typów danych w
Insert.DATA. Przenieś działania związane z połączeniami lub wiadomościami do katalogu osób. - Zastanów się, czy naprawdę potrzebujesz
MANAGE_CONTACTS, korzystając z tabeli powyżej. Jeśli tak, zaplanuj deklarację w Konsoli Play. - Usuń
WRITE_CONTACTSz pliku manifestu, gdy nie będzie już potrzebny w żadnej ścieżce kodu.
Oś czasu
| Kiedy | Skutki |
| 21 października 2026 r. | Google Play ogłasza zasady dotyczące MANAGE_CONTACTS |
| 2026 r. (Android 17, kwartalna wersja platformy 2) | Uprawnienie MANAGE_CONTACTS staje się dostępne |
| 2027 (nadchodząca wersja Androida) | Uprawnienie WRITE_CONTACTS nie przyznaje już dostępu do zapisu aplikacjom kierowanym na nadchodzącą wersję Androida. Intencje dotyczące kontaktów są ustandaryzowane na różnych urządzeniach |
| 2027 r., nie wcześniej niż nadchodząca wersja Androida | Konsola Play prosi aplikacje, które używają uprawnienia MANAGE_CONTACTS, o przesłanie deklaracji |
| 2027 r., nie wcześniej niż nadchodząca wersja Androida | Wymagana zgodność z zasadami Google Play |
Najczęstsze pytania
- Czy dotyczy to każdej aplikacji?
- Wycofanie
WRITE_CONTACTSdotyczy tylko aplikacji kierowanych na nadchodzącą wersję Androida i nowsze. Aplikacje kierowane na starsze wersje zachowają swoje obecne działanie, ale nowy, ustandaryzowany edytor kontaktów będzie dostępny we wszystkich aplikacjach działających w nowym systemie operacyjnym, niezależnie od docelowego pakietu SDK.
- Wycofanie
- Czy moja aplikacja może usuwać kontakty za pomocą intencji?
- No. There's no intent for deleting contacts. Użytkownicy usuwają kontakty w aplikacji Kontakty. Aplikacje z
MANAGE_CONTACTSmogą usuwać kontakty bezpośrednio.
- No. There's no intent for deleting contacts. Użytkownicy usuwają kontakty w aplikacji Kontakty. Aplikacje z
- Mam już własny ekran edycji kontaktów. Czy mogę go zachować?
- Tylko wtedy, gdy Twoja aplikacja kwalifikuje się do
MANAGE_CONTACTS. Chęć zachowania niestandardowego projektu nie jest wystarczającym powodem.
- Tylko wtedy, gdy Twoja aplikacja kwalifikuje się do
- Czy
MANAGE_CONTACTSzastępuje READ_CONTACTS?MANAGE_CONTACTSobejmuje dostęp do odczytu, więc nie musisz prosić o oba uprawnienia, ale wiele aplikacji kwalifikuje się doREAD_CONTACTS, mimo że nie muszą w ogóle modyfikować kontaktów. Te aplikacje mogą nadal prosić oREAD_CONTACTS.
- Co z użytkownikami starszych wersji Androida?
- Intencje kontaktów działają też w starszych wersjach i są obsługiwane przez aplikację Kontakty na urządzeniu. Większość aplikacji będzie działać prawidłowo na wszystkich urządzeniach korzystających z tych intencji. Jeśli w Twojej aplikacji występuje konkretny problem ze spójnością, który został rozwiązany tylko w najnowszych wersjach, możesz zachować uprawnienie
WRITE_CONTACTSw pliku manifestu z odpowiednim zakresem maxSdkVersion.
- Intencje kontaktów działają też w starszych wersjach i są obsługiwane przez aplikację Kontakty na urządzeniu. Większość aplikacji będzie działać prawidłowo na wszystkich urządzeniach korzystających z tych intencji. Jeśli w Twojej aplikacji występuje konkretny problem ze spójnością, który został rozwiązany tylko w najnowszych wersjach, możesz zachować uprawnienie
-
Wiadomości o usłudzePodczas Google I/O 2026 ogłosiliśmy, że Android przestaje być systemem operacyjnym, a staje się systemem opartym na AI. Pokazaliśmy też, jak można tworzyć inteligentne funkcje natywnie w systemie i wykorzystywać możliwości AI od Google w aplikacjach.
Jingyu Shi • Czas czytania: 2 min -
Wiadomości o usłudzeW tym roku na konferencji Google I/O nie tylko przedstawiamy zmiany, ale też pokazujemy fundamentalną zmianę w sposobie tworzenia aplikacji. Nasze najnowsze narzędzia zostały stworzone z myślą o erze agentów i zawierają funkcje, które zwiększają produktywność programistów aplikacji na Androida ORAZ możliwości agentów AI wdrażanych w bazie kodu.
Matthew Warner • Czas czytania: 8 min -
Wiadomości o usłudzeJak ogłosiliśmy dzisiaj podczas The Android Show, Android przekształca się z systemu operacyjnego w system inteligentny, co stwarza więcej możliwości interakcji z aplikacjami.
Matthew McCullough • Czas czytania: 4 min
Otrzymuj co tydzień najnowsze informacje o tworzeniu aplikacji na Androida na swoją skrzynkę odbiorczą.