Added EnsiChatActivity to avoid code duplication for service connection.
This commit is contained in:
parent
3da35725d4
commit
7af368ce31
4 changed files with 88 additions and 47 deletions
|
@ -0,0 +1,65 @@
|
||||||
|
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.bluetooth.{ChatService, ChatServiceBinder}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to [[ChatService]] and provides access to it.
|
||||||
|
*/
|
||||||
|
class EnsiChatActivity extends Activity with ServiceConnection {
|
||||||
|
|
||||||
|
var chatService: Option[ChatService] = None
|
||||||
|
|
||||||
|
var listeners: List[() => Unit] = List.empty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts service and connects to it.
|
||||||
|
*/
|
||||||
|
override def onCreate(savedInstanceState: Bundle): Unit = {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
startService(new Intent(this, classOf[ChatService]))
|
||||||
|
bindService(new Intent(this, classOf[ChatService]), this, Context.BIND_AUTO_CREATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbinds service.
|
||||||
|
*/
|
||||||
|
override def onDestroy(): Unit = {
|
||||||
|
super.onDestroy()
|
||||||
|
unbindService(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls all listeners registered with [[runOnServiceConnected]].
|
||||||
|
*
|
||||||
|
* Clears the list containing them.
|
||||||
|
*/
|
||||||
|
override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
|
||||||
|
val binder = iBinder.asInstanceOf[ChatServiceBinder]
|
||||||
|
chatService = Option(binder.getService)
|
||||||
|
listeners.foreach(_())
|
||||||
|
listeners = List.empty
|
||||||
|
}
|
||||||
|
|
||||||
|
override def onServiceDisconnected(componentName: ComponentName) =
|
||||||
|
chatService = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls l as soon as [[ChatService]] first becomes available.
|
||||||
|
*/
|
||||||
|
def runOnServiceConnected(l: () => Unit): Unit =
|
||||||
|
chatService match {
|
||||||
|
case Some(s) => l()
|
||||||
|
case None => listeners :+= l
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the [[ChatService]].
|
||||||
|
*
|
||||||
|
* Should only be called after [[runOnServiceConnected]] callback was called.
|
||||||
|
*/
|
||||||
|
def service = chatService.get
|
||||||
|
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import com.nutomic.ensichat.fragments.{ChatFragment, ContactsFragment}
|
||||||
/**
|
/**
|
||||||
* Main activity, entry point for app start.
|
* Main activity, entry point for app start.
|
||||||
*/
|
*/
|
||||||
class MainActivity extends Activity {
|
class MainActivity extends EnsiChatActivity {
|
||||||
|
|
||||||
private val RequestSetDiscoverable = 1
|
private val RequestSetDiscoverable = 1
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ class MainActivity extends Activity {
|
||||||
override def onCreate(savedInstanceState: Bundle): Unit = {
|
override def onCreate(savedInstanceState: Bundle): Unit = {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
startService(new Intent(this, classOf[ChatService]))
|
|
||||||
|
|
||||||
val intent: Intent = new
|
val intent: Intent = new
|
||||||
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)
|
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.view.{KeyEvent, LayoutInflater, View, ViewGroup}
|
||||||
import android.widget.TextView.OnEditorActionListener
|
import android.widget.TextView.OnEditorActionListener
|
||||||
import android.widget._
|
import android.widget._
|
||||||
import com.nutomic.ensichat.R
|
import com.nutomic.ensichat.R
|
||||||
|
import com.nutomic.ensichat.activities.EnsiChatActivity
|
||||||
import com.nutomic.ensichat.bluetooth.ChatService.OnMessageReceivedListener
|
import com.nutomic.ensichat.bluetooth.ChatService.OnMessageReceivedListener
|
||||||
import com.nutomic.ensichat.bluetooth.{ChatService, ChatServiceBinder, Device}
|
import com.nutomic.ensichat.bluetooth.{ChatService, ChatServiceBinder, Device}
|
||||||
import com.nutomic.ensichat.messages.{Message, TextMessage}
|
import com.nutomic.ensichat.messages.{Message, TextMessage}
|
||||||
|
@ -41,21 +42,21 @@ class ChatFragment extends ListFragment with OnClickListener
|
||||||
|
|
||||||
private var adapter: ArrayAdapter[TextMessage] = _
|
private var adapter: ArrayAdapter[TextMessage] = _
|
||||||
|
|
||||||
private final val mChatServiceConnection: ServiceConnection = new ServiceConnection {
|
override def onActivityCreated(savedInstanceState: Bundle): Unit = {
|
||||||
override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
|
super.onActivityCreated(savedInstanceState)
|
||||||
val binder: ChatServiceBinder = iBinder.asInstanceOf[ChatServiceBinder]
|
|
||||||
chatService = binder.getService
|
val activity = getActivity.asInstanceOf[EnsiChatActivity]
|
||||||
|
activity.runOnServiceConnected(() => {
|
||||||
|
chatService = activity.service
|
||||||
|
|
||||||
// Read local device ID from service,
|
// Read local device ID from service,
|
||||||
adapter = new MessagesAdapter(getActivity, chatService.localDeviceId)
|
adapter = new MessagesAdapter(getActivity, chatService.localDeviceId)
|
||||||
chatService.registerMessageListener(device, ChatFragment.this)
|
chatService.registerMessageListener(device, ChatFragment.this)
|
||||||
|
|
||||||
if (listView != null) {
|
if (listView != null) {
|
||||||
listView.setAdapter(adapter)
|
listView.setAdapter(adapter)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
override def onServiceDisconnected(componentName: ComponentName): Unit = {
|
|
||||||
chatService = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onCreateView(inflater: LayoutInflater, container: ViewGroup,
|
override def onCreateView(inflater: LayoutInflater, container: ViewGroup,
|
||||||
|
@ -81,9 +82,6 @@ class ChatFragment extends ListFragment with OnClickListener
|
||||||
override def onCreate(savedInstanceState: Bundle): Unit = {
|
override def onCreate(savedInstanceState: Bundle): Unit = {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
getActivity.bindService(new Intent(getActivity, classOf[ChatService]),
|
|
||||||
mChatServiceConnection, Context.BIND_AUTO_CREATE)
|
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
device = new Device.ID(savedInstanceState.getString("device"))
|
device = new Device.ID(savedInstanceState.getString("device"))
|
||||||
}
|
}
|
||||||
|
@ -94,11 +92,6 @@ class ChatFragment extends ListFragment with OnClickListener
|
||||||
outState.putString("device", device.toString)
|
outState.putString("device", device.toString)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onDestroy(): Unit = {
|
|
||||||
super.onDestroy()
|
|
||||||
getActivity.unbindService(mChatServiceConnection)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send message if send button was clicked.
|
* Send message if send button was clicked.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -6,52 +6,37 @@ import android.os.{Bundle, IBinder}
|
||||||
import android.view._
|
import android.view._
|
||||||
import android.widget.{ArrayAdapter, ListView}
|
import android.widget.{ArrayAdapter, ListView}
|
||||||
import com.nutomic.ensichat.R
|
import com.nutomic.ensichat.R
|
||||||
import com.nutomic.ensichat.activities.MainActivity
|
import com.nutomic.ensichat.activities.{EnsiChatActivity, MainActivity}
|
||||||
import com.nutomic.ensichat.bluetooth.{ChatService, ChatServiceBinder, Device}
|
import com.nutomic.ensichat.bluetooth.{ChatService, ChatServiceBinder, Device}
|
||||||
import com.nutomic.ensichat.util.DevicesAdapter
|
import com.nutomic.ensichat.util.{MessagesAdapter, DevicesAdapter}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists all nearby, connected devices.
|
* Lists all nearby, connected devices.
|
||||||
*/
|
*/
|
||||||
class ContactsFragment extends ListFragment with ChatService.OnConnectionChangedListener {
|
class ContactsFragment extends ListFragment with ChatService.OnConnectionChangedListener {
|
||||||
|
|
||||||
private var chatService: ChatService = _
|
private lazy val adapter = new DevicesAdapter(getActivity)
|
||||||
|
|
||||||
private final val ChatServiceConnection: ServiceConnection = new ServiceConnection {
|
override def onActivityCreated(savedInstanceState: Bundle): Unit = {
|
||||||
override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
|
super.onActivityCreated(savedInstanceState)
|
||||||
val binder: ChatServiceBinder = iBinder.asInstanceOf[ChatServiceBinder]
|
|
||||||
chatService = binder.getService
|
|
||||||
chatService.registerConnectionListener(ContactsFragment.this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onServiceDisconnected(componentName: ComponentName): Unit = {
|
val activity = getActivity.asInstanceOf[EnsiChatActivity]
|
||||||
chatService = null
|
activity.runOnServiceConnected(() => {
|
||||||
|
activity.service.registerConnectionListener(ContactsFragment.this)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private var adapter: ArrayAdapter[Device] = _
|
|
||||||
|
|
||||||
override def onCreateView(inflater: LayoutInflater, container: ViewGroup,
|
override def onCreateView(inflater: LayoutInflater, container: ViewGroup,
|
||||||
savedInstanceState: Bundle): View = {
|
savedInstanceState: Bundle): View =
|
||||||
val view: View = inflater.inflate(R.layout.fragment_contacts, container, false)
|
inflater.inflate(R.layout.fragment_contacts, container, false)
|
||||||
view
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onCreate(savedInstanceState: Bundle): Unit = {
|
override def onCreate(savedInstanceState: Bundle): Unit = {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
adapter = new DevicesAdapter(getActivity)
|
|
||||||
setListAdapter(adapter)
|
setListAdapter(adapter)
|
||||||
getActivity.bindService(new Intent(getActivity, classOf[ChatService]),
|
|
||||||
ChatServiceConnection, Context.BIND_AUTO_CREATE)
|
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onDestroy(): Unit = {
|
|
||||||
super.onDestroy()
|
|
||||||
getActivity.unbindService(ChatServiceConnection)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onCreateOptionsMenu(menu: Menu, inflater: MenuInflater): Unit = {
|
override def onCreateOptionsMenu(menu: Menu, inflater: MenuInflater): Unit = {
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
inflater.inflate(R.menu.main, menu)
|
inflater.inflate(R.menu.main, menu)
|
||||||
|
@ -87,8 +72,7 @@ class ContactsFragment extends ListFragment with ChatService.OnConnectionChanged
|
||||||
/**
|
/**
|
||||||
* 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).id)
|
getActivity.asInstanceOf[MainActivity].openChat(adapter.getItem(position).id)
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue