Send address book contacts between devices via NFC

This commit is contained in:
str4d
2014-07-03 12:23:35 +00:00
parent 7ad6543a5b
commit f700132a9e
3 changed files with 236 additions and 84 deletions

View File

@@ -5,6 +5,7 @@
android:versionName="0.1.1" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
<uses-sdk
android:minSdkVersion="9"
@@ -69,6 +70,16 @@
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="i2p.bote.android.addressbook.AddressBookActivity" />
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/i2p.bote:contact"/>
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
</activity>
<activity
android:name=".NetworkInfoActivity"

View File

@@ -1,11 +1,22 @@
package i2p.bote.android.addressbook;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcEvent;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v7.app.ActionBarActivity;
import i2p.bote.android.InitActivities;
public class EditContactActivity extends ActionBarActivity {
NfcAdapter mNfcAdapter;
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -24,7 +35,82 @@ public class EditContactActivity extends ActionBarActivity {
destination = args.getString(EditContactFragment.CONTACT_DESTINATION);
EditContactFragment f = EditContactFragment.newInstance(destination);
getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, f).commit();
.add(android.R.id.content, f).commit();
}
// NFC send only works on API 10+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD_MR1) {
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null &&
Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
mNfcAdapter.setNdefPushMessageCallback(new NfcAdapter.CreateNdefMessageCallback() {
@Override
public NdefMessage createNdefMessage(NfcEvent nfcEvent) {
return getNdefMessage();
}
}, this);
}
}
@SuppressLint("NewApi")
@Override
public void onResume() {
super.onResume();
if (mNfcAdapter != null &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
mNfcAdapter.enableForegroundNdefPush(this, getNdefMessage());
}
// Check to see that the Activity started due to an Android Beam
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction()) ||
NfcAdapter.ACTION_TAG_DISCOVERED.equals(getIntent().getAction())) {
processIntent(getIntent());
}
}
private NdefMessage getNdefMessage() {
EditContactFragment f = (EditContactFragment) getSupportFragmentManager()
.findFragmentById(android.R.id.content);
return f.createNdefMessage();
}
@Override
public void onNewIntent(Intent intent) {
// onResume gets called after this to handle the intent
setIntent(intent);
}
/**
* Parses the NDEF Message from the intent
*/
void processIntent(Intent intent) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs == null || rawMsgs.length < 1)
return; // TODO notify user?
NdefMessage msg = (NdefMessage) rawMsgs[0];
NdefRecord[] records = msg.getRecords();
if (records.length != 2)
return; // TODO notify user?
String name = new String(records[0].getPayload());
String destination = new String(records[1].getPayload());
EditContactFragment f = EditContactFragment.newInstance(
name, destination);
getSupportFragmentManager().beginTransaction()
.replace(android.R.id.content, f).commit();
}
@SuppressLint("NewApi")
@Override
public void onPause() {
super.onPause();
if (mNfcAdapter != null &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
mNfcAdapter.disableForegroundNdefPush(this);
}
}
}

View File

@@ -1,5 +1,27 @@
package i2p.bote.android.addressbook;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -13,35 +35,18 @@ import i2p.bote.android.util.BoteHelper;
import i2p.bote.android.util.EditPictureFragment;
import i2p.bote.fileencryption.PasswordException;
import i2p.bote.packet.dht.Contact;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class EditContactFragment extends EditPictureFragment {
public static final String CONTACT_DESTINATION = "contact_destination";
public static final String NEW_NAME = "new_name";
public static final String NEW_DESTINATION = "new_destination";
static final int REQUEST_DESTINATION_FILE = 3;
private String mDestination;
EditText mNameField;
EditText mDestinationField;
EditText mTextField;
TextView mError;
private String mDestination;
public static EditContactFragment newInstance(String destination) {
EditContactFragment f = new EditContactFragment();
@@ -51,6 +56,15 @@ public class EditContactFragment extends EditPictureFragment {
return f;
}
public static EditContactFragment newInstance(String name, String destination) {
EditContactFragment f = new EditContactFragment();
Bundle args = new Bundle();
args.putString(NEW_NAME, name);
args.putString(NEW_DESTINATION, destination);
f.setArguments(args);
return f;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -59,7 +73,7 @@ public class EditContactFragment extends EditPictureFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_edit_contact, container, false);
}
@@ -68,6 +82,7 @@ public class EditContactFragment extends EditPictureFragment {
super.onViewCreated(view, savedInstanceState);
mDestination = getArguments().getString(CONTACT_DESTINATION);
String newName = getArguments().getString(NEW_NAME);
mNameField = (EditText) view.findViewById(R.id.contact_name);
mDestinationField = (EditText) view.findViewById(R.id.destination);
@@ -90,6 +105,9 @@ public class EditContactFragment extends EditPictureFragment {
// TODO Handle
e.printStackTrace();
}
} else if (newName != null) {
mNameField.setText(newName);
mDestinationField.setText(getArguments().getString(NEW_DESTINATION));
}
Button b = (Button) view.findViewById(R.id.import_destination_from_file);
@@ -100,7 +118,7 @@ public class EditContactFragment extends EditPictureFragment {
i.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(
Intent.createChooser(i,"Select file containing Email Destination"),
Intent.createChooser(i, "Select file containing Email Destination"),
REQUEST_DESTINATION_FILE);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(getActivity(), "Please install a File Manager.",
@@ -110,6 +128,42 @@ public class EditContactFragment extends EditPictureFragment {
});
}
public NdefMessage createNdefMessage() {
NdefMessage msg = new NdefMessage(new NdefRecord[]{
createNameRecord(),
createDestinationRecord()
});
return msg;
}
private NdefRecord createNameRecord() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
return new NdefRecord(
NdefRecord.TNF_EXTERNAL_TYPE,
"i2p.bote:contact".getBytes(),
new byte[0],
mNameField.getText().toString().getBytes()
);
else
return NdefRecord.createExternal(
"i2p.bote", "contact", mNameField.getText().toString().getBytes()
);
}
private NdefRecord createDestinationRecord() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
return new NdefRecord(
NdefRecord.TNF_EXTERNAL_TYPE,
"i2p.bote:contactDestination".getBytes(),
new byte[0],
mDestinationField.getText().toString().getBytes()
);
else
return NdefRecord.createExternal(
"i2p.bote", "contactDestination", mDestinationField.getText().toString().getBytes()
);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.edit_contact, menu);
@@ -118,70 +172,70 @@ public class EditContactFragment extends EditPictureFragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_save_contact:
String picture = getPictureB64();
String name = mNameField.getText().toString();
String destination = mDestinationField.getText().toString();
String text = mTextField.getText().toString();
case R.id.action_save_contact:
String picture = getPictureB64();
String name = mNameField.getText().toString();
String destination = mDestinationField.getText().toString();
String text = mTextField.getText().toString();
mError.setText("");
mError.setText("");
try {
String err = BoteHelper.saveContact(destination, name, picture, text);
if (err == null) {
if (mDestination == null) // Only set if adding new contact
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
} else
mError.setText(err);
} catch (PasswordException e) {
// TODO Auto-generated catch block
e.printStackTrace();
mError.setText(e.getLocalizedMessage());
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
mError.setText(e.getLocalizedMessage());
}
return true;
case R.id.action_delete_contact:
DialogFragment df = new DialogFragment() {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.delete_contact)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
try {
String err = BoteHelper.deleteContact(mDestination);
if (err == null) {
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
} else
mError.setText(err);
} catch (PasswordException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
return builder.create();
try {
String err = BoteHelper.saveContact(destination, name, picture, text);
if (err == null) {
if (mDestination == null) // Only set if adding new contact
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
} else
mError.setText(err);
} catch (PasswordException e) {
// TODO Auto-generated catch block
e.printStackTrace();
mError.setText(e.getLocalizedMessage());
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
mError.setText(e.getLocalizedMessage());
}
};
df.show(getActivity().getSupportFragmentManager(), "deletecontact");
return true;
return true;
default:
return super.onOptionsItemSelected(item);
case R.id.action_delete_contact:
DialogFragment df = new DialogFragment() {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.delete_contact)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
try {
String err = BoteHelper.deleteContact(mDestination);
if (err == null) {
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
} else
mError.setText(err);
} catch (PasswordException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
return builder.create();
}
};
df.show(getActivity().getSupportFragmentManager(), "deletecontact");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@@ -196,7 +250,8 @@ public class EditContactFragment extends EditPictureFragment {
try {
br = new BufferedReader(
new InputStreamReader(
new FileInputStream(file)));
new FileInputStream(file))
);
try {
mDestinationField.setText(br.readLine());
} catch (IOException ioe) {