gpt4 book ai didi

android - 如何在 onNewIntent 执行之前拦截 NFC 标签

转载 作者:行者123 更新时间:2023-11-30 02:19:04 25 4
gpt4 key购买 nike

我有一个应用程序可以捕获 NFC 标签。我过去遇到的问题是用户以不稳定的方式将鼠标悬停在标签上,导致 NFC 适配器触发两次。

我已经做了一些事情来解决这个问题。

list :

<activity
android:name=".NfcActivity"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:noHistory="true"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation">

<intent-filter>


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

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

<data android:mimeType="text/plain" />
</intent-filter>
</activity>

这会将 NFC 捕获 Activity 设置为堆栈中的唯一实例,并且没有历史记录。我已经覆盖了所有可以停止和重新启动此 Activity 的配置更改,后者可能导致将 Intent 数据重新传送到 Activity ,使其看起来像重复扫描。

在 Activity 本身中,我已经覆盖了 onNewIntent,除了显示错误的扫描屏幕外什么都不做。我也明白 onNewIntent 应该从功能的角度反射(reflect) onCreate,但是因为以前版本的应用程序已经向下一个 Activity 发送了 2 次扫描,我只希望 NFC 捕获代码在一个地方,onCreate。

在 onCreate 中,我做了进一步的测试,以防止将鼠标悬停在标签上并创建错误的扫描。

  • 我检查了 Intent 中的已启动表单历史标记。 Android 可以在内存不足时终止应用程序,并在稍后重新启动以重新实现最初的 Intent 。这可能会导致看似重复的扫描。
  • 在 onCreate 中,我检查用户是否仍将手机连接到标签。这证明用户没有将鼠标悬停在带有 ndefTag.connect() 的标签上;

该应用程序似乎运行良好,但在一部特定的手机(三星 Galaxy Young 2)上,如果用户将手机放在标签上几秒钟,NFC 适配器似乎会连续触发几次。

发生这种情况时,原始扫描将被取消。这样做的原因是 oncreate 处理标签但是当后续扫描发生时(通过悬停,偶然), onPause -> onNewIntent 运行。于是Activity跳出onCreate,停止处理tag。 onNewIntent 显示失败的扫描屏幕并启动菜单屏幕。

以上并不是什么大问题,因为所有发生的事情都是用户必须重新扫描标签。

我希望发生的是:

当 onCreate 运行时,无论如何都会处理标签,即使 onNewintent 已执行。有没有办法在达到 onNewintent 和 onPause 之前拦截 Intent ?

也许有一个我可以使用的全局标志,可以首先检查它以表明 onCreate 仍在运行而 onNewIntent 不应该,或者更重要的是,没有调用 onPause 使 onCreate 停止运行。

import java.util.List;
import java.util.concurrent.ExecutionException;

import org.ndeftools.Message;
import org.ndeftools.Record;

import android.app.Activity;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.os.Vibrator;
import android.util.Log;
import android.widget.Toast;

public class NfcActivity extends Activity {

private static final String TAG = NfcActivity.class.getName();

protected NfcAdapter nfcAdapter;
protected PendingIntent nfcPendingIntent;

Handler handler;
Runnable runnable;

Handler failHandler;
Runnable failRunnable;

Parcelable[] messages;

Intent i;

Tag tag;
String tagId;

boolean nfcConnected;

ProgressDialog progressDialog;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.nfcactivitylayout);
Log.e(TAG, "oncreate");
nfcConnected = false;

// initialize NFC
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

tag = null;
tagId = null;

i = getIntent();

if ((i.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {

//check to see if Android has previously killed the app and relaunched it from History
//and delivered the original intent.
//if it has do not process and launch the menu screen
Intent processPayloadIntent = new Intent(NfcActivity.this, NfcscannerActivity.class);
processPayloadIntent.setAction("QRCODE_ACTION");
processPayloadIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(processPayloadIntent);

}else{



tag = i.getParcelableExtra(NfcAdapter.EXTRA_TAG);

tagId = bytesToHexString(tag.getId());

Log.e(TAG, "tagID = " + tagId);

Log.e(TAG, "oncreate intent action = " + i.getAction());




//The activity has captured tag data, prove the user is not hovering over the tag and is doing a good scan
//hovering can trigger the adapter twice

AsyncNfcConnect asnc = new AsyncNfcConnect();
try {
asnc.execute().get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}




Log.e(TAG, "nfcConnected!!!!!!!!!!!!!!!!!!!!!!!!! = " + nfcConnected);

if(nfcConnected == true){


int buildVersionSdk = Build.VERSION.SDK_INT;
int buildVersionCodes = Build.VERSION_CODES.GINGERBREAD;

Log.e(TAG, "buildVersionSdk = " + buildVersionSdk
+ "buildVersionCodes = " + buildVersionCodes);

int themeVersion;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD) {

themeVersion = 2;

} else {

themeVersion = 1;
}

try{

progressDialog = new ProgressDialog(this, themeVersion);
progressDialog.setTitle("NFC Tag Scanned");
progressDialog.setMessage("Processing tag...");
progressDialog.setIndeterminate(true);
progressDialog.show();

}catch(Exception e){ }




if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(i.getAction()) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(i.getAction())) {

if(NfcScannerApplication.isCanScanNfcTag()){

messages = i.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (messages != null) {


//setContentView(R.layout.successfulnfc);

NfcScannerApplication.startNfcTimer();
//Toast.makeText(this, "NFC timer set", Toast.LENGTH_LONG).show();

Log.e(TAG, "Found " + messages.length + " NDEF messages"); // is almost always just one

vibrate(); // signal found messages :-)



initHandler();
handler.postDelayed(runnable, 2000);

}else{

Toast.makeText(this, "Data on tag was not correct", Toast.LENGTH_LONG).show();

try{

handler.removeCallbacks(runnable);
Log.e(TAG, "just removed callback to runnable that reads nfc tag data");

}catch(Exception e){

}




initFailHandler();
failHandler.postDelayed(failRunnable, 1);



}

}else{


try{

handler.removeCallbacks(runnable);
Log.e(TAG, "just removed callback to runnable that reads nfc tag data");

}catch(Exception e){

}




initFailHandler();
failHandler.postDelayed(failRunnable, 1);


}



} else {

Toast.makeText(this, "Tag not recognized correctly", Toast.LENGTH_LONG).show();

try{

handler.removeCallbacks(runnable);
Log.e(TAG, "just removed callback to runnable that reads nfc tag data");

}catch(Exception e){

}




initFailHandler();
failHandler.postDelayed(failRunnable, 1);

}


}else{


try{

Toast.makeText(this, "Phone wasn't connected to Tag", Toast.LENGTH_LONG).show();

handler.removeCallbacks(runnable);
Log.e(TAG, "just removed callback to runnable that reads nfc tag data");

}catch(Exception e){

}




initFailHandler();
failHandler.postDelayed(failRunnable, 1);



}//end of NFC connect test


}//end of launched from history check


}//end of onCreate





@Override
protected void onStart() {
super.onStart();
Log.e(TAG, "onStart");
}





@Override
protected void onStop() {
super.onStop();
Log.e(TAG, "onStop");
}





@Override
public void onNewIntent(Intent intent) {
Log.e(TAG, "onNewIntent");

Toast.makeText(this, "Bad scan!!!", Toast.LENGTH_LONG).show();



initFailHandler();
failHandler.postDelayed(failRunnable, 1);



}//end of onNewIntent






public void enableForegroundMode() {
Log.e(TAG, "enableForegroundMode");

IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); // filter for all
IntentFilter[] writeTagFilters = new IntentFilter[] {tagDetected};
nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);
}

public void disableForegroundMode() {
Log.e(TAG, "disableForegroundMode");

nfcAdapter.disableForegroundDispatch(this);
}





@Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume");

enableForegroundMode();
}

@Override
protected void onPause() {
Log.e(TAG, "onPause");

super.onPause();

disableForegroundMode();

if(handler != null){
handler.removeCallbacks(runnable);
}


}

private void vibrate() {
Log.e(TAG, "vibrate");

Vibrator vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE) ;
vibe.vibrate(500);
}


public void initHandler(){

handler = new Handler();
runnable = new Runnable() {
public void run() {
processTag();

}

private void processTag() {
Log.e(TAG, "about to process tag");

try{
progressDialog.dismiss();

}catch(Exception e){

//do nothing
}

// parse to records
for (int i = 0; i < messages.length; i++) {
try {
List<Record> records = new Message((NdefMessage)messages[i]);

Log.e(TAG, "Found " + records.size() + " records in message " + i);

for(int k = 0; k < records.size(); k++) {
Log.e(TAG, " Record #" + k + " is of class " + records.get(k).getClass().getSimpleName());

Record record = records.get(k);

NdefRecord ndefRecord = record.getNdefRecord();

byte[] arr = ndefRecord.getPayload();

String payload = new String(arr);


if(payload.length() > 0){

payload = payload.substring(3, payload.length());

Log.e(TAG, "payload = " + payload);

String[] splitPayload = payload.split(",");

String tagType = splitPayload[0];
String tagCompany = splitPayload[1];
String tagClientID = splitPayload[2];
String tagClientName = splitPayload[3];

if(! tagClientID.equalsIgnoreCase("0") && tagClientID.length() > 0){

handler.post(new Runnable(){
public void run() {

setContentView(R.layout.successfulnfc);

}
});






Intent processPayloadIntent = new Intent(NfcActivity.this, NfcscannerActivity.class);
processPayloadIntent.putExtra("payload", payload);
processPayloadIntent.putExtra("tagid", tagId);
processPayloadIntent.setAction("NFC");
processPayloadIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//processPayloadIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(processPayloadIntent);
finish();
overridePendingTransition(0, R.anim.activity_animation_zoom_in);





}else{
Toast.makeText(NfcActivity.this, "Tag data problem/Scan problem.", Toast.LENGTH_LONG).show();

initFailHandler();
failHandler.postDelayed(failRunnable, 1);


}

}else{
Toast.makeText(NfcActivity.this, "Tag data problem/Scan problem.", Toast.LENGTH_LONG).show();

initFailHandler();
failHandler.postDelayed(failRunnable, 1);

}



}
} catch (Exception e) {
Log.e(TAG, "Problem parsing message", e);
}

}

}
};

}





public void initFailHandler(){

failHandler = new Handler();
failRunnable = new Runnable() {
public void run() {

returnToMainMenu();

}

private void returnToMainMenu() {
//Log.e(TAG, "about to return to main menu");

try{
progressDialog.dismiss();

}catch(Exception e){

//do nothing
}

Toast.makeText(NfcActivity.this, "Please check your scanning technique.\nPlease do not hover over tag or swipe...", Toast.LENGTH_LONG).show();

failHandler.post(new Runnable(){
public void run() {

setContentView(R.layout.nfcfail);

}
});






//onBackPressed();
Intent processPayloadIntent = new Intent(NfcActivity.this, NfcscannerActivity.class);
processPayloadIntent.setAction("QRCODE_ACTION");
processPayloadIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(processPayloadIntent);
finish();
//overridePendingTransition(0, R.anim.activity_animation_zoom_in);

}
};

}




private String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("0x");
if (src == null || src.length <= 0) {
return null;
}

char[] buffer = new char[2];
for (int i = 0; i < src.length; i++) {
buffer[0] = Character.forDigit((src[i] >>> 4) & 0x0F, 16);
buffer[1] = Character.forDigit(src[i] & 0x0F, 16);
System.out.println(buffer);
stringBuilder.append(buffer);
}

return stringBuilder.toString();
}



private class AsyncNfcConnect extends AsyncTask<String, Void, String> {






@Override
protected String doInBackground(String... params) {

NfcActivity.this.nfcConnected = false;
String result;
Ndef ndefTag = Ndef.get(tag);

try {
Log.e(TAG, "about to test connect()********************************************");
ndefTag.connect(); // this should already perform an IO operation and should therefore fail if there is no tag
Log.e(TAG, "Ndef.connect() connected!********************************************");
NdefMessage ndefMsg = ndefTag.getNdefMessage(); // this reads the current NDEF message from the tag and consequently causes an IO operation

NfcActivity.this.nfcConnected = true;
result = "OK";
return result;

} catch (Exception e) {
// there is no tag or communication with tag dropped
Log.e(TAG, "There a problem with connecting to the tag using Ndef.connect(");
NfcActivity.this.nfcConnected = false;
result = "NOTOK";
return result;
} finally {
try {
ndefTag.close();
} catch (Exception e) {
}
}


}



}//end of Async


}

最佳答案

您似乎坚持不在 onNewIntent() 中处理 NFC Intent 。我建议 onCreate()onNewIntent() 都调用扫描标签的通用过程。这样,两个入口点将遵循相同的代码路径。

您声称应用程序“跳出 onCreate”可能只是一种比喻?发生的情况是您的标签扫描 AsyncNfcConnect 作为后台任务在单独的线程上运行(应该如此)。该任务在 onCreate() 中创建并在 onCreate() 完成后继续运行(您可以在末尾添加 Log 语句onCreate() 检查)。当与标签的连接以某种方式丢失并重新发现标签时,将调用 onNewIntent(),如您所见。

无论如何都无法阻止这种情况的发生,因此您的应用必须能够处理它。要检测并处理它,您可以在 Activity 中设置一些标志以指示您的后台任务正在运行或已经运行。您还可以存储是否发生异常的信息,并在重新发现时再次尝试扫描标签(这可能需要您实现我上面提出的建议)。如果您想让您的应用程序更加防故障,您还可以存储最后一次扫描标签的 ID,以便在您成功扫描(或未扫描)后重新发现它时再次肯定地识别它。当同一标签不断出现异常时,您可以在一定次数后向用户指示他(例如,建议设备与标签的位置不同)。

关于android - 如何在 onNewIntent 执行之前拦截 NFC 标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28860223/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com