Android NFC Writing doesn't work with 2 activities but works with 1

两盒软妹~` 提交于 2019-12-14 03:27:49

问题


I found a tutorial on how to read and write a NDEF NFC tag via a Toggle Button.

I wanted 2 separate buttons and after several days and some help (I am a newbie on Android), I have now managed to do that. I have 2 buttons, related to 2 activities. Clicking on read button will open the read activity and read my tag. Clicking on the write button will open the write activity, pop up the keyboard. I type the text I want to write but when I touch the tag, it sends me back to my main activity where my 2 buttons are. Puzzled...

  • If I create a new app with only the writing code, I can write perfectly (and then read from another app) so I know the code works.

  • I have tried to disable my read button, but it doesn't change anything.

It must be a small thing but after several hours on it, I still cant figure it out. Could somebody please help? The code is below. Cheers.

 public class MainActivity extends Activity implements View.OnClickListener {

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

        Button button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(this);
        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button1:

               Intent detailIntent = new Intent(this, ReadActivity.class);
                startActivity(detailIntent);
                break;

            case R.id.button2:

                Intent detailIntent2 = new Intent(this, WriteActivity3.class);
                startActivity(detailIntent2);
                break;
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}




 public class ReadActivity extends Activity {


     public static final String MIME_TEXT_PLAIN = "text/plain";
     public static final String TAG = "NfcDemo";

     private TextView mTextView;
     private NfcAdapter mNfcAdapter;

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

         mTextView = (TextView) findViewById(R.id.textView_explanation);

         mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

         if (mNfcAdapter == null) {
             // Stop here, we definitely need NFC
             Toast.makeText(this, "This device doesn't support NFC.",
                     Toast.LENGTH_LONG).show();
             finish();
             return;

         }

         if (!mNfcAdapter.isEnabled()) {
             mTextView.setText("NFC is disabled.");
         } else {
             mTextView.setText("Touch a Tag");
         }

         handleIntent(getIntent());
     }

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

         /**
          * It's important, that the activity is in the foreground (resumed). Otherwise
          * an IllegalStateException is thrown.
          */
         setupForegroundDispatch(this, mNfcAdapter);
     }

     @Override
     protected void onPause() {
         /**
          * Call this before onPause, otherwise an IllegalArgumentException is thrown as well.
          */
         stopForegroundDispatch(this, mNfcAdapter);

         super.onPause();
     }

     @Override
     protected void onNewIntent(Intent intent) {
         /**
          * This method gets called, when a new Intent gets associated with the current activity instance.
          * Instead of creating a new activity, onNewIntent will be called. For more information have a look
          * at the documentation.
          *
          * In our case this method gets called, when the user attaches a Tag to the device.
          */
         handleIntent(intent);
     }


     private void handleIntent(Intent intent) {
         String action = intent.getAction();
         if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

             String type = intent.getType();
             if (MIME_TEXT_PLAIN.equals(type)) {

                 Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                 new NdefReaderTask().execute(tag);

             } else {
                 Log.d(TAG, "Wrong mime type: " + type);
             }
         } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {

             // In case we would still use the Tech Discovered Intent
             Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
             String[] techList = tag.getTechList();
             String searchedTech = Ndef.class.getName();

             for (String tech : techList) {
                 if (searchedTech.equals(tech)) {
                     new NdefReaderTask().execute(tag);
                     break;
                 }
             }
         }
     }




     public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
         final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
         intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

         final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);

         IntentFilter[] filters = new IntentFilter[1];
         String[][] techList = new String[][]{};

         // Notice that this is the same filter as in our manifest.
         filters[0] = new IntentFilter();
         filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
         filters[0].addCategory(Intent.CATEGORY_DEFAULT);
         try {
             filters[0].addDataType(MIME_TEXT_PLAIN);
         } catch (MalformedMimeTypeException e) {
             throw new RuntimeException("Check your mime type.");
         }

         adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
     }


     public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
         adapter.disableForegroundDispatch(activity);
     }

     /**
      * Background task for reading the data. Do not block the UI thread while reading.
      */

     private class NdefReaderTask extends AsyncTask<Tag, Void, String> {

         @Override
         protected String doInBackground(Tag... params) {
             Tag tag = params[0];

             Ndef ndef = Ndef.get(tag);
             if (ndef == null) {
                 // NDEF is not supported by this Tag.
                 return null;
             }

             NdefMessage ndefMessage = ndef.getCachedNdefMessage();

             NdefRecord[] records = ndefMessage.getRecords();
             for (NdefRecord ndefRecord : records) {
                 if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
                     try {
                         return readText(ndefRecord);
                     } catch (UnsupportedEncodingException e) {
                         Log.e(TAG, "Unsupported Encoding", e);
                     }
                 }
             }

             return null;
         }

         private String readText(NdefRecord record) throws UnsupportedEncodingException {
        /*
         * See NFC forum specification for "Text Record Type Definition" at 3.2.1
         *
         * http://www.nfc-forum.org/specs/
         *
         * bit_7 defines encoding
         * bit_6 reserved for future use, must be 0
         * bit_5..0 length of IANA language code
         */

             byte[] payload = record.getPayload();

             // Get the Text Encoding

             // String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";

             String textEncoding = new String ("");
             if ((payload[0] & 128) == 0) {
                 textEncoding = "UTF-8";
             } else {
                 textEncoding = "UTF-16";
             }



             // Get the Language Code
             int languageCodeLength = payload[0] & 63;


             // String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
             // e.g. "en"

             // Get the Text
             return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
         }

         @Override
         protected void onPostExecute(String result) {
             if (result != null) {
                 mTextView.setText("The content of the tag is :  " + result);
             }
         }
     }

 }







   public class WriteActivity3 extends Activity {

    NfcAdapter nfcAdapter;
    EditText txtTagContent;

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

        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        txtTagContent = (EditText)findViewById(R.id.txtTagContent);

    }

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

        enableForegroundDispatchSystem();
    }

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

        disableForegroundDispatchSystem();
    }


    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        if (intent.hasExtra(NfcAdapter.EXTRA_TAG)) {
            Toast.makeText(this, "Tag detected...", Toast.LENGTH_SHORT).show();


            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

            // Adding the time
            Date now = new Date();
            //Convert current time to String using specified format
            String format = "  dd-MMM-yyyy HH:mm:ss";
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format, Locale.US);
            String formattedNow = simpleDateFormat.format(now);

            NdefMessage ndefMessage = createNdefMessage(txtTagContent.getText() + formattedNow);

            writeNdefMessage(tag, ndefMessage);
        }

    }

    private void enableForegroundDispatchSystem() {

        Intent intent = new Intent(this, MainActivity.class).addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);

        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

        IntentFilter[] intentFilters = new IntentFilter[]{};

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

    private void disableForegroundDispatchSystem() {
        nfcAdapter.disableForegroundDispatch(this);
    }

    private void formatTag(Tag tag, NdefMessage ndefMessage) {
        try {

            NdefFormatable ndefFormatable = NdefFormatable.get(tag);

            if (ndefFormatable == null) {
                Toast.makeText(this, "Tag is not ndef formatable!", Toast.LENGTH_SHORT).show();
                return;
            }


            ndefFormatable.connect();
            ndefFormatable.format(ndefMessage);
            ndefFormatable.close();

            Toast.makeText(this, "Message writen !", Toast.LENGTH_SHORT).show();

        } catch (Exception e) {
            Log.e("formatTag", e.getMessage());
        }

    }

    private void writeNdefMessage(Tag tag, NdefMessage ndefMessage) {

        try {

            if (tag == null) {
                Toast.makeText(this, "Tag object cannot be null", Toast.LENGTH_SHORT).show();
                return;
            }

            Ndef ndef = Ndef.get(tag);

            if (ndef == null) {
                // format tag with the ndef format and writes the message.
                formatTag(tag, ndefMessage);
            } else {
                ndef.connect();

                if (!ndef.isWritable()) {
                    Toast.makeText(this, "Tag is not writable!", Toast.LENGTH_SHORT).show();

                    ndef.close();
                    return;
                }

                ndef.writeNdefMessage(ndefMessage);
                ndef.close();

                Toast.makeText(this, "Tag writen!", Toast.LENGTH_SHORT).show();

            }

        } catch (Exception e) {
            Log.e("writeNdefMessage", e.getMessage());
        }

    }


    private NdefRecord createTextRecord(String content) {
        try {
            byte[] language;
            language = Locale.getDefault().getLanguage().getBytes("UTF-8");

            final byte[] text = content.getBytes("UTF-8");
            final int languageSize = language.length;
            final int textLength = text.length;
            final ByteArrayOutputStream payload = new ByteArrayOutputStream(1 + languageSize + textLength);

            payload.write((byte) (languageSize & 0x1F));
            payload.write(language, 0, languageSize);
            payload.write(text, 0, textLength);

            return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload.toByteArray());

        } catch (UnsupportedEncodingException e) {
            Log.e("createTextRecord", e.getMessage());
        }
        return null;
    }


    private NdefMessage createNdefMessage(String content) {

        NdefRecord ndefRecord = createTextRecord(content);

        NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{ndefRecord});

        return ndefMessage;
    }


    public void tglReadWriteOnClick(View view){
        txtTagContent.setText("");
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_write_activity3, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}


    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="uk.co.masystems.tagreader" >

    <uses-permission android:name="android.permission.NFC" />

    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".ReadActivity"
            android:label="@string/app_name" >


            // only for NDEF alone
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="text/plain" />
            </intent-filter>
-->
        </activity>
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".WriteActivity"
            android:label="@string/title_activity_write" >
        </activity>
        <activity
            android:name=".WriteActivity2"
            android:label="@string/title_activity_write_activity2" >
        </activity>
        <activity
            android:name=".WriteActivity3"
            android:label="@string/title_activity_write_activity3" >
        </activity>
    </application>

</manifest>

回答1:


OK, I found it. In my WriteActivite3.java, inside the private void enableForegroundDispatchSystem() {} I call for MainActivity and not for WriteActivity3. All working now.



来源:https://stackoverflow.com/questions/30462444/android-nfc-writing-doesnt-work-with-2-activities-but-works-with-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!