`你好, 我正在制作一个 NFC 计时应用程序,我遇到了一个无法克服的问题,如果有人有任何想法,我会很高兴听到。 当我扫描 NFC 标签时,Android 的内置 NFC 读取器不断弹出。 如果我将意图过滤器放入清单文件中,它不会弹出,但每次触摸时它都会一次又一次地拉入我设置的活动,这是不合适的,我还会将 nfc 用于其他活动,所以这不是一个解决方案。 有没有办法阻止内置 nfc 阅读器出现? NFC 芯片只有一个 ID,没有其他内容,并且无法再更改。 🙁 预先非常感谢您的帮助! 代码:
package eu.obsys.staffkeeper.ui.worklogin;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.TagLostException;
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcF;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import eu.obsys.staffkeeper.FirstPageActivity;
import eu.obsys.staffkeeper.R;
import eu.obsys.staffkeeper.data.JsonObjectAsyncResponse;
import eu.obsys.staffkeeper.data.Repository;
import eu.obsys.staffkeeper.model.GpsLocation;
import eu.obsys.staffkeeper.util.GlobalFunction;
public class WorkLogInActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback {
private SharedPreferences sharedPreferences;
private Context context;
private Button logInToWorkCard,logOutToWorkCard, backToMenu, loginButton;
private ImageView thumbnail;
private String bitmapString;
private TextView nfcContent,txtType;
private int employeeId = 0;
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 1888;
private Drawable sampleImage;
//NFC
public static final String MIME_TEXT_PLAIN = "text/plain";
public static final String TAG = "NfcDemo";
private Tag detectedTag;
private NfcAdapter mNfcAdapter;
PendingIntent pendingIntent;
IntentFilter[] readTagFilters;
private String baseUrl;
private static final String GLOBAL_DATA = "globalShared";
String[] perms = {"android.permission.NFC"};
int permsRequestCode = 200;
IntentFilter[] intentFiltersArray;
String[][] techListsArray;
IntentFilter ndef = new IntentFilter();
int loginStatus = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_work_log_in);
requestPermissions(perms, permsRequestCode);
pendingIntent = PendingIntent.getActivity(
this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
PendingIntent.FLAG_MUTABLE);
initVariable();
initNFC();
initListener();
}
public void initVariable() {
context = getApplicationContext();
sharedPreferences = context.getSharedPreferences("placeObject", Context.MODE_PRIVATE);
baseUrl = sharedPreferences.getString("baseUrl", "https://mng.ob-sys.eu/");
logInToWorkCard = findViewById(R.id.loginToWorkCard);
logOutToWorkCard = findViewById(R.id.logoutFromWorkCard);
loginButton = findViewById(R.id.loginButton);
backToMenu = findViewById(R.id.bacToMenuButton);
thumbnail = findViewById(R.id.PhotoThumbnail);
nfcContent = findViewById(R.id.nfcContent);
nfcContent = findViewById(R.id.nfcContent);
nfcContent = findViewById(R.id.nfcContent);
sampleImage = thumbnail.getDrawable();
PackageManager packageManager = context.getPackageManager();
if(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT) == false){
Toast.makeText(context, "This device does not have a camera.", Toast.LENGTH_LONG)
.show();
return;
}
}
public void takePictureAndStoreEmployeeId(int employeeIdLocal) {
mNfcAdapter.disableReaderMode(this);
JSONObject jsonResponse = new Repository().getUserByNFC(baseUrl, employeeIdLocal, WorkLogInActivity.this, new JsonObjectAsyncResponse() {
@Override
public void processFinished(JSONObject jsonObject) {
try {
if(jsonObject.getInt("success") == 1) {
employeeId = employeeIdLocal;
loginStatus = jsonObject.getInt("loginStatus");
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra("android.intent.extras.CAMERA_FACING", 1);
intent.putExtra("android.intent.extra.USE_FRONT_CAMERA", true);
startActivityForResult(intent,
CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void initListener() {
backToMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(WorkLogInActivity.this, FirstPageActivity.class);
startActivity(intent);
finish();
}
});
logInToWorkCard.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
logInToWorkCard.setVisibility(View.INVISIBLE);
Context context = getApplicationContext();
final int duration = Toast.LENGTH_LONG;
// GpsLocation gpsLocation = GlobalFunction.getLocation(context);
new Repository().setLoginStatus(
baseUrl,
employeeId,
1,
sharedPreferences.getInt("placeId", 0),
bitmapString,
WorkLogInActivity.this,
new JsonObjectAsyncResponse() {
@Override
public void processFinished(JSONObject _jsonObject) {
try {
if(_jsonObject.getInt("success") == 1) {
logInToWorkCard.setVisibility(View.VISIBLE);
resetPage();
} else {
logInToWorkCard.setVisibility(View.VISIBLE);
String text = context.getResources().getString(R.string.faultAction) + " Listener";
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
);
}
});
logOutToWorkCard.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
logOutToWorkCard.setVisibility(View.INVISIBLE);
Context context = getApplicationContext();
final int duration = Toast.LENGTH_SHORT;
//GpsLocation gpsLocation = GlobalFunction.getLocation(context);
new Repository().setLoginStatus(
baseUrl,
employeeId,
0,
sharedPreferences.getInt("placeId", 0),
bitmapString,
WorkLogInActivity.this,
new JsonObjectAsyncResponse() {
@Override
public void processFinished(JSONObject _jsonObject) {
try {
if(_jsonObject.getInt("success") == 1) {
logOutToWorkCard.setVisibility(View.VISIBLE);
resetPage();
} else {
logOutToWorkCard.setVisibility(View.VISIBLE);
String text = context.getResources().getString(R.string.faultAction) + " Listener";
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
);
}
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
Bitmap bmp = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 30, stream);
byte[] byteArray = stream.toByteArray();
// convert byte array to Bitmap
bitmapString = Base64.encodeToString(byteArray, Base64.DEFAULT);
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0,
byteArray.length);
if(loginStatus == 1) {
logInToWorkCard.setVisibility(View.INVISIBLE);
logOutToWorkCard.setVisibility(View.VISIBLE);
} else {
logInToWorkCard.setVisibility(View.VISIBLE);
logOutToWorkCard.setVisibility(View.INVISIBLE);
}
// loginButton.setVisibility(View.INVISIBLE);
thumbnail.setImageBitmap(bitmap);
}
}
}
public void resetPage() {
thumbnail.setImageDrawable(sampleImage);
logInToWorkCard.setVisibility(View.INVISIBLE);
logOutToWorkCard.setVisibility(View.INVISIBLE);
}
public void initNFC() {
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("*/*"); /* Handles all MIME based dispatches.
You should specify only the ones that you need. */
}
catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
intentFiltersArray = new IntentFilter[] {ndef, };
techListsArray = new String[][] { new String[] { NfcF.class.getName() } };
try {
if (!mNfcAdapter.isEnabled()) {
txtType.setText("NFC is disabled.");
} else {
//txtType.setText("érkngorbgobrogb");
}
} catch (NullPointerException e) {
Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
finish();
return;
}
}
@Override
protected void onResume() {
super.onResume();
/**
* It's important, that the activity is in the foreground (resumed). Otherwise
* an IllegalStateException is thrown.
*/
if(mNfcAdapter!= null) {
//mNfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray);
Bundle options = new Bundle();
// Work around for some broken Nfc firmware implementations that poll the card too fast
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250);
// Enable ReaderMode for all types of card and disable platform sounds
mNfcAdapter.enableReaderMode(this,
this,
NfcAdapter.FLAG_READER_NFC_A |
NfcAdapter.FLAG_READER_NFC_B |
NfcAdapter.FLAG_READER_NFC_F |
NfcAdapter.FLAG_READER_NFC_V |
NfcAdapter.FLAG_READER_NFC_BARCODE |
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
options);
}
}
@Override
protected void onPause() {
super.onPause();
/**
* Call this before onPause, otherwise an IllegalArgumentException is thrown as well.
*/
if(mNfcAdapter!= null)
mNfcAdapter.disableReaderMode(this);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(permsRequestCode, permissions, grantResults);
switch (permsRequestCode) {
case 200:
boolean nfcAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
break;
}
}
public void onTagDiscovered(Tag tag) {
// Read and or write to Tag here to the appropriate Tag Technology type class
// in this example the card should be an Ndef Technology Type
Ndef mNdef = Ndef.get(tag);
// Check that it is an Ndef capable card
if (mNdef != null) {
// If we want to read
// As we did not turn on the NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK
// We can get the cached Ndef message the system read for us.
NdefMessage mNdefMessage = mNdef.getCachedNdefMessage();
String anyad = "";
NdefRecord[] records = mNdefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
//if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
byte[] payload = ndefRecord.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
try {
anyad = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
} catch (Exception e) {
e.printStackTrace();
}
// }
}
// Or if we want to write a Ndef message
// Create a Ndef Record
//NdefRecord mRecord = NdefRecord.createTextRecord("en", "2");
// Add to a NdefMessage
// NdefMessage mMsg = new NdefMessage(mRecord);
//
// Catch errors
try {
mNdef.connect();
// mNdef.writeNdefMessage(mMsg);
takePictureAndStoreEmployeeId(Integer.parseInt(anyad));
Toast toast = new Toast(getApplicationContext());
toast.makeText(getApplicationContext(),"Read NFC Success", Toast.LENGTH_SHORT).show();
// Make a Sound
try {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(),
notification);
r.play();
} catch (Exception e) {
// Some error playing sound
}
//} catch (FormatException e) {
// if the NDEF Message to write is malformed
} catch (TagLostException e) {
// Tag went out of range before operations were complete
} catch (IOException e) {
// if there is an I/O failure, or the operation is cancelled
} finally {
// Be nice and try and close the tag to
// Disable I/O operations to the tag from this TagTechnology object, and release resources.
try {
mNdef.close();
} catch (IOException e) {
// if there is an I/O failure, or the operation is cancelled
}
}
}
}
}
这个问题很难回答,因为您没有提供卡上数据的完整详细信息。
但问题可能是您在从
disableReaderMode
调用的 takePictureAndStoreEmployeeId
方法中 onTagDiscovered
,因此一旦您读取 NFC 标签一次,您将永远不会再次读取 NFC 标签,因为读取器模式永远不会重新启用。
请记住,当您出示标签时,可以多次触发 NFC 交互。 发生的情况很可能是您呈现它触发的标签
onTagDiscovered
,然后 disableReaderMode
,然后在第二次触发时,系统可以自由显示默认系统 NFC 对话框,因为您已告诉它您不再有兴趣接收NFC 触发器。
解决方案可能不是
disableReaderMode
中 takePictureAndStoreEmployeeId
此外,您的代码中也有很多未使用的内容,您设置了旧的前台 NFC 方法
enableForegroundDispatch
,该方法从未使用过(因为它被使用 enableReaderMode
替换,并且您不应该同时使用两者)