Android NFC Reader выдает "AVC: отказано" - PullRequest
4 голосов
/ 13 октября 2019

Я попытался сделать приложение с инструкциями отсюда: https://developer.android.com/guide/topics/connectivity/nfc/nfc

Но когда я компилирую код и держу карту у своего телефона, я получаю странный звук

У меня включен nfc, и у меня запущен андроид oneplus 6 под управлением Android 9

Когда я проверяю 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, но она выдает ту же ошибку)

Я нашел кого-то с такой же проблемой. они говорят Вы должны перейти по ссылке, а затем посмотреть комментарий № 3. а затем говорят, что это связано с тем, что из-за проблемы безопасности не разрешено писать в каталог 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>

и вот фотография моей активности_xml: activity

Спасибо!

1 Ответ

1 голос
/ 13 октября 2019

Поскольку чтение NFC обрабатывается ОС Android, при чтении карты всегда будет звучать звук.

В зависимости от того, что NDEF записывает на карту и что пытается сделать ваше приложение, определяет, чтоОперационная система работает с данными NFC.

Вы можете загрузить стандартное приложение NFC, например https://play.google.com/store/apps/details?id=com.wakdev.wdnfc&hl=en_US, чтобы проверить, что находится на карте, и записать примеры данных для вашего приложения для чтения.

Похоже, что вы пытаетесь запустить это приложение на 2 телефонах и заставить их говорить, используя устаревшую функциональность Android Beam https://developer.android.com/reference/android/nfc/NfcAdapter.CreateNdefMessageCallback (что, как я обнаружил, никогда не было надежным - именно поэтому они его удаляют)

Но вы говорите

Почему я получаю эту ошибку вместо текстового просмотра, отображающего информацию карты nfc, которую я сканирую

Что говорит о том, что вы пытаетесь прочитатьNFC-карта и используемые методы не для этого.

Вопрос в том, хотите ли вы делать с NFC?

1) Есть ли карта NFC, из-за которой приложение запускаетсяОС Android?

Затем как-нибудь используйте данные на NFC.

Если да, то вам просто нужно вставить правильные фильтры намерений в манифест и обрабатывать их в своей MainActivity, как если бысделать для любого другого намерения, и анализ сообщения NDEF из данных намерения.

См. https://developer.android.com/guide/components/intents-filters#ExampleFilters для некоторых примеров не NFC о том, как ваше приложение может зарегистрировать в ОС, какие типы намерений оно может обработать.

2) В вашем приложении обрабатывать чтение с карты NFC в определенное время

Кажется, это больше того, что вы пытаетесь сделать (и что делают мои приложения)

Длясделать это, вы используете включить диспетчер NFC Foreground 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 для отправкивсе сообщения типа карты NFC в мое приложение, а метод onNewIntent получает намерение, переданное ему операционной системой, и обрабатывает сообщение, если оно является сообщением NDEF.

Вы также можете при создании диспетчера переднего планав onResume добавьте дополнительные фильтры, такие как

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

или удалите фильтры для карт не NDEF (обычно добавляйте все типы, потому что я не хочу, чтобы другие типы карт, такие как бесконтактные банковские карты, запускали другие приложения, пока мое приложение находится вна переднем плане)

...