Android Question How to save a contact with a QRCode VCard

zed

Active Member
Licensed User
Hi all
I created a QRCode application.
I use "ZXingLib by icefairy333 - modified by Johan Schoeman" library to scan the QRCode. Everything works fine.
To create the QRCode, I use "[B4X] QRGenerator - Cross platform QR code generator". Everything works fine.
There is no problem to create a QRCode VCard by following this example "QR Code Vcard".

The problem is how do I save a contact with a QRCode VCard.
The example shows how to create the VCard, but nothing more. If "@james_sgp" can explain how he does it, that would be great.

A request has already been made, "How to open contact intend to add new from vcard" but there was no response.

Thank you so much
 

drgottjr

Expert
Licensed User
Longtime User
you need to parse the vcard and then add a new contact.

there is a library called ez-vcard. you might be able to use
it directly (via javaobject). or you need to wrap it for more
direct use in b4a.

then, to follow google's preferred method, you add the data
to your contacts with an intent. you may also be able to
access android's contacts provider and speak to it.
accessing contacts directly these days may be problematic.

technically, parsing the scanned vcard is simple enough;
it's just roughly formatted text. but there are many, many
fields. working with ez-vcard might make parsing less
error-prone. but with only a couple fields, you could do
it by hand in b4a. if you intend using your app to accept
vcards from anyone, then you need to be able to deal with
all the mandatory and optional fields.

once you have the various populated fields, you include
them in the intent as extras. you start the device's contacts
activity and add the new contact.

i think there is at least 1 contacts utility on the forum. how
up-to-date it is i cannot say. in any case, assuming it
is useful, you still need to have parsed the vcard you
scanned from a qr code.

i took a quick look at ez-vcard. as a standalone .jar, it would parse
vcard for you (i tried it), but it requires another package, which has to be
built. all doable, but a little messy if you're just looking for a
complete parser ready to go.
 
Last edited:
Upvote 0

JohnC

Expert
Licensed User
Longtime User
"The problem is how do I save a contact with a QRCode VCard."

I am a little confused with your question because if you create the qrcode properly, then when a user scans that qrcode, their device should automatically prompt the user to add that contact to their contact list.

For example, if you scan the qrcode in the attached image in post #4:


It should automatically prompt you to save that contact into your device.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
op seems to have scanned the tag (presumably correctly
formatted as vcard), but nothing appears to have been triggered.
if his app is in foreground, his scanner runs, and unless it has
been programmed to parse and add the contact, i don't think
it happens. if his scanner is not running (or is in background),
system might do as you suggest. that's what happens with qr
codes. if you have no scanning apps, android will handle qr codes
"automatically" if you point your camera at one. it will offer to
open a url, and it may handle contacts, but once you have your own
app running, the data in the qr code have to be handled in some way
by your scanning app. if you know how to add a contact, you can do
that after you parse the data.
 
Last edited:
Upvote 0

zed

Active Member
Licensed User
I think my application formats the QRCode VCard correctly. I followed the information of this site .
The logs show the VCard encoding correctly. But nothing happens.
I thought a VCard would automatically support android system and add the contact.
As @drgottjr said I definitely have to decode the VCard and save the contact with INTENT.
But INTENT what? INTENTION TO CONTACT?
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
I think my application formats the QRCode VCard correctly. I followed the information of this site .
The logs show the VCard encoding correctly. But nothing happens.
I thought a VCard would automatically support android system and add the contact.
As @drgottjr said I definitely have to decode the VCard and save the contact with INTENT.
But INTENT what? INTENTION TO CONTACT?
What app are you using to scan the qrcode?

Try using a different app like zxing.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
op is using his app (which is using zxing under the hood). that's why "nothing" happens. he needs to code something to happen. zxing just decodes the qr code.
op needs to consult android documentation: https://developer.android.com/training/contacts-provider/modify-data use of an intent is spelled out. it can be handled in b4a.
scanner - any scanner - decodes the qr code. scanner - any scanner - needs to parse the decoded text and populate discrete fields to create a contact which can then be added to app's contacts list. this is not done automatically by anything; somebody has to program it to occur. you could do it within a scanner app or by passing the job off to another activity to handle the parsing and contact addition.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
Now I understand. Thanks.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
look at this:
https://www.b4x.com/android/forum/threads/how-to-open-contact-intent-to-add-new-from-vcard.145975/
somebody already went through this.

anyway, here's something you could build in b4a.
https://observablehq.com/@tophtucker/vcard-parser

looks like javascript, but you can use it as a base.

take your decoded vcard string and split it on the
eol character(s) to break it up into its components.
build a map of fields you can handle (refer to
@DonManfred's link above). step through each
line of split vcard text and, using the map to match
the fields. once you have the fields that make up
your new contact, run the intent with the fields as
extras. or figure out how to talk to the contacts
provider and have it create the contact, assuming
android still allows this.

regarding splitting the vcard, the eol character is
mostly chr(10), aka CRLF in b4a, but it could be
chr(13) + chr(10), so called "\r\n" sequence. (or it might
also simply be chr(13)). so, after splitting on CRLF, you
need to get rid of chr(13). just replace it with
an empty string "". if there is no chr(13), nothing happens.
no harm, no foul. don't test for it, just replace it:
thisline.replace(chr(13,""). defensive programming would
dictate that you might want to determine if chr(13) was
used in the first place.

if you examine the vcard format, you'll see that each
line may require some parsing before you extract
the actual value you need.

all very tedious, but good experience.

in addition to handling vcards, if your scanning app
came across a hyptertext link qr code, you would now
know that you had to code a little routine to send the
user to a web page. this too does not happen
automatically. you have to add it to your scanner.
qr codes have several such actionable links
beside vcards and https urls: tel, geo, etc, etc. these
all need to be coded by you. ditto for online payment
schemes triggered by qr codes or covid passes
(remember covid?) that used qr codes. all the
processing beyond decoding the qr code had to be
programmed. and in some cases, decoded qr codes
had to then be decrypted. this is what you are
effectively doing with a vcard: decode then "decrypt"
to add it to the contacts list.
 
Last edited:
Upvote 0

zed

Active Member
Licensed User
Thanks for all the information.
I will make a routine to decode the information received by VCard by following the example. (I'm from the web so javascript is not a problem for me).
Maybe with "ContactUtils" it would be possible to save in contacts. I'll try.
If everything works fine, I'll post the solution.

A big thank-you.
 
Upvote 0

GMan

Well-Known Member
Licensed User
Longtime User
I have something similar in use
Screenshot_20230509_170315_Android System.jpg


I can share that DigiVisitcard as shown
 
Upvote 0

zed

Active Member
Licensed User
With the VCard created with my application, I get the same type of information as the @GMan code.
I think my VCard is correct. I will work on the sequel.
THANK YOU.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
just a follow-up.
seems to work like a charm. plus using the intent was not as ugly as i was
expecting. plus it's how google wants us to do it. plus - and this is a
big plus in my mind - if there is any additional information you want
to add or something you want to delete, you can do it right there before
saving the contact.

for me, there is no interest in scanning a qr code with a vcard on it
so i made up a tiny vcard and wrote it to an ndef card. it looks like
a business card, right? i saw a commercial on tv where somebody
hands a "business card" to somebody else. instead of accepting a
germ-filled business card, the other card simply puts his phone next
to it, and one and done. with a qr code, either your app or the
device's camera app has to be launched so you can scan.

so, with just my android's launch screen up, i tapped the card
with my device and the contacts screen popped up with the
new contact's name ready to go. tap "save" and you're done.

here's a "parser" and intent runner. parser needs a "little
work". vcard fields are all ass-backwards, so you have to
flip everything around. plus the phone number seems to
want a particular format. my ill-formatted phone didn't take,
but the new contact is there. also, i note there does not appear
to a "full name" field in contacts. that seems to be a vcard
specialty. you'd have to decide which to use when you add
the contact.

oh, also, no permissions needed with intent.

anyway, easy enough

B4X:
Sub parseVcard( s As String )
    Log(s)
    Dim parts() As String = Regex.Split(CRLF, s)
    Dim name, fullname, tel As String
    For Each p As String In parts
        Log(p)
        Dim bits(2) As String = Regex.Split(":",p)
        Log( bits(0) & "  " & bits(1))
        Select bits(0)
            Case "N":
                name = bits(1)
            Case "FN":
                fullname = bits(1)
            Case "TEL":
                tel = bits(1)
        End Select
    Next
    Dim intent As Intent
    intent.Initialize("android.intent.action.INSERT","")
    intent.setType("vnd.android.cursor.dir/raw_contact")
    intent.PutExtra("name", name)
    intent.PutExtra("tel", tel)
    StartActivity(intent)
End Sub


something just hit me: if you have correctly formatted vcard,
you might not need too parse it. i think android can import
vcards. if you can figure out how to get that going, you
wouldn't need to reformat the vcard into individual fields and
run the contacts intent. there might be some way to save
the scanned vcard to a file and have the system simply
import it.
 

Attachments

  • vcard.png
    vcard.png
    34 KB · Views: 155
Last edited:
Upvote 0

zed

Active Member
Licensed User
It's exactly that.
I created a VCard on a free site and saved in .vcf format
The formatting of the text is really very simple.
In my app, I created a routine to format the text in the same way and I save it in vcf format.
When I click on the file, the contact information is saved.

Now it's like you say
if you can figure out how to get that going, you
wouldn't need to reformat the vcard into individual fields and
run the contacts intent. there might be some way to save
the scanned vcard to a file and have the system simply
import it.
How to automatically run the file or send it to contacts?

I found this on stackoverflow. It could work. I'll try

java:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(storage_path+vfile)),"text/x-vcard"); //storage path is path of your vcf file and vFile is name of that file.
startActivity(intent);

But I don't know java :eek:
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
SEE NEXT POST. B4A CODE THERE

good work. i'm pretty sure it can be done in b4a. by the time i can get back online, somebody else will have told you. you're almost there. somebody will jump in.

actually, start a new thread with just your last post. just say you want help converting the code into b4a. don't get into anything else. only people following this thread will see your last post. you need to start a different thread. you just want help converting that snippet. people who are interested in qr codes are not
necessarily the same people who like dealing with java.
 
Last edited:
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
this will do it (at least it did it for me):
B4X:
    ' copy vcd file from assets to dir.internal
    File.Copy(File.DirAssets,"vcard.vcd",File.DirInternal,"vcard.vcd")
   ' IN YOUR CASE, THERE IS NO FILE TO COPY.  JUST SAVE THE SCANNED VCARD TEXT TO FILE.DIRINTERNAL AS VCARD.VCD

    Dim fp As FileProvider
    fp.Initialize
    File.Copy(File.dirinternal, "vcard.vcd", fp.SharedFolder, "vcard.vcd")
    Dim thisintent As Intent
    thisintent.Initialize(thisintent.ACTION_VIEW,fp.GetFileUri("vcard.vcd"))

    thisintent.SetType("text/x-vcard")
    thisintent.Flags = 0x01
    StartActivity(thisintent)


B4X:
' save as vcard.vcd in file.dirinternal
BEGIN:VCARD
VERSION:3.0
N:Costello;James
FN:James Costello
ORG:anywheresoftwhere
URL:https://www.b4x.com
EMAIL:b4x@b4x.com
TEL;TYPE=work:+1-212-555-1212
End:VCARD


the only way to share a file is with file provider. add that library to ide.
i took your little vcard string and saved it as a ".vcd" file, after filling in some of the fields. that is what you will do after scanning the qr code. save it in file.dirinternal. i copied it from dirassets to dirinternal for the purposes of illustration; you'll just save the text directly to dirinternal as "vcard.vcd". got it?

use code above to deal with file provider and sharing.
run the intent.
after a short delay, you'll see the attached screen cap.
frankly, it's not as nice and quick as the intent i showed you earlier, but it will import a vcard directly. it's funny; there is a little notification that says, "we'll add your contact shortly..." google attempting to show some humor.
 

Attachments

  • vcard.png
    vcard.png
    18.7 KB · Views: 154
Last edited:
Upvote 0
Top