通过启动器启动应用程序时,我运行以下生命周期:
onCreate..., onPostCreate..., onResume..., onNewIntent..., act:android.intent.action.MAIN, mNfcAdapter.disableForegroundDispatch OK.然后,当我点击一个标记时,当我运行以下生命周期时,似乎启动了一个新的应用程序实例:
onPause..., onCreate..., onPostCreate..., onResume..., onNewIntent..., act:android.nfc.action.TAG_DISCOVERED, myTag.mId:048a1382bd2384)由于我试图使用前台调度系统来禁用接收NFC事件,所以我希望我的应用程序忽略NFC标记。那么,为什么我的活动被重新创造了呢?是因为AndroidManifest.xml允许它吗?
package com.example.pdf.nfcaccess;
import android.annotation.SuppressLint;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
// PDf import
import android.telephony.TelephonyManager;
import android.content.Intent;
import android.content.Context;
import android.content.IntentFilter;
import android.app.PendingIntent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.widget.TextView;
import android.widget.Toast;
import android.util.Log;
import android.nfc.tech.NfcF;
import android.nfc.Tag;
/**
* An example full-screen activity that shows and hides the system UI (i.e.
* status bar and navigation/system bar) with user interaction.
*/
public class FullscreenActivity extends AppCompatActivity {
/**
* Whether or not the system UI should be auto-hidden after
* {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
*/
private static final boolean AUTO_HIDE = true;
/**
* If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
* user interaction before hiding the system UI.
*/
private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
/**
* Some older devices needs a small delay between UI widget updates
* and a change of the status and navigation bar.
*/
private static final int UI_ANIMATION_DELAY = 300;
private final Handler mHideHandler = new Handler();
private View mContentView;
private final Runnable mHidePart2Runnable = new Runnable() {
@SuppressLint("InlinedApi")
@Override
public void run() {
// Delayed removal of status and navigation bar
// Note that some of these constants are new as of API 16 (Jelly Bean)
// and API 19 (KitKat). It is safe to use them, as they are inlined
// at compile-time and do nothing on earlier devices.
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
}
};
private View mControlsView;
// application
static FullscreenActivity mInstance;
NfcAdapter mNfcAdapter;
Intent mNfcIntent;
PendingIntent mNfcPendingIntent;
IntentFilter mTagIntentFilter;
IntentFilter[] mIntentFiltersArray;
String[][] mTechLists;
TextView mTagContentText;
// log
//java.util.ArrayList<String> mLogItems = new java.util.ArrayList<String>();
java.util.ArrayList<String> mLogItems = new java.util.ArrayList<String>();
android.widget.ArrayAdapter<String> mLogAdapter;
android.widget.ListView mLogList;
/**/
private final Runnable mShowPart2Runnable = new Runnable() {
@Override
public void run() {
// Delayed display of UI elements
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.show();
}
mControlsView.setVisibility(View.VISIBLE);
}
};
private boolean mVisible;
private final Runnable mHideRunnable = new Runnable() {
@Override
public void run() {
hide();
}
};
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
/* Enable NFC
*/
private final View.OnTouchListener mFuncNfcEnable = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
traceTry("mFuncNfcEnable");
if (mNfcAdapter != null) {
try {
traceTry("mNfcAdapter.enableForegroundDispatch");
mNfcAdapter.enableForegroundDispatch(FullscreenActivity.mInstance, mNfcPendingIntent, mIntentFiltersArray, mTechLists);
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
}
return false;
}
};
/* read Intent
*/
private final View.OnTouchListener mFuncNfcRead = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (mNfcAdapter != null) {
try {
traceTry("onNewIntent");
onNewIntent(getIntent());
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
return false;
}
};
/* Disable NFC
*/
private final View.OnTouchListener mFuncNfcDisable = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN){
traceTry("mFuncNfcDisable");
if (mNfcAdapter != null) {
try {
traceTry("mNfcAdapter.disableForegroundDispatch");
mNfcAdapter.disableForegroundDispatch(FullscreenActivity.mInstance);
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
}
return false;
}
};
/* Quit
*/
private final View.OnTouchListener mFuncBtnQuit = new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
finish();
return false;
}
};
/**/
private void trace(String m) {
Log.d("NFCTags",m);
/*TextView tv = (TextView)findViewById(R.id.logContent_value);
String previous = tv.getText().toString();
tv.setText(previous + "\n" + m);*/
if (mLogAdapter != null) {
mLogItems.add(m);
mLogAdapter.notifyDataSetChanged();
mLogList.setSelection(mLogList.getCount()-1);
}
}
String mMessage = "";
private void traceTry(String m) {
trace(m + "...");
mMessage = m;
}
private void traceOk() {
trace(mMessage + " OK");
mMessage = "";
}
private void traceFails(Throwable t) {
String msg = mMessage + " fails";
if (t != null) {
msg += " exception:" + t.getMessage();
}
trace(msg);
//Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
mMessage = "";
}
/*
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
trace("onCreate...");
// set global unique instance
FullscreenActivity.mInstance = this;
setContentView(R.layout.activity_fullscreen);
// log
mLogItems.add("starts");
mLogAdapter = new android.widget.ArrayAdapter<String>(this, R.layout.support_simple_spinner_dropdown_item, mLogItems);
mLogList = (android.widget.ListView) findViewById(R.id.logList_value);
mLogList.setAdapter(mLogAdapter);
mVisible = true;
mControlsView = findViewById(R.id.fullscreen_content_controls);
mContentView = findViewById(R.id.fullscreen_content);
mTagContentText = (TextView) findViewById(R.id.tagContent_value);
// Set up the user interaction to manually show or hide the system UI.
mContentView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
toggle();
}
});
// Upon interacting with UI controls, delay any scheduled hide()
// operations to prevent the jarring behavior of controls going away
// while interacting with the UI.
findViewById(R.id.nfcRead_btn).setOnTouchListener(mFuncNfcRead);
//findViewById(R.id.nfcDisable_btn).setOnTouchListener(mFuncNfcDisable);
findViewById(R.id.quit_btn).setOnTouchListener(mFuncBtnQuit);
trace("onCreate > before initializing nfc");
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
trace("ID:" + tm.getDeviceId());
trace("Network Operator Name:" + tm.getNetworkOperatorName());
trace("Sim Operator Name:" + tm.getSimOperatorName());
trace("Sim Serial Number:" + tm.getSimSerialNumber());
trace("Phone Type:" + tm.getPhoneType());
trace("Initial Phone Number:" + tm.getLine1Number());
boolean tryNfc = true;
if (tryNfc) {
try {
mMessage = "NfcAdapter.getDefaultAdapter";
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null) {
mMessage = "NFC is not available";
traceFails(null);
return;
} else {
traceOk();
}
} catch (Throwable t) {
traceFails(t);
return;
}
// Check if NFC is enabled
try {
mMessage = "test NfcAdapter.isEnabled";
if (!mNfcAdapter.isEnabled()) {
mMessage = "NFC is not enabled. do it manually";
traceFails(null);
return;
} else {
trace("NFC is enabled.");
}
} catch (Throwable t) {
traceFails(t);
return;
}
try {
mMessage = "create new Intent";
mNfcIntent = new Intent(this, getClass());
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
try {
mMessage = "mNfcIntent.addFlags, PendingIntent.getActivity";
mNfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
mNfcPendingIntent = PendingIntent.getActivity(this, 0, mNfcIntent, 0);
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
try {
mMessage = "new IntentFilter";
mTagIntentFilter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
mTagIntentFilter.addCategory(Intent.CATEGORY_DEFAULT);
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
try {
mMessage = "addDataType, new IntentFilter[]";
mTagIntentFilter.addDataType("*/*");
//mTagIntentFilter.addDataType("text/plain");
mIntentFiltersArray = new IntentFilter[]{mTagIntentFilter};
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
// Setup a tech list for all NfcF tags
try {
mMessage = "new tech list";
//mTechLists = new String[][]{new String[]{NfcF.class.getName()}};
mTechLists = new String[][]{};
traceOk();
} catch (Throwable t) {
traceFails(t);
return;
}
/*
if (mNfcAdapter != null) {
try {
mMessage = "mNfcAdapter.enableForegroundDispatch";
mNfcAdapter.enableForegroundDispatch(FullscreenActivity.mInstance, mNfcPendingIntent, mIntentFiltersArray, mTechLists);
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
*/
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
trace("onPostCreate...");
// Trigger the initial hide() shortly after the activity has been
// created, to briefly hint to the user that UI controls
// are available.
//delayedHide(100);
}
private void toggle() {
trace("toggle...");
if (mVisible) {
hide();
} else {
show();
}
}
private void hide() {
trace("hide...");
// Hide UI first
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
mControlsView.setVisibility(View.GONE);
mVisible = false;
// Schedule a runnable to remove the status and navigation bar after a delay
mHideHandler.removeCallbacks(mShowPart2Runnable);
mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY);
}
@SuppressLint("InlinedApi")
private void show() {
// Show the system bar
mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mVisible = true;
// Schedule a runnable to display UI elements after a delay
mHideHandler.removeCallbacks(mHidePart2Runnable);
mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY);
}
/**
* Schedules a call to hide() in [delay] milliseconds, canceling any
* previously scheduled calls.
*/
private void delayedHide(int delayMillis) {
mHideHandler.removeCallbacks(mHideRunnable);
mHideHandler.postDelayed(mHideRunnable, delayMillis);
}
/**/
public String intentToText(Intent intent){
String report = "?";
try {
Bundle bundle = intent.getExtras();
if (bundle != null) {
java.util.Set<String> keys = bundle.keySet();
java.util.Iterator<String> it = keys.iterator();
report = "Intent:{";
while (it.hasNext()) {
String key = it.next();
report += "\n[" + key + ":" + bundle.get(key) + "],";
}
report += "}\n";
}
}
catch(Throwable t){
trace("intentToText > " + t.getMessage());
}
return report;
}
/**/
public static String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for(byte b: a)
sb.append(String.format("%02x", b & 0xff));
return sb.toString();
}
/**/
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
trace("onNewIntent...");
handleIntent(intent);
}
/**/
void handleIntent(Intent intent) {
if (intent == null) return;
String sAction = intent.getAction();
trace("act:" + sAction);
if( (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
|| (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction()))
|| (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction()))) {
String payload = intent.getDataString();
mTagContentText.setText("act:" + sAction + "\n" + "pload:" + payload + "\n" + intentToText(intent));
Tag myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (myTag != null) {
trace("myTag.mId:" + byteArrayToHex(myTag.getId()));
mTagContentText.setText(mTagContentText.getText() + "\n" + "myTag.mId:" + byteArrayToHex(myTag.getId()));
android.os.Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
for (android.os.Parcelable p : rawMsgs) {
NdefMessage msg = (NdefMessage) p;
NdefRecord[] records = msg.getRecords();
for (NdefRecord record : records) {
short tnf = record.getTnf();
byte[] id = record.getId();
byte[] payLoad = record.getPayload();
}
}
}
}
}
}
/**/
@Override
protected void onResume() {
super.onResume();
trace("onResume...");
if (mNfcAdapter != null) {
try {
// See if the Activity is being started/resumed due to an NFC event and handle it
onNewIntent( getIntent());
}
catch (Throwable t) {
traceFails(t);
}
try {
mMessage = "mNfcAdapter.disableForegroundDispatch";
mNfcAdapter.disableForegroundDispatch(FullscreenActivity.mInstance);
traceOk();
}
catch (Throwable t) {
traceFails(t);
}
}
}
/**/
@Override
protected void onPause() {
super.onPause();
trace("onPause...");
}
}AndroidManifest.xml是:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.pdf.nfcaccess">
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_pdflauncher"
android:label="@string/app_name"
android:supportsRtl="true"
android:debuggable="true"
android:theme="@style/AppTheme">
<activity
android:name=".FullscreenActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:theme="@style/FullscreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
<!--intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"/>
</intent-filter-->
</manifest>发布于 2016-06-08 16:50:26
您接收NFC意图(操作TAG_DISCOVERED),因为您在清单中注册了它:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>这也是你的活动在接收到意图后被重新创建的原因。
您为前景分配注册的意图筛选器(带有任何MIME类型的动作NDEF_DISCOVERED )似乎与您的标记不匹配(或者您还没有调用启用前景调度的代码段)。
请注意,调用disableForegroundDispatch()将禁用以前通过enableForegroundDispatch()注册的前台调度。它不会影响你清单中的意图过滤器。关于如何选择性地禁用清单中注册的意图筛选器,请参见Android: Can I enable/disable an activity's intent filter programmatically?。但是,关于NFC意图,您可能希望通过前台调度系统注册以接收所有标记的事件,然后在onNewIntent()中接收事件时选择性地忽略您不想要的标记。
关于您的代码的更多内容(实际上只涉及NFC部分)
NDEF_DISCOVERED意图筛选器,您通常还希望指定一个与标记的数据类型匹配的<data ... />元素。TAG_DISCOVERED意图筛选器(除非您真正理解并希望了解它的影响)。TAG_DISCOVERED意图过滤器(当在清单中使用时)仅仅是APILevel9(在Android2.3.3之前)的兼容模式,而NFC支持非常非常有限,并且可以用来创建处理任何其他应用程序不支持的NFC标记的应用程序。TECH_DISCOVERED意图筛选器需要一个技术列表XML文件。因此,清单中当前版本的此筛选器将永远不会匹配任何内容。disableForegroundDispatch()中调用onResume()没有任何意义。根据设计,在活动生命周期的这一点上,永远无法启用前台调度。这样做的原因是,您不能在enableForegroundDispatch()之前调用onResume(),并且必须最迟在onPause()中调用disableForegroundDispatch()。enableForegroundDispatch() / onPause()以外的任何地方使用onResume() /onPause()都是没有意义的。如果您想停止侦听其他事件(例如按下按钮)上的标记,您只需在某些标志中记住当前状态(进程/不处理NFC事件),并且当您在onNewIntent()中接收到新的NFC意图时,您将处理或忽略基于该标志的标记。onNewIntent(getIntent());所做的那样)。https://stackoverflow.com/questions/37702519
复制相似问题