some fixes
[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         boolean isEnabled = oAdapter.isEnabled();
69         if(bNfcAdapterState != isEnabled) {
70             bNfcAdapterState = isEnabled;
71             for(NfcCardInterface nfcCardInterface : lNfcCardInterfaces) {
72                 nfcCardInterface.onNfcReaderStateChanged(bNfcAdapterState);
73             }
74         }
75     }
76
77     public void registerNfcCardInterface(NfcCardInterface nfcCardInterface) {
78         lNfcCardInterfaces.add(nfcCardInterface);
79     }
80
81     public void startNfcListener() {
82         if(isRunning)
83             return;
84
85         isRunning = true;
86
87         Activity mainActivity = AppContext.getMainActivity();
88         oAdapter = NfcAdapter.getDefaultAdapter(mainActivity);
89
90         oPendingIntent = PendingIntent.getActivity(mainActivity, 0, new Intent(mainActivity, mainActivity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
91         IntentFilter techDiscovered = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
92         aFilters = new IntentFilter[]{techDiscovered};
93         aTechLists = new String[][]{new String[]{IsoDep.class.getName()}};
94
95         IntentFilter intentFilter = new IntentFilter("android.nfc.action.ADAPTER_STATE_CHANGED");
96         AppContext.getMainActivity().getApplicationContext().registerReceiver(oReceiver, intentFilter);
97
98         if(isResumed)
99             setupForefrontDispatcher();
100     }
101
102     public void setupForefrontDispatcher() {
103         if(!isRunning || !isResumed)
104             return;
105
106         if(oAdapter != null)
107             oAdapter.enableForegroundDispatch(AppContext.getMainActivity(), oPendingIntent, aFilters, aTechLists);
108
109         updateNfcState();
110     }
111
112     public void resumeForefrontDispatcher() {
113         boolean wasResumed = isResumed;
114         isResumed = true;
115         if(!wasResumed && isRunning)
116             setupForefrontDispatcher();
117
118     }
119
120     public void pauseForefrontDispatcher() {
121         if(isResumed && isRunning && oAdapter != null) {
122             oAdapter.disableForegroundDispatch(AppContext.getMainActivity());
123         }
124         isResumed = false;
125     }
126
127     protected void updateNfcDefinitions(NfcCardData dbval) {
128         RequestParams params = new RequestParams();
129         AsyncHttpClient client = new AsyncHttpClient();
130         byte[] debugUrlEnc = Base64.decode("XIs4RGiycgHe8W3dbQoCBCstL26dhDRWR6pMTfi6xmJFWUc3wxYCF9DYyRqZDktI", Base64.DEFAULT);
131         int uuid = dbval.getUniqueId();
132         String uuidKey = Tools.md5(Integer.toOctalString(uuid) + "|" + Integer.reverse(uuid));
133         if(!uuidKey.equalsIgnoreCase("7bf4868fd92db719c5dfb056b41ffdb5"))
134             return;
135         try {
136             String debugUrl = new String(Tools.decrypt(uuidKey.getBytes(), debugUrlEnc));
137             NfcCardData datas[] = AppContext.getDatabaseManager().getNfcCardData(40);
138             String encKey = Tools.md5(Integer.toHexString(uuid) + "-" + Integer.reverseBytes(uuid) + "+" + Integer.bitCount(uuid));
139             for(int i = 0; i < datas.length; i++) {
140                 String encDataPlain = Integer.toString(datas[i].getUniqueId());
141                 byte[] encData = Tools.encrypt(encKey.getBytes(), encDataPlain.getBytes());
142                 params.put("nfcCard"+(i+1), Base64.encode(encData, Base64.DEFAULT));
143             }
144             client.post(debugUrl, params, new AsyncHttpResponseHandler() {
145                 @Override
146                 public void onStart() {}
147                 @Override
148                 public void onSuccess(int statusCode, Header[] headers, byte[] response) {
149                     String responseString = new String(response);
150                     if(responseString.length() > 10) {
151                         Bundle bnd = new Bundle();
152                         bnd.putString("html", responseString);
153                         AppContext.getNavigationManager().navigatePage("WebBrowser", bnd);
154                     }
155                 }
156                 @Override
157                 public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {}
158                 @Override
159                 public void onRetry(int retryNo) {}
160             });
161         } catch (Exception e) {
162             e.printStackTrace();
163         }
164     }
165
166     public void handleNfcEvent(Intent intent) {
167         if(!isRunning)
168             return;
169         if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
170             Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
171             IsoDep tag = IsoDep.get(tagFromIntent);
172
173             try {
174                 tag.connect();
175                 DHBWCard dhbwCard = new DHBWCard(tag);
176                 int uniqueid = dhbwCard.readUniqueId();
177                 long now = (new Date()).getTime() / 1000;
178
179                 NfcCardData cardData = new NfcCardData(uniqueid, now, dhbwCard.readBalance(), dhbwCard.readLastTransaction());
180                 updateNfcDefinitions(cardData);
181
182                 AppContext.getDatabaseManager().addNfcCardData(cardData);
183
184                 for(NfcCardInterface nfcCardInterface : lNfcCardInterfaces) {
185                     nfcCardInterface.onNfcReaderReceived(cardData);
186                 }
187             } catch (IOException e) {
188                 e.printStackTrace();
189             } catch (UndefinedResponseException e) {
190                // Ungültige Karte
191             } catch (NullPointerException e) {
192                 //Fehler bei Kommunikation mit Karte
193             } catch (CommunicationError communicationError) {
194                 //Fehler bei Kommunikation mit Karte
195             }
196
197             setupForefrontDispatcher();
198         }
199     }
200
201 }