- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我一直在 Android Studio 中开发一个应用程序来读写 NFC 标签,特别是 Mifare Classic 标签。 2016 年初(一年前),我设法在我的智能手机(使用 S.O. KitKat)上开发和测试它。
正如我提到的,抛开应用程序,在更新 Android Studio、SDK 和 S.O. 的版本之后。从我的智能手机到 MarshMallow,尝试写入标签时出现此错误:“java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法‘void android.nfc.tech.MifareClassic.connect()’”。
这个错误显然是在尝试连接到 MifareClassic 标签时产生的。
附上我的 Activity 代码,用我认为不相关的...替换了一些部分。
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.os.Bundle;
import android.view.View.OnClickListener;
...
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@SuppressLint("Escribir")
public class escribir extends Activity {
NfcAdapter adapter;
PendingIntent pendingIntent;
IntentFilter writeTagFilters[];
boolean writeMode;
Tag myTag;
MifareClassic mfc;
Context context;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_datospropietario);
context = this;
...
Button btnWrite = (Button)findViewById(R.id.button);
final String b = getIntent().getExtras().getString("datos");
btnWrite.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final String mensaje = (b + ...);
if (first.getText().toString().isEmpty()) {
Toast.makeText(context, context.getString(R.string.missing_fields), Toast.LENGTH_SHORT).show();
} else {
if (myTag == null) {
Toast.makeText(context, context.getString(R.string.error_notag), Toast.LENGTH_LONG).show();
} else {
MifareClassic tmpMFC = null;
try {
tmpMFC = MifareClassic.get(myTag);
} catch (Exception e) {
Toast.makeText(context, context.getString(R.string.error_notag), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
mfc = tmpMFC;
int sect;
if (mfc != null) {
sect = mfc.getSectorCount();
}
try {
mfc.connect();
...
} catch (IOException e) {
Toast.makeText(context, context.getString(R.string.error_notag), Toast.LENGTH_LONG).show();
e.printStackTrace();
myTag = null;
}
}
}
});
adapter = NfcAdapter.getDefaultAdapter(this);
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
writeTagFilters = new IntentFilter[]{tagDetected};
}
private void write(String text, Tag tag, int sector) throws IOException, FormatException {
NdefRecord[] records = {createRecord(text), NdefRecord.createApplicationRecord("my_app")};
NdefMessage mensaje = new NdefMessage(records);
NdefFormatable formatable = NdefFormatable.get(tag);
if (formatable != null) {
formatable.connect();
formatable.format(mensaje);
formatable.close();
} else {
Ndef ndef = Ndef.get(tag);
ndef.connect();
ndef.writeNdefMessage(mensaje);
ndef.close();
}
MifareClassic mfc = MifareClassic.get(tag);
...
}
@SuppressLint("Escribir") private NdefRecord createRecord(String text) throws UnsupportedEncodingException{
String lang = "es";
byte[] textBytes = text.getBytes();
byte[] langBytes = lang.getBytes("US-ASCII");
int langLength = langBytes.length;
int textLength = textBytes.length;
byte[] payLoad = new byte[1 + langLength + textLength];
payLoad[0] = (byte) langLength;
System.arraycopy(langBytes, 0, payLoad, 1, langLength);
System.arraycopy(textBytes, 0, payLoad, 1 + langLength, textLength);
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payLoad);
}
@SuppressLint("Escribir") protected void onNewIntent(Intent intent){
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
}
public void onPause(){
super.onPause();
WriteModeOff();
}
public void onResume(){
super.onResume();
WriteModeOn();
}
@SuppressLint("Escribir") private void WriteModeOn(){
writeMode = true;
adapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null);
}
@SuppressLint("Escribir") private void WriteModeOff(){
writeMode = false;
adapter.disableForegroundDispatch(this);
}
}
最佳答案
在互联网上研究了这个问题后,我发现 NFC 标签写入问题出现在各种设备上,例如某些 HTC 或 Sony Xperia 型号。这些问题是在Android版本升级到SDK 5.1(Lollipop)后出现的。
这个问题的起因是一些制造商修改了堆栈顺序,发现不同的标签类型在请求 TechExtras 时导致冲突并返回 SAK 空值或错误值。
我找到的详细解释如下:
HTC One:看来,这个bug的原因是NfcA的TechExtras为空。但是,TechList 包含 MifareClassic。
Sony Xperia Z3(+ 仿真 MIFARE Classic 标签): buggy 标签在 TechList 中有两个具有不同 SAK 值的 NfcA 和一个 MifareClassic(带有第二个 NfcA 的 Extra)。第二个 NfcA 和 MifareClassic 技术都具有 0x20 的 SAK。根据恩智浦关于识别 MIFARE 标签的指南(第 11 页),这是一个 MIFARE Plus 或 MIFARE DESFire 标签。此方法使用两个 NfcA 出现的 SAK 值或运算(如 NXP 的 MIFARE 类型识别过程指南中所述)创建一个新的 extra,并将第一个 NfcA 的 Extra 替换为新的。
有关更多信息,请参阅 https://github.com/ikarus23/MifareClassicTool/issues/52
以及解决我问题的 bildin 用户提出的补丁:
public Tag patchTag(Tag oTag)
{
if (oTag == null)
return null;
String[] sTechList = oTag.getTechList();
Parcel oParcel, nParcel;
oParcel = Parcel.obtain();
oTag.writeToParcel(oParcel, 0);
oParcel.setDataPosition(0);
int len = oParcel.readInt();
byte[] id = null;
if (len >= 0)
{
id = new byte[len];
oParcel.readByteArray(id);
}
int[] oTechList = new int[oParcel.readInt()];
oParcel.readIntArray(oTechList);
Bundle[] oTechExtras = oParcel.createTypedArray(Bundle.CREATOR);
int serviceHandle = oParcel.readInt();
int isMock = oParcel.readInt();
IBinder tagService;
if (isMock == 0)
{
tagService = oParcel.readStrongBinder();
}
else
{
tagService = null;
}
oParcel.recycle();
int nfca_idx=-1;
int mc_idx=-1;
for(int idx = 0; idx < sTechList.length; idx++)
{
if(sTechList[idx] == NfcA.class.getName())
{
nfca_idx = idx;
}
else if(sTechList[idx] == MifareClassic.class.getName())
{
mc_idx = idx;
}
}
if(nfca_idx>=0&&mc_idx>=0&&oTechExtras[mc_idx]==null)
{
oTechExtras[mc_idx] = oTechExtras[nfca_idx];
}
else
{
return oTag;
}
nParcel = Parcel.obtain();
nParcel.writeInt(id.length);
nParcel.writeByteArray(id);
nParcel.writeInt(oTechList.length);
nParcel.writeIntArray(oTechList);
nParcel.writeTypedArray(oTechExtras,0);
nParcel.writeInt(serviceHandle);
nParcel.writeInt(isMock);
if(isMock==0)
{
nParcel.writeStrongBinder(tagService);
}
nParcel.setDataPosition(0);
Tag nTag = Tag.CREATOR.createFromParcel(nParcel);
nParcel.recycle();
return nTag;
}
此补丁由 bildin ( https://github.com/bildin) 提供。
虽然我测试的设备不是早期品牌,但该补丁在我的 Moto X(第一代)上运行良好,带有修改后的 ROM Marshmallow,所以我想它也适用于具有NXP芯片PN544
关于android - 尝试在空对象引用上调用虚拟方法 'void android.nfc.tech.MifareClassic.connect()',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42963329/
有WHERE 1=1有什么作用如果您在脚本(伪代码)中编写此请求: sql = "SELECT f1,f2,f3 FROM t WHERE 1=1" ++ restOfTheClause
这个问题已经有答案了: R: Convert delimited string into variables (3 个回答) 已关闭 5 年前。 我有一个包含电影数据的表,在最后一列中,它包含电影所属
假设我有一个基类: struct A{ virtual void foo() = 0; }; 然后假设我有一个这样的派生类: struct B : public virtual A{ voi
我有一个小问题,我的 << 运算符没有被正确调用。 这是我的: class SomeInterface { friend std::ostream& operator<<(std::ostrea
首先,我来自 Java 社区,并且仍然是 C++ 的学习者。 请看下面的类 第二张图片显示了类“GameObject”的子类。它还有一个 Display() 方法。 GameObject类有5个子类,
我这里遇到了一些问题。我试图让我的代码像 java 中的接口(interface)一样工作。这个类被其他 2 个继承,因为它们导致了一些问题。而且我还想知道我是否做对了,以及改进我的代码的方法。我是新
在 C++ 中,我有一个基类 A,一个子类 B。两者都有虚方法 Visit。我想在 B 中重新定义“访问”,但 B 需要访问每个 A(以及所有子类)的“访问”功能。 我有类似的东西,但它告诉我 B 无
我有一个抽象类,它是类层次结构的根。该根类有一个带有一些简单实现的方法,似乎没有必要随时随地更改该实现。 使该方法成为非虚方法很好,但是某些子类可能会意外地重新实现它。在这种情况下,虚拟 final方
在 MSDN 上,我发现在抽象方法声明中使用“virtual”修饰符是错误的。我的一位同事应该是非常有经验的开发人员,但他在他的代码中使用了这个: public abstract class Busi
C++ 虚函数表是仅用于确定调用虚函数时应该执行哪一段代码,还是在运行时有其他用途? 在维基百科上,它列出了“动态调度”作为一个原因,但没有深入了解 C++ 的更多细节...... 最佳答案 一些实现
页面大小是否恒定?更具体地说,getconf PAGE_SIZE 给出 4096,这很公平。但这可以通过程序的运行时间改变吗?或者它在整个操作系统进程生成过程中是否保持不变。 IE。 , 进程是否可能
析构函数(当然还有构造函数)和其他成员函数之间的区别在于,如果常规成员函数在派生类中具有主体,则仅执行派生类中的版本。而在析构函数的情况下,派生版本和基类版本都会被执行? 很高兴知道在析构函数(可能是
如果一个函数被定义为虚函数并且与纯虚函数相同,这究竟意味着什么? 最佳答案 来自 Wikipedia's Virtual function... In object-oriented programm
我有一个在 Jetty 下运行的应用程序,我希望该应用程序返回自引用绝对 URL(生成 RSS 提要时,因此客户端必须能够在没有“当前 URL”上下文的情况下工作)。 问题是我事先不知道应用程序将部署
如何在两个virtualtreeview之间复制以复制所有列,而不仅仅是第一列? 复制前: 复制后: 最佳答案 树控件不保存任何数据。它不包含要显示的列数据,因此无法复制它。而是,当树控件想要显示任何
我已将 ShowHint 设置为 true 并将 HintMode 设置为 hmToolTip,但是当我将光标悬停在控件上时,我的 OnGetHint() 事件处理程序甚至没有断点。 知道我做错了什么
我的 friend 正在 Delphi 中使用 VirtualTreeView 工作,并且遇到了下一个问题:他有两列,第一列的每一行都有数据和子项。是否可以不更改第一列宽度来设置最大子列宽度? 图例:
我在我的 Virtual TreeView Component 中使用 TVirtualStringTree ( Delphi project 的一部分)我想创建一个 View ,其中 2 列可以有可
我想遍历 VirtualTreeView 的所有根并将其删除。 我不想清除它。 我收到此代码的访问冲突: var Node : PVirtualNode; begin if VirtualStri
我有一个可以输出表单的 PHP 文件。我想在服务器端调用这个 PHP 文件(当前使用“include”),填写并提交。 这样更好,因此我不必干预实际的 PHP 表单,只需处理表示层,以便数据可以被它自
我是一名优秀的程序员,十分优秀!