Added EnsiChatActivity to avoid code duplication for service connection.

This commit is contained in:
Felix Ableitner 2014-11-13 21:38:34 +02:00
parent 3da35725d4
commit 7af368ce31
4 changed files with 88 additions and 47 deletions

View File

@ -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
}

View File

@ -12,7 +12,7 @@ import com.nutomic.ensichat.fragments.{ChatFragment, ContactsFragment}
/**
* Main activity, entry point for app start.
*/
class MainActivity extends Activity {
class MainActivity extends EnsiChatActivity {
private val RequestSetDiscoverable = 1
@ -26,7 +26,6 @@ class MainActivity extends Activity {
override def onCreate(savedInstanceState: Bundle): Unit = {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
startService(new Intent(this, classOf[ChatService]))
val intent: Intent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)

View File

@ -11,6 +11,7 @@ import android.view.{KeyEvent, LayoutInflater, View, ViewGroup}
import android.widget.TextView.OnEditorActionListener
import android.widget._
import com.nutomic.ensichat.R
import com.nutomic.ensichat.activities.EnsiChatActivity
import com.nutomic.ensichat.bluetooth.ChatService.OnMessageReceivedListener
import com.nutomic.ensichat.bluetooth.{ChatService, ChatServiceBinder, Device}
import com.nutomic.ensichat.messages.{Message, TextMessage}
@ -41,21 +42,21 @@ class ChatFragment extends ListFragment with OnClickListener
private var adapter: ArrayAdapter[TextMessage] = _
private final val mChatServiceConnection: ServiceConnection = new ServiceConnection {
override def onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
val binder: ChatServiceBinder = iBinder.asInstanceOf[ChatServiceBinder]
chatService = binder.getService
override def onActivityCreated(savedInstanceState: Bundle): Unit = {
super.onActivityCreated(savedInstanceState)
val activity = getActivity.asInstanceOf[EnsiChatActivity]
activity.runOnServiceConnected(() => {
chatService = activity.service
// Read local device ID from service,
adapter = new MessagesAdapter(getActivity, chatService.localDeviceId)
chatService.registerMessageListener(device, ChatFragment.this)
if (listView != null) {
listView.setAdapter(adapter)
}
}
override def onServiceDisconnected(componentName: ComponentName): Unit = {
chatService = null
}
})
}
override def onCreateView(inflater: LayoutInflater, container: ViewGroup,
@ -81,9 +82,6 @@ class ChatFragment extends ListFragment with OnClickListener
override def onCreate(savedInstanceState: Bundle): Unit = {
super.onCreate(savedInstanceState)
getActivity.bindService(new Intent(getActivity, classOf[ChatService]),
mChatServiceConnection, Context.BIND_AUTO_CREATE)
if (savedInstanceState != null) {
device = new Device.ID(savedInstanceState.getString("device"))
}
@ -94,11 +92,6 @@ class ChatFragment extends ListFragment with OnClickListener
outState.putString("device", device.toString)
}
override def onDestroy(): Unit = {
super.onDestroy()
getActivity.unbindService(mChatServiceConnection)
}
/**
* Send message if send button was clicked.
*/

View File

@ -6,52 +6,37 @@ import android.os.{Bundle, IBinder}
import android.view._
import android.widget.{ArrayAdapter, ListView}
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.util.DevicesAdapter
import com.nutomic.ensichat.util.{MessagesAdapter, DevicesAdapter}
/**
* Lists all nearby, connected devices.
*/
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 onServiceConnected(componentName: ComponentName, iBinder: IBinder): Unit = {
val binder: ChatServiceBinder = iBinder.asInstanceOf[ChatServiceBinder]
chatService = binder.getService
chatService.registerConnectionListener(ContactsFragment.this)
}
override def onActivityCreated(savedInstanceState: Bundle): Unit = {
super.onActivityCreated(savedInstanceState)
override def onServiceDisconnected(componentName: ComponentName): Unit = {
chatService = null
}
val activity = getActivity.asInstanceOf[EnsiChatActivity]
activity.runOnServiceConnected(() => {
activity.service.registerConnectionListener(ContactsFragment.this)
})
}
private var adapter: ArrayAdapter[Device] = _
override def onCreateView(inflater: LayoutInflater, container: ViewGroup,
savedInstanceState: Bundle): View = {
val view: View = inflater.inflate(R.layout.fragment_contacts, container, false)
view
}
savedInstanceState: Bundle): View =
inflater.inflate(R.layout.fragment_contacts, container, false)
override def onCreate(savedInstanceState: Bundle): Unit = {
super.onCreate(savedInstanceState)
adapter = new DevicesAdapter(getActivity)
setListAdapter(adapter)
getActivity.bindService(new Intent(getActivity, classOf[ChatService]),
ChatServiceConnection, Context.BIND_AUTO_CREATE)
setHasOptionsMenu(true)
}
override def onDestroy(): Unit = {
super.onDestroy()
getActivity.unbindService(ChatServiceConnection)
}
override def onCreateOptionsMenu(menu: Menu, inflater: MenuInflater): Unit = {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.main, menu)
@ -87,8 +72,7 @@ class ContactsFragment extends ListFragment with ChatService.OnConnectionChanged
/**
* 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)
}
}