title: Getting an android app to detect NFC tags
body: <p>I have created an android app for reading NFC tags. <br><br>It can detect if an NFC is around, however it can't read the contents on it nor can I write anything on it. I also have problem with my code on line 79 of the <strong>read_write_successful</strong> class. I made use of the "<strong>createNdefMessage</strong>" method that was declared on line 190.</p>
  
  <p>Below is my code:</p>
  
  <p><strong><em>read_write_successful class</em></strong></p>
  
  <pre><code>public class read_write_successful extends AppCompatActivity {
  
  
      NfcAdapter nfcAdapter;
      ToggleButton tglReadWrite;
      TextView txtTagContent;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
          setContentView(R.layout.mattie_main);
          Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
          setSupportActionBar(toolbar);
  
          nfcAdapter = NfcAdapter.getDefaultAdapter(this);
          tglReadWrite = (ToggleButton)findViewById(R.id.tglReadWrite);
          txtTagContent = (TextView)findViewById(R.id.txtTagContent);
      }
  
      @Override
      protected void onResume() {
          super.onResume();
          enableForegroundDispatchSystem();
      }
  
      @Override
      protected void onPause() {
          super.onPause();
          disableForegroundDispatchSystem();
      }
  
      @Override
      protected void onNewIntent(Intent intent) {
          super.onNewIntent(intent);
          Toast.makeText(this, "NFC intent received!", Toast.LENGTH_LONG).show();
          if (intent.hasExtra(NfcAdapter.EXTRA_TAG)){
              if (tglReadWrite.isChecked()){
                  Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
  
                  if (parcelables != null &amp;&amp; parcelables.length &gt; 0){
                      readTextFromMessage((NdefMessage)parcelables[0]);
                  }
                  else {
  
                      Toast.makeText(this, "No NDEF messages found!", Toast.LENGTH_SHORT).show();
                  }
              }
              else {
                  Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                  NdefMessage ndefMessage = createNdefMessage(txtTagContent.getText() + "");
  
                  byte[] payload = "my string".getBytes();
                  NdefRecord ndefRecord = NdefRecord.createExternal("nfctutorials", "externaltype", payload);
                  ndefMessage = new NdefMessage(new NdefRecord[]{ ndefRecord });
  
                  writeNdefMessage(tag, ndefMessage);
              }
          }
      }
  
      private void readTextFromMessage(NdefMessage ndefMessage) {
          NdefRecord[] ndefRecords = ndefMessage.getRecords();
  
          if (ndefRecords != null &amp;&amp; ndefRecords.length &gt; 0){
  
              NdefRecord ndefRecord = ndefRecords[0];
              String tagContent = getTextFromNdefRecord(ndefRecord);
  
              txtTagContent.setText(tagContent);
          }
          else {
              Toast.makeText(this, "No NDEF records found!", Toast.LENGTH_SHORT).show();
          }
      }
  
      private void enableForegroundDispatchSystem(){
          Intent intent = new Intent(this, read_write_successful.class).addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
          PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
          IntentFilter[] intentFilters = new IntentFilter[]{};
          nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, null);
      }
  
      private void disableForegroundDispatchSystem(){
          nfcAdapter.disableForegroundDispatch(this);
      }
  
      private void formatTag(Tag tag, NdefMessage ndefMessage){
          try{
              NdefFormatable ndefFormatable = NdefFormatable.get(tag);
              if (ndefFormatable == null){
                  Toast.makeText(this, "Tag is not ndef formatable", Toast.LENGTH_SHORT).show();
                  return;
              }
  
              ndefFormatable.connect();
              ndefFormatable.format(ndefMessage);
              ndefFormatable.close();
  
              Toast.makeText(this, "Tag written!", Toast.LENGTH_SHORT).show();
          }
          catch (Exception e){
              Log.e("formatTag",e.getMessage());
          }
      }
  
      private void writeNdefMessage(Tag tag, NdefMessage ndefMessage){
          try{
  
              if (tag == null){
                  Toast.makeText(this, "Tag object cannot be null", Toast.LENGTH_SHORT).show();
                  return;
              }
  
              Ndef ndef = Ndef.get(tag);
              if (ndef == null){
                  //format tag with the ndef format and writes the message.
                  formatTag(tag, ndefMessage);
              }
              else {
                  ndef.connect();
                  if (!ndef.isWritable()){
                      Toast.makeText(this, "Tag is not writable!", Toast.LENGTH_SHORT).show();
  
                      ndef.close();
                      return;
                  }
  
                  ndef.writeNdefMessage(ndefMessage);
                  ndef.close();
  
                  Toast.makeText(this, "Tag written!", Toast.LENGTH_SHORT).show();
              }
          }
          catch (Exception e){
              Log.e("writeNdefMessage",e.getMessage());
          }
      }
  
      private NdefRecord createTextRecord(String content){
          try {
              byte[] language;
              language = Locale.getDefault().getLanguage().getBytes("UTF-8");
  
              final byte[] text = content.getBytes("UTF-8");
              final int languageSize = language.length;
              final int textLength = text.length;
              final ByteArrayOutputStream payload = new ByteArrayOutputStream(1 + languageSize + textLength);
  
              payload.write((byte) (languageSize &amp; 0x1F));
              payload.write(language, 0, languageSize);
              payload.write(text, 0, textLength);
  
              return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload.toByteArray());
          }
          catch (UnsupportedEncodingException e){
              Log.e("createNdefMessage",e.getMessage());
          }
          return null;
      }
  
      private NdefMessage createNdefMessage(String content){
          NdefRecord ndefRecord = createTextRecord(content);
  
          return new NdefMessage(new NdefRecord[]{ndefRecord});
      }
  
      public void tglReadWriteOnClick(View v){
          txtTagContent.setText("");
      }
  
      public String getTextFromNdefRecord(NdefRecord ndefRecord){
          String tagContent = null;
          try {
              byte[] payload = ndefRecord.getPayload();
              String textEncoding = ((payload[0] &amp; 128) == 0) ? "UTF-8" : "UTF-16";
              int languageSize = payload[0] &amp; 51;
              tagContent = new String(payload, languageSize + 1,
                      payload.length - languageSize - 1, textEncoding);
          }
          catch (UnsupportedEncodingException e){
              Log.e("getTextFromNdefRecord", e.getMessage(), e);
          }
          return tagContent;
      }
  }
  </code></pre>
  
  <p><strong><em>MainActivity class</em></strong></p>
  
  <pre><code>public class MainActivity extends AppCompatActivity {
  
  
      private KeyStore keyStore;
      // Variable used for storing the key in the Android Keystore container
      private static final String KEY_NAME = "WERTY";
      private Cipher cipher;
      TextView mattie;
      Button Login;
      Button SignUp;
      Button NextButton;
      Button WriteButton;
      NfcAdapter nfcAdapter;
      ToggleButton tglReadWrite;
      EditText txtTagContent;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
          setContentView(R.layout.activity_main);
  
          Login = (Button) findViewById(R.id.btn_logIn);
          SignUp = (Button)findViewById(R.id.btn_signUp);
          NextButton = (Button)findViewById(R.id.btn_next);
          WriteButton = (Button)findViewById(R.id.btn_write);
          mattie = (TextView)findViewById(R.id.txtMatma);
          Typeface myCustomFont = Typeface.createFromAsset(getAssets(), "fonts/Praetoria D.otf");
          mattie.setTypeface(myCustomFont);
  
          findViewById(R.id.btn_play_again).setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  // We normally won't show the welcome slider again in real app
                  // but this is for testing
                  PrefManager prefManager = new PrefManager(getApplicationContext());
  
                  // make first time launch TRUE
                  prefManager.setFirstTimeLaunch(true);
  
                  startActivity(new Intent(MainActivity.this, WelcomeActivity.class));
                  finish();
              }
          });
  
          // Initializing both Android Keyguard Manager and Fingerprint Manager
          KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
          FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
  
  
          // Checks whether fingerprint permission is set on manifest
          if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
              // TODO: Consider calling
              //    ActivityCompat#requestPermissions
              // here to request the missing permissions, and then overriding
              // public void onRequestPermissionsResult(int requestCode, String[] permissions,
              //                                          int[] grantResults)
              // to handle the case where the user grants the permission. See the documentation
              // for ActivityCompat#requestPermissions for more details.
              return;
          }
  
          // Check whether the device has a Fingerprint sensor.
          if (!fingerprintManager.isHardwareDetected()) {
              Toast.makeText(this, "Your Device does not have a Fingerprint Sensor", Toast.LENGTH_SHORT).show();
          }
          else {
              // Checks whether fingerprint permission is set on manifest
              if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
                  Toast.makeText(this, "Fingerprint authentication permission not enabled", Toast.LENGTH_SHORT).show();
              } else {
                  // Check whether at least one fingerprint is registered
                  if (!fingerprintManager.hasEnrolledFingerprints()) {
                      Toast.makeText(this, "Register at least one fingerprint in Settings", Toast.LENGTH_SHORT).show();
                  } else {
                      // Checks whether lock screen security is enabled or not
                      if (!keyguardManager.isKeyguardSecure()) {
                          Toast.makeText(this, "Lock Screen security not enabled in Settings", Toast.LENGTH_SHORT).show();
                      } else {
                          genKey();
                      }
  
                      if (cipherInit()) {
                          FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
                          FingerprintHandler helper = new FingerprintHandler(this);
                          Register assistance = new Register(this);
                          helper.startAuthentication(fingerprintManager, cryptoObject);
                          assistance.startAuthentication(fingerprintManager, cryptoObject);
                      }
                  }
              }
          }
  
          nfcAdapter = NfcAdapter.getDefaultAdapter(this);
          tglReadWrite = (ToggleButton)findViewById(R.id.tglReadWrite);
          txtTagContent = (EditText) findViewById(R.id.txtTagContent);
          if (nfcAdapter!=null &amp;&amp; nfcAdapter.isEnabled()){
              Toast.makeText(this, "NFC available!", Toast.LENGTH_LONG).show();
          }
          else{
              Toast.makeText(this, "NFC not available! Kindly switch it on in your phone's settings.", Toast.LENGTH_SHORT).show();
              finish();
          }
      }
  
  
      @TargetApi(Build.VERSION_CODES.M)
      private void genKey() {
          try {
              keyStore = KeyStore.getInstance("AndroidKeyStore");
          }
          catch (Exception e) {
              e.printStackTrace();
          }
  
          KeyGenerator keyGenerator;
          try {
              keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES,"AndroidKeyStore");
          } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
              throw new RuntimeException("Failed to get KeyGenerator instance", e);
          }
  
          try {
              keyStore.load(null);
              keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME,KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                      .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                      .setUserAuthenticationRequired(true)
                      .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7).build()
              );
              keyGenerator.generateKey();
          } catch (NoSuchAlgorithmException |
                  InvalidAlgorithmParameterException
                  | CertificateException | IOException e) {
              throw new RuntimeException(e);
          }
      }
  
      @TargetApi(Build.VERSION_CODES.M)
      private boolean cipherInit() {
          try {
              cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES+ "/" +KeyProperties.BLOCK_MODE_CBC+ "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
          } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
              throw new RuntimeException("Failed to get Cipher", e);
          }
  
          try {
              keyStore.load(null);
              SecretKey key = (SecretKey)keyStore.getKey(KEY_NAME, null);
              cipher.init(Cipher.ENCRYPT_MODE, key);
              return true;
          } catch (KeyPermanentlyInvalidatedException e) {
              return false;
          } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
              throw new RuntimeException("Failed to init Cipher", e);
          }
      }
  
      public void signUpBtn(View v){
          Intent iv = new Intent(this, CardNumberSignUpActivity.class);
          startActivity(iv);
      }
      public void loginBtn(View v){
          Intent i = new Intent(this,LoginSuccessfulActivity.class);
          startActivity(i);
      }
  
      public void nextBtn(View v){
          Intent ii = new Intent(this, register_security_successful.class);
          startActivity(ii);
      }
  
      public void writeBtn(View v){
          Intent iii = new Intent(this, read_write_successful.class );
          startActivity(iii);
      }
  
  }
  </code></pre>
  
  <p><strong><em>read_write_successful layout [Relative Layout]</em></strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  
  
  &lt;RelativeLayout 
  
  
  
  xmlns:android="http://schemas.android.com/apk/res/android"
  
  
      android:layout_width="match_parent"
      android:layout_height="match_parent"&gt;
  
      &lt;ToggleButton
          android:text="ToggleButton"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:id="@+id/tglReadWrite"
          android:textOn="@string/txtOn"
          android:textOff="@string/txtOff"
          android:checked="true"
          android:onClick="tglReadWriteOnClick"/&gt;
  
      &lt;EditText
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:id="@+id/txtTagContent"
          android:layout_below="@+id/tglReadWrite"
          android:inputType="text" /&gt;
  &lt;/RelativeLayout&gt;
  </code></pre>