Android Open Source - BusMan Configure Tag Activity






From Project

Back to project page BusMan.

License

The source code is released under:

Apache License

If you think the Android project BusMan listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2013 The Android Open Source Project
 */*from ww w  .  jav  a  2  s  .c  o m*/
 * 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 net.bbuzz.busman;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources.NotFoundException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.os.AsyncTask;
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.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * Derived from "collectable cards/top trumps" NFC demo
 * by Richard Leggett http://www.richardleggett.co.uk
 */
public class ConfigureTagActivity extends Activity implements OnClickListener {

    private static final String TAG = "BusMan";
    public static final String KEY_NFC_RIDER = "nfcrider";
    public static final String ID_SEPARATOR = "@";

    private NfcAdapter mNfcAdapter;
    private Button mWriteTagButton;
    private TextView mResultTextOutput;
    private EditText mRiderIdInput;
    private EditText mRiderNameInput;
    private boolean mWaitingToWriteNfc;
    private String mRiderId;
    private String mRiderName;
    private boolean mMakeReadOnly;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.configure_tag_activity);

        // grab our NFC Adapter
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

        // button that starts the tag-write procedure
        mWriteTagButton = (Button)findViewById(R.id.write_tag_button);
        mWriteTagButton.setOnClickListener(this);

        // TextView that we'll use to output messages to screen
        mResultTextOutput = (TextView) findViewById(R.id.text_view);

        // EditText fields to receive rider inputs
        mRiderIdInput = (EditText) findViewById(R.id.rider_id);
        mRiderNameInput = (EditText) findViewById(R.id.rider_name);

        final Intent intent = getIntent();
        final String nfcRiderText = intent.getStringExtra(KEY_NFC_RIDER);
        if (nfcRiderText != null) {
            final int breakingPoint = nfcRiderText.indexOf('@');
            mRiderIdInput.setText(nfcRiderText.substring(0, breakingPoint));
            mRiderNameInput.setText(nfcRiderText.substring(breakingPoint + 1));
        }
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.options_menu_configure, menu);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.option_settings_too:
                startActivity(new Intent(this, SettingsActivity.class));
                return true;

            case R.id.option_about:
                showAboutDialog(this);
                return true;

            case R.id.option_manifest:
                startActivity(new Intent(this, ManifestActivity.class));
                return true;

            default:
                return super.onOptionsItemSelected(item);
            }
    }

    public static void showAboutDialog(final Context context) {
        String message = "";
        try {
            message = context.getResources().getString(R.string.about_this_app_message,
                    context.getPackageManager().getPackageInfo(context.getPackageName(), 0)
                    .versionName);
        } catch (NotFoundException e) {
        } catch (NameNotFoundException e) {
        }
        new AlertDialog.Builder(context)
                .setTitle(R.string.about_this_app_title)
                .setMessage(message)
                .show();
    }

    public void onClick(View v) {
        if(v.getId() == R.id.write_tag_button) {
            mRiderId = mRiderIdInput.getText().toString();
            mRiderName = mRiderNameInput.getText().toString();
            mMakeReadOnly = ((CheckBox) findViewById(R.id.configure_write_only)).isChecked();

            if (mRiderId != null && !mRiderId.isEmpty()
                    && mRiderName != null && !mRiderName.isEmpty()) {
                Log.d(TAG, "onClick(), id=" + mRiderId + ", name=" + mRiderName);
                displayMessage(R.string.msg_swipe_new_tag);
                writeNfcWhenItAppears();
            } else {
                displayMessage(R.string.msg_enter_both_fields);
            }
        }
    }

    private void maybeEnableForegroundDispatch() {
        Log.d(TAG, "maybeEnableForegroundDispatch(), mWaitingToWriteNfc=" + mWaitingToWriteNfc);
        if (mWaitingToWriteNfc) {
            // set up a PendingIntent to open the app when a tag is scanned
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
            IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
            IntentFilter[] filters = new IntentFilter[] { tagDetected };

            mNfcAdapter.enableForegroundDispatch(this, pendingIntent, filters, null);
        }
    }

    private void maybeDisableForegroundDispatch() {
        Log.d(TAG, "maybeDisableForegroundDispatch(), mWaitingToWriteNfc=" + mWaitingToWriteNfc);
        if (mWaitingToWriteNfc) {
            mNfcAdapter.disableForegroundDispatch(this);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause(), mWaitingToWriteNfc=" + mWaitingToWriteNfc);
        maybeDisableForegroundDispatch();
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume(), mWaitingToWriteNfc=" + mWaitingToWriteNfc);
        maybeEnableForegroundDispatch();
    }

    /**
     * Called when our blank tag is scanned executing the PendingIntent
     */
    @Override
    public void onNewIntent(Intent intent) {
        Log.d(TAG, "onNewIntent(), mWaitingToWriteNfc=" + mWaitingToWriteNfc);
        // Shouldn't I verify that intent is what I'm expecting?
        if (mWaitingToWriteNfc) {
            mWaitingToWriteNfc = false;

            // write to newly scanned tag
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            writeTagInBackground(tag);
        }
    }

    /**
     * Force this Activity to get NFC events first
     */
    private void writeNfcWhenItAppears() {
        Log.d(TAG, "writeNfcWhenItAppears()");
        mWaitingToWriteNfc = true;

        maybeEnableForegroundDispatch();
    }

    private void writeTagInBackground(final Tag tag) {
        new AsyncTask<Tag, Integer, Integer>() {

            @Override
            protected Integer doInBackground(Tag... params) {
                Log.d(TAG, "wtib.doInBackground(), tag=" + params[0]);
                publishProgress(R.string.msg_writing_new_tag);
                return writeTag(params[0]);
            }

            @Override
            protected void onProgressUpdate(Integer... progress) {
                Log.d(TAG, "wtib.onProgressUpdate(), progress=" + progress[0]);
                displayMessage(progress[0]);
            }

            @Override
            protected void onPostExecute(Integer result) {
                Log.d(TAG, "wtib.onPostExecute(), result=" + result);
                if (result == R.string.msg_result_success) {
                    mRiderIdInput.setText("");
                    mRiderNameInput.setText("");
                }
                displayMessage(result);
            }

        }.execute(tag);
    }

    /**
     * Format a tag and write our NDEF message
     * @param tag - the NFC tag info
     * @return resource id of string that explains the outcome
     */
    private int writeTag(Tag tag) {
        final String packageName = getPackageName();
        Log.d(TAG, "writeTag(), tag=" + tag + ", pkg=" + packageName);
        // record to launch Play Store if app is not installed
        NdefRecord appRecord = NdefRecord.createApplicationRecord(getPackageName());

        // package up the id and name; assign our MIME_TYPE
        final String idAndName = packIdAndName();
        Log.d(TAG, "  writeTag(), idAndName=" + idAndName);
        byte[] payload = idAndName.getBytes();
        byte[] mimeBytes = MimeType.BUSMAN_MIMETYPE.getBytes(Charset.forName("US-ASCII"));
        NdefRecord cardRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes,
                                                new byte[0], payload);
        NdefMessage message = new NdefMessage(new NdefRecord[] { cardRecord, appRecord});

        try {
            // see if tag is already NDEF formatted
            Ndef ndef = Ndef.get(tag);
            if (ndef != null) {
                ndef.connect();

                if (!ndef.isWritable()) {
                    Log.e(TAG, "writeTag result: Read-only tag.");
                    return R.string.msg_result_error_read_only;
                }

                // work out how much space we need for the data
                int size = message.toByteArray().length;
                if (ndef.getMaxSize() < size) {
                    Log.e(TAG, "writeTag result: Tag doesn't have enough free space.");
                    return R.string.msg_result_error_tag_too_small;
                }

                if (mMakeReadOnly && !ndef.canMakeReadOnly()) {
                    Log.e(TAG, "writeTag result: Requested read-only, but tag isn't capable");
                    return R.string.msg_result_cant_make_read_only;
                }

                ndef.writeNdefMessage(message);
                if (mMakeReadOnly) {
                    ndef.makeReadOnly();
                }
                Log.d(TAG, "writeTag result: Tag written successfully.");
                return R.string.msg_result_success;
            } else {
                // attempt to format tag
                NdefFormatable format = NdefFormatable.get(tag);
                if (format != null) {
                    try {
                        format.connect();
                        format.format(message);
                        Log.d(TAG, "writeTag result: Tag written successfully!\n"
                                + "Close this app and scan tag.");
                        return R.string.msg_result_success_formatted;
                    } catch (IOException e) {
                        Log.e(TAG, "writeTag result: Unable to format tag to NDEF.");
                        return R.string.msg_result_error_cant_format_tag;
                    }
                } else {
                    Log.e(TAG, "writeTag result: Tag doesn't appear to support NDEF format.");
                    return R.string.msg_result_error_not_ndef_tag;
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "writeTag result: Failed to write tag");
        }

        return R.string.msg_result_error_cant_write_tag;
    }

    // TODO: use JSON instead of ad hoc?
    private String packIdAndName() {
        // trim any domain name from the id
        final String id = mRiderId.replaceFirst(ID_SEPARATOR + ".*", "");
        return id + ID_SEPARATOR + mRiderName;
    }

    private void displayMessage(int stringResourceId) {
        displayMessage(getApplicationContext().getResources().getString(stringResourceId));
    }

    private void displayMessage(String message) {
        Log.d(TAG, "displayMessage: " + message);
        mResultTextOutput.setText(message);
    }
}




Java Source Code List

net.bbuzz.busman.ConfigureTagActivity.java
net.bbuzz.busman.ManifestActivity.java
net.bbuzz.busman.MimeType.java
net.bbuzz.busman.RiderMessages.java
net.bbuzz.busman.SettingsActivity.java