Я новичок в NFC с Android и пытаюсь создать приложение для обмена сообщениями с NFC.
У меня есть первое действие, которое отправляет содержимое представления EditText на другой телефон при передаче и отображает входящее сообщение в TextView на другом телефоне. Это прекрасно работает.
У меня есть другое действие, которое используется для добавления контакта в реестр контактов, оно должно работать следующим образом:
- A хочет добавить B в качестве контакта,
- А переходит к AddContactActivity, вводит имя контакта в представлении EditText,
- затем B касается телефона A (в том же действии) и отправляет свой идентификатор (открытый ключ для дальнейшего шифрования).
Моя проблема заключается в том, что хотя код, касающийся отправки через 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>