Var/val should be lower camel case.
This commit is contained in:
parent
4ca13ed3d9
commit
32fd7638e0
|
@ -32,7 +32,7 @@ class AddressTest extends AndroidTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(a1, new Address(a1Binary))
|
assertEquals(a1, new Address(a1Binary))
|
||||||
assertEquals(a1Binary.deep, a1.Bytes.deep)
|
assertEquals(a1Binary.deep, a1.bytes.deep)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ class MessageHeaderTest extends AndroidTestCase {
|
||||||
val bytes = h.write(0)
|
val bytes = h.write(0)
|
||||||
val header = MessageHeader.read(bytes)
|
val header = MessageHeader.read(bytes)
|
||||||
assertEquals(h, header)
|
assertEquals(h, header)
|
||||||
assertEquals(bytes.length, header.Length)
|
assertEquals(bytes.length, header.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ class ResultAddContactTest extends AndroidTestCase {
|
||||||
val rac = new ResultAddContact(a)
|
val rac = new ResultAddContact(a)
|
||||||
val bytes = rac.write
|
val bytes = rac.write
|
||||||
val read = ResultAddContact.read(bytes)
|
val read = ResultAddContact.read(bytes)
|
||||||
assertEquals(a, read.Accepted)
|
assertEquals(a, read.accepted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,20 +40,20 @@ class DatabaseTest extends AndroidTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
def testMessageCount(): Unit = {
|
def testMessageCount(): Unit = {
|
||||||
val msg1 = database.getMessages(m1.Header.Origin, 1)
|
val msg1 = database.getMessages(m1.Header.origin, 1)
|
||||||
assertEquals(1, msg1.size)
|
assertEquals(1, msg1.size)
|
||||||
|
|
||||||
val msg2 = database.getMessages(m1.Header.Origin, 3)
|
val msg2 = database.getMessages(m1.Header.origin, 3)
|
||||||
assertEquals(2, msg2.size)
|
assertEquals(2, msg2.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
def testMessageOrder(): Unit = {
|
def testMessageOrder(): Unit = {
|
||||||
val msg = database.getMessages(m1.Header.Target, 1)
|
val msg = database.getMessages(m1.Header.target, 1)
|
||||||
assertTrue(msg.contains(m3))
|
assertTrue(msg.contains(m3))
|
||||||
}
|
}
|
||||||
|
|
||||||
def testMessageSelect(): Unit = {
|
def testMessageSelect(): Unit = {
|
||||||
val msg = database.getMessages(m1.Header.Target, 2)
|
val msg = database.getMessages(m1.Header.target, 2)
|
||||||
assertTrue(msg.contains(m1))
|
assertTrue(msg.contains(m1))
|
||||||
assertTrue(msg.contains(m3))
|
assertTrue(msg.contains(m3))
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ class DatabaseTest extends AndroidTestCase {
|
||||||
database.addContact(UserTest.u1)
|
database.addContact(UserTest.u1)
|
||||||
val contacts = database.getContacts
|
val contacts = database.getContacts
|
||||||
assertEquals(1, contacts.size)
|
assertEquals(1, contacts.size)
|
||||||
assertEquals(Some(UserTest.u1), database.getContact(UserTest.u1.Address))
|
assertEquals(Some(UserTest.u1), database.getContact(UserTest.u1.address))
|
||||||
}
|
}
|
||||||
|
|
||||||
def testAddContactCallback(): Unit = {
|
def testAddContactCallback(): Unit = {
|
||||||
|
@ -76,8 +76,8 @@ class DatabaseTest extends AndroidTestCase {
|
||||||
|
|
||||||
def testGetContact(): Unit = {
|
def testGetContact(): Unit = {
|
||||||
database.addContact(UserTest.u2)
|
database.addContact(UserTest.u2)
|
||||||
assertTrue(database.getContact(UserTest.u1.Address).isEmpty)
|
assertTrue(database.getContact(UserTest.u1.address).isEmpty)
|
||||||
val c = database.getContact(UserTest.u2.Address)
|
val c = database.getContact(UserTest.u2.address)
|
||||||
assertTrue(c.nonEmpty)
|
assertTrue(c.nonEmpty)
|
||||||
assertEquals(Some(UserTest.u2), c)
|
assertEquals(Some(UserTest.u2), c)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,9 @@ class AddContactsActivity extends EnsiChatActivity with ChatService.OnConnection
|
||||||
*/
|
*/
|
||||||
override def onItemClick(parent: AdapterView[_], view: View, position: Int, id: Long): Unit = {
|
override def onItemClick(parent: AdapterView[_], view: View, position: Int, id: Long): Unit = {
|
||||||
val contact = adapter.getItem(position)
|
val contact = adapter.getItem(position)
|
||||||
service.sendTo(contact.Address, new RequestAddContact())
|
service.sendTo(contact.address, new RequestAddContact())
|
||||||
val intent = new Intent(this, classOf[ConfirmAddContactDialog])
|
val intent = new Intent(this, classOf[ConfirmAddContactDialog])
|
||||||
intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, contact.Address.toString)
|
intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, contact.address.toString)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,11 +55,11 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
||||||
val remoteTitle = view.findViewById(R.id.remote_identicon_title).asInstanceOf[TextView]
|
val remoteTitle = view.findViewById(R.id.remote_identicon_title).asInstanceOf[TextView]
|
||||||
|
|
||||||
local.setImageBitmap(IdenticonGenerator.generate(Crypto.getLocalAddress(this), (150, 150), this))
|
local.setImageBitmap(IdenticonGenerator.generate(Crypto.getLocalAddress(this), (150, 150), this))
|
||||||
remote.setImageBitmap(IdenticonGenerator.generate(user.Address, (150, 150), this))
|
remote.setImageBitmap(IdenticonGenerator.generate(user.address, (150, 150), this))
|
||||||
remoteTitle.setText(getString(R.string.remote_fingerprint_title, user.Name))
|
remoteTitle.setText(getString(R.string.remote_fingerprint_title, user.name))
|
||||||
|
|
||||||
new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AppTheme))
|
new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AppTheme))
|
||||||
.setTitle(getString(R.string.add_contact_dialog, user.Name))
|
.setTitle(getString(R.string.add_contact_dialog, user.name))
|
||||||
.setView(view)
|
.setView(view)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(android.R.string.yes, this)
|
.setPositiveButton(android.R.string.yes, this)
|
||||||
|
@ -78,7 +78,7 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
||||||
finish()
|
finish()
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
service.sendTo(user.Address, new ResultAddContact(result))
|
service.sendTo(user.address, new ResultAddContact(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,8 +88,8 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
||||||
if (localConfirmed && remoteConfirmed) {
|
if (localConfirmed && remoteConfirmed) {
|
||||||
Log.i(Tag, "Adding new contact " + user.toString)
|
Log.i(Tag, "Adding new contact " + user.toString)
|
||||||
// Get the user again, in case it was updated in the mean time.
|
// Get the user again, in case it was updated in the mean time.
|
||||||
service.database.addContact(service.getUser(user.Address))
|
service.database.addContact(service.getUser(user.address))
|
||||||
Toast.makeText(this, getString(R.string.contact_added, user.Name), Toast.LENGTH_SHORT)
|
Toast.makeText(this, getString(R.string.contact_added, user.name), Toast.LENGTH_SHORT)
|
||||||
.show()
|
.show()
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
@ -102,12 +102,12 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
||||||
* the user is in this activity.
|
* the user is in this activity.
|
||||||
*/
|
*/
|
||||||
override def onMessageReceived(msg: Message): Unit = {
|
override def onMessageReceived(msg: Message): Unit = {
|
||||||
if (msg.Header.Origin != user.Address || msg.Header.Target != Crypto.getLocalAddress(this))
|
if (msg.Header.origin != user.address || msg.Header.target != Crypto.getLocalAddress(this))
|
||||||
return
|
return
|
||||||
|
|
||||||
msg.Body match {
|
msg.Body match {
|
||||||
case m: ResultAddContact =>
|
case m: ResultAddContact =>
|
||||||
if (m.Accepted) {
|
if (m.accepted) {
|
||||||
Log.i(Tag, user.toString + " accepted us as a contact, updating state")
|
Log.i(Tag, user.toString + " accepted us as a contact, updating state")
|
||||||
remoteConfirmed = true
|
remoteConfirmed = true
|
||||||
addContactIfBothConfirmed()
|
addContactIfBothConfirmed()
|
||||||
|
|
|
@ -38,7 +38,7 @@ class EnsiChatActivity extends Activity with ServiceConnection {
|
||||||
*/
|
*/
|
||||||
override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
|
override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
|
||||||
val binder = iBinder.asInstanceOf[ChatServiceBinder]
|
val binder = iBinder.asInstanceOf[ChatServiceBinder]
|
||||||
chatService = Option(binder.Service)
|
chatService = Option(binder.service)
|
||||||
listeners.foreach(_())
|
listeners.foreach(_())
|
||||||
listeners = Set.empty
|
listeners = Set.empty
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ class MainActivity extends EnsiChatActivity {
|
||||||
override def onSaveInstanceState(outState: Bundle): Unit = {
|
override def onSaveInstanceState(outState: Bundle): Unit = {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
getFragmentManager.putFragment(outState, classOf[ContactsFragment].getName, contactsFragment)
|
getFragmentManager.putFragment(outState, classOf[ContactsFragment].getName, contactsFragment)
|
||||||
currentChat.collect{case c => outState.putByteArray("current_chat", c.Bytes)}
|
currentChat.collect{case c => outState.putByteArray("current_chat", c.bytes)}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -26,7 +26,7 @@ object BluetoothInterface {
|
||||||
/**
|
/**
|
||||||
* Handles all Bluetooth connectivity.
|
* Handles all Bluetooth connectivity.
|
||||||
*/
|
*/
|
||||||
class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends InterfaceHandler {
|
class BluetoothInterface(service: ChatService, crypto: Crypto) extends InterfaceHandler {
|
||||||
|
|
||||||
private val Tag = "BluetoothInterface"
|
private val Tag = "BluetoothInterface"
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
||||||
private var connections = new HashMap[Device.ID, TransferThread]()
|
private var connections = new HashMap[Device.ID, TransferThread]()
|
||||||
|
|
||||||
private lazy val listenThread =
|
private lazy val listenThread =
|
||||||
new ListenThread(Service.getString(R.string.app_name), btAdapter, onConnectionOpened)
|
new ListenThread(service.getString(R.string.app_name), btAdapter, onConnectionOpened)
|
||||||
|
|
||||||
private var cancelDiscovery = false
|
private var cancelDiscovery = false
|
||||||
|
|
||||||
|
@ -49,11 +49,11 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
||||||
* Initializes and starts discovery and listening.
|
* Initializes and starts discovery and listening.
|
||||||
*/
|
*/
|
||||||
override def create(): Unit = {
|
override def create(): Unit = {
|
||||||
Service.registerReceiver(DeviceDiscoveredReceiver,
|
service.registerReceiver(DeviceDiscoveredReceiver,
|
||||||
new IntentFilter(BluetoothDevice.ACTION_FOUND))
|
new IntentFilter(BluetoothDevice.ACTION_FOUND))
|
||||||
Service.registerReceiver(BluetoothStateReceiver,
|
service.registerReceiver(BluetoothStateReceiver,
|
||||||
new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
|
new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED))
|
||||||
Service.registerReceiver(DiscoveryFinishedReceiver,
|
service.registerReceiver(DiscoveryFinishedReceiver,
|
||||||
new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
|
new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
|
||||||
startBluetoothConnections()
|
startBluetoothConnections()
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,9 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
||||||
override def destroy(): Unit = {
|
override def destroy(): Unit = {
|
||||||
listenThread.cancel()
|
listenThread.cancel()
|
||||||
cancelDiscovery = true
|
cancelDiscovery = true
|
||||||
Service.unregisterReceiver(DeviceDiscoveredReceiver)
|
service.unregisterReceiver(DeviceDiscoveredReceiver)
|
||||||
Service.unregisterReceiver(BluetoothStateReceiver)
|
service.unregisterReceiver(BluetoothStateReceiver)
|
||||||
Service.unregisterReceiver(DiscoveryFinishedReceiver)
|
service.unregisterReceiver(DiscoveryFinishedReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,9 +90,9 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
||||||
btAdapter.startDiscovery()
|
btAdapter.startDiscovery()
|
||||||
}
|
}
|
||||||
|
|
||||||
val scanInterval = PreferenceManager.getDefaultSharedPreferences(Service)
|
val scanInterval = PreferenceManager.getDefaultSharedPreferences(service)
|
||||||
.getString("scan_interval_seconds", "15").toInt * 1000
|
.getString("scan_interval_seconds", "15").toInt * 1000
|
||||||
Service.MainHandler.postDelayed(new Runnable {
|
service.MainHandler.postDelayed(new Runnable {
|
||||||
override def run(): Unit = discover()
|
override def run(): Unit = discover()
|
||||||
}, scanInterval)
|
}, scanInterval)
|
||||||
}
|
}
|
||||||
|
@ -111,10 +111,10 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
||||||
*/
|
*/
|
||||||
private val DiscoveryFinishedReceiver = new BroadcastReceiver() {
|
private val DiscoveryFinishedReceiver = new BroadcastReceiver() {
|
||||||
override def onReceive(context: Context, intent: Intent): Unit = {
|
override def onReceive(context: Context, intent: Intent): Unit = {
|
||||||
discovered.filterNot(d => connections.keySet.contains(d.Id))
|
discovered.filterNot(d => connections.keySet.contains(d.id))
|
||||||
.foreach { d =>
|
.foreach { d =>
|
||||||
new ConnectThread(d, onConnectionOpened).start()
|
new ConnectThread(d, onConnectionOpened).start()
|
||||||
devices += (d.Id -> d)
|
devices += (d.id -> d)
|
||||||
}
|
}
|
||||||
discovered = Set[Device]()
|
discovered = Set[Device]()
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
||||||
override def onReceive(context: Context, intent: Intent): Unit = {
|
override def onReceive(context: Context, intent: Intent): Unit = {
|
||||||
intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) match {
|
intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) match {
|
||||||
case BluetoothAdapter.STATE_ON =>
|
case BluetoothAdapter.STATE_ON =>
|
||||||
if (Crypto.localKeysExist)
|
if (crypto.localKeysExist)
|
||||||
startBluetoothConnections()
|
startBluetoothConnections()
|
||||||
case BluetoothAdapter.STATE_TURNING_OFF =>
|
case BluetoothAdapter.STATE_TURNING_OFF =>
|
||||||
Log.i(Tag, "Bluetooth disabled, stopping connectivity")
|
Log.i(Tag, "Bluetooth disabled, stopping connectivity")
|
||||||
|
@ -144,20 +144,20 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
||||||
* Initiates data transfer with device.
|
* Initiates data transfer with device.
|
||||||
*/
|
*/
|
||||||
def onConnectionOpened(device: Device, socket: BluetoothSocket): Unit = {
|
def onConnectionOpened(device: Device, socket: BluetoothSocket): Unit = {
|
||||||
devices += (device.Id -> device)
|
devices += (device.id -> device)
|
||||||
connections += (device.Id ->
|
connections += (device.id ->
|
||||||
new TransferThread(device, socket, this, Crypto, onReceiveMessage))
|
new TransferThread(device, socket, this, crypto, onReceiveMessage))
|
||||||
connections(device.Id).start()
|
connections(device.id).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes device from active connections.
|
* Removes device from active connections.
|
||||||
*/
|
*/
|
||||||
def onConnectionClosed(device: Device, socket: BluetoothSocket): Unit = {
|
def onConnectionClosed(device: Device, socket: BluetoothSocket): Unit = {
|
||||||
devices -= device.Id
|
devices -= device.id
|
||||||
connections -= device.Id
|
connections -= device.id
|
||||||
Service.callConnectionListeners()
|
service.callConnectionListeners()
|
||||||
addressDeviceMap.inverse().remove(device.Id)
|
addressDeviceMap.inverse().remove(device.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -170,13 +170,13 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
||||||
*/
|
*/
|
||||||
private def onReceiveMessage(msg: Message, device: Device.ID): Unit = msg.Body match {
|
private def onReceiveMessage(msg: Message, device: Device.ID): Unit = msg.Body match {
|
||||||
case info: ConnectionInfo =>
|
case info: ConnectionInfo =>
|
||||||
val address = Crypto.calculateAddress(info.key)
|
val address = crypto.calculateAddress(info.key)
|
||||||
// Service.onConnectionOpened sends message, so mapping already needs to be in place.
|
// Service.onConnectionOpened sends message, so mapping already needs to be in place.
|
||||||
addressDeviceMap.put(address, device)
|
addressDeviceMap.put(address, device)
|
||||||
if (!Service.onConnectionOpened(msg))
|
if (!service.onConnectionOpened(msg))
|
||||||
addressDeviceMap.remove(address)
|
addressDeviceMap.remove(address)
|
||||||
case _ =>
|
case _ =>
|
||||||
Service.onMessageReceived(msg)
|
service.onMessageReceived(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,7 +32,7 @@ class ConnectThread(device: Device, onConnected: (Device, BluetoothSocket) => Un
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i(Tag, "Successfully connected to device " + device.Name)
|
Log.i(Tag, "Successfully connected to device " + device.name)
|
||||||
onConnected(new Device(device.bluetoothDevice, true), socket)
|
onConnected(new Device(device.bluetoothDevice, true), socket)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,13 @@ private[bluetooth] object Device {
|
||||||
/**
|
/**
|
||||||
* Holds bluetooth device IDs, which are just wrapped addresses (used for type safety).
|
* Holds bluetooth device IDs, which are just wrapped addresses (used for type safety).
|
||||||
*
|
*
|
||||||
* @param Id A bluetooth device address.
|
* @param id A bluetooth device address.
|
||||||
*/
|
*/
|
||||||
case class ID(private val Id: String) {
|
case class ID(private val id: String) {
|
||||||
|
|
||||||
require(Id.matches("([A-Z0-9][A-Z0-9]:){5}[A-Z0-9][A-Z0-9]"), "Invalid device ID format")
|
require(id.matches("([A-Z0-9][A-Z0-9]:){5}[A-Z0-9][A-Z0-9]"), "Invalid device ID format")
|
||||||
|
|
||||||
override def toString = Id
|
override def toString = id
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ private[bluetooth] object Device {
|
||||||
/**
|
/**
|
||||||
* Holds information about a remote bluetooth device.
|
* Holds information about a remote bluetooth device.
|
||||||
*/
|
*/
|
||||||
private[bluetooth] case class Device(Id: Device.ID, Name: String, Connected: Boolean,
|
private[bluetooth] case class Device(id: Device.ID, name: String, connected: Boolean,
|
||||||
btDevice: Option[BluetoothDevice] = None) {
|
btDevice: Option[BluetoothDevice] = None) {
|
||||||
|
|
||||||
def this(btDevice: BluetoothDevice, connected: Boolean) = {
|
def this(btDevice: BluetoothDevice, connected: Boolean) = {
|
||||||
|
|
|
@ -52,7 +52,7 @@ class TransferThread(device: Device, socket: BluetoothSocket, Handler: Bluetooth
|
||||||
if (inStream.available() > 0) {
|
if (inStream.available() > 0) {
|
||||||
val msg = Message.read(inStream)
|
val msg = Message.read(inStream)
|
||||||
|
|
||||||
onReceive(msg, device.Id)
|
onReceive(msg, device.id)
|
||||||
Log.v(Tag, "Receiving " + msg)
|
Log.v(Tag, "Receiving " + msg)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
|
|
@ -48,7 +48,7 @@ class ChatFragment extends ListFragment with OnClickListener
|
||||||
chatService = activity.service
|
chatService = activity.service
|
||||||
|
|
||||||
chatService.database.getContact(address)
|
chatService.database.getContact(address)
|
||||||
.foreach(c => getActivity.setTitle(c.Name))
|
.foreach(c => getActivity.setTitle(c.name))
|
||||||
|
|
||||||
// Read local device ID from service,
|
// Read local device ID from service,
|
||||||
adapter = new MessagesAdapter(getActivity, address)
|
adapter = new MessagesAdapter(getActivity, address)
|
||||||
|
@ -90,7 +90,7 @@ class ChatFragment extends ListFragment with OnClickListener
|
||||||
|
|
||||||
override def onSaveInstanceState(outState: Bundle): Unit = {
|
override def onSaveInstanceState(outState: Bundle): Unit = {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
outState.putByteArray("device", address.Bytes)
|
outState.putByteArray("device", address.bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -110,7 +110,7 @@ class ChatFragment extends ListFragment with OnClickListener
|
||||||
* Displays new messages in UI.
|
* Displays new messages in UI.
|
||||||
*/
|
*/
|
||||||
override def onMessageReceived(msg: Message): Unit = {
|
override def onMessageReceived(msg: Message): Unit = {
|
||||||
if (Set(msg.Header.Origin, msg.Header.Target).contains(address))
|
if (Set(msg.Header.origin, msg.Header.target).contains(address))
|
||||||
adapter.add(msg)
|
adapter.add(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ class ContactsFragment extends ListFragment with OnContactsUpdatedListener {
|
||||||
* Opens a chat with the clicked device.
|
* Opens a chat with the clicked device.
|
||||||
*/
|
*/
|
||||||
override def onListItemClick(l: ListView, v: View, position: Int, id: Long): Unit =
|
override def onListItemClick(l: ListView, v: View, position: Int, id: Long): Unit =
|
||||||
getActivity.asInstanceOf[MainActivity].openChat(adapter.getItem(position).Address)
|
getActivity.asInstanceOf[MainActivity].openChat(adapter.getItem(position).address)
|
||||||
|
|
||||||
override def onContactsUpdated(): Unit = {
|
override def onContactsUpdated(): Unit = {
|
||||||
getActivity.runOnUiThread(new Runnable {
|
getActivity.runOnUiThread(new Runnable {
|
||||||
|
|
|
@ -48,7 +48,7 @@ class SettingsFragment extends PreferenceFragment with OnPreferenceChangeListene
|
||||||
if (preference.getKey == KeyUserName) {
|
if (preference.getKey == KeyUserName) {
|
||||||
val service = getActivity.asInstanceOf[EnsiChatActivity].service
|
val service = getActivity.asInstanceOf[EnsiChatActivity].service
|
||||||
service.database.getContacts
|
service.database.getContacts
|
||||||
.foreach(c => service.sendTo(c.Address, new UserName(newValue.toString)))
|
.foreach(c => service.sendTo(c.address, new UserName(newValue.toString)))
|
||||||
}
|
}
|
||||||
preference.setSummary(newValue.toString)
|
preference.setSummary(newValue.toString)
|
||||||
true
|
true
|
||||||
|
|
|
@ -21,23 +21,23 @@ object Address {
|
||||||
/**
|
/**
|
||||||
* Holds a device address and provides conversion methods.
|
* Holds a device address and provides conversion methods.
|
||||||
*
|
*
|
||||||
* @param Bytes SHA-256 hash of the node's public key.
|
* @param bytes SHA-256 hash of the node's public key.
|
||||||
*/
|
*/
|
||||||
case class Address(Bytes: Array[Byte]) {
|
case class Address(bytes: Array[Byte]) {
|
||||||
|
|
||||||
require(Bytes.length == Address.Length, "Invalid address length (was " + Bytes.length + ")")
|
require(bytes.length == Address.Length, "Invalid address length (was " + bytes.length + ")")
|
||||||
|
|
||||||
def this(base16: String) {
|
def this(base16: String) {
|
||||||
this(BaseEncoding.base16().decode(base16))
|
this(BaseEncoding.base16().decode(base16))
|
||||||
}
|
}
|
||||||
|
|
||||||
override def hashCode = util.Arrays.hashCode(Bytes)
|
override def hashCode = util.Arrays.hashCode(bytes)
|
||||||
|
|
||||||
override def equals(a: Any) = a match {
|
override def equals(a: Any) = a match {
|
||||||
case o: Address => Bytes.deep == o.Bytes.deep
|
case o: Address => bytes.deep == o.bytes.deep
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
override def toString = BaseEncoding.base16().encode(Bytes)
|
override def toString = BaseEncoding.base16().encode(bytes)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import com.nutomic.ensichat.util.Database
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.concurrent.ExecutionContext.Implicits.global
|
import scala.concurrent.ExecutionContext.Implicits.global
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
import scala.ref.WeakReference
|
|
||||||
|
|
||||||
object ChatService {
|
object ChatService {
|
||||||
|
|
||||||
|
@ -151,10 +150,10 @@ class ChatService extends Service {
|
||||||
* Decrypts and verifies incoming messages, forwards valid ones to [[onNewMessage()]].
|
* Decrypts and verifies incoming messages, forwards valid ones to [[onNewMessage()]].
|
||||||
*/
|
*/
|
||||||
def onMessageReceived(msg: Message): Unit = {
|
def onMessageReceived(msg: Message): Unit = {
|
||||||
if (msg.Header.Target == Crypto.getLocalAddress(this)) {
|
if (msg.Header.target == Crypto.getLocalAddress(this)) {
|
||||||
val decrypted = crypto.decrypt(msg)
|
val decrypted = crypto.decrypt(msg)
|
||||||
if (!crypto.verify(decrypted)) {
|
if (!crypto.verify(decrypted)) {
|
||||||
Log.i(Tag, "Ignoring message with invalid signature from " + msg.Header.Origin)
|
Log.i(Tag, "Ignoring message with invalid signature from " + msg.Header.origin)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
onNewMessage(decrypted)
|
onNewMessage(decrypted)
|
||||||
|
@ -168,25 +167,25 @@ class ChatService extends Service {
|
||||||
*/
|
*/
|
||||||
private def onNewMessage(msg: Message): Unit = msg.Body match {
|
private def onNewMessage(msg: Message): Unit = msg.Body match {
|
||||||
case name: UserName =>
|
case name: UserName =>
|
||||||
val contact = new User(msg.Header.Origin, name.Name)
|
val contact = new User(msg.Header.origin, name.name)
|
||||||
knownUsers += contact
|
knownUsers += contact
|
||||||
if (database.getContact(msg.Header.Origin).nonEmpty)
|
if (database.getContact(msg.Header.origin).nonEmpty)
|
||||||
database.changeContactName(contact)
|
database.changeContactName(contact)
|
||||||
|
|
||||||
callConnectionListeners()
|
callConnectionListeners()
|
||||||
case _: RequestAddContact =>
|
case _: RequestAddContact =>
|
||||||
if (msg.Header.Origin == Crypto.getLocalAddress(this))
|
if (msg.Header.origin == Crypto.getLocalAddress(this))
|
||||||
return
|
return
|
||||||
|
|
||||||
Log.i(Tag, "Remote device " + msg.Header.Origin +
|
Log.i(Tag, "Remote device " + msg.Header.origin +
|
||||||
" wants to add us as a contact, showing notification")
|
" wants to add us as a contact, showing notification")
|
||||||
val intent = new Intent(this, classOf[ConfirmAddContactDialog])
|
val intent = new Intent(this, classOf[ConfirmAddContactDialog])
|
||||||
intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, msg.Header.Origin.toString)
|
intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, msg.Header.origin.toString)
|
||||||
val pi = PendingIntent.getActivity(this, 0, intent,
|
val pi = PendingIntent.getActivity(this, 0, intent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT)
|
PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
|
||||||
val notification = new Notification.Builder(this)
|
val notification = new Notification.Builder(this)
|
||||||
.setContentTitle(getString(R.string.notification_friend_request, getUser(msg.Header.Origin)))
|
.setContentTitle(getString(R.string.notification_friend_request, getUser(msg.Header.origin)))
|
||||||
.setSmallIcon(R.drawable.ic_launcher)
|
.setSmallIcon(R.drawable.ic_launcher)
|
||||||
.setContentIntent(pi)
|
.setContentIntent(pi)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
|
@ -259,6 +258,6 @@ class ChatService extends Service {
|
||||||
btInterface.getConnections
|
btInterface.getConnections
|
||||||
|
|
||||||
def getUser(address: Address) =
|
def getUser(address: Address) =
|
||||||
knownUsers.find(_.Address == address).getOrElse(new User(address, address.toString))
|
knownUsers.find(_.address == address).getOrElse(new User(address, address.toString))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,4 +2,4 @@ package com.nutomic.ensichat.protocol
|
||||||
|
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
|
|
||||||
case class ChatServiceBinder (Service: ChatService) extends Binder
|
case class ChatServiceBinder (service: ChatService) extends Binder
|
||||||
|
|
|
@ -141,11 +141,11 @@ class Crypto(Context: Context) {
|
||||||
def verify(msg: Message, key: PublicKey = null): Boolean = {
|
def verify(msg: Message, key: PublicKey = null): Boolean = {
|
||||||
val publicKey =
|
val publicKey =
|
||||||
if (key != null) key
|
if (key != null) key
|
||||||
else loadKey(msg.Header.Origin.toString, classOf[PublicKey])
|
else loadKey(msg.Header.origin.toString, classOf[PublicKey])
|
||||||
val sig = Signature.getInstance(SignAlgorithm)
|
val sig = Signature.getInstance(SignAlgorithm)
|
||||||
sig.initVerify(publicKey)
|
sig.initVerify(publicKey)
|
||||||
sig.update(msg.Body.write)
|
sig.update(msg.Body.write)
|
||||||
sig.verify(msg.Crypto.Signature.get)
|
sig.verify(msg.Crypto.signature.get)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -229,7 +229,7 @@ class Crypto(Context: Context) {
|
||||||
private def keyFolder = new File(Context.getFilesDir, "keys")
|
private def keyFolder = new File(Context.getFilesDir, "keys")
|
||||||
|
|
||||||
def encrypt(msg: Message, key: PublicKey = null): Message = {
|
def encrypt(msg: Message, key: PublicKey = null): Message = {
|
||||||
assert(msg.Crypto.Signature.isDefined, "Message must be signed before encryption")
|
assert(msg.Crypto.signature.isDefined, "Message must be signed before encryption")
|
||||||
|
|
||||||
// Symmetric encryption of data
|
// Symmetric encryption of data
|
||||||
val secretKey = makeSecretKey()
|
val secretKey = makeSecretKey()
|
||||||
|
@ -240,25 +240,25 @@ class Crypto(Context: Context) {
|
||||||
// Asymmetric encryption of secret key
|
// Asymmetric encryption of secret key
|
||||||
val publicKey =
|
val publicKey =
|
||||||
if (key != null) key
|
if (key != null) key
|
||||||
else loadKey(msg.Header.Target.toString, classOf[PublicKey])
|
else loadKey(msg.Header.target.toString, classOf[PublicKey])
|
||||||
val asymmetricCipher = Cipher.getInstance(KeyAlgorithm)
|
val asymmetricCipher = Cipher.getInstance(KeyAlgorithm)
|
||||||
asymmetricCipher.init(Cipher.WRAP_MODE, publicKey)
|
asymmetricCipher.init(Cipher.WRAP_MODE, publicKey)
|
||||||
|
|
||||||
new Message(msg.Header,
|
new Message(msg.Header,
|
||||||
new CryptoData(msg.Crypto.Signature, Option(asymmetricCipher.wrap(secretKey))), encrypted)
|
new CryptoData(msg.Crypto.signature, Option(asymmetricCipher.wrap(secretKey))), encrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
def decrypt(msg: Message): Message = {
|
def decrypt(msg: Message): Message = {
|
||||||
// Asymmetric decryption of secret key
|
// Asymmetric decryption of secret key
|
||||||
val asymmetricCipher = Cipher.getInstance(KeyAlgorithm)
|
val asymmetricCipher = Cipher.getInstance(KeyAlgorithm)
|
||||||
asymmetricCipher.init(Cipher.UNWRAP_MODE, loadKey(PrivateKeyAlias, classOf[PrivateKey]))
|
asymmetricCipher.init(Cipher.UNWRAP_MODE, loadKey(PrivateKeyAlias, classOf[PrivateKey]))
|
||||||
val key = asymmetricCipher.unwrap(msg.Crypto.Key.get, SymmetricKeyAlgorithm, Cipher.SECRET_KEY)
|
val key = asymmetricCipher.unwrap(msg.Crypto.key.get, SymmetricKeyAlgorithm, Cipher.SECRET_KEY)
|
||||||
|
|
||||||
// Symmetric decryption of data
|
// Symmetric decryption of data
|
||||||
val symmetricCipher = Cipher.getInstance(SymmetricCipherAlgorithm)
|
val symmetricCipher = Cipher.getInstance(SymmetricCipherAlgorithm)
|
||||||
symmetricCipher.init(Cipher.DECRYPT_MODE, key)
|
symmetricCipher.init(Cipher.DECRYPT_MODE, key)
|
||||||
val decrypted = copyThroughCipher(symmetricCipher, msg.Body.asInstanceOf[EncryptedBody].Data)
|
val decrypted = copyThroughCipher(symmetricCipher, msg.Body.asInstanceOf[EncryptedBody].data)
|
||||||
val body = msg.Header.MessageType match {
|
val body = msg.Header.messageType match {
|
||||||
case RequestAddContact.Type => RequestAddContact.read(decrypted)
|
case RequestAddContact.Type => RequestAddContact.read(decrypted)
|
||||||
case ResultAddContact.Type => ResultAddContact.read(decrypted)
|
case ResultAddContact.Type => ResultAddContact.read(decrypted)
|
||||||
case Text.Type => Text.read(decrypted)
|
case Text.Type => Text.read(decrypted)
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Router(activeConnections: () => Set[Address], send: (Address, Message) =>
|
||||||
private var messageSeen = Set[(Address, Int)]()
|
private var messageSeen = Set[(Address, Int)]()
|
||||||
|
|
||||||
def onReceive(msg: Message): Unit = {
|
def onReceive(msg: Message): Unit = {
|
||||||
val info = (msg.Header.Origin, msg.Header.SeqNum)
|
val info = (msg.Header.origin, msg.Header.seqNum)
|
||||||
if (messageSeen.contains(info))
|
if (messageSeen.contains(info))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
package com.nutomic.ensichat.protocol
|
package com.nutomic.ensichat.protocol
|
||||||
|
|
||||||
|
case class User(address: Address, name: String)
|
||||||
case class User(Address: Address, Name: String)
|
|
|
@ -36,11 +36,11 @@ object CryptoData {
|
||||||
/**
|
/**
|
||||||
* Holds the signature and (optional) key that are stored in a message.
|
* Holds the signature and (optional) key that are stored in a message.
|
||||||
*/
|
*/
|
||||||
case class CryptoData(Signature: Option[Array[Byte]], Key: Option[Array[Byte]]) {
|
case class CryptoData(signature: Option[Array[Byte]], key: Option[Array[Byte]]) {
|
||||||
|
|
||||||
override def equals(a: Any): Boolean = a match {
|
override def equals(a: Any): Boolean = a match {
|
||||||
case o: CryptoData => util.Arrays.equals(Signature.orNull, o.Signature.orNull) &&
|
case o: CryptoData => util.Arrays.equals(signature.orNull, o.signature.orNull) &&
|
||||||
util.Arrays.equals(Key.orNull, o.Key.orNull)
|
util.Arrays.equals(key.orNull, o.key.orNull)
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,15 +49,15 @@ case class CryptoData(Signature: Option[Array[Byte]], Key: Option[Array[Byte]])
|
||||||
*/
|
*/
|
||||||
def write: Array[Byte] = {
|
def write: Array[Byte] = {
|
||||||
val b = ByteBuffer.allocate(length)
|
val b = ByteBuffer.allocate(length)
|
||||||
BufferUtils.putUnsignedShort(b, Signature.get.length)
|
BufferUtils.putUnsignedShort(b, signature.get.length)
|
||||||
BufferUtils.putUnsignedShort(b, keyLength)
|
BufferUtils.putUnsignedShort(b, keyLength)
|
||||||
b.put(Signature.get)
|
b.put(signature.get)
|
||||||
if (Key.nonEmpty) b.put(Key.get)
|
if (key.nonEmpty) b.put(key.get)
|
||||||
b.array()
|
b.array()
|
||||||
}
|
}
|
||||||
|
|
||||||
def length = 4 + Signature.get.length + keyLength
|
def length = 4 + signature.get.length + keyLength
|
||||||
|
|
||||||
private def keyLength = if (Key.isDefined) Key.get.length else 0
|
private def keyLength = if (key.isDefined) key.get.length else 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ package com.nutomic.ensichat.protocol.messages
|
||||||
/**
|
/**
|
||||||
* Represents the data in an encrypted message body.
|
* Represents the data in an encrypted message body.
|
||||||
*/
|
*/
|
||||||
case class EncryptedBody(Data: Array[Byte]) extends MessageBody {
|
case class EncryptedBody(data: Array[Byte]) extends MessageBody {
|
||||||
|
|
||||||
override def messageType = -1
|
override def messageType = -1
|
||||||
|
|
||||||
def write = Data
|
def write = data
|
||||||
|
|
||||||
override def length = Data.length
|
override def length = data.length
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ object Message {
|
||||||
stream.read(headerBytes, 0, MessageHeader.Length)
|
stream.read(headerBytes, 0, MessageHeader.Length)
|
||||||
val header = MessageHeader.read(headerBytes)
|
val header = MessageHeader.read(headerBytes)
|
||||||
|
|
||||||
val contentLength = (header.Length - MessageHeader.Length).toInt
|
val contentLength = (header.length - MessageHeader.Length).toInt
|
||||||
val contentBytes = new Array[Byte](contentLength)
|
val contentBytes = new Array[Byte](contentLength)
|
||||||
var numRead = 0
|
var numRead = 0
|
||||||
do {
|
do {
|
||||||
|
@ -36,7 +36,7 @@ object Message {
|
||||||
val (crypto, remaining) = CryptoData.read(contentBytes)
|
val (crypto, remaining) = CryptoData.read(contentBytes)
|
||||||
|
|
||||||
val body =
|
val body =
|
||||||
header.MessageType match {
|
header.messageType match {
|
||||||
case ConnectionInfo.Type => ConnectionInfo.read(remaining)
|
case ConnectionInfo.Type => ConnectionInfo.read(remaining)
|
||||||
case _ => new EncryptedBody(remaining)
|
case _ => new EncryptedBody(remaining)
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,13 +45,13 @@ object MessageHeader {
|
||||||
/**
|
/**
|
||||||
* First part of any message, used for routing.
|
* First part of any message, used for routing.
|
||||||
*/
|
*/
|
||||||
case class MessageHeader(MessageType: Int,
|
case class MessageHeader(messageType: Int,
|
||||||
HopLimit: Int,
|
hopLimit: Int,
|
||||||
Origin: Address,
|
origin: Address,
|
||||||
Target: Address,
|
target: Address,
|
||||||
SeqNum: Int,
|
seqNum: Int,
|
||||||
Length: Long = -1,
|
length: Long = -1,
|
||||||
HopCount: Int = 0) {
|
hopCount: Int = 0) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the header to byte array.
|
* Writes the header to byte array.
|
||||||
|
@ -59,16 +59,16 @@ case class MessageHeader(MessageType: Int,
|
||||||
def write(contentLength: Int): Array[Byte] = {
|
def write(contentLength: Int): Array[Byte] = {
|
||||||
val b = ByteBuffer.allocate(MessageHeader.Length)
|
val b = ByteBuffer.allocate(MessageHeader.Length)
|
||||||
|
|
||||||
val versionAndType = (MessageHeader.Version << 12) | MessageType
|
val versionAndType = (MessageHeader.Version << 12) | messageType
|
||||||
BufferUtils.putUnsignedShort(b, versionAndType)
|
BufferUtils.putUnsignedShort(b, versionAndType)
|
||||||
BufferUtils.putUnsignedByte(b, HopLimit)
|
BufferUtils.putUnsignedByte(b, hopLimit)
|
||||||
BufferUtils.putUnsignedByte(b, HopCount)
|
BufferUtils.putUnsignedByte(b, hopCount)
|
||||||
|
|
||||||
BufferUtils.putUnsignedInt(b, MessageHeader.Length + contentLength)
|
BufferUtils.putUnsignedInt(b, MessageHeader.Length + contentLength)
|
||||||
b.put(Origin.Bytes)
|
b.put(origin.bytes)
|
||||||
b.put(Target.Bytes)
|
b.put(target.bytes)
|
||||||
|
|
||||||
BufferUtils.putUnsignedShort(b, SeqNum)
|
BufferUtils.putUnsignedShort(b, seqNum)
|
||||||
BufferUtils.putUnsignedShort(b, 0)
|
BufferUtils.putUnsignedShort(b, 0)
|
||||||
|
|
||||||
b.array()
|
b.array()
|
||||||
|
@ -76,11 +76,11 @@ case class MessageHeader(MessageType: Int,
|
||||||
|
|
||||||
override def equals(a: Any): Boolean = a match {
|
override def equals(a: Any): Boolean = a match {
|
||||||
case o: MessageHeader =>
|
case o: MessageHeader =>
|
||||||
MessageType == o.MessageType &&
|
messageType == o.messageType &&
|
||||||
HopLimit == o.HopLimit &&
|
hopLimit == o.hopLimit &&
|
||||||
Origin == o.Origin &&
|
origin == o.origin &&
|
||||||
Target == o.Target &&
|
target == o.target &&
|
||||||
HopCount == o.HopCount
|
hopCount == o.hopCount
|
||||||
// Don't compare length as it may be unknown (when header was just created without a body).
|
// Don't compare length as it may be unknown (when header was just created without a body).
|
||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,13 @@ object ResultAddContact {
|
||||||
/**
|
/**
|
||||||
* Contains the result of a [[RequestAddContact]] message.
|
* Contains the result of a [[RequestAddContact]] message.
|
||||||
*/
|
*/
|
||||||
case class ResultAddContact(Accepted: Boolean) extends MessageBody {
|
case class ResultAddContact(accepted: Boolean) extends MessageBody {
|
||||||
|
|
||||||
override def messageType = ResultAddContact.Type
|
override def messageType = ResultAddContact.Type
|
||||||
|
|
||||||
override def write: Array[Byte] = {
|
override def write: Array[Byte] = {
|
||||||
val b = ByteBuffer.allocate(length)
|
val b = ByteBuffer.allocate(length)
|
||||||
BufferUtils.putUnsignedByte(b, if (Accepted) 0x80 else 0)
|
BufferUtils.putUnsignedByte(b, if (accepted) 0x80 else 0)
|
||||||
(0 to 1).foreach(_ => BufferUtils.putUnsignedByte(b, 0))
|
(0 to 1).foreach(_ => BufferUtils.putUnsignedByte(b, 0))
|
||||||
b.array()
|
b.array()
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,18 +24,18 @@ object UserName {
|
||||||
/**
|
/**
|
||||||
* Holds the display name of the sender.
|
* Holds the display name of the sender.
|
||||||
*/
|
*/
|
||||||
case class UserName(Name: String) extends MessageBody {
|
case class UserName(name: String) extends MessageBody {
|
||||||
|
|
||||||
override def messageType = UserName.Type
|
override def messageType = UserName.Type
|
||||||
|
|
||||||
override def write: Array[Byte] = {
|
override def write: Array[Byte] = {
|
||||||
val b = ByteBuffer.allocate(length)
|
val b = ByteBuffer.allocate(length)
|
||||||
val bytes = Name.getBytes(Message.Charset)
|
val bytes = name.getBytes(Message.Charset)
|
||||||
BufferUtils.putUnsignedInt(b, bytes.length)
|
BufferUtils.putUnsignedInt(b, bytes.length)
|
||||||
b.put(bytes)
|
b.put(bytes)
|
||||||
b.array()
|
b.array()
|
||||||
}
|
}
|
||||||
|
|
||||||
override def length = 4 + Name.getBytes(Message.Charset).length
|
override def length = 4 + name.getBytes(Message.Charset).length
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,8 @@ class Database(context: Context)
|
||||||
override def onMessageReceived(msg: Message): Unit = msg.Body match {
|
override def onMessageReceived(msg: Message): Unit = msg.Body match {
|
||||||
case text: Text =>
|
case text: Text =>
|
||||||
val cv = new ContentValues()
|
val cv = new ContentValues()
|
||||||
cv.put("origin", msg.Header.Origin.toString)
|
cv.put("origin", msg.Header.origin.toString)
|
||||||
cv.put("target", msg.Header.Target.toString)
|
cv.put("target", msg.Header.target.toString)
|
||||||
// toString used as workaround for compile error with Long.
|
// toString used as workaround for compile error with Long.
|
||||||
cv.put("date", text.time.getTime.toString)
|
cv.put("date", text.time.getTime.toString)
|
||||||
cv.put("text", text.text)
|
cv.put("text", text.text)
|
||||||
|
@ -130,16 +130,16 @@ class Database(context: Context)
|
||||||
*/
|
*/
|
||||||
def addContact(contact: User): Unit = {
|
def addContact(contact: User): Unit = {
|
||||||
val cv = new ContentValues()
|
val cv = new ContentValues()
|
||||||
cv.put("address", contact.Address.toString)
|
cv.put("address", contact.address.toString)
|
||||||
cv.put("name", contact.Name.toString)
|
cv.put("name", contact.name.toString)
|
||||||
getWritableDatabase.insert("contacts", null, cv)
|
getWritableDatabase.insert("contacts", null, cv)
|
||||||
contactsUpdatedListeners.foreach(_.onContactsUpdated() )
|
contactsUpdatedListeners.foreach(_.onContactsUpdated() )
|
||||||
}
|
}
|
||||||
|
|
||||||
def changeContactName(contact: User): Unit = {
|
def changeContactName(contact: User): Unit = {
|
||||||
val cv = new ContentValues()
|
val cv = new ContentValues()
|
||||||
cv.put("name", contact.Name.toString)
|
cv.put("name", contact.name.toString)
|
||||||
getWritableDatabase.update("contacts", cv, "address = ?", Array(contact.Address.toString))
|
getWritableDatabase.update("contacts", cv, "address = ?", Array(contact.address.toString))
|
||||||
contactsUpdatedListeners.foreach(_.onContactsUpdated())
|
contactsUpdatedListeners.foreach(_.onContactsUpdated())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ object IdenticonGenerator {
|
||||||
* @param size The size of the bitmap returned.
|
* @param size The size of the bitmap returned.
|
||||||
*/
|
*/
|
||||||
def generate(address: Address, size: (Int, Int), context: Context): Bitmap = {
|
def generate(address: Address, size: (Int, Int), context: Context): Bitmap = {
|
||||||
val hash = address.Bytes
|
val hash = address.bytes
|
||||||
|
|
||||||
// Create base image and colors.
|
// Create base image and colors.
|
||||||
var identicon = Bitmap.createBitmap(Width, Height, Config.ARGB_8888)
|
var identicon = Bitmap.createBitmap(Width, Height, Config.ARGB_8888)
|
||||||
|
|
|
@ -26,7 +26,7 @@ class MessagesAdapter(context: Context, remoteAddress: Address) extends
|
||||||
|
|
||||||
val lp = new RelativeLayout.LayoutParams(tv.getLayoutParams)
|
val lp = new RelativeLayout.LayoutParams(tv.getLayoutParams)
|
||||||
val margin = (MessageMargin * context.getResources.getDisplayMetrics.density).toInt
|
val margin = (MessageMargin * context.getResources.getDisplayMetrics.density).toInt
|
||||||
if (getItem(position).Header.Origin != remoteAddress) {
|
if (getItem(position).Header.origin != remoteAddress) {
|
||||||
view.setGravity(Gravity.RIGHT)
|
view.setGravity(Gravity.RIGHT)
|
||||||
lp.setMargins(margin, 0, 0, 0)
|
lp.setMargins(margin, 0, 0, 0)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,7 +15,7 @@ class UsersAdapter(context: Context) extends
|
||||||
override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
|
override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
|
||||||
val view = super.getView(position, convertView, parent)
|
val view = super.getView(position, convertView, parent)
|
||||||
val title: TextView = view.findViewById(android.R.id.text1).asInstanceOf[TextView]
|
val title: TextView = view.findViewById(android.R.id.text1).asInstanceOf[TextView]
|
||||||
title.setText(getItem(position).Name)
|
title.setText(getItem(position).name)
|
||||||
view
|
view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue