Bluetooth LE (Low power bluetooth®)-Part Two

Source: Internet
Author: User

Review

In the previous article we introduced the background of Bluetooth Le and explained what we will be developing in this series of articles, but there is no actual code. We will correct this in this article, and we will ensure that the Bluetooth operation is decoupled from the UI by defining the Service/activity architecture.

Service and Activity Communication

Before we go on, I should point out that we are not going to explore the details of ble in this article. At first, we were going to create an activity and bind the service, which would allow us to decouple all Bluetooth operations from the UI, while allowing us to update the UI after receiving the data from BLE.

To do this, we'll use Messenger mode. It enables us to communicate between two components without any direct method call. The messenger pattern requires each component to implement its own Messenger implementation: When an instance of the class is created, the incoming message object is processed. The implementation of the activity and service will run on the UI thread, but we will make sure that they are transparent to each other on their method calls.

Make our code easier to understand and maintain by implementing their respective Messenger implementations and logical processing in the appropriate places.

public class Bleservice extends Service {public static final String TAG = "Bleservice";    static final int msg_register = 1;    static final int msg_unregister = 2;    Private final Messenger Mmessenger;    Private final list<messenger> mclients = new linkedlist<messenger> ();    Public Bleservice () {Mmessenger = new Messenger (new Incominghandler (this));    } @Override Public IBinder onbind (Intent Intent) {return mmessenger.getbinder ();         } private static Class Incominghandler extends Handler {private final weakreference<bleservice> mservice;        Public Incominghandler (Bleservice service) {mservice = new weakreference<bleservice> (service);            } @Override public void Handlemessage (Message msg) {Bleservice service = Mservice.get ();                        if (service! = NULL) {switch (msg.what) {case Msg_register: SerVice.mClients.add (Msg.replyto);                        LOG.D (TAG, "registered");                    Break                        Case MSG_UNREGISTER:service.mClients.remove (Msg.replyto);                        LOG.D (TAG, "unegistered");                    Break                Default:super.handleMessage (msg); }            }        }    }}

The basic code is very simple, but there are still some nuances worth explaining.

First, Innerhandler is declared static. Do not attempt to implement this with a non-static inner class, otherwise it will leak memory (leaking memories), which can be very serious. This is because a non-static inner class of a class can hold an instance of the class and have direct access to its member variables and methods. Simply put, the Java garbage collector will not break objects referenced by other objects (which is actually a little more complicated than that, but enough to explain what happened). The parent class instance of the handler is a service object (an Android Context), so if any object holds a reference to the handler instance, it will implicitly prevent the service object from being garbage collected. This is called a "context leak (contextual leak)". It's also a very bad thing, because the context can be quite large.

(Translator Note: For more information about "Context Leak" see http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html)

The way we avoid context leaks is to always declare internal classes as static, if they is declared within classes which subclass context (I don't know how to translate). This also means that we have lost one of the main advantages of using an inner class: the ability to access the parent class property and the (or or) method. But we can easily overcome this by using weakreference (weak references). A weak reference allows us to maintain a reference to an object and does not prevent it from being reclaimed by the garbage collection mechanism.

So our Innerhandler class is constructed to have a reference to an instance of its parent class wrapped in a WeakReference object. Instead of directly owning a reference to its parent class. This way Innerhandler can call WeakReference's get () method to get a reference to its parent class instance. We need to make a null judgment because the instance of the parent class will be empty if it is garbage collected, but if it is not empty, then we can use that instance's reference in exactly the same way as a non-static inner class.

Another thing worth mentioning is that we currently have two types of messages: registration and de-registration. This allows multiple users to subscribe to the information sent by the service (the service will get updated information from our BLE device). In our sample application only activity will get updated information from the service, but in the real world the application may have more data needed for the component, so the Publish/subscribe model is appropriate.

Our activity:

public class Bleactivity extends Activity {public static final String TAG = "Bluetoothle";    Private final Messenger Mmessenger;    Private Intent mserviceintent;    Private Messenger mservice = null; Private Serviceconnection mconnection = new Serviceconnection () {@Override public void Onservicecon            nected (componentname name, IBinder service) {mservice = new Messenger (service);                try {Message msg = Message.obtain (null, bleservice.msg_register);                    if (msg! = null) {Msg.replyto = Mmessenger;                Mservice.send (msg);                } else {mservice = null;                }} catch (Exception e) {LOG.W (TAG, "Error Connecting to Bleservice", e);            Mservice = null;     }} @Override public void onservicedisconnected (componentname name) {       Mservice = null;    }    };        Public bleactivity () {super ();    Mmessenger = new Messenger (new Incominghandler (this));        } @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);        Setcontentview (r.layout.activity_ble);    Mserviceintent = new Intent (this, bleservice.class); } @Override protected void OnStop () {if (mservice! = null) {try {Message msg = M                Essage.obtain (null, bleservice.msg_unregister);                    if (msg! = null) {Msg.replyto = Mmessenger;                Mservice.send (msg);                     }} catch (Exception e) {LOG.W (TAG, "Error unregistering with Bleservice",                e);            Mservice = null;            } finally {Unbindservice (mconnection);    }} super.onstop ();  } @Override  protected void OnStart () {Super.onstart ();    Bindservice (Mserviceintent, mconnection, bind_auto_create); } private static Class Incominghandler extends Handler {private final weakreference<bleactivity> Mactivit        Y Public Incominghandler (bleactivity activity) {mactivity = new weakreference<bleactivity>        (activity);            } @Override public void Handlemessage (Message msg) {bleactivity activity = mactivity.get ();        if (activity! = null) {//todo:do something} super.handlemessage (msg); }    }}

Bind and unbind the service in the OnStart () and OnStop () methods of the activity. In the Serviceconnection method (callback when the service binding and unbind operation is complete), Activity's Messenger implements registration and anti-registration by sending the appropriate message to service Messenger.

After that we need to add the appropriate declaration in manifest (I did not show it here, but I can see it in the source code). We have a simple activity and service pairing that they can communicate with each other. If we run this app, it doesn't do anything, but it shows the registration/logoff work we expect in Logcat:

Com.stylingandroid.ble d/bleservice:registeredcom.stylingandroid.ble d/bleservice:unegistered

So now we have the framework of an app that allows us to collect data from the service and update our UI.

Next stage Notice

Sorry, we're out of the box that didn't contain the code last week, although this week's article contains code that is not very relevant to the topic of this series of articles (Bluetooth LE). But it's a good start to learn about BLE, and the next article will begin to combine ble with our discoveries.

The source code for this article can be found here.

Bluetooth LE (Low power bluetooth®)-Part Two

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.