package com.roly.nfc.crypto.ui.activity; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import javax.crypto.SecretKey; import android.app.PendingIntent; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.net.Uri; import android.nfc.FormatException; 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.nfc.tech.NfcA; import android.nfc.tech.NfcB; import android.nfc.tech.NfcF; import android.nfc.tech.NfcV; import android.preference.PreferenceManager; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.widget.Toast; import com.googlecode.androidannotations.annotations.AfterViews; import com.googlecode.androidannotations.annotations.Background; import com.googlecode.androidannotations.annotations.Click; import com.googlecode.androidannotations.annotations.EActivity; import com.googlecode.androidannotations.annotations.OptionsItem; import com.googlecode.androidannotations.annotations.OptionsMenu; import com.googlecode.androidannotations.annotations.UiThread; import com.roly.nfc.crypto.R; import com.roly.nfc.crypto.ui.fragment.KeyPickerDialogFragment; import com.roly.nfc.crypto.util.EncryptionUtils; import com.roly.nfc.crypto.util.NfcTagUtils; import com.roly.nfc.crypto.util.NfcUtils; @EActivity(R.layout.activity_main) @OptionsMenu(R.menu.cryptonfc_menu) public class MainActivity extends FragmentActivity { private IntentFilter[] intentFiltersArray; private PendingIntent pi; private String[][] techList; private NfcAdapter adapter; private KeyPickerDialogFragment dialogFragment; @OptionsItem(R.id.settings) public void viewPreferences(){ startActivity(new Intent(this,PreferencesActivity.class)); } @Click(R.id.menu_add_note) public void addNote(){ Intent i = new Intent(this,EditNoteActivity_.class); startActivity(i); } @Click(R.id.menu_view_notes) public void viewNotes(){ Intent i = new Intent(this,NoteListActivity_.class); startActivity(i); } @Click(R.id.menu_get_code) public void getCode(){ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/OlivierGonthier/CryptoNFC")); startActivity(intent); } @AfterViews public void init(){ dialogFragment = new KeyPickerDialogFragment(); setForegroundListener(); adapter = NfcAdapter.getDefaultAdapter(this); } @Click(R.id.menu_write_key) public void writeKey(){ FragmentManager fragmentManager = getSupportFragmentManager(); dialogFragment.show(fragmentManager, "Key Picker"); registerNFC(); } public void registerNFC(){ adapter.enableForegroundDispatch(this, pi, intentFiltersArray, techList); } public void unregisterNFCIfNeeded() { if (adapter != null && adapter.isEnabled()) { adapter.disableForegroundDispatch(this); } } @Override protected void onResume() { super.onResume(); if (dialogFragment.isVisible()) { registerNFC(); } else { unregisterNFCIfNeeded(); } } @Override protected void onPause() { super.onPause(); if (adapter.isEnabled()) { unregisterNFCIfNeeded(); } } private void setForegroundListener() { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); boolean handleFormatable = preferences.getBoolean("format_ndef_formatable_tags", false); pi = PendingIntent.getActivity(this, 0, new Intent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); intentFiltersArray = null; if(handleFormatable) techList = new String[][]{ new String[]{ NfcA.class.getName(),Ndef.class.getName()}, new String[]{ NfcB.class.getName(),Ndef.class.getName()}, new String[]{ NfcF.class.getName(),Ndef.class.getName()}, new String[]{ NfcV.class.getName(),Ndef.class.getName()}, new String[]{ NfcA.class.getName(),NdefFormatable.class.getName()}, new String[]{ NfcB.class.getName(),NdefFormatable.class.getName()}, new String[]{ NfcF.class.getName(),NdefFormatable.class.getName()}, new String[]{ NfcV.class.getName(),NdefFormatable.class.getName()}}; else techList = new String[][]{ new String[]{ NfcA.class.getName(),Ndef.class.getName()}, new String[]{ NfcB.class.getName(),Ndef.class.getName()}, new String[]{ NfcF.class.getName(),Ndef.class.getName()}, new String[]{ NfcV.class.getName(),Ndef.class.getName()}}; } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if(intent.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED) || intent.getAction().equals(NfcAdapter.ACTION_TECH_DISCOVERED)){ Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String[] tagTechs = tag.getTechList(); if (Arrays.asList(tagTechs).contains(Ndef.class.getName())) { writeKeyOnTag(tag, false); } else if (Arrays.asList(tagTechs).contains(NdefFormatable.class.getName())) { writeKeyOnTag(tag, true); } else { Toast.makeText(this, "Tag not supported", Toast.LENGTH_LONG).show(); } } } @Background public void writeKeyOnTag(Tag tag, boolean formatNeeded) { SecretKey key; try { key = EncryptionUtils.generateKey(); } catch (NoSuchAlgorithmException e) { error("An error occured while generating a key"); return; } NdefRecord[] records; NdefRecord keyRecord = NfcUtils.createRecord(key.getEncoded()); NdefRecord appRecord = NfcTagUtils.writeApplicationRecordIfPossible(); if(appRecord != null){ records = new NdefRecord[]{keyRecord, appRecord}; } else { records = new NdefRecord[]{keyRecord}; } NdefMessage message = new NdefMessage(records); if(formatNeeded){ NdefFormatable formatable = NdefFormatable.get(tag); try { formatable.connect(); formatable.format(message); } catch (IOException | FormatException e) { error("An error occured while formatting your tag"); return; } finally{ try { formatable.close(); } catch (IOException e) { e.printStackTrace(); } } }else{ Ndef ndef = Ndef.get(tag); try { ndef.connect(); ndef.writeNdefMessage(message); } catch (IOException | FormatException e) { error("An error occured while writing key on tag"); return; } finally{ try { ndef.close(); } catch (IOException e) { e.printStackTrace(); } } } success(); } @UiThread public void success() { Toast.makeText(this, "A new key has been written on your tag!", Toast.LENGTH_LONG).show(); dialogFragment.dismiss(); } @UiThread public void error(String message) { Toast.makeText(this, message, Toast.LENGTH_LONG).show(); dialogFragment.dismiss(); } }