Made member names lowercase, minor code formatting.
This commit is contained in:
parent
3a90f2d9a3
commit
e38e805c1b
29 changed files with 152 additions and 174 deletions
|
@ -6,19 +6,19 @@ import junit.framework.Assert._
|
|||
|
||||
class CryptoTest extends AndroidTestCase {
|
||||
|
||||
lazy val Crypto: Crypto = new Crypto(getContext)
|
||||
private lazy val crypto: Crypto = new Crypto(getContext)
|
||||
|
||||
override def setUp(): Unit = {
|
||||
super.setUp()
|
||||
if (!Crypto.localKeysExist) {
|
||||
Crypto.generateLocalKeys()
|
||||
if (!crypto.localKeysExist) {
|
||||
crypto.generateLocalKeys()
|
||||
}
|
||||
}
|
||||
|
||||
def testSignVerify(): Unit = {
|
||||
MessageTest.messages.foreach { m =>
|
||||
val signed = Crypto.sign(m)
|
||||
assertTrue(Crypto.verify(signed, Crypto.getLocalPublicKey))
|
||||
val signed = crypto.sign(m)
|
||||
assertTrue(crypto.verify(signed, crypto.getLocalPublicKey))
|
||||
assertEquals(m.Header, signed.Header)
|
||||
assertEquals(m.Body, signed.Body)
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ class CryptoTest extends AndroidTestCase {
|
|||
|
||||
def testEncryptDecrypt(): Unit = {
|
||||
MessageTest.messages.foreach{ m =>
|
||||
val encrypted = Crypto.encrypt(Crypto.sign(m), Crypto.getLocalPublicKey)
|
||||
val decrypted = Crypto.decrypt(encrypted)
|
||||
val encrypted = crypto.encrypt(crypto.sign(m), crypto.getLocalPublicKey)
|
||||
val decrypted = crypto.decrypt(encrypted)
|
||||
assertEquals(m.Body, decrypted.Body)
|
||||
assertEquals(m.Header, encrypted.Header)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package com.nutomic.ensichat.protocol.messages
|
||||
|
||||
import java.util.GregorianCalendar
|
||||
|
||||
import android.test.AndroidTestCase
|
||||
import com.nutomic.ensichat.protocol.messages.MessageHeaderTest._
|
||||
import com.nutomic.ensichat.protocol.{Address, AddressTest}
|
||||
import junit.framework.Assert._
|
||||
import com.nutomic.ensichat.protocol.messages.MessageHeaderTest._
|
||||
|
||||
object MessageHeaderTest {
|
||||
|
||||
|
@ -35,4 +33,4 @@ class MessageHeaderTest extends AndroidTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@ package com.nutomic.ensichat.protocol.messages
|
|||
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.util.GregorianCalendar
|
||||
import com.nutomic.ensichat.protocol.messages.MessageHeaderTest._
|
||||
import com.nutomic.ensichat.protocol.messages.MessageTest._
|
||||
|
||||
import android.test.AndroidTestCase
|
||||
import com.nutomic.ensichat.protocol.{AddressTest, Crypto, messages}
|
||||
import com.nutomic.ensichat.protocol.messages.MessageHeaderTest._
|
||||
import com.nutomic.ensichat.protocol.messages.MessageTest._
|
||||
import com.nutomic.ensichat.protocol.{AddressTest, Crypto}
|
||||
import junit.framework.Assert._
|
||||
|
||||
import scala.collection.immutable.TreeSet
|
||||
|
@ -25,12 +25,12 @@ object MessageTest {
|
|||
|
||||
class MessageTest extends AndroidTestCase {
|
||||
|
||||
lazy val Crypto: Crypto = new Crypto(getContext)
|
||||
private lazy val crypto: Crypto = new Crypto(getContext)
|
||||
|
||||
override def setUp(): Unit = {
|
||||
super.setUp()
|
||||
if (!Crypto.localKeysExist) {
|
||||
Crypto.generateLocalKeys()
|
||||
if (!crypto.localKeysExist) {
|
||||
crypto.generateLocalKeys()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,27 +50,27 @@ class MessageTest extends AndroidTestCase {
|
|||
val header = new MessageHeader(ConnectionInfo.Type, 0xff, AddressTest.a4, AddressTest.a2, 0, 56)
|
||||
val m = new Message(header, ConnectionInfoTest.generateCi(getContext))
|
||||
|
||||
val signed = Crypto.sign(m)
|
||||
val signed = crypto.sign(m)
|
||||
val bytes = signed.write
|
||||
val read = Message.read(new ByteArrayInputStream(bytes))
|
||||
|
||||
assertEquals(signed, read)
|
||||
assertTrue(Crypto.verify(read, Crypto.getLocalPublicKey))
|
||||
assertTrue(crypto.verify(read, crypto.getLocalPublicKey))
|
||||
}
|
||||
|
||||
def testSerializeEncrypted(): Unit = {
|
||||
MessageTest.messages.foreach{ m =>
|
||||
val signed = Crypto.sign(m)
|
||||
val encrypted = Crypto.encrypt(signed, Crypto.getLocalPublicKey)
|
||||
val signed = crypto.sign(m)
|
||||
val encrypted = crypto.encrypt(signed, crypto.getLocalPublicKey)
|
||||
val bytes = encrypted.write
|
||||
|
||||
val read = Message.read(new ByteArrayInputStream(bytes))
|
||||
assertEquals(encrypted.Crypto, read.Crypto)
|
||||
val decrypted = Crypto.decrypt(read)
|
||||
val decrypted = crypto.decrypt(read)
|
||||
assertEquals(m.Header, decrypted.Header)
|
||||
assertEquals(m.Body, decrypted.Body)
|
||||
assertTrue(Crypto.verify(decrypted, Crypto.getLocalPublicKey))
|
||||
assertTrue(crypto.verify(decrypted, crypto.getLocalPublicKey))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,60 +23,60 @@ class DatabaseTest extends AndroidTestCase {
|
|||
|
||||
private var dbFile: String = _
|
||||
|
||||
private var Database: Database = _
|
||||
private var database: Database = _
|
||||
|
||||
override def setUp(): Unit = {
|
||||
Database = new Database(new TestContext(getContext))
|
||||
Database.onMessageReceived(m1)
|
||||
Database.onMessageReceived(m2)
|
||||
Database.onMessageReceived(m3)
|
||||
database = new Database(new TestContext(getContext))
|
||||
database.onMessageReceived(m1)
|
||||
database.onMessageReceived(m2)
|
||||
database.onMessageReceived(m3)
|
||||
}
|
||||
|
||||
override def tearDown(): Unit = {
|
||||
super.tearDown()
|
||||
Database.close()
|
||||
database.close()
|
||||
getContext.deleteDatabase(dbFile)
|
||||
}
|
||||
|
||||
def testMessageCount(): Unit = {
|
||||
val msg1 = Database.getMessages(m1.Header.Origin, 1)
|
||||
val msg1 = database.getMessages(m1.Header.Origin, 1)
|
||||
assertEquals(1, msg1.size)
|
||||
|
||||
val msg2 = Database.getMessages(m1.Header.Origin, 3)
|
||||
val msg2 = database.getMessages(m1.Header.Origin, 3)
|
||||
assertEquals(2, msg2.size)
|
||||
}
|
||||
|
||||
def testMessageOrder(): Unit = {
|
||||
val msg = Database.getMessages(m1.Header.Target, 1)
|
||||
val msg = database.getMessages(m1.Header.Target, 1)
|
||||
assertTrue(msg.contains(m3))
|
||||
}
|
||||
|
||||
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(m3))
|
||||
}
|
||||
|
||||
def testAddContact(): Unit = {
|
||||
Database.addContact(UserTest.u1)
|
||||
val contacts = Database.getContacts
|
||||
database.addContact(UserTest.u1)
|
||||
val contacts = database.getContacts
|
||||
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 = {
|
||||
val latch = new CountDownLatch(1)
|
||||
Database.runOnContactsUpdated(() => {
|
||||
database.runOnContactsUpdated(() => {
|
||||
latch.countDown()
|
||||
})
|
||||
Database.addContact(UserTest.u1)
|
||||
database.addContact(UserTest.u1)
|
||||
latch.await()
|
||||
}
|
||||
|
||||
def testGetContact(): Unit = {
|
||||
Database.addContact(UserTest.u2)
|
||||
assertTrue(Database.getContact(UserTest.u1.Address).isEmpty)
|
||||
val c = Database.getContact(UserTest.u2.Address)
|
||||
database.addContact(UserTest.u2)
|
||||
assertTrue(database.getContact(UserTest.u1.Address).isEmpty)
|
||||
val c = database.getContact(UserTest.u2.Address)
|
||||
assertTrue(c.nonEmpty)
|
||||
assertEquals(Some(UserTest.u2), c)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ class AddContactsActivity extends EnsiChatActivity with ChatService.OnConnection
|
|||
|
||||
private val Tag = "AddContactsActivity"
|
||||
|
||||
private lazy val Adapter = new UsersAdapter(this)
|
||||
private lazy val adapter = new UsersAdapter(this)
|
||||
|
||||
/**
|
||||
* Initializes layout, registers connection and message listeners.
|
||||
|
@ -30,13 +30,13 @@ class AddContactsActivity extends EnsiChatActivity with ChatService.OnConnection
|
|||
|
||||
setContentView(R.layout.activity_add_contacts)
|
||||
val list = findViewById(android.R.id.list).asInstanceOf[ListView]
|
||||
list.setAdapter(Adapter)
|
||||
list.setAdapter(adapter)
|
||||
list.setOnItemClickListener(this)
|
||||
list.setEmptyView(findViewById(android.R.id.empty))
|
||||
|
||||
runOnServiceConnected(() => {
|
||||
service.registerConnectionListener(AddContactsActivity.this)
|
||||
service.Database.runOnContactsUpdated(updateList)
|
||||
service.database.runOnContactsUpdated(updateList)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ class AddContactsActivity extends EnsiChatActivity with ChatService.OnConnection
|
|||
* Initiates adding the device as contact if it hasn't been added yet.
|
||||
*/
|
||||
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())
|
||||
val intent = new Intent(this, classOf[ConfirmAddContactDialog])
|
||||
intent.putExtra(ConfirmAddContactDialog.ExtraContactAddress, contact.Address.toString)
|
||||
|
@ -67,8 +67,8 @@ class AddContactsActivity extends EnsiChatActivity with ChatService.OnConnection
|
|||
private def updateList(): Unit ={
|
||||
runOnUiThread(new Runnable {
|
||||
override def run(): Unit = {
|
||||
Adapter.clear()
|
||||
(service.getConnections -- service.Database.getContacts).foreach(Adapter.add)
|
||||
adapter.clear()
|
||||
(service.getConnections -- service.database.getContacts).foreach(adapter.add)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
|||
|
||||
private val Tag = "ConfirmAddContactDialog"
|
||||
|
||||
private lazy val User = service.getUser(
|
||||
private lazy val user = service.getUser(
|
||||
new Address(getIntent.getStringExtra(ConfirmAddContactDialog.ExtraContactAddress)))
|
||||
|
||||
private var localConfirmed = false
|
||||
|
@ -55,11 +55,11 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
|||
val remoteTitle = view.findViewById(R.id.remote_identicon_title).asInstanceOf[TextView]
|
||||
|
||||
local.setImageBitmap(IdenticonGenerator.generate(Crypto.getLocalAddress(this), (150, 150), this))
|
||||
remote.setImageBitmap(IdenticonGenerator.generate(User.Address, (150, 150), this))
|
||||
remoteTitle.setText(getString(R.string.remote_fingerprint_title, User.Name))
|
||||
remote.setImageBitmap(IdenticonGenerator.generate(user.Address, (150, 150), this))
|
||||
remoteTitle.setText(getString(R.string.remote_fingerprint_title, user.Name))
|
||||
|
||||
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)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.yes, this)
|
||||
|
@ -76,7 +76,7 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
|||
case DialogInterface.BUTTON_NEGATIVE =>
|
||||
false
|
||||
}
|
||||
service.sendTo(User.Address, new ResultAddContact(result))
|
||||
service.sendTo(user.Address, new ResultAddContact(result))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,10 +84,10 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
|||
*/
|
||||
private def addContactIfBothConfirmed(): Unit = {
|
||||
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
|
||||
service.Database.addContact(service.getUser(User.Address))
|
||||
Toast.makeText(this, getString(R.string.contact_added, User.Name), Toast.LENGTH_SHORT)
|
||||
service.database.addContact(service.getUser(user.Address))
|
||||
Toast.makeText(this, getString(R.string.contact_added, user.Name), Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
finish()
|
||||
}
|
||||
|
@ -100,17 +100,17 @@ class ConfirmAddContactDialog extends EnsiChatActivity with OnMessageReceivedLis
|
|||
* the user is in this activity.
|
||||
*/
|
||||
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
|
||||
|
||||
msg.Body match {
|
||||
case m: ResultAddContact =>
|
||||
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
|
||||
addContactIfBothConfirmed()
|
||||
} else {
|
||||
Log.i(Tag, User.toString + " denied us as a contact, showing toast")
|
||||
Log.i(Tag, user.toString + " denied us as a contact, showing toast")
|
||||
Toast.makeText(this, R.string.contact_not_added, Toast.LENGTH_LONG).show()
|
||||
finish()
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@ package com.nutomic.ensichat.activities
|
|||
import android.app.Activity
|
||||
import android.content.{ComponentName, Context, Intent, ServiceConnection}
|
||||
import android.os.{Bundle, IBinder}
|
||||
import com.nutomic.ensichat.protocol.ChatService
|
||||
import com.nutomic.ensichat.protocol.ChatServiceBinder
|
||||
import com.nutomic.ensichat.protocol.{ChatService, ChatServiceBinder}
|
||||
|
||||
/**
|
||||
* Connects to [[ChatService]] and provides access to it.
|
||||
|
@ -39,7 +38,7 @@ class EnsiChatActivity extends Activity with ServiceConnection {
|
|||
*/
|
||||
override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
|
||||
val binder = iBinder.asInstanceOf[ChatServiceBinder]
|
||||
chatService = Option(binder.getService)
|
||||
chatService = Option(binder.Service)
|
||||
listeners.foreach(_())
|
||||
listeners = Set.empty
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ class MainActivity extends EnsiChatActivity {
|
|||
|
||||
private val RequestSetDiscoverable = 1
|
||||
|
||||
private var ContactsFragment: ContactsFragment = _
|
||||
private var contactsFragment: ContactsFragment = _
|
||||
|
||||
private var currentChat: Option[Address] = None
|
||||
|
||||
|
@ -42,16 +42,16 @@ class MainActivity extends EnsiChatActivity {
|
|||
|
||||
val fm = getFragmentManager
|
||||
if (savedInstanceState != null) {
|
||||
ContactsFragment = fm.getFragment(savedInstanceState, classOf[ContactsFragment].getName)
|
||||
contactsFragment = fm.getFragment(savedInstanceState, classOf[ContactsFragment].getName)
|
||||
.asInstanceOf[ContactsFragment]
|
||||
if (savedInstanceState.containsKey("current_chat")) {
|
||||
currentChat = Option(new Address(savedInstanceState.getByteArray("current_chat")))
|
||||
openChat(currentChat.get)
|
||||
}
|
||||
} else {
|
||||
ContactsFragment = new ContactsFragment()
|
||||
contactsFragment = new ContactsFragment()
|
||||
fm.beginTransaction()
|
||||
.add(android.R.id.content, ContactsFragment)
|
||||
.add(android.R.id.content, contactsFragment)
|
||||
.commit()
|
||||
}
|
||||
|
||||
|
@ -64,14 +64,14 @@ class MainActivity extends EnsiChatActivity {
|
|||
*/
|
||||
override def onSaveInstanceState(outState: Bundle): Unit = {
|
||||
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)}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exits with error if bluetooth was not enabled/not set discoverable,
|
||||
*/
|
||||
override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent): Unit = {
|
||||
override def onActivityResult(requestCode: Int, resultCode: Int, data: Intent): Unit =
|
||||
requestCode match {
|
||||
case RequestSetDiscoverable =>
|
||||
if (resultCode == Activity.RESULT_CANCELED) {
|
||||
|
@ -79,7 +79,6 @@ class MainActivity extends EnsiChatActivity {
|
|||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a chat fragment for the given device, creating the fragment if needed.
|
||||
|
@ -88,21 +87,21 @@ class MainActivity extends EnsiChatActivity {
|
|||
currentChat = Some(address)
|
||||
getFragmentManager
|
||||
.beginTransaction()
|
||||
.detach(ContactsFragment)
|
||||
.detach(contactsFragment)
|
||||
.add(android.R.id.content, new ChatFragment(address))
|
||||
.commit()
|
||||
getActionBar.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* If in a ChatFragment, goes back up to ContactsFragment.
|
||||
* If in a ChatFragment, goes back up to contactsFragment.
|
||||
*/
|
||||
override def onBackPressed(): Unit = {
|
||||
if (currentChat != None) {
|
||||
getFragmentManager
|
||||
.beginTransaction()
|
||||
.remove(getFragmentManager.findFragmentById(android.R.id.content))
|
||||
.attach(ContactsFragment)
|
||||
.attach(contactsFragment)
|
||||
.commit()
|
||||
currentChat = None
|
||||
getActionBar.setDisplayHomeAsUpEnabled(false)
|
||||
|
|
|
@ -38,7 +38,7 @@ class SettingsActivity extends EnsiChatActivity {
|
|||
override def onOptionsItemSelected(item: MenuItem): Boolean = item.getItemId match {
|
||||
case android.R.id.home =>
|
||||
NavUtils.navigateUpFromSameTask(this)
|
||||
true;
|
||||
true
|
||||
case _ =>
|
||||
super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
|
|
@ -30,20 +30,20 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
|
||||
private val Tag = "BluetoothInterface"
|
||||
|
||||
private lazy val BtAdapter = BluetoothAdapter.getDefaultAdapter
|
||||
private lazy val btAdapter = BluetoothAdapter.getDefaultAdapter
|
||||
|
||||
private var devices = new HashMap[Device.ID, Device]()
|
||||
|
||||
private var connections = new HashMap[Device.ID, TransferThread]()
|
||||
|
||||
private lazy val ListenThread =
|
||||
new ListenThread(Service.getString(R.string.app_name), BtAdapter, onConnectionOpened)
|
||||
private lazy val listenThread =
|
||||
new ListenThread(Service.getString(R.string.app_name), btAdapter, onConnectionOpened)
|
||||
|
||||
private var cancelDiscovery = false
|
||||
|
||||
private var discovered = Set[Device]()
|
||||
|
||||
private val AddressDeviceMap = HashBiMap.create[Address, Device.ID]()
|
||||
private val addressDeviceMap = HashBiMap.create[Address, Device.ID]()
|
||||
|
||||
/**
|
||||
* Initializes and starts discovery and listening.
|
||||
|
@ -62,7 +62,7 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
* Stops discovery and listening.
|
||||
*/
|
||||
override def destroy(): Unit = {
|
||||
ListenThread.cancel()
|
||||
listenThread.cancel()
|
||||
cancelDiscovery = true
|
||||
Service.unregisterReceiver(DeviceDiscoveredReceiver)
|
||||
Service.unregisterReceiver(BluetoothStateReceiver)
|
||||
|
@ -73,7 +73,7 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
* Starts discovery and listening.
|
||||
*/
|
||||
private def startBluetoothConnections(): Unit = {
|
||||
ListenThread.start()
|
||||
listenThread.start()
|
||||
cancelDiscovery = false
|
||||
discover()
|
||||
}
|
||||
|
@ -85,9 +85,9 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
if (cancelDiscovery)
|
||||
return
|
||||
|
||||
if (!BtAdapter.isDiscovering) {
|
||||
if (!btAdapter.isDiscovering) {
|
||||
Log.v(Tag, "Starting discovery")
|
||||
BtAdapter.startDiscovery()
|
||||
btAdapter.startDiscovery()
|
||||
}
|
||||
|
||||
val scanInterval = PreferenceManager.getDefaultSharedPreferences(Service)
|
||||
|
@ -113,9 +113,9 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
override def onReceive(context: Context, intent: Intent): Unit = {
|
||||
discovered.filterNot(d => connections.keySet.contains(d.Id))
|
||||
.foreach { d =>
|
||||
new ConnectThread(d, onConnectionOpened).start()
|
||||
devices += (d.Id -> d)
|
||||
}
|
||||
new ConnectThread(d, onConnectionOpened).start()
|
||||
devices += (d.Id -> d)
|
||||
}
|
||||
discovered = Set[Device]()
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
startBluetoothConnections()
|
||||
case BluetoothAdapter.STATE_TURNING_OFF =>
|
||||
Log.i(Tag, "Bluetooth disabled, stopping connectivity")
|
||||
ListenThread.cancel()
|
||||
listenThread.cancel()
|
||||
cancelDiscovery = true
|
||||
connections.foreach(_._2.close())
|
||||
case _ =>
|
||||
|
@ -156,9 +156,8 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
def onConnectionClosed(device: Device, socket: BluetoothSocket): Unit = {
|
||||
devices -= device.Id
|
||||
connections -= device.Id
|
||||
val inv = AddressDeviceMap.inverse()
|
||||
Service.callConnectionListeners()
|
||||
inv.remove(device.Id)
|
||||
addressDeviceMap.inverse().remove(device.Id)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,9 +172,9 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
case info: ConnectionInfo =>
|
||||
val address = Crypto.calculateAddress(info.key)
|
||||
// Service.onConnectionOpened sends message, so mapping already needs to be in place.
|
||||
AddressDeviceMap.put(address, device)
|
||||
addressDeviceMap.put(address, device)
|
||||
if (!Service.onConnectionOpened(msg))
|
||||
AddressDeviceMap.remove(address)
|
||||
addressDeviceMap.remove(address)
|
||||
case _ =>
|
||||
Service.onMessageReceived(msg)
|
||||
}
|
||||
|
@ -183,14 +182,13 @@ class BluetoothInterface(Service: ChatService, Crypto: Crypto) extends Interface
|
|||
/**
|
||||
* Sends the message to the target address specified in the message header.
|
||||
*/
|
||||
override def send(msg: Message): Unit = {
|
||||
connections.apply(AddressDeviceMap.get(msg.Header.Target)).send(msg)
|
||||
}
|
||||
override def send(msg: Message): Unit =
|
||||
connections.apply(addressDeviceMap.get(msg.Header.Target)).send(msg)
|
||||
|
||||
/**
|
||||
* Returns all active Bluetooth connections.
|
||||
*/
|
||||
def getConnections: Set[Address] =
|
||||
connections.map(x => AddressDeviceMap.inverse().get(x._1)).toSet
|
||||
connections.map(x => addressDeviceMap.inverse().get(x._1)).toSet
|
||||
|
||||
}
|
||||
|
|
|
@ -13,18 +13,18 @@ class ConnectThread(device: Device, onConnected: (Device, BluetoothSocket) => Un
|
|||
|
||||
private val Tag = "ConnectThread"
|
||||
|
||||
private val Socket: BluetoothSocket =
|
||||
private val socket: BluetoothSocket =
|
||||
device.bluetoothDevice.createInsecureRfcommSocketToServiceRecord(BluetoothInterface.AppUuid)
|
||||
|
||||
override def run(): Unit = {
|
||||
Log.i(Tag, "Connecting to " + device.toString)
|
||||
try {
|
||||
Socket.connect()
|
||||
socket.connect()
|
||||
} catch {
|
||||
case e: IOException =>
|
||||
Log.v(Tag, "Failed to connect to " + device.toString, e)
|
||||
try {
|
||||
Socket.close()
|
||||
socket.close()
|
||||
} catch {
|
||||
case e2: IOException =>
|
||||
Log.e(Tag, "Failed to close socket", e2)
|
||||
|
@ -33,7 +33,7 @@ class ConnectThread(device: Device, onConnected: (Device, BluetoothSocket) => Un
|
|||
}
|
||||
|
||||
Log.i(Tag, "Successfully connected to device " + device.Name)
|
||||
onConnected(new Device(device.bluetoothDevice, true), Socket)
|
||||
onConnected(new Device(device.bluetoothDevice, true), socket)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ class ListenThread(name: String, adapter: BluetoothAdapter,
|
|||
|
||||
private val Tag: String = "ListenThread"
|
||||
|
||||
private val ServerSocket: BluetoothServerSocket =
|
||||
private val serverSocket: BluetoothServerSocket =
|
||||
try {
|
||||
adapter.listenUsingInsecureRfcommWithServiceRecord(name, BluetoothInterface.AppUuid)
|
||||
} catch {
|
||||
|
@ -32,7 +32,7 @@ class ListenThread(name: String, adapter: BluetoothAdapter,
|
|||
try {
|
||||
// This is a blocking call and will only return on a
|
||||
// successful connection or an exception
|
||||
socket = ServerSocket.accept()
|
||||
socket = serverSocket.accept()
|
||||
} catch {
|
||||
case e: IOException =>
|
||||
// This happens if Bluetooth is disabled manually.
|
||||
|
@ -49,7 +49,7 @@ class ListenThread(name: String, adapter: BluetoothAdapter,
|
|||
def cancel(): Unit = {
|
||||
Log.i(Tag, "Canceling listening")
|
||||
try {
|
||||
ServerSocket.close()
|
||||
serverSocket.close()
|
||||
} catch {
|
||||
case e: IOException =>
|
||||
Log.e(Tag, "Failed to close listener", e)
|
||||
|
|
|
@ -23,7 +23,7 @@ class TransferThread(device: Device, socket: BluetoothSocket, Handler: Bluetooth
|
|||
|
||||
private val Tag: String = "TransferThread"
|
||||
|
||||
val InStream: InputStream =
|
||||
val inStream: InputStream =
|
||||
try {
|
||||
socket.getInputStream
|
||||
} catch {
|
||||
|
@ -32,7 +32,7 @@ class TransferThread(device: Device, socket: BluetoothSocket, Handler: Bluetooth
|
|||
null
|
||||
}
|
||||
|
||||
val OutStream: OutputStream =
|
||||
val outStream: OutputStream =
|
||||
try {
|
||||
socket.getOutputStream
|
||||
} catch {
|
||||
|
@ -49,8 +49,8 @@ class TransferThread(device: Device, socket: BluetoothSocket, Handler: Bluetooth
|
|||
|
||||
while (socket.isConnected) {
|
||||
try {
|
||||
if (InStream.available() > 0) {
|
||||
val msg = Message.read(InStream)
|
||||
if (inStream.available() > 0) {
|
||||
val msg = Message.read(inStream)
|
||||
|
||||
onReceive(msg, device.Id)
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ class TransferThread(device: Device, socket: BluetoothSocket, Handler: Bluetooth
|
|||
|
||||
def send(msg: Message): Unit = {
|
||||
try {
|
||||
OutStream.write(msg.write)
|
||||
outStream.write(msg.write)
|
||||
} catch {
|
||||
case e: IOException => Log.e(Tag, "Failed to write message", e)
|
||||
}
|
||||
|
|
|
@ -9,12 +9,10 @@ import android.widget.TextView.OnEditorActionListener
|
|||
import android.widget._
|
||||
import com.nutomic.ensichat.R
|
||||
import com.nutomic.ensichat.activities.EnsiChatActivity
|
||||
import com.nutomic.ensichat.protocol.{User, ChatService, Address}
|
||||
import com.nutomic.ensichat.protocol.ChatService.OnMessageReceivedListener
|
||||
import com.nutomic.ensichat.protocol.messages.{Message, Text}
|
||||
import com.nutomic.ensichat.util.{Database, MessagesAdapter}
|
||||
|
||||
import scala.collection.SortedSet
|
||||
import com.nutomic.ensichat.protocol.{Address, ChatService}
|
||||
import com.nutomic.ensichat.util.MessagesAdapter
|
||||
|
||||
/**
|
||||
* Represents a single chat with another specific device.
|
||||
|
@ -49,13 +47,13 @@ class ChatFragment extends ListFragment with OnClickListener
|
|||
activity.runOnServiceConnected(() => {
|
||||
chatService = activity.service
|
||||
|
||||
chatService.Database.getContact(address)
|
||||
chatService.database.getContact(address)
|
||||
.foreach(c => getActivity.setTitle(c.Name))
|
||||
|
||||
// Read local device ID from service,
|
||||
adapter = new MessagesAdapter(getActivity, address)
|
||||
chatService.registerMessageListener(ChatFragment.this)
|
||||
chatService.Database.getMessages(address, 15).foreach(adapter.add)
|
||||
chatService.database.getMessages(address, 15).foreach(adapter.add)
|
||||
|
||||
if (listView != null) {
|
||||
listView.setAdapter(adapter)
|
||||
|
@ -86,9 +84,8 @@ class ChatFragment extends ListFragment with OnClickListener
|
|||
override def onCreate(savedInstanceState: Bundle): Unit = {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
if (savedInstanceState != null)
|
||||
address = new Address(savedInstanceState.getByteArray("device"))
|
||||
}
|
||||
}
|
||||
|
||||
override def onSaveInstanceState(outState: Bundle): Unit = {
|
||||
|
|
|
@ -15,23 +15,23 @@ import com.nutomic.ensichat.util.UsersAdapter
|
|||
*/
|
||||
class ContactsFragment extends ListFragment {
|
||||
|
||||
private lazy val Adapter = new UsersAdapter(getActivity)
|
||||
private lazy val adapter = new UsersAdapter(getActivity)
|
||||
|
||||
private lazy val Database = getActivity.asInstanceOf[EnsiChatActivity].service.Database
|
||||
private lazy val database = getActivity.asInstanceOf[EnsiChatActivity].service.database
|
||||
|
||||
override def onCreate(savedInstanceState: Bundle): Unit = {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setListAdapter(Adapter)
|
||||
setListAdapter(adapter)
|
||||
setHasOptionsMenu(true)
|
||||
|
||||
getActivity.asInstanceOf[EnsiChatActivity].runOnServiceConnected(() => {
|
||||
Database.getContacts.foreach(Adapter.add)
|
||||
Database.runOnContactsUpdated(() => {
|
||||
database.getContacts.foreach(adapter.add)
|
||||
database.runOnContactsUpdated(() => {
|
||||
getActivity.runOnUiThread(new Runnable {
|
||||
override def run(): Unit = {
|
||||
Adapter.clear()
|
||||
Database.getContacts.foreach(Adapter.add)
|
||||
adapter.clear()
|
||||
database.getContacts.foreach(adapter.add)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -47,27 +47,25 @@ class ContactsFragment extends ListFragment {
|
|||
inflater.inflate(R.menu.main, menu)
|
||||
}
|
||||
|
||||
override def onOptionsItemSelected(item: MenuItem): Boolean = {
|
||||
item.getItemId match {
|
||||
case R.id.add_contact =>
|
||||
startActivity(new Intent(getActivity, classOf[AddContactsActivity]))
|
||||
true
|
||||
case R.id.settings =>
|
||||
startActivity(new Intent(getActivity, classOf[SettingsActivity]))
|
||||
true
|
||||
case R.id.exit =>
|
||||
getActivity.stopService(new Intent(getActivity, classOf[ChatService]))
|
||||
getActivity.finish()
|
||||
true
|
||||
case _ =>
|
||||
super.onOptionsItemSelected(item)
|
||||
}
|
||||
override def onOptionsItemSelected(item: MenuItem): Boolean = item.getItemId match {
|
||||
case R.id.add_contact =>
|
||||
startActivity(new Intent(getActivity, classOf[AddContactsActivity]))
|
||||
true
|
||||
case R.id.settings =>
|
||||
startActivity(new Intent(getActivity, classOf[SettingsActivity]))
|
||||
true
|
||||
case R.id.exit =>
|
||||
getActivity.stopService(new Intent(getActivity, classOf[ChatService]))
|
||||
getActivity.finish()
|
||||
true
|
||||
case _ =>
|
||||
super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a chat with the clicked device.
|
||||
*/
|
||||
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)
|
||||
|
||||
}
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
package com.nutomic.ensichat.fragments
|
||||
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.preference.Preference.OnPreferenceChangeListener
|
||||
import android.preference.{PreferenceManager, Preference, PreferenceFragment}
|
||||
import android.util.Log
|
||||
import android.preference.{Preference, PreferenceFragment, PreferenceManager}
|
||||
import com.nutomic.ensichat.R
|
||||
import com.nutomic.ensichat.activities.EnsiChatActivity
|
||||
import com.nutomic.ensichat.protocol.Address
|
||||
import com.nutomic.ensichat.protocol.messages.UserName
|
||||
import com.nutomic.ensichat.fragments.SettingsFragment._
|
||||
import com.nutomic.ensichat.protocol.messages.UserName
|
||||
|
||||
object SettingsFragment {
|
||||
|
||||
|
@ -28,9 +25,9 @@ class SettingsFragment extends PreferenceFragment with OnPreferenceChangeListene
|
|||
super.onCreate(savedInstanceState)
|
||||
|
||||
addPreferencesFromResource(R.xml.settings)
|
||||
val name = findPreference(KeyUserName)
|
||||
name.setOnPreferenceChangeListener(this)
|
||||
val name = findPreference(KeyUserName)
|
||||
val scanInterval = findPreference(KeyScanInterval)
|
||||
name.setOnPreferenceChangeListener(this)
|
||||
scanInterval.setOnPreferenceChangeListener(this)
|
||||
|
||||
val pm = PreferenceManager.getDefaultSharedPreferences(getActivity)
|
||||
|
@ -44,7 +41,7 @@ class SettingsFragment extends PreferenceFragment with OnPreferenceChangeListene
|
|||
override def onPreferenceChange(preference: Preference, newValue: AnyRef): Boolean = {
|
||||
if (preference.getKey == KeyUserName) {
|
||||
val service = getActivity.asInstanceOf[EnsiChatActivity].service
|
||||
service.Database.getContacts
|
||||
service.database.getContacts
|
||||
.foreach(c => service.sendTo(c.Address, new UserName(newValue.toString)))
|
||||
}
|
||||
preference.setSummary(newValue.toString)
|
||||
|
|
|
@ -51,11 +51,11 @@ class ChatService extends Service {
|
|||
|
||||
private val Tag = "ChatService"
|
||||
|
||||
lazy val Database = new Database(this)
|
||||
lazy val database = new Database(this)
|
||||
|
||||
val MainHandler = new Handler()
|
||||
|
||||
private lazy val Binder = new ChatServiceBinder(this)
|
||||
private lazy val binder = new ChatServiceBinder(this)
|
||||
|
||||
private lazy val crypto = new Crypto(this)
|
||||
|
||||
|
@ -90,7 +90,7 @@ class ChatService extends Service {
|
|||
pm.edit().putString(SettingsFragment.KeyUserName,
|
||||
BluetoothAdapter.getDefaultAdapter.getName).apply()
|
||||
|
||||
registerMessageListener(Database)
|
||||
registerMessageListener(database)
|
||||
|
||||
Future {
|
||||
crypto.generateLocalKeys()
|
||||
|
@ -106,7 +106,7 @@ class ChatService extends Service {
|
|||
|
||||
override def onStartCommand(intent: Intent, flags: Int, startId: Int) = Service.START_STICKY
|
||||
|
||||
override def onBind(intent: Intent) = Binder
|
||||
override def onBind(intent: Intent) = binder
|
||||
|
||||
/**
|
||||
* Registers a listener that is called whenever a new message is sent or received.
|
||||
|
@ -130,7 +130,7 @@ class ChatService extends Service {
|
|||
if (!bluetoothInterface.getConnections.contains(target))
|
||||
return
|
||||
|
||||
val header = new MessageHeader(body.Type, MessageHeader.DefaultHopLimit,
|
||||
val header = new MessageHeader(body.messageType, MessageHeader.DefaultHopLimit,
|
||||
Crypto.getLocalAddress(this), target, 0, 0)
|
||||
|
||||
val msg = new Message(header, body)
|
||||
|
@ -158,8 +158,8 @@ class ChatService extends Service {
|
|||
case name: UserName =>
|
||||
val contact = new User(msg.Header.Origin, name.Name)
|
||||
connections += contact
|
||||
if (Database.getContact(msg.Header.Origin).nonEmpty)
|
||||
Database.changeContactName(contact)
|
||||
if (database.getContact(msg.Header.Origin).nonEmpty)
|
||||
database.changeContactName(contact)
|
||||
|
||||
callConnectionListeners()
|
||||
case _: RequestAddContact =>
|
||||
|
@ -242,7 +242,7 @@ class ChatService extends Service {
|
|||
*/
|
||||
def getConnections: Set[User] = {
|
||||
bluetoothInterface.getConnections.map{ address =>
|
||||
(Database.getContacts ++ connections).find(_.Address == address) match {
|
||||
(database.getContacts ++ connections).find(_.Address == address) match {
|
||||
case Some(contact) => contact
|
||||
case None => new User(address, address.toString)
|
||||
}
|
||||
|
|
|
@ -2,8 +2,4 @@ package com.nutomic.ensichat.protocol
|
|||
|
||||
import android.os.Binder
|
||||
|
||||
class ChatServiceBinder (service: ChatService) extends Binder {
|
||||
|
||||
def getService = service
|
||||
|
||||
}
|
||||
case class ChatServiceBinder (Service: ChatService) extends Binder
|
||||
|
|
|
@ -33,7 +33,7 @@ object ConnectionInfo {
|
|||
*/
|
||||
case class ConnectionInfo(key: PublicKey) extends MessageBody {
|
||||
|
||||
override def Type = ConnectionInfo.Type
|
||||
override def messageType = ConnectionInfo.Type
|
||||
|
||||
override def write: Array[Byte] = {
|
||||
val b = ByteBuffer.allocate(length)
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package com.nutomic.ensichat.protocol.messages
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.Arrays
|
||||
import java.util
|
||||
|
||||
import android.util.Log
|
||||
import com.nutomic.ensichat.protocol.BufferUtils
|
||||
|
||||
object CryptoData {
|
||||
|
@ -40,8 +39,8 @@ object CryptoData {
|
|||
case class CryptoData(Signature: Option[Array[Byte]], Key: Option[Array[Byte]]) {
|
||||
|
||||
override def equals(a: Any): Boolean = a match {
|
||||
case o: CryptoData =>
|
||||
Arrays.equals(Signature.orNull, o.Signature.orNull) && Arrays.equals(Key.orNull, o.Key.orNull)
|
||||
case o: CryptoData => util.Arrays.equals(Signature.orNull, o.Signature.orNull) &&
|
||||
util.Arrays.equals(Key.orNull, o.Key.orNull)
|
||||
case _ => false
|
||||
}
|
||||
|
||||
|
@ -61,4 +60,4 @@ case class CryptoData(Signature: Option[Array[Byte]], Key: Option[Array[Byte]])
|
|||
|
||||
private def keyLength = if (Key.isDefined) Key.get.length else 0
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ package com.nutomic.ensichat.protocol.messages
|
|||
*/
|
||||
case class EncryptedBody(Data: Array[Byte]) extends MessageBody {
|
||||
|
||||
override def Type = -1
|
||||
override def messageType = -1
|
||||
|
||||
def write = Data
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ package com.nutomic.ensichat.protocol.messages
|
|||
*/
|
||||
abstract class MessageBody {
|
||||
|
||||
def Type: Int
|
||||
def messageType: Int
|
||||
|
||||
/**
|
||||
* Writes the message contents to a byte array.
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.nutomic.ensichat.protocol.messages
|
||||
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.Date
|
||||
|
||||
import com.nutomic.ensichat.protocol.{Address, BufferUtils}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ object RequestAddContact {
|
|||
*/
|
||||
case class RequestAddContact() extends MessageBody {
|
||||
|
||||
override def Type = RequestAddContact.Type
|
||||
override def messageType = RequestAddContact.Type
|
||||
|
||||
override def write: Array[Byte] = {
|
||||
val b = ByteBuffer.allocate(length)
|
||||
|
|
|
@ -25,7 +25,7 @@ object ResultAddContact {
|
|||
*/
|
||||
case class ResultAddContact(Accepted: Boolean) extends MessageBody {
|
||||
|
||||
override def Type = ResultAddContact.Type
|
||||
override def messageType = ResultAddContact.Type
|
||||
|
||||
override def write: Array[Byte] = {
|
||||
val b = ByteBuffer.allocate(length)
|
||||
|
|
|
@ -28,7 +28,7 @@ object Text {
|
|||
*/
|
||||
case class Text(text: String, time: Date = new Date()) extends MessageBody {
|
||||
|
||||
override def Type = Text.Type
|
||||
override def messageType = Text.Type
|
||||
|
||||
override def write: Array[Byte] = {
|
||||
val b = ByteBuffer.allocate(length)
|
||||
|
|
|
@ -26,8 +26,7 @@ object UserName {
|
|||
*/
|
||||
case class UserName(Name: String) extends MessageBody {
|
||||
|
||||
override def Type = UserName.Type
|
||||
|
||||
override def messageType = UserName.Type
|
||||
|
||||
override def write: Array[Byte] = {
|
||||
val b = ByteBuffer.allocate(length)
|
||||
|
@ -39,4 +38,4 @@ case class UserName(Name: String) extends MessageBody {
|
|||
|
||||
override def length = 4 + Name.getBytes(Message.Charset).length
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.util.Date
|
|||
|
||||
import android.content.{ContentValues, Context}
|
||||
import android.database.sqlite.{SQLiteDatabase, SQLiteOpenHelper}
|
||||
import android.util.Log
|
||||
import com.nutomic.ensichat.protocol.ChatService.OnMessageReceivedListener
|
||||
import com.nutomic.ensichat.protocol._
|
||||
import com.nutomic.ensichat.protocol.messages._
|
||||
|
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import android.view.{View, ViewGroup}
|
||||
import android.widget.{ArrayAdapter, TextView}
|
||||
import com.nutomic.ensichat.bluetooth.Device
|
||||
import com.nutomic.ensichat.protocol.{User, Address}
|
||||
import com.nutomic.ensichat.protocol.User
|
||||
|
||||
/**
|
||||
* Displays [[Device]]s in ListView.
|
||||
|
|
Reference in a new issue