Kontakty Omówienie: http://saigeethamn.blogspot.in/2011/05/contacts-api-20-and-above-android.html All data related to a contact is stored in this generic data table with each row telling what is the data it stores through its MIME type. So we could have a Phone.CONTENT_ITEM_TYPE as the MIME type of the data row, it contains Phone data. Similarly, if we have Email.CONTENT_ITEM_TYPE as the row’s MIME type, then it stores email data. Like this lot of data rows are associated with a single Raw Contact Więcej szczegółów: http://www.higherpass.com/Android/Tutorials/Working-With-Android-Contacts/ ----------------------------------------- Lista kontaktów 1. Tworzymy projekt aplikacji Android App (Xamarin) o nazwie Kontakty. Wybieramy szablon Blank App i Android 5.0 (Lollipop). Będziemy używać Contacts API 2.0. 2. Przechodzimy do pliku Resources/layout/activity_main.xml 3. Następnie modyfikujemy plik res/values/strings.xml Kontakty Settings Kontakty <--- Dodane Settings Kontakty 4. Do katalogu głównego dodajemy plik klasy Kontakt.cs zawierający klasę z na razie jedna statyczna metodą: using System; using System.Collections.Generic; using Android.Content; using Android.Database; using Android.Provider; namespace Kontakty { class Kontakt { //pozniej bedziemy czytali liste rekordów z większą ilością szczegółów public static List listaNazwWszystkichKontaktow(ContentResolver contentResolver) { List lista = new List(); ICursor cursor = contentResolver.Query(ContactsContract.Contacts.ContentUri, null, null, null, null); if (cursor.Count > 0) { while (cursor.MoveToNext()) { string nazwa = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.DisplayName)); string id = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.Id)); lista.Add("[" + id + "] " + nazwa); } } else { lista = null; } cursor.Close(); return lista; } } } 5. Mając taką metodę możemy zapełnić kontrolkę ListView łańcuchami z nazwami kontaktów. W tym celu w klasie MainActivity: using Android.App; using Android.OS; using Android.Support.V7.App; using Android.Runtime; using Android.Widget; using System.Collections.Generic; using Android.Content.PM; namespace Kontakty { [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] public class MainActivity : AppCompatActivity { private ListView listView; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.activity_main); showContacts(); } private void showContacts() { //dane dla listy List lista = Kontakt.ListaNazwWszystkichKontaktow(this.ContentResolver); if (lista == null) { TextView naglowek = FindViewById(Resource.Id.naglowek); naglowek.Text = "Brak zdefiniowanych kontaktów"; } ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, lista); // kontrolka listView = FindViewById(Resource.Id.listView); listView.Adapter = adapter; } } } 6. Uruchomienie aplikacji skończy się błędem. Aby odczytać listę kontaktów, aplikacja musi mieć odpowiednie uprawnienia. W ustawieniach należy dodać uprawnienie READ_CONTACTS (przez Properties/Android Manifest). Lista kontaktów może być pusta. Można utworzyć przykładowe kontakty korzystając z interfejsu androida, ale można też stworzyć kontakty z poziomu aplikacji (poniżej). 7. Od wersji Marshmallow należy pobrać uprawnienia dodatkowo w runtime: using Android.App; using Android.OS; using Android.Support.V7.App; using Android.Runtime; using Android.Widget; using System.Collections.Generic; using Android.Content.PM; namespace Kontakty { [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] public class MainActivity : AppCompatActivity { private ListView listView; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.activity_main); if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M && this.CheckSelfPermission(Android.Manifest.Permission.ReadContacts) != Permission.Granted) { this.RequestPermissions(new string[] { Android.Manifest.Permission.ReadContacts }, PERMISSIONS_REQUEST_READ_CONTACTS); //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method } else { // Android version is lesser than 6.0 or the permission is already granted. showContacts(); } } private void showContacts() { //dane dla listy List lista = Kontakt.ListaNazwWszystkichKontaktow(this.ContentResolver); if (lista == null) { TextView naglowek = FindViewById(Resource.Id.naglowek); naglowek.Text = "Brak zdefiniowanych kontaktów"; } ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, lista); // kontrolka listView = FindViewById(Resource.Id.listView); listView.Adapter = adapter; } private const int PERMISSIONS_REQUEST_READ_CONTACTS = 100; public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults) { base.OnRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS) { if (grantResults[0] == Permission.Granted) { // Permission is granted showContacts(); } else { Toast.MakeText(this, "Nie można wyświetlać kontaktów do momentu udzielenia zgody", ToastLength.Short).Show(); } } } } } --------------- Zapis nowego kontaktu do bazy danych i usunięcie wszystkich istniejących 8. Rozbudujmy klasę Kontakt z pliku Kontakt.cs czyniąc z niej klasę encji (nadal niekompletną): using System.Collections.Generic; using Android.Content; using Android.Database; using Android.Net; using Android.Provider; namespace Kontakty { class Kontakt { public string NazwaWyswietlana; public string TelefonKomorkowy; public string TelefonDomowy; public string TelefonWPracy; public string EmailWPracy; public string Firma; public string Tytul; //mozna uzupelnic m.in. o zdjecie public Kontakt( string nazwaWyswietlana, string telefonKomorkowy, string telefonDomowy, string telefonWPracy, string emailWPracy, string firma, string tytul) { this.NazwaWyswietlana = nazwaWyswietlana; this.TelefonKomorkowy = telefonKomorkowy; this.TelefonDomowy = telefonDomowy; this.TelefonWPracy = telefonWPracy; this.EmailWPracy = emailWPracy; this.Firma = firma; this.Tytul = tytul; } public static List ListaNazwWszystkichKontaktow(ContentResolver contentResolver) { List lista = new List(); ICursor cursor = contentResolver.Query(ContactsContract.Contacts.ContentUri, null, null, null, null); if (cursor.Count > 0) { while (cursor.MoveToNext()) { string nazwa = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.DisplayName)); string id = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.Id)); lista.Add("[" + id + "] " + nazwa); } } else { lista = null; } cursor.Close(); return lista; } public static void UsuńWszystkieKontakty(ContentResolver contentResolver) { ICursor cursor = contentResolver.Query(ContactsContract.Contacts.ContentUri, null, null, null, null); while (cursor.MoveToNext()) { string klucz = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.LookupKey)); Uri uri = Uri.WithAppendedPath(ContactsContract.Contacts.ContentLookupUri, klucz); contentResolver.Delete(uri, null, null); } cursor.Close(); } //Zrodlo: http://stackoverflow.com/questions/4744187/how-to-add-new-contacts-in-android private static void dodajNowyKontaktDoBazy(ContentResolver contentResolver, Kontakt kontakt) { List dodawanyKontakt = new List(); dodawanyKontakt.Add(ContentProviderOperation.NewInsert( ContactsContract.RawContacts.ContentUri) .WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountType, null) .WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountName, null) .Build()); if (kontakt.NazwaWyswietlana != null) { dodawanyKontakt.Add(ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri) .WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0) .WithValue(ContactsContract.Data.InterfaceConsts.Mimetype, ContactsContract.CommonDataKinds.StructuredName.ContentItemType) .WithValue(ContactsContract.CommonDataKinds.StructuredName.DisplayName, kontakt.NazwaWyswietlana) .Build()); } if (kontakt.TelefonKomorkowy != null) { dodawanyKontakt.Add(ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri) .WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0) .WithValue(ContactsContract.Data.InterfaceConsts.Mimetype, ContactsContract.CommonDataKinds.Phone.ContentItemType) .WithValue(ContactsContract.CommonDataKinds.Phone.Number, kontakt.TelefonKomorkowy) //.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.GetTypeLabelResource(PhoneDataKind.Mobile)) .WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom) .WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Label, "Mobile") .Build()); } if (kontakt.TelefonDomowy != null) { dodawanyKontakt.Add(ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri) .WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0) .WithValue(ContactsContract.Data.InterfaceConsts.Mimetype, ContactsContract.CommonDataKinds.Phone.ContentItemType) .WithValue(ContactsContract.CommonDataKinds.Phone.Number, kontakt.TelefonDomowy) //.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.GetTypeLabelResource(PhoneDataKind.Home)) .WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom) .WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Label, "Home") .Build()); } if (kontakt.TelefonWPracy != null) { dodawanyKontakt.Add(ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri) .WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0) .WithValue(ContactsContract.Data.InterfaceConsts.Mimetype, ContactsContract.CommonDataKinds.Phone.ContentItemType) .WithValue(ContactsContract.CommonDataKinds.Phone.Number, kontakt.TelefonWPracy) //.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.GetTypeLabelResource(PhoneDataKind.Work)) .WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom) .WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Label, "Work") .Build()); } if (kontakt.EmailWPracy != null) { dodawanyKontakt.Add(ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri) .WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0) .WithValue(ContactsContract.Data.InterfaceConsts.Mimetype, ContactsContract.CommonDataKinds.Email.ContentItemType) .WithValue(ContactsContract.CommonDataKinds.Email.InterfaceConsts.Data, kontakt.EmailWPracy) //.WithValue(ContactsContract.CommonDataKinds.Email.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Email.GetTypeLabelResource(EmailDataKind.Work)) .WithValue(ContactsContract.CommonDataKinds.Email.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom) .WithValue(ContactsContract.CommonDataKinds.Email.InterfaceConsts.Label, "Work") .Build()); } if (string.IsNullOrEmpty(kontakt.Firma) && string.IsNullOrEmpty(kontakt.Tytul)) { dodawanyKontakt.Add(ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri) .WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0) .WithValue(ContactsContract.Data.InterfaceConsts.Mimetype, ContactsContract.CommonDataKinds.Organization.ContentItemType) .WithValue(ContactsContract.CommonDataKinds.Organization.Company, kontakt.Firma) //.WithValue(ContactsContract.CommonDataKinds.Organization.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Organization.GetTypeLabelResource(OrganizationDataKind.Work)) .WithValue(ContactsContract.CommonDataKinds.Organization.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom) .WithValue(ContactsContract.CommonDataKinds.Organization.InterfaceConsts.Label, "Work") .WithValue(ContactsContract.CommonDataKinds.Organization.Title, kontakt.Tytul) //.WithValue(ContactsContract.CommonDataKinds.Organization.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Organization.GetTypeLabelResource(OrganizationDataKind.Work)) .WithValue(ContactsContract.CommonDataKinds.Organization.InterfaceConsts.Type, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom) .WithValue(ContactsContract.CommonDataKinds.Organization.InterfaceConsts.Label, "Work") .Build()); } //prosba do dostawcy kontaktaktow o utworzenie nowego kontaktu //try //{ contentResolver.ApplyBatch(ContactsContract.Authority, dodawanyKontakt); //return true; //} //catch (Exception e) //{ //e.printStackTrace(); //return false; //} } public void Zapisz(ContentResolver contentResolver) { dodajNowyKontaktDoBazy(contentResolver, this); } } } 9. W klasie aktywności dodajemy kod usuwający wszystkie istniejące kontakty i dodające dwa nowe oraz pobierający w runtime uprawnienie do zmiany kontaktów: using Android.App; using Android.OS; using Android.Support.V7.App; using Android.Runtime; using Android.Widget; using System.Collections.Generic; using Android.Content.PM; namespace Kontakty { [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] public class MainActivity : AppCompatActivity { private ListView listView; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.activity_main); if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M && this.CheckSelfPermission(Android.Manifest.Permission.WriteContacts) != Permission.Granted) { this.RequestPermissions(new string[] { Android.Manifest.Permission.WriteContacts }, PERMISSIONS_REQUEST_WRITE_CONTACTS); } else { addContacts(); } if (Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M && this.CheckSelfPermission(Android.Manifest.Permission.ReadContacts) != Permission.Granted) { this.RequestPermissions(new string[] { Android.Manifest.Permission.ReadContacts }, PERMISSIONS_REQUEST_READ_CONTACTS); //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method } else { // Android version is lesser than 6.0 or the permission is already granted. showContacts(); } } private void addContacts() { Kontakt.UsuńWszystkieKontakty(ContentResolver); try { new Kontakt( "Jacek Matulewski", "+48600123456", null, "+48(56)6113310", "jacek@fizyka.umk.pl", "UMK", "Dr").Zapisz(ContentResolver); new Kontakt( "Jan Kowalski", "+48600987654", "11111111", "+48(56)1111111", "jankowalski@firma.pl", "AAAAA", null).Zapisz(ContentResolver); } catch (Java.Lang.Exception exc) { Toast.MakeText(ApplicationContext, "Nie udało się dodać kontaktu (" + exc.Message + ")", ToastLength.Long).Show(); } } private void showContacts() { //dane dla listy List lista = Kontakt.ListaNazwWszystkichKontaktow(this.ContentResolver); if (lista == null) { TextView naglowek = FindViewById(Resource.Id.naglowek); naglowek.Text = "Brak zdefiniowanych kontaktów"; return; } ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, lista); // kontrolka listView = FindViewById(Resource.Id.listView); listView.Adapter = adapter; } private const int PERMISSIONS_REQUEST_READ_CONTACTS = 100; private const int PERMISSIONS_REQUEST_WRITE_CONTACTS = 101; public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults) { base.OnRequestPermissionsResult(requestCode, permissions, grantResults); switch(requestCode) { case PERMISSIONS_REQUEST_READ_CONTACTS: if (grantResults[0] == Permission.Granted) { // Permission is granted showContacts(); } else { Toast.MakeText(this, "Nie można wyświetlać kontaktów do momentu udzielenia zgody", ToastLength.Short).Show(); } break; case PERMISSIONS_REQUEST_WRITE_CONTACTS: if (grantResults[0] == Permission.Granted) { addContacts(); showContacts(); } else { Toast.MakeText(this, "Nie można dodawać kontaktów do momentu udzielenia zgody", ToastLength.Short).Show(); } break; } } } } 10. Do tego potrzebne jest uprawnienie, które dodajemy do manifestu: WRITE_CONTACTS ---------------------- Odczyt kompletnych kontaktów 11. Do klasy Kontakt dodajmy jeszcze jedną statyczną metodę pozwalającą na odczyt pełnej listy kontaktów oraz statyczną metodę wspomagającą tworzenie instancji kontaktów na podstawie danych z rekordu bazy danych: namespace Kontakty { class Kontakt { ... private static Kontakt odczytajKontaktZBazyDanych(ContentResolver contentResolver, ICursor cursor) { string id = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.Id)); string nazwaWyświetlana = cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.DisplayName)); string telefonKomórkowy = "", telefonDomowy = "", telefonWPracy = "", emailWPracy = "", firma = "", tytuł = ""; if (int.Parse(cursor.GetString(cursor.GetColumnIndex(ContactsContract.Contacts.InterfaceConsts.HasPhoneNumber))) > 0) { ICursor numeryTelefonow = contentResolver.Query(ContactsContract.CommonDataKinds.Phone.ContentUri, null, ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + " = " + id, null, null); while (numeryTelefonow.MoveToNext()) { string numer = numeryTelefonow.GetString(numeryTelefonow.GetColumnIndex(ContactsContract.CommonDataKinds.Phone.Number)); string typNumeru = numeryTelefonow.GetString(numeryTelefonow.GetColumnIndex(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Label)); switch (typNumeru) { case "Mobile": telefonKomórkowy = numer; break; case "Home": telefonDomowy = numer; break; case "Work": telefonWPracy = numer; break; } } numeryTelefonow.Close(); } ICursor adresyEmail = contentResolver.Query(ContactsContract.CommonDataKinds.Email.ContentUri, null, ContactsContract.CommonDataKinds.Email.InterfaceConsts.ContactId + " = " + id, null, null); while (adresyEmail.MoveToNext()) { string adresEmail = adresyEmail.GetString(adresyEmail.GetColumnIndex(ContactsContract.CommonDataKinds.Email.InterfaceConsts.Data)); string typAdresu = adresyEmail.GetString(adresyEmail.GetColumnIndex(ContactsContract.CommonDataKinds.Email.InterfaceConsts.Label)); if (typAdresu == "Work") { emailWPracy = adresEmail; break; //przerwanie petli while } } adresyEmail.Close(); //organizacja string where = ContactsContract.Data.InterfaceConsts.ContactId + " = ? AND " + ContactsContract.Data.InterfaceConsts.Mimetype + " = ?"; string[] whereParams = new string[] { id, ContactsContract.CommonDataKinds.Organization.ContentItemType }; ICursor organizacje = contentResolver.Query(ContactsContract.Data.ContentUri, null, where, whereParams, null); if (organizacje.MoveToFirst()) { firma = organizacje.GetString(organizacje.GetColumnIndex(ContactsContract.CommonDataKinds.Organization.InterfaceConsts.Data)); tytuł = organizacje.GetString(organizacje.GetColumnIndex(ContactsContract.CommonDataKinds.Organization.Title)); } organizacje.Close(); return new Kontakt(nazwaWyświetlana, telefonKomórkowy, telefonDomowy, telefonWPracy, emailWPracy, firma, tytuł); } public static List ListaWszystkichKontaktow(ContentResolver contentResolver) { List lista = new List(); ICursor cursor = contentResolver.Query(ContactsContract.Contacts.ContentUri, null, null, null, null); if (cursor.Count > 0) { while (cursor.MoveToNext()) { Kontakt kontakt = odczytajKontaktZBazyDanych(contentResolver, cursor); lista.Add(kontakt); } } else { lista = null; } return lista; } public static List ListaOpisowWszystkichKontaktow(ContentResolver contentResolver) { List listaKontaktow = Kontakt.ListaWszystkichKontaktow(contentResolver); List lista = new List(); foreach (Kontakt kontakt in listaKontaktow) { string opis = kontakt.Tytul + " " + kontakt.NazwaWyswietlana + "\ntel. kom.:" + kontakt.TelefonKomorkowy + "\ne-mail:" + kontakt.EmailWPracy; lista.Add(opis.Trim()); } return lista; } } } 12. Metoda ListaOpisowWszystkichKontaktow służy jedynie do testowania metody ListaWszystkichKontaktow. Korzystając z tej nowej statycznej metody Kontakt.ListaOpisowWszystkichKontaktow wyświetlmy w liście więcej informacji o kontaktach. Wystarczy podmienić metodę ListaOpisowNazwKontaktow: public class MainActivity extends Activity { private void showContacts() { //dane dla listy //List lista = Kontakt.ListaNazwWszystkichKontaktow(this.ContentResolver); List lista = Kontakt.ListaOpisowWszystkichKontaktow(this.ContentResolver); <------------ if (lista == null) { TextView naglowek = FindViewById(Resource.Id.naglowek); naglowek.Text = "Brak zdefiniowanych kontaktów"; return; } ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, lista); // kontrolka listView = FindViewById(Resource.Id.listView); listView.Adapter = adapter; } ---------------------- Użycie danych z kontaktów do inicjacji połączenia wychodzącego 13. Zaczniemy od przygotowania menu podręcznego inicjowanego dłuższym przytrzymaniem pozycji w liście. W metodzie MainActivity.showContacts dodajemy: private void showContacts() { //dane dla listy //List lista = Kontakt.ListaNazwWszystkichKontaktow(this.ContentResolver); List lista = Kontakt.ListaOpisowWszystkichKontaktow(this.ContentResolver); if (lista == null) { TextView naglowek = FindViewById(Resource.Id.naglowek); naglowek.Text = "Brak zdefiniowanych kontaktów"; return; } ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, lista); // kontrolka listView = FindViewById(Resource.Id.listView); listView.Adapter = adapter; List listaKontaktów = Kontakt.ListaWszystkichKontaktow(ContentResolver); <------------------------ listView.ItemLongClick += (object sender, AdapterView.ItemLongClickEventArgs e) => { Kontakt kontakt = listaKontaktów[e.Position]; Android.App.AlertDialog.Builder adb = new Android.App.AlertDialog.Builder(e.Parent.Context); adb.SetTitle(kontakt.NazwaWyswietlana); string[] etykiety = { "Zadzwoń (tel. kom.)", "Wyślij SMS", "Napisz e-mail", "Anuluj" }; adb.SetItems( etykiety, (object _sender, Android.Content.DialogClickEventArgs _e) => { switch (_e.Which) { case 0: break; case 1: break; case 2: break; default: case 3: break; } }); Android.App.AlertDialog ad = adb.Create(); ad.Show(); }; } 14. Wystarczy teraz tylko uzupełnić instrukcję switch case 0 o odpowiednią intencję: [To jako zadanie do samodzielnego wykonania!!!] switch (_e.Which) { case 0: Intent i = new Intent(Intent.ActionCall); i.SetData(Android.Net.Uri.Parse("tel:" + kontakt.TelefonKomorkowy)); //Finish(); StartActivity(i); break; Uwaga! Przed uruchomieniem dodajemy do manifestu uprawnienie do dzwonienia (CALL_PHONE). W nowszych systemach (Android 8.0 Oreo) należy to uprawnienie pobrać też w runtime (na wzór uprawnień do czytania kontaktów w tym samym projekcie). --------------------------- [Dalsze też jako zadania] Wysyłanie SMSów 15. Można to zrobić na dwa sposoby. Albo, tak jak w przypadku inicjacji połączeń użyć systemowej aktywności, albo skorzystać z niskopoziomowego API android.telephony: Uwaga! Pierwsza wersja nie wymaga specjalnych uprawnień, ponieważ pojawia się okno z treścią SMS i przyciskiem do wysłania switch (_e.Which) { case 0: { Intent i = new Intent(Intent.ActionCall); i.SetData(Android.Net.Uri.Parse("tel:" + kontakt.TelefonKomorkowy)); //Finish(); StartActivity(i); } break; case 1: { string tekst = "Przykładowa treść"; Intent i = new Intent(Intent.ActionSendto, Android.Net.Uri.Parse("smsto:" + kontakt.TelefonKomorkowy)); i.PutExtra("sms_body", tekst); StartActivity(i); } break; /* //Java SmsManager sms = SmsManager.getDefault(); PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0, new Intent(getBaseContext(),KontaktyActivity.class), 0); sms.sendTextMessage(kontakt.telefonKomorkowy, null, tekst, null, null); Toast.makeText(getBaseContext(), "Wyslanie SMSa powiodło się", Toast.LENGTH_LONG).show(); */ W tym drugim (zakomentowanym) przypadku potrzebne jest uprawnienie: --------------------------- Wysyłanie listów e-mail 16. W przypadku listów e-mail dwie wariacje metody (plain i z formatowaniem): case 2: { string tekst = "Przykładowa treść"; Intent i = new Intent(Intent.ActionSend); i.SetType("message/rfc822"); i.PutExtra(Intent.ExtraEmail, new string[] { kontakt.EmailWPracy }); //tu moze byc wielu odbiorcow i.PutExtra(Intent.ExtraSubject, "Temat listu"); i.PutExtra(Intent.ExtraText, tekst); try { StartActivity(Intent.CreateChooser(i, "Wyślij e-mail...")); } catch (Android.Content.ActivityNotFoundException) { Toast.MakeText(this, "Brak zainstalowanych aplikacji do wysyłania listów e-mail", ToastLength.Short).Show(); } } break; /* //Java Intent intencja = new Intent(Intent.ACTION_SENDTO); // it's not ACTION_SEND intencja.setType("text/plain"); intencja.putExtra(Intent.EXTRA_SUBJECT, "Temat listu"); intencja.putExtra(Intent.EXTRA_TEXT, tekst); intencja.setData(Uri.parse("mailto:"+kontakt.emailWPracy)); // or just "mailto:" for blank intencja.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // this will make such that when user returns to your app, your app is displayed, instead of the email app. startActivity(intencja); */ } break;