/**************************************************************************** * Copyright (C) 2012 HS Coburg. * All rights reserved. * Contact: ecsec GmbH (info@ecsec.de) * * This file is part of the Open eCard App. * * GNU General Public License Usage * This file may be used under the terms of the GNU General Public * License version 3.0 as published by the Free Software Foundation * and appearing in the file LICENSE.GPL included in the packaging of * this file. Please review the following information to ensure the * GNU General Public License version 3.0 requirements will be met: * http://www.gnu.org/copyleft/gpl.html. * * Other Usage * Alternatively, this file may be used in accordance with the terms * and conditions contained in a signed written agreement between * you and ecsec GmbH. * ***************************************************************************/ package org.openecard.android; import android.app.Activity; import android.app.Application; import android.app.Notification; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.nfc.NfcAdapter; import android.nfc.NfcManager; import android.preference.PreferenceManager; import iso.std.iso_iec._24727.tech.schema.ConnectionHandleType; import iso.std.iso_iec._24727.tech.schema.EstablishContext; import iso.std.iso_iec._24727.tech.schema.EstablishContextResponse; import java.io.File; import org.openecard.addon.AddonManager; import org.openecard.android.activities.TerminalFactoryActivity; import org.openecard.common.ClientEnv; import org.openecard.common.ECardConstants; import org.openecard.common.I18n; import org.openecard.common.enums.EventType; import org.openecard.common.ifd.AndroidTerminalFactory; import org.openecard.common.interfaces.Dispatcher; import org.openecard.common.interfaces.EventCallback; import org.openecard.common.sal.state.CardStateMap; import org.openecard.common.sal.state.SALStateCallback; import org.openecard.event.EventManager; import org.openecard.gui.MessageDialog; import org.openecard.gui.UserConsent; import org.openecard.gui.android.AndroidUserConsent; import org.openecard.gui.message.DialogType; import org.openecard.ifd.protocol.pace.PACEProtocolFactory; import org.openecard.ifd.scio.IFD; import org.openecard.ifd.scio.IFDException; import org.openecard.ifd.scio.IFDProperties; import org.openecard.ifd.scio.wrapper.IFDTerminalFactory; import org.openecard.management.TinyManagement; import org.openecard.recognition.CardRecognition; import org.openecard.sal.TinySAL; import org.openecard.scio.NFCFactory; import org.openecard.transport.dispatcher.MessageDispatcher; import org.openecard.ws.marshal.WSMarshallerException; import org.openecard.ws.marshal.WsdefProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class is instantiated when the process of this application is created. * Therefore the global application state is maintained here. * * @author Dirk Petrautzki <petrautzki@hs-coburg.de> */ public class ApplicationContext extends Application implements EventCallback { private static final Logger logger = LoggerFactory.getLogger(ApplicationContext.class); private final I18n lang = I18n.getTranslation("android"); private static final String SDCARD_OPENECARD = "/sdcard/.openecard/"; private static final int NOTIFICATION_ID = 22; private ClientEnv env; private TinySAL sal; private IFD ifd; private CardRecognition recognition; private CardStateMap cardStates; private EventManager em; private TinyManagement management; private byte[] contextHandle; private Dispatcher dispatcher; private boolean initialized; private UserConsent gui; private AndroidTerminalFactory terminalFactory; private boolean usingNFC; private NotificationManager notificationManager; private AddonManager manager; public boolean usingNFC() { return usingNFC; } public boolean isInitialized() { return initialized; } public CardRecognition getRecognition() { return recognition; } public CardStateMap getCardStates() { return cardStates; } public ClientEnv getEnv() { return env; } public UserConsent getGUI() { return gui; } public AddonManager getManager() { return manager; } /** * Shut down the whole client by shutting down components. */ public void shutdown() { logger.debug("shutdown"); // shutdown is currently disabled because of the binding changeover /* // destroy EventManager try { if (em != null) { em.terminate(); } } catch (Exception ex) { logger.error("An exception occurred while destroying EventManager.", ex); } finally { em = null; recognition = null; } // destroy Management try { if (management != null) { TerminateFramework terminateFramework = new TerminateFramework(); management.terminateFramework(terminateFramework); } } catch (Exception ex) { logger.error("An exception occurred while destroying Management.", ex); } finally { management = null; } // destroy SAL try { if (sal != null) { Terminate terminate = new Terminate(); sal.terminate(terminate); } } catch (Exception ex) { logger.error("An exception occurred while destroying SAL.", ex); } finally { sal = null; cardStates = null; } // destroy IFD try { if (ifd != null) { ReleaseContext releaseContext = new ReleaseContext(); releaseContext.setContextHandle(contextHandle); ifd.releaseContext(releaseContext); } } catch (Exception ex) { logger.error("An exception occurred while destroying IFD.", ex); } finally { ifd = null; contextHandle = null; } // destroy TerminalFactory try { if (terminalFactory != null) { terminalFactory.stop(); } } catch (Exception ex) { logger.error("An exception occurred while destroying TerminalFactory.", ex); } finally { terminalFactory = null; } // destroy the remaining components env = null; initialized = false; */ Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); File f = new File(SDCARD_OPENECARD); Uri uri = Uri.fromFile(f); intent.setData(uri); sendBroadcast(intent); } /** * Initialize the client by setting properties for Android and starting up each module. * * @param activityContext */ public void initialize(Activity activityContext) { logger.debug("initialize"); if (initialized) { return; } // GUI gui = new AndroidUserConsent(activityContext); notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); // load logging config AndroidUtils.initLogging(this); // read factory out of preferences SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); String noFactory = ""; String factoryImpl = preferences.getString("org.openecard.ifd.scio.factory.impl", noFactory); // if there was no factory set, start the activity to set one and return if (factoryImpl.equals(noFactory)) { Intent i = new Intent(this, TerminalFactoryActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.putExtra("firstStart", true); this.startActivity(i); return; } IFDProperties.setProperty("org.openecard.ifd.scio.factory.impl", factoryImpl); WsdefProperties.setProperty("org.openecard.ws.marshaller.impl", "org.openecard.ws.android.AndroidMarshaller"); try { terminalFactory = (AndroidTerminalFactory) IFDTerminalFactory.getInstance(); } catch (IFDException e) { //TODO log System.exit(0); } usingNFC = terminalFactory instanceof NFCFactory; if (usingNFC) { NfcManager nfcManager = (NfcManager) this.getSystemService(Context.NFC_SERVICE); NfcAdapter adapter = nfcManager.getDefaultAdapter(); if (adapter == null || !adapter.isEnabled()) { MessageDialog dialog = gui.obtainMessageDialog(); String message = lang.translationForKey("android.error.nfc_error"); String title = lang.translationForKey("error"); dialog.showMessageDialog(message, title, DialogType.ERROR_MESSAGE); return; } } terminalFactory.start(this); // Client environment env = new ClientEnv(); // Management management = new TinyManagement(env); env.setManagement(management); // Dispatcher dispatcher = new MessageDispatcher(env); env.setDispatcher(dispatcher); // IFD ifd = new IFD(); ifd.setDispatcher(dispatcher); ifd.setGUI(gui); ifd.addProtocol(ECardConstants.Protocol.PACE, new PACEProtocolFactory()); env.setIFD(ifd); EstablishContext establishContext = new EstablishContext(); EstablishContextResponse establishContextResponse = ifd.establishContext(establishContext); if (establishContextResponse.getResult().getResultMajor().equals(ECardConstants.Major.OK)) { if (establishContextResponse.getContextHandle() != null) { contextHandle = establishContextResponse.getContextHandle(); } else { logger.error("EstablishContext failed."); MessageDialog dialog = gui.obtainMessageDialog(); String message = lang.translationForKey("ifd.context.error"); String title = lang.translationForKey("error"); dialog.showMessageDialog(message, title, DialogType.ERROR_MESSAGE); return; } } else { logger.error("EstablishContext failed."); MessageDialog dialog = gui.obtainMessageDialog(); String message = lang.translationForKey("ifd.context.error"); String title = lang.translationForKey("error"); dialog.showMessageDialog(message, title, DialogType.ERROR_MESSAGE); return; } try { recognition = new CardRecognition(ifd, contextHandle); recognition.setGUI(gui); } catch (Exception ex) { logger.error(ex.getMessage(), ex); MessageDialog dialog = gui.obtainMessageDialog(); String message = lang.translationForKey("recognition.error"); String title = lang.translationForKey("error"); dialog.showMessageDialog(message, title, DialogType.ERROR_MESSAGE); return; } // EventManager em = new EventManager(recognition, env, contextHandle); env.setEventManager(em); // CardStateMap this.cardStates = new CardStateMap(); SALStateCallback salCallback = new SALStateCallback(recognition, cardStates); em.registerAllEvents(salCallback); em.registerAllEvents(this); // SAL sal = new TinySAL(env, cardStates); sal.setGUI(gui); env.setSAL(sal); em.initialize(); try { manager = new AddonManager(dispatcher, gui, cardStates, recognition, em); sal.setAddonManager(manager); AddonManagerSingleton.setInstance(manager); } catch (WSMarshallerException e) { logger.error("Registering of core add-ons failed.", e); System.exit(-1); } // control interface is started in the TCTokenService initialized = true; } @Override public void signalEvent(EventType eventType, Object eventData) { if (eventType.equals(EventType.CARD_RECOGNIZED)) { if (eventData instanceof ConnectionHandleType) { ConnectionHandleType ch = (ConnectionHandleType) eventData; String cardType = ch.getRecognitionInfo().getCardType(); String cardName = recognition.getTranslatedCardName(cardType); showNotification(lang.translationForKey("android.notification.card_recognized", cardName)); } } else if (eventType.equals(EventType.CARD_REMOVED)) { showNotification(lang.translationForKey("android.notification.card_removed")); } else if (eventType.equals(EventType.TERMINAL_ADDED)) { if (eventData instanceof ConnectionHandleType) { ConnectionHandleType ch = (ConnectionHandleType) eventData; showNotification(lang.translationForKey("android.notification.terminal_added", ch.getIFDName())); } } else if (eventType.equals(EventType.TERMINAL_REMOVED)) { if (eventData instanceof ConnectionHandleType) { ConnectionHandleType ch = (ConnectionHandleType) eventData; showNotification(lang.translationForKey("android.notification.terminal_removed", ch.getIFDName())); } } } private void showNotification(String message) { long currentTime = System.currentTimeMillis(); Notification notification = new Notification(android.R.drawable.stat_notify_sync, message, currentTime); notification.flags = Notification.FLAG_AUTO_CANCEL; notification.setLatestEventInfo(this, "Open eCard App", "", null); notificationManager.notify(NOTIFICATION_ID, notification); try { // wait 2 secs before closing the notification, else it won't be seen on tablets Thread.sleep(2000); } catch (InterruptedException e) { // ignore } notificationManager.cancel(NOTIFICATION_ID); } }