Ada*_*hns 6 android nfc android-10.0
在 Android 10 中,我注意到我从操作系统收到一条 Toast 消息,指出“此 NFC 标签不支持应用程序”或“此 NFC 标签不支持应用程序”(取决于设备):
奇怪的是,我看到 ToastenableReaderMode在前台 Activity 中处于活动状态。在所有以前的 Android 版本中,enableReaderMode都会覆盖 Android 意图标记调度系统。这是 Android 10 中的错误吗?
我知道enableForegroundDispatch也存在,并且该 API似乎确实覆盖了意图标签调度系统,即使在 Android 10 中也是如此。但我想继续控制仅由 提供的 NFC 发现声音enableReaderMode。
我还知道我可以在清单中声明一个意图过滤器,以在继续使用的同时摆脱 Toast enableReaderMode,但这也会产生意想不到的副作用(例如,我的应用程序可能会在从设备主屏幕读取 NFC 标签时启动,我不想)。
是的,这似乎是一个错误,因为 Android 操作系统在以下条件下会触发新的 tagDiscovery 事件:
由于这会触发操作系统级别的事件,因此它可以暂停重点活动,可能会显示 toast 屏幕或显示相关的应用程序选择框。
为了解决这个问题,
解决方法1:
缺点:您可能需要向用户显示一条消息,以将标签/卡从设备附近移除。
解决方法2:
缺点:不会显示弹出窗口,但仍然会触发标签发现声音。
两种解决方案都不需要定义意图过滤器。
下面是实现这两种解决方法的示例代码。
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.os.Bundle;
import android.widget.Toast;
import java.io.IOException;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity
{
private NfcAdapter nfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//Assuming nfc adapter is present and active, such checks are ignored for code clarity,
//production code must check for hardware nfc adapter existence
nfcAdapter = NfcAdapter.getDefaultAdapter(this); //Get the default NFC adapter from OS
//Additional initialization code
}
private void onTagDiscovered(Tag tag)
{
try
{
if (tag == null)
return;
//Assumption: We're using an NFC card that supports IsoDep
IsoDep iso = IsoDep.get(tag);
if (iso == null)
return;
iso.setTimeout(1000);
iso.connect();
//doCardReadWrite(iso);
iso.close();
//Workaround 1
//Wait until the card has been removed from the range of NFC
//Then finish the activity
while(true)
{
try
{
iso.connect();
Thread.sleep(100);
iso.close();
}
catch (IOException | InterruptedException e)
{
//On this example, once we're done with the activity, we want to close it
//then onPause event will call disableReaderMode, at that moment we don't want a card to be in proximity
onCardRemoved();
break;
}
}
//End of Workaround 1
}
catch (IOException e)
{
Toast.makeText(this, "Tag disconnected. Reason: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void onCardRemoved()
{
this.finish();
}
@Override
protected void onResume()
{
super.onResume();
//Workaround 2
//Legacy nfc reader activation method, just enabled it but we won't use it
//(to fully support [e.g. OS version < v4.4.4] you must override onNewIntent(Intent intent) method as well)
//create intent/tag filters to be used with enableForegroundDispatch
PendingIntent pendingIntent = PendingIntent.getActivity(
this,
0,
new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
0
);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
IntentFilter[] writeTagFilters = new IntentFilter[]{tagDetected};
nfcAdapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null);
//End of Workaround 2
//ReaderMode activation
Bundle options = new Bundle();
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 1000);//Presence check interval
final int READER_FLAGS = NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS;
nfcAdapter.enableReaderMode(this, new NfcAdapter.ReaderCallback()
{
@Override
public void onTagDiscovered(Tag tag)
{
MainActivity.this.onTagDiscovered(tag);
}
}, READER_FLAGS, options);
}
@Override
protected void onPause()
{
nfcAdapter.disableReaderMode(this);
//Workaround 2
nfcAdapter.disableForegroundDispatch(this);
super.onPause();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1690 次 |
| 最近记录: |