我是Android的新手,我正在尝试用NFC制作一种消息应用程序。
我有第一个活动,在发送光束时将EditText视图的内容发送到另一部手机,并在另一部手机上的TextView上显示传入消息。这很好。
我有另一个用于向联系人注册表添加联系人的活动,它应该如下工作:
我的问题是,即使有关通过NFC发送的代码在两个活动之间基本相同,当我发布第二个活动(AddContactActivity)时,发送的意图的动作是ACTION_MAIN
而不是ACTION_NDEF_DISCOVERED
,具有开启第一项活动的效果,因而无法通过正确的治疗。
以下是MainActivity的代码:
public class MainActivity extends Activity {
private TextView mTextView;
private EditText mEdit;
NfcAdapter nfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
mTextView = (TextView)findViewById(R.id.retour);
mEdit = (EditText)findViewById(R.id.editText);
nfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() {
@Override public NdefMessage createNdefMessage(NfcEvent event) {
String stringOut = mEdit.getText().toString();
byte[] bytesOut = stringOut.getBytes();
NdefRecord ndefRecordOut = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA,
"text/plain".getBytes(),
new byte[] {},
bytesOut);
NdefMessage ndefMessageout = new NdefMessage(ndefRecordOut);
return ndefMessageout;
}
}, this);
checkAndProcessBeamIntent(intent);
}
@Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("text/plain");
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
}
IntentFilter[] intentFiltersArray = new IntentFilter[] {ndef, };
nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, null);
}
private void checkAndProcessBeamIntent(Intent intent) {
String action = intent.getAction();
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED)){
Parcelable[] parcelables =
intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage inNdefMessage = (NdefMessage)parcelables[0];
NdefRecord[] inNdefRecords = inNdefMessage.getRecords();
NdefRecord NdefRecord_0 = inNdefRecords[0];
String inMsg = new String(NdefRecord_0.getPayload());
mTextView.setText(inMsg);
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Toast.makeText(MainActivity.this,
intent.getAction().toString(),
Toast.LENGTH_LONG).show();
checkAndProcessBeamIntent(intent);
}
@Override
public void onPause() {
super.onPause();
nfcAdapter.disableForegroundDispatch(this);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public void generateKeys(){
Calendar cal = Calendar.getInstance();
Date now = cal.getTime();
cal.add(Calendar.YEAR, 1);
Date end = cal.getTime();
KeyPairGenerator kpg = null;
try {
kpg = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
try {
kpg.initialize(new KeyPairGeneratorSpec.Builder(getApplicationContext())
.setAlias("Keys")
.setStartDate(now)
.setEndDate(end)
.setSerialNumber(BigInteger.valueOf(1))
.setSubject(new X500Principal("CN=test1"))
.build());
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
kpg.generateKeyPair();
}
public void goToAddContact(View view) {
Intent intent = new Intent(this, AddContactActivity.class);
intent.setAction("NewActivity");
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
}
以下是AddContactActivity的代码:
public class AddContactActivity extends Activity{
NfcAdapter nfcAdapter;
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_contact);
editText = (EditText)findViewById(R.id.editText);
nfcAdapter = NfcAdapter.getDefaultAdapter(getApplicationContext());
Intent intent = getIntent();
nfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() {
@Override public NdefMessage createNdefMessage(NfcEvent event) {
String stringOut = getMyPublicKey();
byte[] bytesOut = stringOut.getBytes();
NdefRecord ndefRecordOut = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA,
"text/plain".getBytes(),
new byte[] {},
bytesOut);
NdefMessage ndefMessageout = new NdefMessage(ndefRecordOut);
return ndefMessageout;
}
}, this);
checkAndProcessBeamIntent(intent);
}
@Override
public void onResume() {
super.onResume();
Intent intent = getIntent();
Toast.makeText(AddContactActivity.this,
"onResume : "+intent.getAction().toString(),
Toast.LENGTH_LONG).show();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("text/plain");
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
}
IntentFilter[] intentFiltersArray = new IntentFilter[] {ndef, };
nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, null);
}
public void addContactDataBase(String publicKey){
SQLiteHelper sqLiteHelper = new SQLiteHelper(this);
sqLiteHelper.addUser(new User(editText.getText().toString(), publicKey));
}
public void checkUserInDataBase(String publicKey){
SQLiteHelper sqLiteHelper = new SQLiteHelper(this);
User u = sqLiteHelper.getUser(publicKey);
Toast.makeText(AddContactActivity.this,
""+u.getName(),
Toast.LENGTH_LONG).show();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Toast.makeText(AddContactActivity.this,
"OnNewIntent : "+intent.getAction().toString(),
Toast.LENGTH_LONG).show();
checkAndProcessBeamIntent(intent);
}
@Override
public void onPause() {
super.onPause();
nfcAdapter.disableForegroundDispatch(this);
}
private void checkAndProcessBeamIntent(Intent intent) {
String action = intent.getAction();
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED)){
Toast.makeText(AddContactActivity.this,
"COUCOU",
Toast.LENGTH_LONG).show();
Parcelable[] parcelables =
intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage inNdefMessage = (NdefMessage)parcelables[0];
NdefRecord[] inNdefRecords = inNdefMessage.getRecords();
NdefRecord NdefRecord_0 = inNdefRecords[0];
String inMsg = new String(NdefRecord_0.getPayload());
addContactDataBase(inMsg);
checkUserInDataBase(inMsg);
}
}
public String getMyPublicKey(){
KeyStore ks = null;
RSAPublicKey publicKey = null;
try {
ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry)ks.getEntry("Keys", null);
publicKey = (RSAPublicKey) keyEntry.getCertificate().getPublicKey();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableEntryException e) {
e.printStackTrace();
}
return publicKey.toString();
}
}
以下是清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bsauzet.testnfc" >
<uses-permission android:name="android.permission.NFC" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AddContactActivity"
android:label="@string/title_activity_add_contact"
android:launchMode="singleTop">
<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>
</application>
</manifest>
答案 0 :(得分:0)
检查您的appCompat库。 appCompat库的损坏可能会导致错误的意图异常。特别是当您从另一台PC或工作区(和/或IDE)移动项目时。
答案 1 :(得分:0)
在收到NFC事件时获得ACTION_MAIN
而不是ACTION_NDEF_DISCOVERED
的意图,这是典型的迹象,表明收到了包含Android应用程序记录(AAR)的NDEF消息,并且是第一条记录的数据类型任何意图过滤器都没有匹配NDEF消息。
您的CreateNdefMessageCallback.createNdefMessage()
方法显然不会在NDEF消息中添加AAR。因此,您仍然会收到包含AAR的NDEF消息的唯一原因是createNdefMessage()
会引发未处理的异常。在这种情况下,NFC堆栈将自动生成包含Play商店链接和AAR的NDEF消息。
可能导致createNdefmessage()
提出未处理异常的最有可能的地方是getMyPublicKey()
(因为MainActivity
和AddContactActivity
之间唯一不同的部分)。
因此,我们可以将问题跟踪到您的代码的这一部分:
ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry)ks.getEntry("Keys", null);
publicKey = (RSAPublicKey) keyEntry.getCertificate().getPublicKey();
此代码
ks
,keyEntry
或keyEntry.getCertificate()
为空,或者ks.getEntry("Keys", null)
无法转换为a KeyStore.PrivateKeyEntry
)或publicKey
为null
,导致在尝试调用{{1}时未处理NullPointerException
}(在toString()
)。