org.ndeftools.NfcDetectorActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.ndeftools.NfcDetectorActivity.java

Source

/***************************************************************************
 * 
 * This file is part of the 'NDEF Tools for Android' project at
 * http://code.google.com/p/ndef-tools-for-android/
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 ****************************************************************************/

package org.ndeftools;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;

/**
 * 
 * Abstract {@link Activity} for detecting incoming NFC messages.<br/><br/>
 * 
 *  - detects whether NFC is available (if device has NFC chip).<br/>
 *  - detect whether NFC setting is on or off, and whether it changes from off to on or on to off.<br/>
 *  - detect incoming data tags or beams.<br/>
 * 
 * @author Thomas Rorvik Skjolberg
 *
 */

public abstract class NfcDetectorActivity extends FragmentActivity {

    private static final String TAG = NfcDetectorActivity.class.getName();

    protected NfcAdapter nfcAdapter;
    protected IntentFilter[] writeTagFilters;
    protected PendingIntent nfcPendingIntent;

    protected boolean foreground = false;
    protected boolean intentProcessed = false;
    protected boolean nfcEnabled = false;

    protected boolean detecting = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");

        // Check for available NFC Adapter
        PackageManager pm = getPackageManager();
        if (pm != null && !pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
            Log.d(TAG, "NFC feature not found");

            onNfcFeatureNotFound();
        } else {
            Log.d(TAG, "NFC feature found");

            onNfcFeatureFound();
        }
    }

    /**
     * Notify that NFC is available
     */

    protected void onNfcFeatureFound() {
        initializeNfc();
        detectInitialNfcState();
    }

    /**
     * 
     * Initialize Nfc fields
     * 
     */

    protected void initializeNfc() {
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        IntentFilter techDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
        writeTagFilters = new IntentFilter[] { ndefDetected, tagDetected, techDetected };
    }

    /**
     * 
     * Detect initial NFC state.
     * 
     */

    protected void detectInitialNfcState() {
        nfcEnabled = nfcAdapter.isEnabled();
        if (nfcEnabled) {
            Log.d(TAG, "NFC is enabled");

            onNfcStateEnabled();
        } else {
            Log.d(TAG, "NFC is disabled"); // change state in wireless settings

            onNfcStateDisabled();
        }
    }

    /**
     * 
     * NFC feature was found and is currently enabled
     * 
     */

    protected abstract void onNfcStateEnabled();

    /**
     * 
     * NFC feature was found but is currently disabled
     * 
     */

    protected abstract void onNfcStateDisabled();

    @Override
    protected void onResume() {
        super.onResume();

        if (nfcAdapter != null) {
            // enable foreground mode if nfc is on and we have started detecting
            boolean enabled = nfcAdapter.isEnabled();
            if (enabled && detecting) {
                enableForeground();
            }

            detectNfcStateChanges();
        }

        if (!intentProcessed) {
            intentProcessed = true;

            processIntent();
        }

    }

    /**
     * 
     * NFC setting changed since last check. For example, the user enabled NFC in the wireless settings.
     * 
     */

    protected abstract void onNfcStateChange(boolean enabled);

    /**
     * 
     * Detect changes in NFC settings - enabled/disabled
     * 
     */

    protected void detectNfcStateChanges() {
        boolean enabled = nfcAdapter.isEnabled();
        if (nfcEnabled != enabled) {
            onNfcStateChange(enabled);

            nfcEnabled = enabled;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();

        if (nfcAdapter != null) {
            disableForeground();
        }
    }

    @Override
    public void onNewIntent(Intent intent) {

        Log.d(TAG, "onNewIntent");

        // onResume gets called after this to handle the intent
        intentProcessed = false;

        setIntent(intent);
    }

    protected void enableForeground() {
        if (!foreground) {
            Log.d(TAG, "Enable nfc forground mode");

            nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);

            foreground = true;
        }
    }

    /**
     * 
     * Start detecting NDEF messages
     * 
     */

    protected void startDetecting() {
        if (!detecting) {
            enableForeground();

            detecting = true;
        }
    }

    /**
     * 
     * Stop detecting NDEF messages
     * 
     */

    protected void stopDetecting() {
        if (detecting) {
            disableForeground();

            detecting = false;
        }
    }

    protected void disableForeground() {
        if (foreground) {
            Log.d(TAG, "Disable nfc forground mode");

            nfcAdapter.disableForegroundDispatch(this);

            foreground = false;
        }
    }

    /**
     * 
     * Process the current intent, looking for NFC-related actions
     * 
     */

    public void processIntent() {
        Intent intent = getIntent();
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            Log.d(TAG, "Process NDEF discovered action");

            nfcIntentDetected(intent, NfcAdapter.ACTION_NDEF_DISCOVERED);
        } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
            Log.d(TAG, "Process APP_TAG discovered action");

            nfcIntentDetected(intent, NfcAdapter.ACTION_TAG_DISCOVERED);
        } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
            Log.d(TAG, "Process TECH discovered action");

            nfcIntentDetected(intent, NfcAdapter.ACTION_TECH_DISCOVERED);
        } else {
            Log.d(TAG, "Ignore action " + intent.getAction());
        }
    }

    /**
     * 
     * Launch an activity for nfc (or wireless) settings, so that the user might enable or disable nfc
     * 
     */

    protected void startNfcSettingsActivity() {
        if (android.os.Build.VERSION.SDK_INT >= 16) {
            startActivity(new Intent(android.provider.Settings.ACTION_NFC_SETTINGS));
        } else {
            startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
        }
    }

    /**
     * 
     * Incoming NFC communication (in form of tag or beam) detected
     * 
     */

    protected abstract void nfcIntentDetected(Intent intent, String action);

    /**
     * 
     * This device does not have NFC hardware
     * 
     */

    protected abstract void onNfcFeatureNotFound();

    public boolean isDetecting() {
        return detecting;
    }

    public void setDetecting(boolean detecting) {
        this.detecting = detecting;
    }

}