Remove the My Tag feature.
Jeff Hamilton [Wed, 3 Nov 2010 20:14:46 +0000 (15:14 -0500)]
Change-Id: I4488dcb66fc43c8fd67e39276fb866eb08ebc2f2

Android.mk
src/com/android/apps/tag/EditTagActivity.java [deleted file]
src/com/android/apps/tag/MyTagActivity.java [deleted file]
src/com/android/apps/tag/TagBrowserActivity.java
src/com/android/apps/tag/TagContentSelector.java [deleted file]
src/com/android/apps/tag/record/VCardRecord.java
src/com/android/vcard/VCardUtils.java

index 7fa60a0..dd1d1b1 100644 (file)
@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := Tag
 
-#LOCAL_SDK_VERSION := current
+LOCAL_SDK_VERSION := current
 
 include $(BUILD_PACKAGE)
 
diff --git a/src/com/android/apps/tag/EditTagActivity.java b/src/com/android/apps/tag/EditTagActivity.java
deleted file mode 100644 (file)
index 50c4df9..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.apps.tag;
-
-import com.android.apps.tag.record.ImageRecord;
-import com.android.apps.tag.record.ParsedNdefRecord;
-import com.android.apps.tag.record.RecordEditInfo;
-import com.android.apps.tag.record.RecordEditInfo.EditCallbacks;
-import com.android.apps.tag.record.UriRecord;
-import com.android.apps.tag.record.VCardRecord;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-
-import android.app.Activity;
-import android.app.Dialog;
-import android.content.Intent;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import java.util.ArrayList;
-import java.util.Set;
-
-/**
- * A base {@link Activity} class for an editor of an {@link NdefMessage} tag.
- *
- * The core of the editing is done by various child {@link View}s that differ based on
- * {@link ParsedNdefRecord} types. Each type of {@link ParsedNdefRecord} can build views to
- * pick/select a new piece of content, or edit an existing content for the {@link NdefMessage}.
- */
-public abstract class EditTagActivity extends Activity implements OnClickListener, EditCallbacks {
-
-    private static final String BUNDLE_KEY_OUTSTANDING_PICK = "outstanding-pick";
-    protected static final int DIALOG_ID_ADD_CONTENT = 0;
-
-    private static final Set<String> SUPPORTED_RECORD_TYPES = ImmutableSet.of(
-        ImageRecord.RECORD_TYPE,
-        UriRecord.RECORD_TYPE,
-        VCardRecord.RECORD_TYPE
-    );
-
-    /**
-     * Records contained in the current message being edited.
-     */
-    protected final ArrayList<RecordEditInfo> mRecords = Lists.newArrayList();
-
-    /**
-     * The container where the subviews for each record are housed.
-     */
-    private ViewGroup mContentRoot;
-
-    /**
-     * Info about an outstanding picking activity to add a new record.
-     */
-    private RecordEditInfo mRecordWithOutstandingPick;
-
-    private LayoutInflater mInflater;
-
-    @Override
-    protected void onCreate(Bundle savedState) {
-        super.onCreate(savedState);
-
-        if (savedState != null) {
-            mRecordWithOutstandingPick = savedState.getParcelable(BUNDLE_KEY_OUTSTANDING_PICK);
-        }
-        mInflater = LayoutInflater.from(this);
-    }
-
-    protected ViewGroup getContentRoot() {
-        if (mContentRoot == null) {
-            mContentRoot = (ViewGroup) findViewById(R.id.content_parent);
-        }
-        return mContentRoot;
-    }
-
-    /**
-     * @return The list of {@link ParsedNdefRecord} types that this editor supports. Subclasses
-     *     may override to filter out specific types.
-     */
-    public Set<String> getSupportedTypes() {
-        return SUPPORTED_RECORD_TYPES;
-    }
-
-    /**
-     * Builds a {@link View} used as an item in a list when picking a new piece of content to add
-     * to the tag.
-     */
-    public View getAddView(ViewGroup parent, String type) {
-        if (ImageRecord.RECORD_TYPE.equals(type)) {
-            return ImageRecord.getAddView(this, mInflater, parent);
-        } else if (UriRecord.RECORD_TYPE.equals(type)) {
-            return UriRecord.getAddView(this, mInflater, parent);
-        } else if (VCardRecord.RECORD_TYPE.equals(type)) {
-            return VCardRecord.getAddView(this, mInflater, parent);
-        }
-        throw new IllegalArgumentException("Not a supported view type");
-    }
-
-    /**
-     * Builds a snapshot of current values as held in the internal state of this editor.
-     */
-    public ArrayList<NdefRecord> getValues() {
-        ArrayList<NdefRecord> result = new ArrayList<NdefRecord>(mRecords.size());
-        for (RecordEditInfo editInfo : mRecords) {
-            result.add(editInfo.getValue());
-        }
-        return result;
-    }
-
-    /**
-     * Builds a {@link View} used as an item in a list when editing content for a tag.
-     */
-    public void addRecord(RecordEditInfo editInfo) {
-        mRecords.add(Preconditions.checkNotNull(editInfo));
-        addViewForRecord(editInfo);
-    }
-
-    /**
-     * Adds a child editor view for a record.
-     */
-    public void addViewForRecord(RecordEditInfo editInfo) {
-        ViewGroup root = getContentRoot();
-        View editView = editInfo.getEditView(this, mInflater, root, this);
-        root.addView(mInflater.inflate(R.layout.tag_divider, root, false));
-        root.addView(editView);
-    }
-
-    protected void rebuildChildViews() {
-        ViewGroup root = getContentRoot();
-        root.removeAllViews();
-        for (RecordEditInfo editInfo : mRecords) {
-            addViewForRecord(editInfo);
-        }
-    }
-
-    @Override
-    protected Dialog onCreateDialog(int id, Bundle args) {
-        if (id == DIALOG_ID_ADD_CONTENT) {
-            return new TagContentSelector(this);
-        }
-        return super.onCreateDialog(id, args);
-    }
-
-    @Override
-    protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
-        super.onPrepareDialog(id, dialog, args);
-        if (dialog instanceof TagContentSelector) {
-            ((TagContentSelector) dialog).rebuildViews();
-        }
-    }
-
-    /**
-     * Displays a {@link Dialog} to select a new content type to add to the Tag.
-     */
-    protected void showAddContentDialog() {
-        showDialog(DIALOG_ID_ADD_CONTENT);
-    }
-
-    @Override
-    public void startPickForRecord(RecordEditInfo editInfo, Intent intent) {
-        mRecordWithOutstandingPick = editInfo;
-        startActivityForResult(intent, 0);
-    }
-
-    /**
-     * Handles a click to select and add a new content type.
-     */
-    public void onAddContentClick(View target) {
-        Object tag = target.getTag();
-        if ((tag == null) || !(tag instanceof RecordEditInfo)) {
-            return;
-        }
-
-        RecordEditInfo info = (RecordEditInfo) tag;
-        Intent pickIntent = info.getPickIntent();
-        if (pickIntent != null) {
-            startPickForRecord(info, pickIntent);
-        } else {
-            // Does not require an external Activity. Add the edit view directly.
-            addRecord(info);
-        }
-    }
-
-    @Override
-    public void deleteRecord(RecordEditInfo editInfo) {
-        mRecords.remove(editInfo);
-        rebuildChildViews();
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if ((resultCode != RESULT_OK) || (data == null)) {
-            mRecordWithOutstandingPick = null;
-            return;
-        }
-        if (mRecordWithOutstandingPick == null) {
-            return;
-        }
-
-        // Handles results from another Activity that picked content to write to a tag.
-        RecordEditInfo recordInfo = mRecordWithOutstandingPick;
-        try {
-            recordInfo.handlePickResult(this, data);
-        } catch (IllegalArgumentException ex) {
-            if (mRecords.contains(recordInfo)) {
-                deleteRecord(recordInfo);
-            }
-            return;
-        }
-
-        if (mRecords.contains(recordInfo)) {
-            // Editing an existing record. Just rebuild everything.
-            rebuildChildViews();
-
-        } else {
-            // Adding a new record.
-            addRecord(recordInfo);
-        }
-        // TODO: handle errors in picking (e.g. the image is too big, etc).
-
-        mRecordWithOutstandingPick = null;
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-
-        if (mRecordWithOutstandingPick != null) {
-            outState.putParcelable(BUNDLE_KEY_OUTSTANDING_PICK, mRecordWithOutstandingPick);
-        }
-    }
-}
diff --git a/src/com/android/apps/tag/MyTagActivity.java b/src/com/android/apps/tag/MyTagActivity.java
deleted file mode 100644 (file)
index 96bf0d2..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.apps.tag;
-
-import com.android.apps.tag.message.NdefMessageParser;
-import com.android.apps.tag.message.ParsedNdefMessage;
-import com.android.apps.tag.record.ParsedNdefRecord;
-import com.android.apps.tag.record.RecordEditInfo;
-import com.android.apps.tag.record.TextRecord;
-import com.android.apps.tag.record.UriRecord;
-import com.android.apps.tag.record.VCardRecord;
-import com.google.common.collect.Lists;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.net.Uri;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.nfc.NfcAdapter;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.CheckBox;
-import android.widget.EditText;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Editor {@link Activity} for the tag that can be programmed into the device.
- */
-public class MyTagActivity extends EditTagActivity implements OnClickListener {
-
-    private static final String LOG_TAG = "TagEditor";
-
-    private EditText mTextView;
-    private CheckBox mEnabled;
-
-    /**
-     * Whether or not data was already parsed from an {@link Intent}. This happens when the user
-     * shares data via the My tag feature.
-     */
-    private boolean mParsedIntent = false;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        setContentView(R.layout.my_tag_activity);
-
-        findViewById(R.id.toggle_enabled_target).setOnClickListener(this);
-        findViewById(R.id.add_content_target).setOnClickListener(this);
-
-        mTextView = (EditText) findViewById(R.id.input_tag_text);
-        mEnabled = (CheckBox) findViewById(R.id.toggle_enabled_checkbox);
-
-        populateEditor();
-    }
-
-    private void populateEditor() {
-        NdefMessage localMessage = NfcAdapter.getDefaultAdapter().getLocalNdefMessage();
-
-        if (Intent.ACTION_SEND.equals(getIntent().getAction()) && !mParsedIntent) {
-            if (localMessage != null) {
-                // TODO: prompt user for confirmation about wiping their old tag.
-            }
-
-            if (buildFromIntent(getIntent())) {
-                return;
-            }
-
-            mParsedIntent = true;
-
-        } else if (localMessage == null) {
-            mEnabled.setChecked(false);
-            return;
-
-        } else {
-            // Locally stored message.
-            ParsedNdefMessage parsed = NdefMessageParser.parse(localMessage);
-            List<ParsedNdefRecord> records = parsed.getRecords();
-
-            // There is always a "Text" record for a My Tag.
-            if (records.size() < 1) {
-                Log.w(LOG_TAG, "Local record not in expected format");
-                return;
-            }
-            mEnabled.setChecked(true);
-            mTextView.setText(((TextRecord) records.get(0)).getText());
-
-            mRecords.clear();
-            for (int i = 1, len = records.size(); i < len; i++) {
-                RecordEditInfo editInfo = records.get(i).getEditInfo(this);
-                if (editInfo != null) {
-                    addRecord(editInfo);
-                }
-            }
-            rebuildChildViews();
-        }
-    }
-
-    /**
-     * Populates the editor from extras in a given {@link Intent}
-     * @param intent the {@link Intent} to parse.
-     * @return whether or not the {@link Intent} could be handled.
-     */
-    private boolean buildFromIntent(final Intent intent) {
-        String type = intent.getType();
-
-        if ("text/plain".equals(type)) {
-            String title = getIntent().getStringExtra(Intent.EXTRA_SUBJECT);
-            mTextView.setText((title == null) ? "" : title);
-
-            String text = getIntent().getStringExtra(Intent.EXTRA_TEXT);
-            try {
-                URL parsed = new URL(text);
-
-                // Valid URL.
-                mTextView.setText("");
-                mRecords.add(new UriRecord.UriRecordEditInfo(text));
-                rebuildChildViews();
-
-            } catch (MalformedURLException ex) {
-                // Ignore. Just treat as plain text.
-                mTextView.setText((text == null) ? "" : text);
-            }
-
-            mEnabled.setChecked(true);
-            onSave();
-            return true;
-
-        } else if ("text/x-vcard".equals(type)) {
-            Uri stream = (Uri) getIntent().getParcelableExtra(Intent.EXTRA_STREAM);
-            if (stream != null) {
-                RecordEditInfo editInfo = VCardRecord.editInfoForUri(stream);
-                if (editInfo != null) {
-                    mRecords.add(editInfo);
-                    rebuildChildViews();
-                }
-            }
-        }
-        // TODO: handle images.
-        return false;
-    }
-
-    /**
-     * Persists content to store.
-     */
-    private void onSave() {
-        String text = mTextView.getText().toString();
-        NfcAdapter nfc = NfcAdapter.getDefaultAdapter();
-
-        if (!mEnabled.isChecked()) {
-            nfc.setLocalNdefMessage(null);
-            return;
-        }
-
-        Locale locale = getResources().getConfiguration().locale;
-        ArrayList<NdefRecord> values = Lists.newArrayList(
-                TextRecord.newTextRecord(text, locale)
-        );
-
-        values.addAll(getValues());
-
-        Log.d(LOG_TAG, "Writing local NdefMessage from tag app....");
-        nfc.setLocalNdefMessage(new NdefMessage(values.toArray(new NdefRecord[values.size()])));
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        onSave();
-    }
-
-    @Override
-    public void onClick(View target) {
-        switch (target.getId()) {
-            case R.id.toggle_enabled_target:
-                boolean enabled = !mEnabled.isChecked();
-                mEnabled.setChecked(enabled);
-
-                // TODO: Persist to some store.
-                if (enabled) {
-                    onSave();
-                } else {
-                    NfcAdapter.getDefaultAdapter().setLocalNdefMessage(null);
-                }
-                break;
-
-            case R.id.add_content_target:
-                showAddContentDialog();
-                break;
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.menu, menu);
-        return true;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case R.id.help:
-                HelpUtils.openHelp(this);
-                return true;
-
-            default:
-                return super.onOptionsItemSelected(item);
-        }
-    }
-}
index 6df1567..d9bd04c 100644 (file)
@@ -60,11 +60,6 @@ public class TagBrowserActivity extends TabActivity implements DialogInterface.O
                 .setContent(new Intent().setClass(this, TagList.class)
                         .putExtra(TagList.EXTRA_SHOW_STARRED_ONLY, true)));
 
-        tabHost.addTab(tabHost.newTabSpec("mytag")
-                .setIndicator(getText(R.string.tab_my_tag),
-                        res.getDrawable(R.drawable.ic_tab_my_tag))
-                .setContent(new Intent().setClass(this, MyTagActivity.class)));
-
         SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);
         if (!preferences.getBoolean(PREF_KEY_SHOW_INTRO, false)) {
             preferences.edit().putBoolean(PREF_KEY_SHOW_INTRO, true).apply();
diff --git a/src/com/android/apps/tag/TagContentSelector.java b/src/com/android/apps/tag/TagContentSelector.java
deleted file mode 100644 (file)
index e1055a6..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.apps.tag;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.nfc.NdefRecord;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * A {@link Dialog} that presents options to select data which can be written into a
- * {@link NdefRecord} for an NFC tag.
- */
-public class TagContentSelector extends AlertDialog
-        implements DialogInterface.OnClickListener, android.view.View.OnClickListener {
-
-    private final EditTagActivity mActivity;
-    private final ViewGroup mListRoot;
-
-    public TagContentSelector(EditTagActivity activity) {
-        super(activity);
-        mActivity = activity;
-
-        setTitle(activity.getResources().getString(R.string.select_type));
-
-        LayoutInflater inflater = LayoutInflater.from(activity);
-        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.tag_content_selector, null);
-        mListRoot = (ViewGroup) root.findViewById(R.id.list);
-
-        rebuildViews();
-
-        setView(root);
-        setIcon(0);
-        setButton(
-                DialogInterface.BUTTON_POSITIVE,
-                activity.getString(android.R.string.cancel),
-                this);
-    }
-
-    public void rebuildViews() {
-        mListRoot.removeAllViews();
-        for (String type : mActivity.getSupportedTypes()) {
-            View selectItemView = mActivity.getAddView(mListRoot, type);
-            if (selectItemView != null) {
-                selectItemView.setOnClickListener(this);
-                mListRoot.addView(selectItemView);
-            }
-        }
-    }
-
-
-    @Override
-    public void onClick(DialogInterface dialog, int which) {
-        dismiss();
-    }
-
-    @Override
-    public void onClick(View target) {
-        mActivity.onAddContentClick(target);
-        dismiss();
-    }
-}
index 362a447..bfaa180 100644 (file)
@@ -26,8 +26,8 @@ import com.android.vcard.VCardParser_V21;
 import com.android.vcard.VCardParser_V30;
 import com.android.vcard.exception.VCardException;
 import com.android.vcard.exception.VCardVersionException;
-import com.google.android.collect.Lists;
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
 
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
index a6eba12..c40eed7 100644 (file)
@@ -422,6 +422,22 @@ public class VCardUtils {
         return containsOnlyPrintableAscii(Arrays.asList(values));
     }
 
+    public static boolean isPrintableAscii(final char c) {
+        final int asciiFirst = 0x20;
+        final int asciiLast = 0x7E;  // included
+        return (asciiFirst <= c && c <= asciiLast) || c == '\r' || c == '\n';
+    }
+
+    public static boolean isPrintableAsciiOnly(final CharSequence str) {
+        final int len = str.length();
+        for (int i = 0; i < len; i++) {
+            if (!isPrintableAscii(str.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     public static boolean containsOnlyPrintableAscii(final Collection<String> values) {
         if (values == null) {
             return true;
@@ -430,7 +446,7 @@ public class VCardUtils {
             if (TextUtils.isEmpty(value)) {
                 continue;
             }
-            if (!TextUtils.isPrintableAsciiOnly(value)) {
+            if (!isPrintableAsciiOnly(value)) {
                 return false;
             }
         }