package interdroid.swan.crossdevice;
import interdroid.sense.LoginActivity;
import interdroid.sense.RegistrationActivity;
import interdroid.sense.SettingsActivity;
import interdroid.swan.R;
import interdroid.swan.swansong.Expression;
import java.io.IOException;
import java.util.List;
import nl.sense_os.service.constants.SensePrefs;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.content.res.TypedArray;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
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.AbsListView.MultiChoiceModeListener;
import android.widget.BaseAdapter;
import android.widget.CheckedTextView;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.gcm.GoogleCloudMessaging;
/**
* Activity that shows which remote devices are known and enables to pair with
* other devices.
*
* @author rkemp
*
*/
public class SwanLakeActivity extends ListActivity {
private static final String TAG = "SwanLakeActivity";
private static final int DIALOG_SET_NAME = 1;
private NfcAdapter mNfcAdapter;
private RegisteredSWANsAdapter mAdapter;
private EditText mNameEditText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.swanlake_cab, menu);
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
SparseBooleanArray array = getListView()
.getCheckedItemPositions();
List<String> names = Registry
.getNames(SwanLakeActivity.this);
for (int i = 0; i < names.size(); i++) {
if (array.get(i)) {
Registry.remove(SwanLakeActivity.this, names.get(i));
}
}
mAdapter.notifyDataSetChanged();
}
mode.finish();
return true;
}
@Override
public void onItemCheckedStateChanged(ActionMode mode,
int position, long id, boolean checked) {
mode.setTitle(getListView().getCheckedItemCount() + " selected");
}
});
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
mAdapter = new RegisteredSWANsAdapter();
onNewIntent(getIntent());
setListAdapter(mAdapter);
}
@Override
protected Dialog onCreateDialog(int id) {
mNameEditText = new EditText(this);
mNameEditText.setPadding(10, 10, 10, 10);
mNameEditText.setText(PreferenceManager.getDefaultSharedPreferences(
SwanLakeActivity.this).getString("name",
"SWAN-" + System.currentTimeMillis()));
return new AlertDialog.Builder(this)
.setTitle("Choose a name for your device")
.setView(mNameEditText)
.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (mNameEditText.getText().toString().contains(":")) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(
SwanLakeActivity.this,
"Character ':' is not allowed in the name, pick another name.",
Toast.LENGTH_LONG).show();
}
});
return;
}
PreferenceManager
.getDefaultSharedPreferences(
SwanLakeActivity.this)
.edit()
.putString("name",
mNameEditText.getText().toString())
.commit();
updateNFC();
}
}).create();
}
@SuppressWarnings("deprecation")
@Override
protected void onPause() {
// mNfcAdapter.disableForegroundDispatch(this);
mNfcAdapter.disableForegroundNdefPush(this);
super.onPause();
}
@Override
protected void onNewIntent(Intent intent) {
// NDEF exchange mode
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
// just get the data from the intent
String authority = intent.getData().getAuthority();
final String name = authority.split(":")[0];
String regId = authority.split(":", 2)[1];
if (!Registry.add(this, name, regId)) {
// pop up duplicate dialog
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(SwanLakeActivity.this,
"Duplicate '" + name + "', to be implemented",
Toast.LENGTH_LONG).show();
}
});
} else {
mAdapter.notifyDataSetChanged();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.swanlake, menu);
((Switch) (menu.findItem(R.id.action_enable).getActionView()))
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked
&& Registry.get(SwanLakeActivity.this,
Expression.LOCATION_SELF) == null) {
// first time, we should register with gcm in the
// background now.
registerBackground((Switch) buttonView);
} else {
PreferenceManager
.getDefaultSharedPreferences(
SwanLakeActivity.this).edit()
.putBoolean("enabled", isChecked).commit();
}
}
});
return true;
}
@SuppressWarnings("deprecation")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_share:
updateNFC();
break;
case R.id.action_set_name:
showDialog(DIALOG_SET_NAME);
break;
case R.id.login:
startActivity(new Intent(this, LoginActivity.class));
break;
case R.id.logout:
// clear cached settings of the previous user (e.g. device id)
Editor authEditor = getSharedPreferences(SensePrefs.AUTH_PREFS, MODE_PRIVATE).edit();
authEditor.clear();
authEditor.commit();
// update UI
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(SwanLakeActivity.this, R.string.logout_success, Toast.LENGTH_LONG)
.show();
}
});
break;
case R.id.signup:
startActivity(new Intent(this, RegistrationActivity.class));
break;
case R.id.settings:
startActivity(new Intent(this, SettingsActivity.class));
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("deprecation")
private void updateNFC() {
String regId = Registry.get(this, Expression.LOCATION_SELF);
if (regId == null) {
Log.d(TAG,
"Not registered with Google Cloud Messaging, cannot share");
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(
SwanLakeActivity.this,
"Not registered with Google Cloud Messaging, cannot share",
Toast.LENGTH_LONG).show();
}
});
return;
}
if (mNfcAdapter != null) {
String userFriendlyName = PreferenceManager
.getDefaultSharedPreferences(SwanLakeActivity.this)
.getString("name", null);
if (userFriendlyName == null) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(SwanLakeActivity.this,
"Please set a name for your device",
Toast.LENGTH_SHORT).show();
showDialog(DIALOG_SET_NAME);
}
});
return;
}
NdefRecord data = NdefRecord.createUri("swan://" + userFriendlyName
+ ":" + regId);
NdefMessage message = new NdefMessage(new NdefRecord[] { data });
mNfcAdapter.enableForegroundNdefPush(this, message);
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(SwanLakeActivity.this,
"Ready for NFC sharing", Toast.LENGTH_LONG).show();
}
});
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
((Switch) (menu.findItem(R.id.action_enable).getActionView()))
.setChecked(PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("enabled", false));
return super.onPrepareOptionsMenu(menu);
}
private void registerBackground(final Switch switchWidget) {
switchWidget.setEnabled(false);
new Thread() {
public void run() {
try {
if (SwanGCMConstants.API_KEY.equals(SwanGCMConstants.EMPTY)
|| SwanGCMConstants.SENDER_ID
.equals(SwanGCMConstants.EMPTY)) {
throw new RuntimeException(
"Please provide valid values in SwanGCMConstants");
}
Registry.add(SwanLakeActivity.this,
Expression.LOCATION_SELF, GoogleCloudMessaging
.getInstance(SwanLakeActivity.this)
.register(SwanGCMConstants.SENDER_ID));
PreferenceManager
.getDefaultSharedPreferences(SwanLakeActivity.this)
.edit().putBoolean("enabled", true).commit();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(
SwanLakeActivity.this,
"Got a registration ID: "
+ Registry.get(
SwanLakeActivity.this,
Expression.LOCATION_SELF),
Toast.LENGTH_LONG).show();
}
});
} catch (IOException e) {
Log.d(TAG,
"Failed to register with Google Cloud Messaging", e);
runOnUiThread(new Runnable() {
@Override
public void run() {
switchWidget.setChecked(false);
Toast.makeText(
SwanLakeActivity.this,
"Failed to register with Google Cloud Messaging",
Toast.LENGTH_LONG).show();
}
});
}
runOnUiThread(new Runnable() {
@Override
public void run() {
switchWidget.setEnabled(true);
}
});
}
}.start();
}
class RegisteredSWANsAdapter extends BaseAdapter {
@Override
public int getCount() {
return Registry.getNames(SwanLakeActivity.this).size();
}
@Override
public Object getItem(int position) {
return Registry.getNames(SwanLakeActivity.this).get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@SuppressWarnings("deprecation")
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater
.from(SwanLakeActivity.this)
.inflate(
android.R.layout.simple_list_item_multiple_choice,
null);
}
TypedArray ta = SwanLakeActivity.this
.obtainStyledAttributes(new int[] { android.R.attr.activatedBackgroundIndicator });
convertView.setBackgroundDrawable(ta.getDrawable(0));
ta.recycle();
((CheckedTextView) (convertView.findViewById(android.R.id.text1)))
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getListView().setItemChecked(position,
!((CheckedTextView) v).isChecked());
}
});
((TextView) (convertView.findViewById(android.R.id.text1)))
.setText(getItem(position).toString());
((TextView) (convertView.findViewById(android.R.id.text1)))
.setPadding(20, 20, 20, 20);
return convertView;
}
}
}