【问题标题】:Android NFC: one activity to send and one to receive onlyAndroid NFC:一项发送活动,一项仅接收活动
【发布时间】:2014-11-04 19:58:35
【问题描述】:

我希望我的 ActivityNFCSender 通过 NFC 向我的 ActivityNFCReceiver 发送一个整数。下面的代码有效。但是有一个问题:建立连接时,两个活动都显示提示发送!但我只希望第一个能够发送(整数)并显示提示。怎么做?

ActivityNFCSender

public class ActivityNFCSender extends ActivityBase {

public static final String EXTRA_RES_ID = "res_id";

private NfcAdapter mNfcAdapter;
private int mReservServerId;


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

    mReservServerId = getIntent().getIntExtra(EXTRA_RES_ID, 0);
}


public void onResume(){
    super.onResume();   

    mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if(mNfcAdapter == null){
        messageDialogQuit(R.string.error_no_nfc);
    }
    else if(!mNfcAdapter.isEnabled()){
        new AlertDialog.Builder(this).setCancelable(true).setMessage(R.string.error_nfc_off)
            .setPositiveButton(R.string.turn_on, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();
                        Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
                        startActivity(settingsIntent);                          
                    }
                })
            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();    
                        finish();
                    }
                })                  
            .create().show();
    }
    else{           
        //Set sending
        mNfcAdapter.enableForegroundNdefPush(ActivityNFCSender.this,  getIntAsNdef(mReservServerId));
    }
}

public void onPause(){      
    if(mNfcAdapter != null && mNfcAdapter.isEnabled()){
        mNfcAdapter.disableForegroundNdefPush(this);
    }
    super.onPause();        
}


private NdefMessage getIntAsNdef(int pInt) {
    byte[] textBytes = (pInt+"").getBytes(Charset.forName("UTF8"));
    NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "text/plain".getBytes(), new byte[] {}, textBytes);
    return new NdefMessage(new NdefRecord[] {
        textRecord
    });
}

ActivityNFCReceiver

public class ActivityNFCReceiver extends ActivityBase {

private NfcAdapter mNfcAdapter;
private PendingIntent mNfcPendingIntent;
private IntentFilter[] mNdefExchangeFilters;    


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

    ((TextView) findViewById(R.id.nfcTVStatus)).setText(R.string.receiving);
}


public void onResume(){
    super.onResume();   

    mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if(mNfcAdapter == null){
        messageDialogQuit(R.string.error_no_nfc);
    }
    else if(!mNfcAdapter.isEnabled()){
        new AlertDialog.Builder(this).setCancelable(true).setMessage(R.string.error_nfc_off)
            .setPositiveButton(R.string.turn_on, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();
                        Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS);
                        startActivity(settingsIntent);                          
                    }
                })
            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.dismiss();    
                        finish();
                    }
                })                  
            .create().show();
    }
    else{           
        mNfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        // Intent filters for exchanging over p2p.
        IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndefDetected.addDataType("text/plain");
        } 
        catch (MalformedMimeTypeException e) {
            e.printStackTrace();
        }

        mNdefExchangeFilters = new IntentFilter[] { ndefDetected };

        //set receiving
        mNfcAdapter.enableForegroundDispatch(ActivityNFCReceiver.this, mNfcPendingIntent, mNdefExchangeFilters, null);
    }
}

public void onPause(){      
    if(mNfcAdapter != null && mNfcAdapter.isEnabled()){
        mNfcAdapter.disableForegroundDispatch(ActivityNFCReceiver.this);
    }
    super.onPause();        
}


@Override
protected void onNewIntent(Intent intent) {
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
        NdefMessage[] msgs = getNdefMessages(intent);
        if(msgs.length > 0){
            try{
                NdefRecord firstRecord = msgs[0].getRecords()[0];
                byte[] payload = firstRecord.getPayload();
                String str = new String(payload, Charset.forName("UTF8"));

                int reservServerId = Integer.parseInt(str);
                returnResult(reservServerId);
            }
            catch(Exception e){
                messageDialog(R.string.error_during_NFC);
            }
        }
    }
}


public void onCancelClicked(View pV){
    finish();
}

private NdefMessage[] getNdefMessages(Intent intent) {
    // Parse the intent
    NdefMessage[] msgs = null;
    String action = intent.getAction();
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMsgs != null) {
            msgs = new NdefMessage[rawMsgs.length];
            for (int i = 0; i < rawMsgs.length; i++) {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }
        }
        else {
            // Unknown tag type
            byte[] empty = new byte[] {};
            NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
            NdefMessage msg = new NdefMessage(new NdefRecord[] { record });
            msgs = new NdefMessage[] { msg };
        }
    }
    else {
        Log.d(TAG, "Unknown intent.");
        finish();
    }
    return msgs;
}


private void returnResult(int pResServerId){
    Intent result = new Intent();
    result.putExtra(ActivityCompanySubMenu.EXTRA_RES_SERVER_ID, pResServerId);
    setResult(RESULT_OK, result);
    finish();
}

}

【问题讨论】:

    标签: android nfc nfc-p2p android-beam


    【解决方案1】:

    您可以使用NfcAdapter.setNdefPushMessage 方法为特定活动(即您的ActivityNFCReceiver)禁用Beam UI:

    public void onCreate(Bundle savedInstanceState) {
    
        [...]
    
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (mNfcAdapter != null) {
            mNfcAdapter.setNdefPushMessage(null, this);
        }
    }
    

    请注意,自 Android 4.0(API 级别 14)以来,enableForegroundNdefPush 方法已被弃用,并且几乎所有支持 NFC 的 Android 设备都使用 Android 4.0 或更高版本。


    虽然在 Nexus 设备上以这种方式禁用 Beam UI 并且是官方记录的方式(请参阅 setNdefPushMessage):

    如果调用 setNdefPushMessage(...) 时带有一个空的 NDEF 消息 [...],那么 NDEF 推送将完全禁用指定活动。这也会禁用任何默认的 NDEF 消息,Android 操作系统本来会代表您为这些活动发送的。

    似乎——不幸的是——这不适用于某些 Android 设备的 NFC 实现。例如,它不适用于运行 Android 4.3 的三星 Galaxy S3。

    【讨论】:

    • 我更改了代码并添加了 mNfcAdapter.setNdefPushMessage(null, this);就在 mNfcAdapter.enableForegroundDispatch(ActivityNFCReceiver.this, mNfcPendingIntent, mNdefExchangeFilters, null) 之后;在接收器活动中,但结果相同:两个设备都显示发送提示。我可能是错的,但我认为 enableForegroundDispatch() 函数是启用接收。我希望接收器活动处于前台并接收整数。
    • 顺便说一句,ANY Activity 显示此系统提示(Activity 的图像变小,Android 询问我是否要发送。什么?我不知道)。感谢您到目前为止的回复,希望您能进一步帮助我...
    • 一般来说,您应该在活动生命周期中尽早使用 setNdefPushMessage(即在onCreate() 中)。但是,这并不能解释为什么在您的情况下会显示 Beam UI。您使用的是哪个 Anadroid 版本?
    • 我添加了 mNfcAdapter = NfcAdapter.getDefaultAdapter(this); if(mNfcAdapter != null){ mNfcAdapter.setNdefPushMessage(null, this); } 到 ActivityNFCReceiver 的 onCreate() 但仍然存在同样的问题。我禁用了 onResume 中的代码,只是为了测试 - 还是一样。该设备是带有 Android 4.3 的三星 Galaxy S3。发件人是带有 Android 4.4.2 的 Nexus7 但无论如何:无论是否启用 NFC,发送提示都会出现在每个活动中。
    • NFC始终启用(除非您通过 Android 设置菜单完全禁用 NFC 功能)。默认情况下,活动将尝试发送 Android 应用程序记录,以便在另一台设备上启动相同的应用程序(因此是 Beam UI)。使用setNdefPushMessage 方法将NDEF 消息设置为null 应该禁用此默认行为。这似乎适用于我尝试过的 Nexus 设备。
    猜你喜欢
    • 2013-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 2023-04-01
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多