有什么方法可以阻止我的 Android 应用程序在后台扫描 nfc 标签吗?

Is there any way to stop my Android App from scanning nfc tags in the background?

假设我想制作一个应用程序,当用户点击“扫描标签”按钮时扫描 nfc 标签。

目前我遇到了一些问题,尽管我花了上周的时间试图自己解决这个问题

我面临的主要问题是该应用程序将在后台扫描 nfc 标签(或至少看起来像),并将打开我的应用程序的一个新实例,但名称为“Nfc 服务”(这不是我命名我的应用程序的名称)。

我面临的另一个问题是,在代码中,当我尝试调用我的“readTag()”方法时,它只有在打开我之前说过的“Nfc 服务”时才有效,否则它不读取标签,而只是中断。据我了解,readTag() 方法似乎在后台 运行 而不是我告诉它的时候。

TL;DR:我不希望我的应用程序在后台扫描 nfc 标签,而只是在按下按钮时扫描。

非常感谢您的帮助,尤其是因为我的截止日期是明天 T-T

这是我的一些代码(遗憾的是我无法展示所有内容):

AndroidManifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ips.software.iasset_ips">

    <uses-permission android:name="android.permission.INTERNET" />
    <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:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.IAssetIPS">
        <activity android:name=".WebViews.AssetInfoWebView"></activity>
        <activity android:name=".Activities.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <action android:name="android.nfc.action.TECH_DISCOVERED" />

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

            </intent-filter>

            <meta-data
                android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />
        </activity>
    </application>

</manifest>

xml/nfc_tech_filter:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
</resources>

MainActivity:(仅与问题相关的部分)

// package + all the imports
// ...

public class MainActivity extends AppCompatActivity {

    private Button scanButton;

    NfcAdapter adapter;
    Tag tag;

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


        configureScanButton();
    }

    private void configureScanButton() {
        scanButton= findViewById(R.id.scanButton);
        scanButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                readTag();
             }
        });
    }

    public void readTag() {
        adapter = NfcAdapter.getDefaultAdapter(this); // initialize the nfc reader
        checkNfcSupport(); // check if device supports nfc, if not close and Toast.show
        tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG); // read the tag
        decodeSerialNumberFromTag(); // can't show you this function, but it's only decoding, it shouldn't be the cause of the problem
        Toast.makeText(this, "Serial Number: " + serialNumber, Toast.LENGTH_LONG).show();
    }
}

是的,我想就这些了,如果我想扫描新标签时可以调用 readTag() 方法就好了。

我说的太多了,先谢谢你了:D

启动您的应用程序与 NFC 标签交互的唯一方法是通过 NFC 服务,但如果您对其进行正确编程,则有可能实现您想要的行为。

首先,清单 Intent 过滤器实际上只是告诉 NFC 服务在正确类型的标签进入范围时 start/restart 您的应用程序。

中所述,与应用程序的“launchMode”有交互

当您的应用程序为 运行 时处理 NFC 标签的方法是使用 enableForegroundDispatch 或使用更好的 enableReaderMode APIs 告诉 NFC 服务当 Tag 进入范围时,以不同的方式向您传递 Tag 对象。

更好的enableReaderMode API读写的例子在(你可以忽略写位)

仅当您按下按钮时才对标签执行某些操作不是正常的工作流程,因为标签可能在也可能不在范围内,当您在当前 readTag 方法中实际执行的操作是按下按钮只是在处理 activity 启动时存储的 Intent,实际上并没有对标签进行 I/O 读取。标签 UID 和存储在标签上的任何 NDEF 消息在进入范围时都将缓存在标签中 Object/Intent。

要在 onTagDiscovered 方法中使用 enableReaderMode 做类似的事情,您可以将标记对象存储在 Activity class 中,然后在 class 中处理它您按下按钮并检查 Tag 对象是否 null 即用户按下按钮时没有 Tag 都在范围内。

如果你想在按下按钮时读取其他非缓存数据,你需要处理标记输出或范围错误以及其他 I/O 错误,就像你在标记进入时立即处理标记一样范围,只是你更有可能拥有它们。

我想说的是,在您的应用程序中使用 NFC enableForegroundDispatch 或使用更好的 enableReaderMode 作为 NFC 服务向您发送标签对象始终是一个好习惯,即使您不这样做也是如此不想在那个时间点对它做任何事情,因为它会阻止 NFC 服务启动另一个应用程序来处理它,甚至会阻止它自己在你的应用程序顶部显示一个关于进入范围内的标签的基本信息屏幕。例如在 onNewIntentonTagDiscovered

中有一个空方法