Search code examples
javaandroidnfc

Check if nfc tag is near by


I want my phone to detect if there is a nfc tag near by (near the surface of it) The following code has no errors but as soon as i run the app, it crashes. It would be very helpful if someone of you can look through my code and check if there is something i dont see. Down bellow is the runtimeerror.

public class AccessControlActivity extends AppCompatActivity {

    NfcAdapter nfcAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_access_control);

         nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        // Checks if there is NFC function
        if(nfcAdapter != null && nfcAdapter.isEnabled()) {
            //Toast.makeText(this, "NFC works", Toast.LENGTH_SHORT).show();
        }
        else {
            Toast.makeText(this, "NFC is not available!", Toast.LENGTH_SHORT).show();
            //finish();
        }


    }


    @Override
    protected  void onNewIntent(Intent intent) {
        Toast.makeText(this, "NFC intent received", Toast.LENGTH_LONG).show();
        super.onNewIntent(intent);
    }

    @Override
    protected void onResume() {
        Intent intent = new Intent(this, AccessControlActivity.class);
        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
        IntentFilter[] intentFilters = new IntentFilter[]{};

        nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, null);


        super.onResume();
    }

    @Override
    protected void onPause() {
        nfcAdapter.disableForegroundDispatch(this);


        super.onPause();
    }
}

The runtimeerror looks like this:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.nfc.netvision, PID: 5484
    java.lang.RuntimeException: Unable to resume activity {com.nfc.netvision/com.nfc.netvision.AccessControlActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.nfc.NfcAdapter.enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], java.lang.String[][])' on a null object reference
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4341)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4373)
        at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:216)
        at android.app.ActivityThread.main(ActivityThread.java:7464)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.nfc.NfcAdapter.enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], java.lang.String[][])' on a null object reference
        at com.nfc.netvision.AccessControlActivity.onResume(AccessControlActivity.java:116)
        at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1456)
        at android.app.Activity.performResume(Activity.java:8125)
        at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4331)
        at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4373) 
        at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52) 
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loop(Looper.java:216) 
        at android.app.ActivityThread.main(ActivityThread.java:7464) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955) 
I/Process: Sending signal. PID: 5484 SIG: 9

Solution

  • So you check that the nfcAdapter != null in onCreate and just show a toast, your app will then blindly go and try and use a possibly null adapter in onResume.

    This would explain the Attempt to invoke virtual method on a null object reference in onResume as the variable nfcAdapter is probably null in onResume

    You should check for null again in onResume

    Also your Intent filters don't look right as well, they code either cause no Intents to be sent to you or the opposite cause all including non NFC Intents to be sent to you.

    More normal code to get called when any type of tag is presented would be.

        @Override
        protected void onResume() {
            super.onResume();
    
            IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
            IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
            try {
                ndefDetected.addDataType("*/*");
            } catch (IntentFilter.MalformedMimeTypeException e) {}
            IntentFilter techDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
            IntentFilter[] nfcIntentFilter = new IntentFilter[]{ndefDetected,techDetected,tagDetected};
    
            PendingIntent pendingIntent = PendingIntent.getActivity(
                    this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
            if(nfcAdapter!= null)
                nfcAdapter.enableForegroundDispatch(this, pendingIntent, nfcIntentFilter, null);
    
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            if(nfcAdapter!= null)
                nfcAdapter.disableForegroundDispatch(this);
        }