Android NFC阅读器显示“ AVC:被拒绝”

时间:2019-10-12 21:12:18

标签: java android android-studio nfc

我尝试按照此处的说明制作应用: https://developer.android.com/guide/topics/connectivity/nfc/nfc

但是当我编译代码并在手机上拿着卡时,我得到a weird sound

我的nfc已打开,并且我有一个运行Android 9的oneplus 6

当我检查logcat时,我看到一个错误:

56:27.888 7834-7850/com.appname  D/DecorView: onWindowFocusChangedFromViewRoot hasFocus: true, DecorView@6302a6f[MainActivity]
2019-10-12 22:56:27.913 7834-7834/com.appname  W/RenderThread: type=1400 audit(0.0:2504791): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=21655 scontext=u:r:untrusted_app:s0:c16,c257,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
2019-10-12 22:56:27.928 7834-7880/com.appname E/libc: Access denied finding property "vendor.debug.egl.swapinterval"

为什么我收到此错误,而不是显示textview的nfc卡即时扫描信息(我尝试了多种nfc卡,但给出了相同的错误)

我发现某个人也有同样的问题。 they say,您应该点击链接,然后观看评论3。然后they say与安全问题有关,这与不允许写入tmp目录有关。

请帮助我解决此问题,这是我的MainActivity.java:

package com.packagename;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.renderscript.RenderScript;
import android.widget.TextView;
import android.widget.Toast;

import static android.nfc.NdefRecord.createMime;

public class MainActivity extends AppCompatActivity implements CreateNdefMessageCallback {
    NfcAdapter nfcAdapter;
    TextView textView;

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

        // Check for available NFC Adapter
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        // Register callback
        nfcAdapter.setNdefPushMessageCallback(this, this);
    }

    @Override
    public NdefMessage createNdefMessage(NfcEvent event) {
        String text = ("Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis());
        NdefMessage msg = new NdefMessage(
                new NdefRecord[] { createMime(
                        "application/vnd.com.example.android.beam", text.getBytes())
                        /**
                         * The Android Application Record (AAR) is commented out. When a device
                         * receives a push with an AAR in it, the application specified in the AAR
                         * is guaranteed to run. The AAR overrides the tag dispatch system.
                         * You can add it back in to guarantee that this
                         * activity starts when receiving a beamed message. For now, this code
                         * uses the tag dispatch system.
                        */
                        //,NdefRecord.createApplicationRecord("com.example.android.beam")
                });
        return msg;
    }

    @Override
    public void onResume() {
        super.onResume();
        // Check to see that the Activity started due to an Android Beam
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
            processIntent(getIntent());
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent);
    }

    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    void processIntent(Intent intent) {
        textView = findViewById(R.id.textView);
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        // record 0 contains the MIME type, record 1 is the AAR, if present
        textView.setText(new String(msg.getRecords()[0].getPayload()));
    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.packagename">
    <uses-permission android:name="android.permission.NFC" />
    <uses-feature android:name="android.hardware.nfc" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

,这里是我的activity_main.xml的图片: activity

谢谢!

1 个答案:

答案 0 :(得分:1)

由于NFC读取由Android操作系统处理,因此在读取卡时始终会发出声音。

根据卡上NDEF记录的内容以及您的应用程序尝试执行的操作来确定操作系统对NFC数据的处理方式。

您可以下载https://play.google.com/store/apps/details?id=com.wakdev.wdnfc&hl=en_US之类的通用NFC应用程序来检查卡上的内容,并编写一些示例数据供应用程序读取。

您似乎正在尝试在2部手机上运行该应用程序,并使用不推荐使用的Android Beam功能https://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback(我发现它从来都不可靠-这就是为什么他们将其删除的原因)让他们进行交谈

但是你说

  

为什么我会收到此错误,而不是在textview中显示   nfc卡即时扫描的信息

建议您尝试读取NFC卡,但所使用的方法不适用于此操作。

问题是您要使用NFC吗?

1)NFC卡是否使您的APP被Android OS启动?

然后以某种方式使用NFC上的数据。

如果是,那么您应该将正确的意图过滤器放入清单中,并像处理其他任何意图那样在MainActivity中处理它们,并从意图数据中解析NDEF消息。

有关一些非NFC的示例,请参见https://developer.android.com/guide/components/intents-filters#ExampleFilters,以了解您的应用如何向操作系统注册其可以处理的Intent类型。

2)在您的App中,有时会处理从NFC卡读取的信息

这似乎是您正在尝试做的事情(以及我的Apps所做的事情)

为此,您可以启用NFC前景调度程序https://developer.android.com/reference/android/nfc/NfcAdapter.html#enableForegroundDispatch(android.app.Activity,%20android.app.PendingIntent,%20android.content.IntentFilter%5B%5D,%20java.lang.String%5B%5D%5B%5D)

我在活动中使用以下类型的代码

public class ViewNFCCardsActivity extends AppCompatActivity {

    private NfcAdapter mNfcAdapter;

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

        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
    }


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

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

        try {
                ndefDetected.addDataType("*/*");
            } catch (IntentFilter.MalformedMimeTypeException e) {}

        PendingIntent pendingIntent = PendingIntent.getActivity(
                this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        if(mNfcAdapter!= null)
            mNfcAdapter.enableForegroundDispatch(this, pendingIntent, nfcIntentFilter, null);

    }

    @Override
    protected void onPause() {
        super.onPause();
        if(mNfcAdapter!= null)
            mNfcAdapter.disableForegroundDispatch(this);
    }


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

        TextView textView = (TextView) findViewById(R.id.MessageText);

        // High level way to get Ndef records from what is already been read from the tag
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawMessages != null) {
                // Only need the first message
                NdefMessage msg = (NdefMessage) rawMessages[0];
                // Only need the first record in message
                String message = new String(msg.getRecords()[0].getPayload());
                textView.setText(message);
            }
        }
    }

onResume告诉Android OS将所有NFC卡类型的消息发送到我的应用程序,并且onNewIntent方法获取OS传递给它的Intent并处理消息(如果它是NDEF消息)

您还可以在onResume中创建Foreground Dispatcher时,添加其他过滤器,例如

try {
            ndefDetected.addDataType("custom/text");
        } catch (IntentFilter.MalformedMimeTypeException e) {}

或删除非NDEF卡的过滤器(通常添加所有类型,因为我不希望其他类型的卡(例如非接触式银行卡)在我的应用处于前台时触发其他应用)