应该工作,但不能使用此NFC代码

时间:2013-12-23 13:03:50

标签: android nfc

我的主要活动中有此代码。在此活动中,我将数据写入NFC标签。这项工作非常完美:

public class MainActivity extends Activity implements OnClickListener {
private NfcAdapter mAdapter;
private boolean mInWriteMode;
private Button mWriteTagButton;
private TextView mTextView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    // grab our NFC Adapter
    mAdapter = NfcAdapter.getDefaultAdapter(this);

    // button that starts the tag-write procedure
    mWriteTagButton = (Button)findViewById(R.id.write_tag_button);
    mWriteTagButton.setOnClickListener(this);

    // TextView that we'll use to output messages to screen
    mTextView = (TextView)findViewById(R.id.text_view);
}

public void onClick(View v) {
    if(v.getId() == R.id.write_tag_button) {
        displayMessage("Touch and hold tag against phone to write.");
        enableWriteMode();
    }
}

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

/**
 * Called when our blank tag is scanned executing the PendingIntent
 */
@Override
public void onNewIntent(Intent intent) {
    if(mInWriteMode) {
        mInWriteMode = false;

        // write to newly scanned tag
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        writeTag(tag);
    }
}

/**
 * Force this Activity to get NFC events first
 */
private void enableWriteMode() {
    mInWriteMode = true;

    // set up a PendingIntent to open the app when a tag is scanned
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
        new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
    IntentFilter[] filters = new IntentFilter[] { tagDetected };

    mAdapter.enableForegroundDispatch(this, pendingIntent, filters, null);
}

private void disableWriteMode() {
    mAdapter.disableForegroundDispatch(this);
}

/**
 * Format a tag and write our NDEF message
 */
private boolean writeTag(Tag tag) {
    // record to launch Play Store if app is not installed
    NdefRecord appRecord = NdefRecord.createApplicationRecord(getPackageName());

    // record that contains our custom "retro console" game data, using custom MIME_TYPE
    byte[] payload = getRandomConsole().getBytes();
    byte[] mimeBytes = MimeType.NFC_DEMO.getBytes(Charset.forName("US-ASCII"));
    NdefRecord cardRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, mimeBytes, 
                                            new byte[0], payload);
    NdefMessage message = new NdefMessage(new NdefRecord[] { cardRecord, appRecord});

    try {
        // see if tag is already NDEF formatted
        Ndef ndef = Ndef.get(tag);
        if (ndef != null) {
            ndef.connect();

            if (!ndef.isWritable()) {
                displayMessage("Read-only tag.");
                return false;
            }

            // work out how much space we need for the data
            int size = message.toByteArray().length;
            if (ndef.getMaxSize() < size) {
                displayMessage("Tag doesn't have enough free space.");
                return false;
            }

            ndef.writeNdefMessage(message);
            displayMessage("Tag written successfully.");
            return true;
        } else {
            // attempt to format tag
            NdefFormatable format = NdefFormatable.get(tag);
            if (format != null) {
                try {
                    format.connect();
                    format.format(message);
                    displayMessage("Tag written successfully!\nClose this app and scan tag.");
                    return true;
                } catch (IOException e) {
                    displayMessage("Unable to format tag to NDEF.");
                    return false;
                }
            } else {
                displayMessage("Tag doesn't appear to support NDEF format.");
                return false;
            }
        }
    } catch (Exception e) {
        displayMessage("Failed to write tag");
    }

    return false;
}

private String getRandomConsole() {
    double rnd = Math.random();
    if(rnd<0.25) return "Random-1";
    else if(rnd<0.5) return "Random-2";
    else if(rnd<0.75) return "Random-3";
    else return "Random-4";
}

private void displayMessage(String message) {
    mTextView.setText(message);
}

}

然后,这是我从NFC标签读取数据的活动。理论上,当发现NFC标签时,这是系统启动但系统启动先前活动的活动。这是代码:

public class CardActivity extends Activity {
private TextView mCardView;

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

    // ImageView that we'll use to display cards
    mCardView = (TextView)findViewById(R.id.card_view);

    // see if app was started from a tag and show game console
    Intent intent = getIntent();
    if(intent.getType() != null && intent.getType().equals(MimeType.NFC_DEMO)) {
        Parcelable[] rawMsgs = getIntent().getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        NdefRecord cardRecord = msg.getRecords()[0];
        String consoleName = new String(cardRecord.getPayload());
        mCardView.setText(consoleName);
    }
}

}

清单文件是这样的:

<?xml version="1.0" encoding="utf-8"?>

<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />

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

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <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=".CardActivity"
        android:label="@string/app_name" >

        <intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
            <data android:mimeType="application/vnd.daggothSoft.nfcdemo"/>
            <category android:name="android.intent.category.DEFAULT"/>
        </intent-filter>
    </activity>

</application>

MIME-Type的最后一个活动是:

public class MimeType {
public static final String NFC_DEMO = "application/vnd.daggothSoft.nfcdemo";

}

问题在于,当我扫描NFC标签时,根据清单,启动系统的活动不是应该的。始终启动主要活动。我不知道问题出在哪里,问题是什么......好吧,任何评论或帮助都会非常有用。

谢谢,真的,谢谢;)

1 个答案:

答案 0 :(得分:0)

注意Android的用于intent过滤器的MIME类型匹配区分大小写 - 尽管MIME类型本身并非如此。因此,对于Android(以及几乎在任何地方使用它们),您应该坚持使用仅使用小写字母的MIME类型的约定。

特别是对于存储在NFC标签上的MIME类型记录,Android会自动将它们转换为全小写字母,以克服意图过滤器中区分大小写的问题。因此,在您的示例中,将意图过滤器中的类型名称更改为"application/vnd.daggothsoft.nfcdemo"将起作用:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <data android:mimeType="application/vnd.daggothsoft.nfcdemo"/>
    <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

然后,您还应确保仅使用小写字母编写MIME类型:

public static final String NFC_DEMO = "application/vnd.daggothsoft.nfcdemo";