1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.apps.tag.record;
18
19import com.android.apps.tag.R;
20import com.android.vcard.VCardConfig;
21import com.android.vcard.VCardEntry;
22import com.android.vcard.VCardEntryConstructor;
23import com.android.vcard.VCardEntryHandler;
24import com.android.vcard.VCardParser;
25import com.android.vcard.VCardParser_V21;
26import com.android.vcard.VCardParser_V30;
27import com.android.vcard.exception.VCardException;
28import com.android.vcard.exception.VCardVersionException;
29import com.google.android.collect.Lists;
30import com.google.common.base.Preconditions;
31
32import android.app.Activity;
33import android.content.ActivityNotFoundException;
34import android.content.ContentUris;
35import android.content.Context;
36import android.content.Intent;
37import android.content.pm.PackageManager;
38import android.content.pm.ResolveInfo;
39import android.content.res.AssetFileDescriptor;
40import android.database.Cursor;
41import android.graphics.BitmapFactory;
42import android.graphics.drawable.BitmapDrawable;
43import android.graphics.drawable.Drawable;
44import android.net.Uri;
45import android.nfc.NdefRecord;
46import android.os.AsyncTask;
47import android.os.Parcel;
48import android.os.Parcelable;
49import android.provider.ContactsContract;
50import android.text.TextUtils;
51import android.util.Log;
52import android.view.LayoutInflater;
53import android.view.View;
54import android.view.View.OnClickListener;
55import android.view.ViewGroup;
56import android.widget.ImageView;
57import android.widget.TextView;
58
59import java.io.ByteArrayInputStream;
60import java.io.FileInputStream;
61import java.io.FileNotFoundException;
62import java.io.IOException;
63import java.io.InputStream;
64import java.lang.ref.WeakReference;
65import java.util.ArrayList;
66import java.util.List;
67import java.util.Locale;
68
69/**
70 * VCard Ndef Record object
71 */
72public class VCardRecord extends ParsedNdefRecord implements OnClickListener {
73    private static final String TAG = VCardRecord.class.getSimpleName();
74
75    public static final String RECORD_TYPE = "vcard";
76
77    private final byte[] mVCard;
78
79    private VCardRecord(byte[] content) {
80        mVCard = content;
81    }
82
83    @Override
84    public View getView(Activity activity, LayoutInflater inflater, ViewGroup parent, int offset) {
85
86        Uri uri = activity.getIntent().getData();
87        uri = Uri.withAppendedPath(uri, Integer.toString(offset));
88        uri = Uri.withAppendedPath(uri, "mime");
89
90        // TODO: parse content and display something nicer.
91        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
92
93        CharSequence template = activity.getResources().getText(R.string.import_vcard);
94        String description = TextUtils.expandTemplate(template, getDisplayName()).toString();
95
96        return RecordUtils.getViewsForIntent(activity, inflater, parent, this, intent, description);
97    }
98
99    @Override
100    public String getSnippet(Context context, Locale locale) {
101        CharSequence template = context.getResources().getText(R.string.vcard_title);
102        return TextUtils.expandTemplate(template, getDisplayName()).toString();
103    }
104
105    public String getDisplayName() {
106        try {
107            ArrayList<VCardEntry> entries = getVCardEntries();
108            if (!entries.isEmpty()) {
109                return entries.get(0).getDisplayName();
110            }
111        } catch (Exception e) {
112        }
113
114        return "vCard";
115    }
116
117    private ArrayList<VCardEntry> getVCardEntries() throws IOException, VCardException {
118        final ArrayList<VCardEntry> entries = Lists.newArrayList();
119
120        final int type = VCardConfig.VCARD_TYPE_UNKNOWN;
121        final VCardEntryConstructor constructor = new VCardEntryConstructor(type);
122        constructor.addEntryHandler(new VCardEntryHandler() {
123            @Override public void onStart() {}
124            @Override public void onEnd() {}
125
126            @Override
127            public void onEntryCreated(VCardEntry entry) {
128                entries.add(entry);
129            }
130        });
131
132        VCardParser parser = new VCardParser_V21(type);
133        try {
134            parser.parse(new ByteArrayInputStream(mVCard), constructor);
135        } catch (VCardVersionException e) {
136            try {
137                parser = new VCardParser_V30(type);
138                parser.parse(new ByteArrayInputStream(mVCard), constructor);
139            } finally {
140            }
141        }
142
143        return entries;
144    }
145
146    private static Intent getPickContactIntent() {
147        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
148        intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
149        return intent;
150    }
151
152    public static VCardRecord parse(NdefRecord record) {
153        MimeRecord underlyingRecord = MimeRecord.parse(record);
154
155        // TODO: Add support for other vcard mime types.
156        Preconditions.checkArgument("text/x-vcard".equals(underlyingRecord.getMimeType()));
157        return new VCardRecord(underlyingRecord.getContent());
158    }
159
160    public static NdefRecord newVCardRecord(byte[] data) {
161        return MimeRecord.newMimeRecord("text/x-vcard", data);
162    }
163
164    @Override
165    public void onClick(View view) {
166        RecordUtils.ClickInfo info = (RecordUtils.ClickInfo) view.getTag();
167        try {
168            info.activity.startActivity(info.intent);
169            info.activity.finish();
170        } catch (ActivityNotFoundException e) {
171            // The activity wansn't found for some reason. Don't crash, but don't do anything.
172            Log.e(TAG, "Failed to launch activity for intent " + info.intent, e);
173        }
174    }
175
176    public static boolean isVCard(NdefRecord record) {
177        try {
178            parse(record);
179            return true;
180        } catch (IllegalArgumentException e) {
181            return false;
182        }
183    }
184}
185