net.kazzz.NFCTagWriter.java Source code

Java tutorial

Introduction

Here is the source code for net.kazzz.NFCTagWriter.java

Source

/*
 * 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.kazzz;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;

import net.kazzz.felica.FeliCaException;
import net.kazzz.felica.FeliCaLiteTag;
import net.kazzz.felica.NfcFeliCaTagFragment;
import net.kazzz.felica.command.ReadResponse;
import net.kazzz.felica.lib.FeliCaLib.IDm;
import net.kazzz.felica.lib.FeliCaLib.MemoryConfigurationBlock;
import net.kazzz.felica.lib.R;
import net.kazzz.iso15693.ISO15693Exception;
import net.kazzz.iso15693.ISO15693Tag;
import net.kazzz.iso15693.ISO15693TagFragment;
import net.kazzz.iso15693.command.ReadMultipleBlocksResponse;
import net.kazzz.iso15693.command.ReadMultipleBlocksResponse.BlockData;
import net.kazzz.iso15693.command.SystemInformationResponse;
import net.kazzz.iso15693.lib.ISO15693Lib.MemorySizeInfo;
import net.kazzz.task.FeliCaLiteWriteTask;
import net.kazzz.task.ISO15693WriteTask;
import net.kazzz.util.ArrayUtil;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.nfc.Tag;
import android.nfc.tech.NfcF;
import android.nfc.tech.NfcV;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * NFC Tag?????????????
 *
 * @author Kazzz
 * @date 2011/03/01
 * @since Android API Level 10
 *y
 */

public class NFCTagWriter extends FragmentActivity implements OnClickListener {
    private String TAG = "NFCTagWriter";

    // FeliCaLite???? ( S_PAD013 )
    private final static String[] blockNums_FelicaLite = new String[] { "S_PAD0", "S_PAD1", "S_PAD2", "S_PAD3",
            "S_PAD4", "S_PAD5", "S_PAD6", "S_PAD7", "S_PAD8", "S_PAD9", "S_PAD10", "S_PAD11", "S_PAD12",
            "S_PAD13" };

    /**
     * ??????????
     * 
     * @date 2011/02/22
     * @since Android API Level 9
     *
     */
    public class ViewHolder {
        String blockName;
        boolean isWritable;
        String accessMode;
        byte[] data;
    }

    private Tag mNfcTag;
    private NfcFeliCaTagFragment mFeliCafragment;
    private ISO15693TagFragment mISO15693Fragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //IME???
        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        //?
        setContentView(R.layout.writer);

        final Button btnWrite = (Button) findViewById(R.id.btn_write);
        btnWrite.setOnClickListener(this);
        btnWrite.setEnabled(false);

        final EditText editWrite = (EditText) findViewById(R.id.edit_write);
        editWrite.setEnabled(false);

        final ListView listMemBlock = (ListView) findViewById(R.id.list_memblock);

        final CheckBox chkUseNDEF = (CheckBox) findViewById(R.id.chk_useNDEF);

        Intent intent = getIntent();
        this.mNfcTag = (Tag) intent.getParcelableExtra("nfcTag");

        if (isFeliCaLiteTag(mNfcTag)) {
            //FeliCaLite
            chkUseNDEF.setVisibility(View.GONE);
            mFeliCafragment = new NfcFeliCaTagFragment(this);
            prepareFeliCaLite(btnWrite, editWrite, listMemBlock);
        } else if (isISO15693Tag(mNfcTag)) {
            //ISO15693
            chkUseNDEF.setVisibility(View.VISIBLE);
            mISO15693Fragment = new ISO15693TagFragment(this);
            prepareISO15693(btnWrite, editWrite, listMemBlock);
        }
    }

    /**
     * ??FeliCa(Lite)??????
     * 
     * @param tag 
     * @return boolean ?FeliCalite??true??? 
     */
    private boolean isFeliCaLiteTag(Tag tag) {
        String[] techs = this.mNfcTag.getTechList();
        return ArrayUtil.contains(techs, NfcF.class.getName());
    }

    /**
     * ??ISO15693??????
     * 
     * @param tag 
     * @return boolean ?FeliCalite??true??? 
     */
    private boolean isISO15693Tag(Tag tag) {
        String[] techs = this.mNfcTag.getTechList();
        return ArrayUtil.contains(techs, NfcV.class.getName());
    }

    /**
     * ISO15693 Tag????????
     * 
     * 
     * @param btnWrite ?????
     * @param editWrite ??
     * @param listMemBlock?
     * @param useNDEFNDEF????
     */
    private void prepareISO15693(final Button btnWrite, final EditText editWrite, final ListView listMemBlock) {
        final CheckBox chkUseNDEF = (CheckBox) findViewById(R.id.chk_useNDEF);

        //??
        ISO15693Tag ft = new ISO15693Tag(this.mNfcTag);
        try {
            SystemInformationResponse sysInfo = ft.getSystemInformation();
            if (sysInfo == null || sysInfo.hasError()) {
                throw new ISO15693Exception(
                        "ISO15693 ??????????? : "
                                + sysInfo.getErrorCode());
            }

            final MemorySizeInfo memInfo = sysInfo.getMemoryInfo();
            if (memInfo == null || memInfo.getNumberOfBlocks() == 0) {
                throw new ISO15693Exception("ISO15693 ?????????");
            }

            chkUseNDEF.setOnCheckedChangeListener(new OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    listMemBlock.setEnabled(!chkUseNDEF.isChecked());
                    listMemBlock.setClickable(!chkUseNDEF.isChecked());
                    //NDEF??NDEF?????
                    if (chkUseNDEF.isChecked()) {
                        btnWrite.setEnabled(true);
                        editWrite.setEnabled(true);
                        //NDEF????10byte?
                        editWrite.setHint((memInfo.getBlockSize() * memInfo.getNumberOfBlocks()) - 10
                                + "??");
                    } else {
                        if (editWrite.getText().length() > 0) {
                            btnWrite.setEnabled(true);
                            editWrite.setEnabled(true);
                        } else {
                            btnWrite.setEnabled(false);
                            editWrite.setEnabled(false);
                        }
                        editWrite.setHint(memInfo.getBlockSize() + "??");
                    }
                }
            });

            ReadMultipleBlocksResponse rbResp = ft.readMultipleBlocks((byte) 0, memInfo.getBlockSize(),
                    memInfo.getNumberOfBlocks());
            if (rbResp == null || rbResp.hasError()) {
                throw new ISO15693Exception(
                        "ISO15693 ReadMultipleBlock?????" + sysInfo.getErrorCode());
            }

            //??????
            ViewHolder[] holders = new ViewHolder[memInfo.getNumberOfBlocks()];
            for (byte i = 0; i < memInfo.getNumberOfBlocks(); i++) {
                BlockData bd = rbResp.getBlockDatas()[i];

                ViewHolder holder = new ViewHolder();
                holder.blockName = "block " + i;
                holder.isWritable = !bd.isLocked();
                holder.accessMode = bd.isLocked() ? "(Lock)" : "(UnLock)";

                //??
                if (bd.getData() != null && bd.getData().length > 0) {
                    holder.data = bd.getData();
                } else {
                    holder.data = new byte[memInfo.getBlockSize()];
                    for (int b = 0; b < holder.data.length; b++) {
                        holder.data[b] = 0x00; //??
                    }
                }
                holders[i] = holder;
            }
            final LayoutInflater layoutInflater = (LayoutInflater) this
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            //ArrayAdapter? (??
            ArrayAdapter<ViewHolder> adapter = new ArrayAdapter<ViewHolder>(this,
                    android.R.layout.simple_list_item_multiple_choice, holders) {

                /* (non-Javadoc)
                 * @see android.widget.BaseAdapter#isEnabled(int)
                 */
                @Override
                public boolean isEnabled(int position) {
                    SparseBooleanArray arry = listMemBlock.getCheckedItemPositions();
                    if (arry.indexOfValue(true) != -1 && !arry.get(position) //??????? 
                            && (!arry.get(position - 1) && !arry.get(position + 1))) //????? 
                    {
                        //???????
                        return false;
                    }
                    return super.isEnabled(position);
                }

                /* (non-Javadoc)
                 * @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)
                 */
                @Override
                public View getView(int position, View convertView, ViewGroup parent) {

                    if (null == convertView) {
                        convertView = layoutInflater.inflate(android.R.layout.simple_list_item_multiple_choice,
                                null);
                    }

                    ViewHolder holder = this.getItem(position);

                    if (holder != null) {

                        StringBuilder sb = new StringBuilder();
                        sb.append(holder.blockName).append(" ").append(holder.accessMode).append("\n");
                        if (holder.data != null && holder.data.length > 0) {
                            //UTF-8?
                            Charset utfEncoding = Charset.forName("UTF-8");
                            sb.append(" : ").append(new String(holder.data, utfEncoding).trim());
                        }
                        ((TextView) convertView).setText(sb.toString());
                    }
                    return convertView;
                }

            };

            listMemBlock.setAdapter(adapter);

            // ?????  
            //listMemBlock.setItemsCanFocus(false);  
            //?
            listMemBlock.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

            listMemBlock.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                    //?????
                    SparseBooleanArray arry = listMemBlock.getCheckedItemPositions();

                    ByteBuffer buff = ByteBuffer.allocate(arry.size() * memInfo.getBlockSize());
                    int writableBlockCount = 0;
                    for (int i = 0; i < arry.size(); i++) {
                        int key = arry.keyAt(i);
                        //?????
                        Object o = parent.getItemAtPosition(key);
                        if (o != null && o instanceof ViewHolder) {
                            ViewHolder holder = (ViewHolder) o;
                            if (holder.isWritable) {
                                writableBlockCount++;
                                if (holder.data != null && holder.data.length > 0) {
                                    buff.put(holder.data);
                                }
                            }
                        }
                    }
                    //UTF-8?
                    StringBuilder sb = new StringBuilder();
                    Charset utfEncoding = Charset.forName("UTF-8");
                    sb.append(new String(buff.array(), utfEncoding).trim());

                    editWrite.setHint(memInfo.getBlockSize() * writableBlockCount + "??");

                    if (writableBlockCount > 0) {
                        editWrite.setText(sb.toString().trim());
                        editWrite.setTag(arry);
                        //????????????
                        btnWrite.setEnabled(true);
                        editWrite.setEnabled(true);
                    } else {
                        btnWrite.setEnabled(false);
                        editWrite.setEnabled(false);
                    }

                }
            });
        } catch (ISO15693Exception e) {
            e.printStackTrace();
            Log.e(TAG, e.toString());
        }
    }

    /**
     * FeliCaLite Tag????????
     * 
     * @param btnWrite ?????
     * @param editWrite ??
     * @param listMemBlock?
     */
    private void prepareFeliCaLite(final Button btnWrite, final EditText editWrite, final ListView listMemBlock) {
        //??
        ViewHolder[] holders = new ViewHolder[14];
        FeliCaLiteTag ft = new FeliCaLiteTag(this.mNfcTag);
        try {
            IDm idm = ft.pollingAndGetIDm();
            if (idm == null) {
                throw new FeliCaException("FeliCa Lite ??IDm?????????");
            }
            //MemoryConfig ??
            MemoryConfigurationBlock mb = ft.getMemoryConfigBlock();

            //????????
            for (byte i = 0; i < 14; i++) {
                ViewHolder holder = new ViewHolder();
                holder.blockName = blockNums_FelicaLite[i];
                holder.isWritable = mb.isWritable(i);
                holder.accessMode = mb.isWritable(i) ? "(R/W)" : "(RO)";

                //??
                ReadResponse rr = ft.readWithoutEncryption(i);
                if (rr != null && rr.getStatusFlag1() == 0) {
                    holder.data = rr.getBlockData();
                }
                holders[i] = holder;
            }
        } catch (FeliCaException e) {
            e.printStackTrace();
            Log.e(TAG, e.toString());
        }
        final LayoutInflater layoutInflater = (LayoutInflater) this
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //ArrayAdapter? (??
        ArrayAdapter<ViewHolder> adapter = new ArrayAdapter<ViewHolder>(this, android.R.layout.simple_list_item_1,
                holders) {

            /* (non-Javadoc)
             * @see android.widget.ArrayAdapter#getView(int, android.view.View, android.view.ViewGroup)
             */
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {

                if (null == convertView) {
                    convertView = layoutInflater.inflate(android.R.layout.simple_list_item_1, null);
                }

                ViewHolder holder = this.getItem(position);

                if (holder != null) {

                    StringBuilder sb = new StringBuilder();
                    sb.append(holder.blockName).append(" ").append(holder.accessMode).append("\n");
                    if (holder.data != null && holder.data.length > 0) {
                        //UTF-8?
                        Charset utfEncoding = Charset.forName("UTF-8");
                        sb.append(" : ").append(new String(holder.data, utfEncoding).trim());
                    }
                    ((TextView) convertView).setText(sb.toString());
                }
                return convertView;
            }

        };

        listMemBlock.setAdapter(adapter);

        // ????EditText??
        listMemBlock.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Object o = parent.getItemAtPosition(position);

                if (o != null && o instanceof ViewHolder) {
                    ViewHolder holder = (ViewHolder) o;
                    if (holder.data != null && holder.data.length > 0) {
                        //UTF-8?
                        Charset utfEncoding = Charset.forName("UTF-8");
                        editWrite.setText(new String(holder.data, utfEncoding).trim());
                        editWrite.setTag(position);
                    }

                    //????????????
                    btnWrite.setEnabled(holder.isWritable);
                    editWrite.setEnabled(holder.isWritable);
                } else {
                    btnWrite.setEnabled(false);
                    editWrite.setEnabled(false);
                }

            }
        });
    }

    /**
     * ????????
     * ?VICC???????
     * 
     */
    public void onClick(final View v) {
        try {
            final int id = v.getId();
            if (id != R.id.btn_write)
                return;

            final ProgressDialog dialog = new ProgressDialog(this);
            dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            dialog.setIndeterminate(true);

            AsyncTask<Void, Void, ?> writeDataTask = null;
            if (isFeliCaLiteTag(mNfcTag)) {
                // FeliCatLite
                writeDataTask = new FeliCaLiteWriteTask(this, mNfcTag);
            } else

            if (isISO15693Tag(mNfcTag)) {
                final CheckBox chkUseNDEF = (CheckBox) findViewById(R.id.chk_useNDEF);
                //ISO15693
                writeDataTask = new ISO15693WriteTask(this, mNfcTag, chkUseNDEF.isChecked());
            }
            // ??
            writeDataTask.execute();

        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "writeData", e);
            Toast.makeText(v.getContext(), "???? : " + e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }
}