2021-02-16 13:42:49 +01:00
|
|
|
package com.jens.automation2.receivers;
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.pm.PackageManager;
|
|
|
|
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.Build;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
|
|
import com.jens.automation2.AutomationService;
|
|
|
|
import com.jens.automation2.Miscellaneous;
|
|
|
|
import com.jens.automation2.R;
|
|
|
|
import com.jens.automation2.Rule;
|
2021-12-13 20:03:00 +01:00
|
|
|
import com.jens.automation2.Trigger;
|
2021-02-16 13:42:49 +01:00
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
|
|
|
@SuppressLint("NewApi")
|
|
|
|
public class NfcReceiver
|
|
|
|
{
|
|
|
|
public static final String MIME_TEXT_PLAIN = "text/plain";
|
|
|
|
public static String lastReadLabel = null;
|
|
|
|
|
|
|
|
private static NfcAdapter nfcAdapter = null;
|
|
|
|
public static NfcAdapter getNfcAdapter(Context context)
|
|
|
|
{
|
|
|
|
if(nfcAdapter == null)
|
|
|
|
{
|
|
|
|
if(Build.VERSION.SDK_INT <= 10)
|
|
|
|
{
|
|
|
|
// NFC not supported until after Gingerbread.
|
|
|
|
Miscellaneous.logEvent("w", "NFC", context.getResources().getString(R.string.nfcNotSupportedInThisAndroidVersionYet), 3);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nfcAdapter = NfcAdapter.getDefaultAdapter(context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nfcAdapter;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void setNfcAdapter(NfcAdapter nfcAdapter)
|
|
|
|
{
|
|
|
|
NfcReceiver.nfcAdapter = nfcAdapter;
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressLint("NewApi")
|
|
|
|
public static void checkIntentForNFC(Context context, Intent intent)
|
|
|
|
{
|
|
|
|
if(!NfcReceiver.checkNfcRequirements(context, false))
|
|
|
|
return;
|
|
|
|
|
|
|
|
String action = intent.getAction();
|
|
|
|
if(action == null)
|
|
|
|
{
|
|
|
|
Miscellaneous.logEvent("i", "NFC", "action=null", 5);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
|
|
|
|
{
|
|
|
|
Miscellaneous.logEvent("i", "NFC", "ACTION_NDEF_DISCOVERED", 4);
|
|
|
|
|
|
|
|
getNfcAdapter(context);
|
|
|
|
|
|
|
|
if(nfcAdapter == null) // if it's still null the device doesn't support NFC
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
String mimeType = intent.getType();
|
|
|
|
if(mimeType.equals(MIME_TEXT_PLAIN))
|
|
|
|
{
|
|
|
|
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
|
|
|
|
|
|
|
|
// if(NfcReceiver.discoveredTag == null)
|
|
|
|
// NfcReceiver.discoveredTag = tag;
|
|
|
|
|
|
|
|
new NdefReaderTask().execute(tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action))
|
|
|
|
// {
|
|
|
|
//
|
|
|
|
// // In case we would still use the Tech Discovered Intent
|
|
|
|
// Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
|
|
|
|
// String[] techList = tag.getTechList();
|
|
|
|
// String searchedTech = Ndef.class.getName();
|
|
|
|
//
|
|
|
|
// for (String tech : techList)
|
|
|
|
// {
|
|
|
|
// if (searchedTech.equals(tech))
|
|
|
|
// {
|
|
|
|
// new NdefReaderTask().execute(tag);
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// // No NFC NDEF intent
|
|
|
|
// Miscellaneous.logEvent("w", "NFC", context.getResources().getString(R.string.nfcNoNdefIntentBut) + " " + action + ".", 5);
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressLint("NewApi")
|
|
|
|
public static class NdefReaderTask extends AsyncTask<Tag, Void, String>
|
|
|
|
{
|
|
|
|
@Override
|
|
|
|
protected String doInBackground(Tag... params)
|
|
|
|
{
|
|
|
|
Tag tag = params[0];
|
|
|
|
|
|
|
|
Ndef ndef = Ndef.get(tag);
|
|
|
|
if (ndef == null)
|
|
|
|
{
|
|
|
|
// NDEF is not supported by this Tag.
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
|
|
|
|
NdefRecord[] records = ndefMessage.getRecords();
|
|
|
|
for (NdefRecord ndefRecord : records)
|
|
|
|
{
|
|
|
|
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT))
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return readText(ndefRecord);
|
|
|
|
}
|
|
|
|
catch (UnsupportedEncodingException e)
|
|
|
|
{
|
|
|
|
Miscellaneous.logEvent("e", "NFC", Miscellaneous.getAnyContext().getString(R.string.nfcUnsupportedEncoding) + " " + Log.getStackTraceString(e), 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
|
|
|
|
// return readTag(tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPostExecute(String result)
|
|
|
|
{
|
|
|
|
if (result != null && result.length() > 0)
|
|
|
|
{
|
|
|
|
// Text of tag is now stored in variable "result"
|
|
|
|
lastReadLabel = result;
|
|
|
|
Miscellaneous.logEvent("i", "NFC", Miscellaneous.getAnyContext().getResources().getString(R.string.nfcTagFoundWithText) + " " + result, 3);
|
|
|
|
Toast.makeText(Miscellaneous.getAnyContext(), Miscellaneous.getAnyContext().getResources().getString(R.string.nfcTagFoundWithText) + " " + result, Toast.LENGTH_LONG).show();
|
|
|
|
|
|
|
|
AutomationService asInstance = AutomationService.getInstance();
|
|
|
|
if(asInstance == null)
|
|
|
|
{
|
|
|
|
Context context = Miscellaneous.getAnyContext();
|
|
|
|
if(context != null)
|
|
|
|
{
|
|
|
|
Miscellaneous.logEvent("w", "NFC", context.getResources().getString(R.string.serviceNotRunning) + " " + context.getResources().getString(R.string.cantRunRule), 4);
|
|
|
|
Toast.makeText(context, context.getResources().getString(R.string.serviceNotRunning) + " " + context.getResources().getString(R.string.cantRunRule), Toast.LENGTH_LONG).show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-12-13 20:03:00 +01:00
|
|
|
ArrayList<Rule> allRulesWithNfcTags = Rule.findRuleCandidates(Trigger.Trigger_Enum.nfcTag);
|
2021-02-16 13:42:49 +01:00
|
|
|
for(int i=0; i<allRulesWithNfcTags.size(); i++)
|
|
|
|
{
|
2021-12-07 23:10:37 +01:00
|
|
|
if(allRulesWithNfcTags.get(i).getsGreenLight(asInstance))
|
2021-02-16 13:42:49 +01:00
|
|
|
allRulesWithNfcTags.get(i).activate(asInstance, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class NdefWriterTask extends AsyncTask<Object, Void, Boolean>
|
|
|
|
{
|
|
|
|
@Override
|
|
|
|
protected Boolean doInBackground(Object... params)
|
|
|
|
{
|
|
|
|
String textToWrite = (String)params[0];
|
|
|
|
Tag tagToWrite = (Tag)params[1];
|
|
|
|
return writeTag(textToWrite, tagToWrite);
|
|
|
|
}
|
|
|
|
|
|
|
|
// @Override
|
|
|
|
// protected void onPostExecute(Boolean result)
|
|
|
|
// {
|
|
|
|
// return result;
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String readTag(Tag tag)
|
|
|
|
{
|
|
|
|
// if(tag == null)
|
|
|
|
// {
|
|
|
|
// Toast.makeText(Miscellaneous.getAnyContext(), Miscellaneous.getAnyContext().getResources().getString(R.string.nfcNoTag), Toast.LENGTH_LONG).show();
|
|
|
|
// return null;
|
|
|
|
// }
|
|
|
|
|
|
|
|
Ndef ndef = Ndef.get(tag);
|
|
|
|
if (ndef == null)
|
|
|
|
{
|
|
|
|
// NDEF is not supported by this Tag.
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
|
|
|
|
|
|
|
|
NdefRecord[] records = ndefMessage.getRecords();
|
|
|
|
for (NdefRecord ndefRecord : records)
|
|
|
|
{
|
|
|
|
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT))
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
return readText(ndefRecord);
|
|
|
|
}
|
|
|
|
catch (UnsupportedEncodingException e)
|
|
|
|
{
|
|
|
|
Miscellaneous.logEvent("w", "NFC", "Unsupported Encoding: " + Log.getStackTraceString(e), 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static String readText(NdefRecord record) throws UnsupportedEncodingException
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
|
|
|
|
*
|
|
|
|
* http://www.nfc-forum.org/specs/
|
|
|
|
*
|
|
|
|
* bit_7 defines encoding
|
|
|
|
* bit_6 reserved for future use, must be 0
|
|
|
|
* bit_5..0 length of IANA language code
|
|
|
|
*/
|
|
|
|
|
|
|
|
byte[] payload = record.getPayload();
|
|
|
|
|
|
|
|
// Get the Text Encoding
|
|
|
|
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
|
|
|
|
|
|
|
|
// Get the Language Code
|
|
|
|
int languageCodeLength = payload[0] & 0063;
|
|
|
|
|
|
|
|
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
|
|
|
|
// e.g. "en"
|
|
|
|
|
|
|
|
// Get the Text
|
|
|
|
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean writeTag(String textToWrite, Tag tag)
|
|
|
|
{
|
|
|
|
Miscellaneous.logEvent("i", "NFC", "Attempting to write tag...", 2);
|
|
|
|
|
|
|
|
String packageName = Miscellaneous.getAnyContext().getPackageName();
|
|
|
|
NdefRecord appRecord = NdefRecord.createApplicationRecord(packageName);
|
|
|
|
// Record with actual data we care about
|
|
|
|
byte[] textBytes = textToWrite.getBytes();
|
|
|
|
byte[] textPayload = new byte[textBytes.length + 3];
|
|
|
|
textPayload[0] = 0x02; // 0x02 = UTF8
|
|
|
|
textPayload[1] = 'e'; // Language = en
|
|
|
|
textPayload[2] = 'n';
|
|
|
|
System.arraycopy(textBytes, 0, textPayload, 3, textBytes.length);
|
|
|
|
NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], textPayload);
|
|
|
|
|
|
|
|
// Complete NDEF message with both records
|
|
|
|
NdefMessage completeMessageToWrite = new NdefMessage(new NdefRecord[] {textRecord, appRecord});
|
|
|
|
|
|
|
|
int size = completeMessageToWrite.toByteArray().length;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
Ndef ndef = Ndef.get(tag);
|
|
|
|
if (ndef != null)
|
|
|
|
{
|
|
|
|
ndef.connect();
|
|
|
|
if (ndef.isWritable() && ndef.getMaxSize() > size)
|
|
|
|
{
|
|
|
|
ndef.writeNdefMessage(completeMessageToWrite);
|
|
|
|
Miscellaneous.logEvent("i", "NFC", "Done writing tag.", 2);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
NdefFormatable format = NdefFormatable.get(tag);
|
|
|
|
if (format != null)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
format.connect();
|
|
|
|
format.format(completeMessageToWrite);
|
|
|
|
Miscellaneous.logEvent("i", "NFC", "Done writing tag.", 2);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
catch(IOException e)
|
|
|
|
{
|
|
|
|
Miscellaneous.logEvent("e", "NFC", "Error writing tag: " + Log.getStackTraceString(e), 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(Exception e)
|
|
|
|
{
|
|
|
|
Miscellaneous.logEvent("e", "NFC", "Error writing tag: " + Log.getStackTraceString(e), 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean checkNfcRequirements(Context context, boolean showErrorMessage)
|
|
|
|
{
|
|
|
|
if(!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC))
|
|
|
|
{
|
|
|
|
if(showErrorMessage)
|
|
|
|
Toast.makeText(context, context.getResources().getString(R.string.deviceDoesNotHaveNfc), Toast.LENGTH_LONG).show();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if(Build.VERSION.SDK_INT <= 10)
|
|
|
|
{
|
|
|
|
// NFC not supported until after Gingerbread.
|
|
|
|
if(showErrorMessage)
|
|
|
|
Toast.makeText(context, context.getResources().getString(R.string.nfcNotSupportedInThisAndroidVersionYet), Toast.LENGTH_LONG).show();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|