-1

I'm new to the NFC technology and thought of starting with reading and writing a tag. For the reading purpose I am using a MIRFARE 1K smart card and for writing I am using an NTAG203. All I want is to get the TagID in the reading process and send the TagID and datetime stamp to the NTAG203.

Issues:

  1. My application is having difficulty in compiling. It keeps giving me Error generating final archive: Failed to create 'C:\Android WS\TabletApp\bin\TabletApp.apks': Access is denied error. I clean the project and restart Eclipse but in vain. It only goes away when I restart my laptop. Any suggestions for this?

  2. When the application works, it still does not give me the ID. I scan my card/tag and the MainActivity(ScanningActivity here) loads again and again. The control does not go further than this. Any suggestions on how to work on it?

public class ScanningActivity extends Activity {
    private NfcAdapter sNfcAdapter;
    Locale locale = new Locale("en", "US");
    byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
    boolean encodeInUtf8 = false;
    Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
    int utfBit = encodeInUtf8 ? 0 : (1 << 7);
    char status = (char)(utfBit + langBytes.length);

    static String bin2hex(byte[] data) {
        return String.format("%0" + (data.length * 2) + "X", new BigInteger(1, data));
    }
    /* write to tag */

    boolean writeNdefMessageToTag(NdefMessage message, Tag detectedTag) throws FormatException {
        int size = message.toByteArray().length;
        try {
            Ndef ndef = Ndef.get(detectedTag);
            if (ndef != null) {
                ndef.connect();
                if (!ndef.isWritable()) {
                    Toast.makeText(this, "Tag is read-only.", Toast.LENGTH_SHORT).show();
                    return false;
                }
                if (ndef.getMaxSize() < size) {
                    Toast.makeText(this,
                                   "The data cannot be written since the tag capacity is" + ndef.getMaxSize() +
                                   " bytes and the data to be transferred is " + size + " bytes",
                                   Toast.LENGTH_LONG).show();
                    return false;
                }

                ndef.writeNdefMessage(message);
                ndef.close();
                Toast.makeText(this, "Data sent to the Tag", Toast.LENGTH_LONG).show();
                return true;

            } else {
                NdefFormatable ndefFormat = NdefFormatable.get(detectedTag);
                if (ndefFormat != null) {
                    try {
                        ndefFormat.connect();
                        ndefFormat.format(message);
                        ndefFormat.close();
                        Toast.makeText(this, "Data sent", Toast.LENGTH_LONG).show();
                        return true;
                    } catch (IOException e) {
                        Toast.makeText(this, "Unable to format tag", Toast.LENGTH_LONG).show();
                        return false;
                    }
                } else {
                    Toast.makeText(this, "Not supported tag", Toast.LENGTH_LONG).show();
                    return false;
                }

            }
        } catch (IOException e) {
            Toast.makeText(this, "Sending failed", Toast.LENGTH_LONG).show();
        }
        return false;

    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scanning);

        TextView tg = (TextView)findViewById(R.id.tagid);
        final TextView tvtime = (TextView)findViewById(R.id.datetime);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
        String currentTimeStamp = dateFormat.format(new Date()); // Find todays date
        tvtime.setText(currentTimeStamp);

        sNfcAdapter = NfcAdapter.getDefaultAdapter(this);

        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
        if (sNfcAdapter == null) {
            Toast.makeText(this, "This device does not support NFC or you have not scanned the card properly",
                           Toast.LENGTH_LONG).show();
            return;
        }

        if (!sNfcAdapter.isEnabled()) {
            Toast.makeText(this, "Looks like the NFC is not enabled on your device", Toast.LENGTH_LONG).show();
            new AlertDialog.Builder(this).setTitle("NFC disabled").setMessage(
                    "Looks like the NFC is not enabled on your device. Please enable it.").setPositiveButton(
                    "Ok", null).show();
        }
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(getIntent().getAction())) {
            Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
            try {
                String TagID = tag.getId().toString();
                tg.setText(bin2hex(tag.getId()));
                Toast.makeText(getApplicationContext(), bin2hex(tag.getId()), Toast.LENGTH_LONG).show();
                Toast.makeText(this, TagID, Toast.LENGTH_LONG).show();
            } catch (Exception ex) {
                new AlertDialog.Builder(this).setTitle("Error!").setPositiveButton("Ok",
                                                                                   new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Intent i = new Intent(ScanningActivity.this, ScanningActivity.class);
                        startActivity(i);
                    }
                }).setMessage(ex.getMessage() + "\n\nPlease click Ok. This will restart the application").create().show();

                new AlertDialog.Builder(this).setTitle("Transferring the data").setPositiveButton("Ok",
                                                                                                  new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
                        TextView tvData = (TextView)findViewById(R.id.Data);
                        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
                            Tag tag1 = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
                            String DataToSend = tvtime.getText().toString() + tag1.getId().toString();
                            //String DataToSend = "Data";
                            //tvData.setText(tvtime.getText().toString()+tag.getId().toString());
                            byte[] textBytes = DataToSend.getBytes(utfEncoding);
                            byte[] dataa = new byte[1 + langBytes.length + textBytes.length];
                            dataa[0] = (byte)status;
                            System.arraycopy(langBytes, 0, dataa, 1, langBytes.length);
                            System.arraycopy(textBytes, 0, dataa, 1 + langBytes.length, textBytes.length);;
                            NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                                                                   NdefRecord.RTD_TEXT, new byte[0], dataa);
                            NdefMessage newMessage = new NdefMessage(new NdefRecord[] { textRecord });

                            try {
                                writeNdefMessageToTag(newMessage, tag1);
                            } catch (FormatException e) {

                                e.printStackTrace();
                            }
                        }
                    }
                }).setMessage(
                        "Place this tablet on the RFID Tag on the Microbiology Form. Keep it there until you get to the next screen").create().show();

            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.scanning, menu);
        return true;
    }
}

and the Manifest is

<uses-permission android:name="android.permission.NFC"/>

<uses-sdk
    android:minSdkVersion="13"
    android:targetSdkVersion="17" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.tabletapp.ScanningActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain" />
        </intent-filter>
    </activity>
</application>

Update:

  1. The app does not show any toast. When I put a card/tag on the device, I am asked which app will I like to use. I select the one we are talking about and the 'ScanningActivity' (MainActivity) loads again. Neither does not show me the ID nor does it go past the scanning activity.

  2. I want to read the ID from a card and then write it, along with the timestamp, to another tag.

Michael Roland
  • 39,663
  • 10
  • 99
  • 206
CSA
  • 9
  • 5
  • I do not understand why someone has downvoted this question. If you felt it was not an appropriate question or if it lacked something, please comment as well. – CSA Apr 22 '15 at 08:43
  • What's the actual problem that you have? Does your app show any toast (one with the tag ID or any error message)? Do you want to read the ID from the tag and then write it to the same tag or to another tag? Does your app read the ID into `R.id.tagid` and your problem is that you can't write to the second tag or does it even fail at doing that? – Michael Roland Apr 23 '15 at 05:50
  • @MichaelRoland Here are the answers. Apologies for not being clear earlier. 1. The app does not show any toast. When I put a card/tag on the device, I am asked which app will I like to use. I select the one we are talking about and the 'ScanningActivity' (MainActivity) loads again. Neither does not show me the ID nor does it go past the scanning activity. 2. I want to read the ID from a card and then write it, along with the timestamp, to another tag. – CSA Apr 23 '15 at 11:22

1 Answers1

1

There's quite a lot of problems in your code, so I will just focus on the most obvious ones:

  1. You registered for the NDEF_DISCOVERED in your AndroidManifest.xml. However, in onCreate() you will only read the ID when you get a TAG_DISCOVERED intent. You have to change this to match the NDEF_DISCOVERED intent. (I hereby assume that you tag contains a text record that matches your intent filter.)

  2. tag.getId().toString() won't give you much useful information as tag.getId() returns a byte array. You might always want to use your bin2hex() method to convert the ID to a human-readable string.

  3. You should avoid to perform any interaction with NFC tags upon clicking a button. (I.e. what you currently do in onClick(DialogInterface dialog, int which).) Both, the button click and the NFC interaction should be considered as human-inputs and you should avoid to require two human inputs at the same time. (Moreover, bott are event based and you cannot directly combine them.) You could instead set a flag in the onClick() method that indicates that data should be written to the tag upon the next NFC discovery event.

  4. If you want to scan the first tag, launch your activity due to this event, and keep the activity open while you scan the second tag, you should use the foreground dispatch system (also see this answer). That way, you foreground activity can handle repeated scanning of tags without getting restarted (and without giving control to any other activity that would otherwise be triggered by a tag).

Community
  • 1
  • 1
Michael Roland
  • 39,663
  • 10
  • 99
  • 206