我猜当你们看到这个标题时,大多数人都会目瞪口呆,并认为我们以前也见过这个标题,我同意,但我已经尽了一切努力来解决这个问题,但它无法解决。好了。
我的应用程序可以从主屏幕(图标)启动,一切正常——它扫描NFC标签并将相关数据发送到服务器。然而,我也希望该应用程序从NFC标签启动,这没有问题。然而当应用程序通过NFC标签启动时,您可以移除手机并将其重新呈现给应该的标签,然后读取标签并将数据发送到服务器。与通过图标启动应用程序的行为完全相同,但当你扫描NFC标签时,这一次启动了应用程序的新实例,最终将当前实例踢下堆栈,即忙于读取标签的实例版本,因此我得到了ANR。
简而言之:
从主屏幕->扫描标签->应用程序启动
然后重新扫描标签->
应用程序的当前实例将消失,取而代之的是一个新实例。我希望上一个实例保持原样并工作。
在这一点上,我的一些猜测是:-NFC没有正确注册到应用程序,因此操作系统会采取默认行为
-当通过NFC标签启动时,有一个未正确设置的标志,告诉操作系统该活动不需要重新启动。
无论如何,这是代码:
<uses-permission android:name="android.permission.NFC"/>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"android:host="@string/URL_for_intent_filtering" android:pathPrefix="/id/" />
//Procedure of NFC startup called from OnCreate
private void startNFC()
{
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(! mNfcAdapter.isEnabled())//check the NFC is switched on
{
mMainActivityHandler.sendEmptyMessage(NFC_DISABLED);
}
//its ok to carry on and instantiate the NFC even though its not enabled.
if(mNfcAdapter != null)
{
int requestID = (int) System.currentTimeMillis();
mPendingIntent = PendingIntent.getActivity(this, requestID, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_UPDATE_CURRENT);
IntentFilter intentF = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
intentF.addDataScheme("http");
intentfilter = new IntentFilter[] {intentF};
if(DEBUG) Log.i("DEBUG","+++++++++++++++++++++++++++++++++++++++++++++++ NFC HAS BEEN STARTED");
}else
{
//we have a problem with the NFC adapter probably because the device doesn't have one.
if(DEBUG) Log.i("DEBUG","+++++++++++++++++++++++++++++++++++++++++++++++ NFC HAS FAILED");
mMainActivityHandler.sendEmptyMessage(NFC_FAILED);
}
}
@Override
protected void onPause()
{
if(DEBUG) Log.i("MA","+++++++++++++++++++++++++++++++++++++++ ON PAUSE");
try{
mNfcAdapter.disableForegroundDispatch(this);
}catch(Exception e)
{
}
super.onPause();
}
//and here we should reinstate the NFC adapter
@Override
protected void onResume()
{
if(DEBUG) Log.i("MA","+++++++++++++++++++++++++++++++++++++++ ON RESUME");
//setupDataListener(true);
setupServerComms(getApplicationContext());
//mNfcAdapter.enableForegroundDispatch(this,mPendingIntent,intentfilter,null);
mNfcAdapter.enableForegroundDispatch(this,mPendingIntent,null,null);
super.onResume();
}
只需将AndroidManifest.xml
中的这一行添加到Activity
中,就可能完成。
android:launchMode="singleTask"
所以你想要的是让应用程序捕捉意图,然后读取信息并对其进行正确的处理?好吧,你有一个挂起的意图,用来做这件事,但你的设置似乎与我通常做的有点不同。下面是一个我如何使用挂起的目的来捕获标签数据的例子(从那里你可以做任何你想做的事,比如把它发送到服务器):
Class example{
NfcAdapter adapter;
Tag motor;
String FileName;
PendingIntent detectTag;
IntentFilter NFC;
IntentFilter [] Catcher;
String [][] TechList;
TextView readToField;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_activity);
// Catch NFC detects
adapter = NfcAdapter.getDefaultAdapter(this);
detectTag = PendingIntent.getActivity(this,0,new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
NFC = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
Catcher = new IntentFilter[] {NFC,};
TechList = new String [][]{new String[]{android.nfc.tech.NfcV.class.getName()}};
}
public void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
motor = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Bridge bridge = (Bridge) getApplication();
bridge.setCurrentTag(motor);
}
public void onPause()
{
super.onPause();
adapter.disableForegroundDispatch(this);
}
public void onResume()
{
super.onResume();
adapter.enableForegroundDispatch(this,detectTag ,Catcher , TechList);
}
}
Bridge对象只是我用来保存标记信息的一个类,这样我就可以将信息发送到其他(幕后)类的标记。
最后,我一直被告知,对于onResume
和onPause
,您应该首先调用super.method
。