From 79995b210a0a1b0d40bd76dc7543aa022e924bd2 Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Wed, 13 Sep 2023 04:05:05 +0200 Subject: [PATCH] Feature: Export contact information to address book --- .../mainFragments/MainInfoFragment.java | 2 +- .../mainFragments/PersonFragment.java | 51 +++++++++++++++ .../java/eu/jonahbauer/qed/model/Person.java | 1 + .../java/eu/jonahbauer/qed/util/Actions.java | 65 +++++++++++++++++++ app/src/main/res/menu/menu_export_contact.xml | 11 ++++ app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 7 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/menu/menu_export_contact.xml diff --git a/app/src/main/java/eu/jonahbauer/qed/activities/mainFragments/MainInfoFragment.java b/app/src/main/java/eu/jonahbauer/qed/activities/mainFragments/MainInfoFragment.java index bea54e6..d1c7768 100644 --- a/app/src/main/java/eu/jonahbauer/qed/activities/mainFragments/MainInfoFragment.java +++ b/app/src/main/java/eu/jonahbauer/qed/activities/mainFragments/MainInfoFragment.java @@ -41,7 +41,7 @@ public final View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewG } @Override - public final void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { postponeEnterTransition(200, TimeUnit.MILLISECONDS); var manager = getChildFragmentManager(); diff --git a/app/src/main/java/eu/jonahbauer/qed/activities/mainFragments/PersonFragment.java b/app/src/main/java/eu/jonahbauer/qed/activities/mainFragments/PersonFragment.java index defb003..0fc8571 100644 --- a/app/src/main/java/eu/jonahbauer/qed/activities/mainFragments/PersonFragment.java +++ b/app/src/main/java/eu/jonahbauer/qed/activities/mainFragments/PersonFragment.java @@ -1,14 +1,28 @@ package eu.jonahbauer.qed.activities.mainFragments; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; + import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.MenuProvider; +import androidx.lifecycle.Lifecycle; + +import java.util.function.Supplier; + import eu.jonahbauer.qed.R; import eu.jonahbauer.qed.activities.sheets.InfoFragment; import eu.jonahbauer.qed.activities.sheets.person.PersonInfoFragment; import eu.jonahbauer.qed.model.Person; import eu.jonahbauer.qed.model.viewmodel.InfoViewModel; import eu.jonahbauer.qed.model.viewmodel.PersonViewModel; +import eu.jonahbauer.qed.util.Actions; import eu.jonahbauer.qed.util.Themes; import eu.jonahbauer.qed.util.ViewUtils; +import lombok.RequiredArgsConstructor; public class PersonFragment extends MainInfoFragment { @@ -24,8 +38,24 @@ public void onCreateViewModel() { mPersonViewModel.load(person); setColor(Themes.colorful(requireContext(), person.getId())); + + + } + + @Override + public final void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + PersonFragmentArgs args = PersonFragmentArgs.fromBundle(getArguments()); + Person person = args.getPerson(); + if (person != null) { + var menuProvider = new ExportContactMenuProvider(person); + requireActivity().addMenuProvider(menuProvider, getViewLifecycleOwner(), Lifecycle.State.RESUMED); + } } + + @Override public @NonNull InfoFragment createFragment() { return PersonInfoFragment.newInstance(); @@ -35,4 +65,25 @@ public void onCreateViewModel() { public @NonNull InfoViewModel getInfoViewModel() { return mPersonViewModel; } + + @RequiredArgsConstructor + private class ExportContactMenuProvider implements MenuProvider { + + @NonNull + private final Person person; + + @Override + public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) { + menuInflater.inflate(R.menu.menu_export_contact, menu); + } + + @Override + public boolean onMenuItemSelected(@NonNull MenuItem menuItem) { + if (menuItem.getItemId() == R.id.export_contact) { + Actions.exportToAddressBook(getContext(), person); + return true; + } + return false; + } + } } diff --git a/app/src/main/java/eu/jonahbauer/qed/model/Person.java b/app/src/main/java/eu/jonahbauer/qed/model/Person.java index 3a529cc..c6fb31e 100644 --- a/app/src/main/java/eu/jonahbauer/qed/model/Person.java +++ b/app/src/main/java/eu/jonahbauer/qed/model/Person.java @@ -73,6 +73,7 @@ public class Person implements Parcelable { private Instant loaded; // Pair of type and number/name + @NonNull private final Set> contacts = new LinkedHashSet<>(); private final Set addresses = new LinkedHashSet<>(); private final Set events = new ObjectLinkedOpenCustomHashSet<>(Registration.STRATEGY_ID); diff --git a/app/src/main/java/eu/jonahbauer/qed/util/Actions.java b/app/src/main/java/eu/jonahbauer/qed/util/Actions.java index 1bddf1d..6f4b332 100644 --- a/app/src/main/java/eu/jonahbauer/qed/util/Actions.java +++ b/app/src/main/java/eu/jonahbauer/qed/util/Actions.java @@ -6,10 +6,12 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.provider.CalendarContract; +import android.provider.ContactsContract; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.util.Pair; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; @@ -27,6 +29,8 @@ import java.time.LocalTime; import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.LinkedHashSet; import lombok.experimental.UtilityClass; @@ -94,6 +98,67 @@ public static boolean recordToCalendar(@NonNull Context context, @NonNull Event return tryStartActivity(context, intent); } + /** + * Launches an {@link Intent} to {@linkplain Intent#ACTION_INSERT insert} the given person into the contact book. + * The following attributes are included: + *
    + *
  • the {@linkplain Person::getFullName full name},
  • + *
  • the {@linkplain Person::getPhone phone number},
  • + *
  • the {@linkplain Person::getEmail mail address}.
  • + *
+ */ + public static boolean exportToAddressBook(@NonNull Context context, @NonNull Person person) { + Intent intent = new Intent(Intent.ACTION_INSERT) + .setType(ContactsContract.Contacts.CONTENT_TYPE) + .putExtra(ContactsContract.Intents.Insert.NAME, person.getFullName()) + .putExtra(ContactsContract.Intents.Insert.NOTES, "QED"); + if(person.getEmail() != null) + intent.putExtra(ContactsContract.Intents.Insert.EMAIL, person.getEmail()); + var contacts = person.getContacts(); + var data = new ArrayList(); + var numPhones = 0; + for (var contact : contacts) { + switch (contact.first.toLowerCase()) { + case "daheim": + case "mobil": + case "phone": + case "telefon": + case "festnetz": + if(numPhones > 2) break; + String phoneType, phone; + switch(numPhones){ + case 0: + phone = ContactsContract.Intents.Insert.PHONE; + phoneType = ContactsContract.Intents.Insert.PHONE_TYPE; + break; + case 1: + phone = ContactsContract.Intents.Insert.SECONDARY_PHONE; + phoneType = ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE; + break; + default: + phone = ContactsContract.Intents.Insert.TERTIARY_PHONE; + phoneType = ContactsContract.Intents.Insert.TERTIARY_PHONE; + break; + }; + intent.putExtra(phoneType, contact.first); + intent.putExtra(phone, contact.second); + numPhones++; + break; + default: + var row = new ContentValues(); + row.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE); + row.put(ContactsContract.CommonDataKinds.Im.DATA, contact.second); + row.put(ContactsContract.CommonDataKinds.Im.PROTOCOL, ContactsContract.CommonDataKinds.Im.PROTOCOL_CUSTOM); + row.put(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL, contact.first); + data.add(row); + break; + } + } + intent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, data); + + return tryStartActivity(context, intent); + } + /** * Launches an {@link Intent} to {@linkplain Intent#ACTION_DIAL dial} {@code tel:${phoneNumber}}. * @return {@code true} when a suitable activity was found and started diff --git a/app/src/main/res/menu/menu_export_contact.xml b/app/src/main/res/menu/menu_export_contact.xml new file mode 100644 index 0000000..c0b69ec --- /dev/null +++ b/app/src/main/res/menu/menu_export_contact.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b558668..8a9e71e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -14,6 +14,7 @@ %,d Treffer Details Öffne im Browser + Kontakt speichern %s - %s Aktualisieren Erneut versuchen diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 79501e3..d020b40 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,6 +15,7 @@ %,d Hits Details Open in browser + Export contact %s - %s Refresh Retry