如何使用 Xamarin(Android) 向联系人添加 VCard?

How can I add a VCard to contacts with Xamarin(Android)?

1.With这个方法我可以把Vcard传给联系人,但是这个方法已经过时了,我找不到把VCard/网站添加到联系人/网站的方法。如何编写当前添加Vcard到联系人的方法?

public void SaveContacts(
    string name, string number, string email, string
    company, string jobtitle, string postal, string website)
{
    var activity = Forms.Context as Activity;
    var intent = new Intent(Intent.ActionInsert);
    intent.SetType(ContactsContract.Contacts.ContentType);
    intent.PutExtra(ContactsContract.Intents.Insert.Name, name);
    intent.PutExtra(ContactsContract.Intents.Insert.Phone, number);
    intent.PutExtra(ContactsContract.Intents.Insert.Email, email);
    intent.PutExtra(ContactsContract.Intents.Insert.Company, company);
    intent.PutExtra(ContactsContract.Intents.Insert.JobTitle, jobtitle);
    intent.PutExtra(ContactsContract.Intents.Insert.Postal, postal);
    intent.PutExtra(ContactsContract.Intents.Insert.Notes, website);

    activity.StartActivity(intent);
    Toast.MakeText(activity, "ContactSaved", ToastLength.Short).Show();
}

您可以参考下面的代码,可以在android中添加多个phone号码的联系人。它对我有用。

 public class MainActivity : AppCompatActivity
    {
        public  string TAG
        {
            get
            {
                return "MainActivity";
            }
        }
        static readonly int REQUEST_CONTACTS = 1;

        static string[] PERMISSIONS_CONTACT = {
            Manifest.Permission.ReadContacts,
            Manifest.Permission.WriteContacts
        };

        Button button;

        View  layout;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);

            layout = FindViewById(Resource.Id.root_layout);

        }

        public void NewContact(ref List<ContentProviderOperation> ops, string displayName, string Number1, string Number2, string Number3, string Number4)
        {
            ContentProviderOperation.Builder builder =
                ContentProviderOperation.NewInsert(ContactsContract.RawContacts.ContentUri);
            builder.WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountType, null);
            builder.WithValue(ContactsContract.RawContacts.InterfaceConsts.AccountName, null);
            ops.Add(builder.Build());

            //Name  
            builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
            builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
            builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                              ContactsContract.CommonDataKinds.StructuredName.ContentItemType);
            builder.WithValue(ContactsContract.CommonDataKinds.StructuredName.DisplayName, displayName);
            //builder.WithValue(ContactsContract.CommonDataKinds.StructuredName.GivenName, firstName);  
            ops.Add(builder.Build());

            //Number1  
            builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
            builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
            builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                              ContactsContract.CommonDataKinds.Phone.ContentItemType);
            builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, Number1);
            builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
                              ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
            builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Data2, (int)PhoneDataKind.Mobile);

            ops.Add(builder.Build());
            //Number2  
            if (!string.IsNullOrEmpty(Number2))
            {
                builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
                builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
                builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                                  ContactsContract.CommonDataKinds.Phone.ContentItemType);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, Number2);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
                                  ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Data2, (int)PhoneDataKind.Mobile);
                ops.Add(builder.Build());
            }

            if (!string.IsNullOrEmpty(Number3))
            {
                builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
                builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
                builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                                  ContactsContract.CommonDataKinds.Phone.ContentItemType);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, Number3);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
                                  ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Data2, (int)PhoneDataKind.Mobile);
                ops.Add(builder.Build());
            }

            if (!string.IsNullOrEmpty(Number4))
            {
                builder = ContentProviderOperation.NewInsert(ContactsContract.Data.ContentUri);
                builder.WithValueBackReference(ContactsContract.Data.InterfaceConsts.RawContactId, 0);
                builder.WithValue(ContactsContract.Data.InterfaceConsts.Mimetype,
                                  ContactsContract.CommonDataKinds.Phone.ContentItemType);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.Number, Number4);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Type,
                                  ContactsContract.CommonDataKinds.Phone.InterfaceConsts.TypeCustom);
                builder.WithValue(ContactsContract.CommonDataKinds.Phone.InterfaceConsts.Data2, (int)PhoneDataKind.Mobile);
                ops.Add(builder.Build());
            }

        }

        /*
        public void SaveContacts(string filename)
        {
            var documentsPath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads);
            var filePath = Path.Combine(documentsPath.AbsolutePath, filename);
            var fileContent = File.ReadAllLines(filePath);

            List<ContentProviderOperation> ops = new List<ContentProviderOperation>();

            foreach (var strLine in fileContent)
            {
                if (string.IsNullOrEmpty(strLine))
                    continue;
                var array = strLine.Split(new string[] { "\t", ":" }, StringSplitOptions.RemoveEmptyEntries);

               // NewContact(...);

                //Add the new contact  
                ContentProviderResult[] res;
                res = ContentResolver.ApplyBatch(ContactsContract.Authority, ops);
                ops.Clear();
            }
        }

        */
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
        {
             if (requestCode == REQUEST_CONTACTS)
            {
                Log.Info(TAG, "Received response for contact permissions request.");

                // We have requested multiple permissions for contacts, so all of them need to be
                // checked.
                if (PermissionUtil.VerifyPermissions(grantResults))
                {
                    // All required permissions have been granted, display contacts fragment.
                    Snackbar.Make(layout, Resource.String.permission_available_contacts, Snackbar.LengthShort).Show();

                    // save contact
                    saveContact();
                }
                else
                {
                    Log.Info(TAG, "Contacts permissions were NOT granted.");
                    Snackbar.Make(layout, Resource.String.permissions_not_granted, Snackbar.LengthShort).Show();
                }

            }
            else
            {
                base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }


        [Export]
        public void SaveContacts(View v)
        {
            Log.Info(TAG, "Show contacts button pressed. Checking permissions.");

            // Verify that all required contact permissions have been granted.
            if (ActivityCompat.CheckSelfPermission(this, Manifest.Permission.ReadContacts) != (int)Permission.Granted
                || ActivityCompat.CheckSelfPermission(this, Manifest.Permission.WriteContacts) != (int)Permission.Granted)
            {
                // Contacts permissions have not been granted.
                Log.Info(TAG, "Contact permissions has NOT been granted. Requesting permissions.");
                RequestContactsPermissions();
            }
            else
            {
                // Contact permissions have been granted. Show the contacts fragment.
                Log.Info(TAG, "Contact permissions have already been granted. Displaying contact details.");

                //Add the new contact

                saveContact();
            }
        }


        void RequestContactsPermissions()
        {
            if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.ReadContacts)
                || ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.WriteContacts))
            {

                // Provide an additional rationale to the user if the permission was not granted
                // and the user would benefit from additional context for the use of the permission.
                // For example, if the request has been denied previously.
                Log.Info(TAG, "Displaying contacts permission rationale to provide additional context.");

                // Display a SnackBar with an explanation and a button to trigger the request.
                Snackbar.Make(layout, Resource.String.permission_contacts_rationale,
                    Snackbar.LengthIndefinite).SetAction(Resource.String.ok, new Action<View>(delegate (View obj) {
                        ActivityCompat.RequestPermissions(this, PERMISSIONS_CONTACT, REQUEST_CONTACTS);
                    })).Show();

            }
            else
            {
                // Contact permissions have not been granted yet. Request them directly.
                ActivityCompat.RequestPermissions(this, PERMISSIONS_CONTACT, REQUEST_CONTACTS);
            }
        }


        public void saveContact() {
            List<ContentProviderOperation> ops = new List<ContentProviderOperation>();
            NewContact(ref ops, "test", "1234", "2234", "3234", "4234");

            //Add the new contact
            ContentProviderResult[] res;
            try
            {
                res = ContentResolver.ApplyBatch(ContactsContract.Authority, ops);
                ops.Clear();//Add this line   
                Toast.MakeText(this, "contact saved !", ToastLength.Short).Show();
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine("**************-----------> : " + e.Message);
                Toast.MakeText(this, "contact not saved_message !", ToastLength.Long).Show();
            }
        }
    }

class PermissionUtil

public abstract  class PermissionUtil
{
    public static bool VerifyPermissions(Permission[] grantResults)
    {
        // At least one result must be checked.
        if (grantResults.Length < 1)
            return false;

        // Verify that each required permission has been granted, otherwise return false.
        foreach (Permission result in grantResults)
        {
            if (result != Permission.Granted)
            {
                return false;
            }
        }
        return true;
    }
}

布局activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
     android:id="@+id/root_layout"
    >

    <Button
        android:id="@+id/saveBtn"
        android:onClick="SaveContacts"
        android:text="save"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

注:

1.Rembember 在清单中添加以下权限:

<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />

针对 Android 6.0 的应用程序必须始终执行运行时权限检查。

更多详情,请查看:https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/permissions?tabs=windows

2.add 参考 Mono.Android.Export;

3.You 可以参考官方示例:https://github.com/xamarin/monodroid-samples/tree/master/android-m/RuntimePermissions .

1.I现在找到了添加运行时权限的方法:

      public async Task GetContactAsync()
    {
        var status = await CheckAndRequestPermissionAsync(new Permissions.ContactsWrite());
        if (status != PermissionStatus.Granted)
        {
            await DisplayAlert("Permission for Contacts denied.", "The last time you refused the authorization to access the Contacts.Give this app the authorization for your Contacts to add Contacts directly via a QR-Code.", "OK.");
            Navigation.RemovePage(this);
            return;
        }

        //Add vcard to contacts
        SaveContacts(vCardName, vCardTel, vCardEmail, vCardORG, vCardTitle, vCardAdress, vCardURL);
        Navigation.RemovePage(this);
    }

    public async Task<PermissionStatus> CheckAndRequestPermissionAsync<T>(T permission)
                where T : BasePermission
    {
        var status = await permission.CheckStatusAsync();
        if (status != PermissionStatus.Granted)
        {
            status = await permission.RequestAsync();
        }

        return status;
    }