Hacking into Android's Bluetooth support

Tutorials with advanced 'difficulty' and more Lines of Code.

Hacking into Android's Bluetooth support

Postby paller » Tue Jan 29, 2008 11:57 pm

Hacking into Android's Bluetooth support


Click here for the cross-referenced version of this entry

I have been mentioning that wicked Bluetooth service for two posts but eventually something else was more interesting. Well, finding something more interesting was easy because it turned out pretty soon that the Bluetooth support in m3-rc37a version of the emulator is half-ready at best. I cannot be sure but it seems that the hcid daemon on which Android's Bluez port is based is completely missing or at least is not launched properly along with other system services.

Is there a point then to deal with Bluetooth given the current state of the emulator? IMHO, yes, because when the shiny new version of the emulator comes out, applications will be ready to run. At the present state of affairs this approach means that we have to live with a bit (lot!) of hacking.

For the moment, I was interested in the discovery process. Discovery in the present implementation does not work but that did not prevent me simulating it. By taking apart org.bluez.IBluetoothService and android.server.BluetoothService classes with the jad tool, it quickly became evident that the discovery process is based on 4 intent messages.

* org.bluez.intent.action.DISCOVERY_STARTED - delivered when the discovery process starts.
* org.bluez.intent.action.REMOTE_DEVICE_FOUND - delivered when one device is discovered. It has 3 parameters in the Intent's Bundle: "address" (String) is the Bluetooth address of the device, "class" (Integer) is the class of the Bluetooth device and "rssi" (Short) is the Received Signal Strength Indicator.
* org.bluez.intent.action.REMOTE_NAME_UPDATED - delivered when the user-friendly name of one device is discovered. This message follows an earlier REMOTE_DEVICE_FOUND message and carries the user-friendly name ("name" (String)) along with the Bluetooth address ("address" (String)).
* org.bluez.intent.action.DISCOVERY_COMPLETED - delivered when the discovery process finishes.

You can download the example program from here.

The discovery simulator itself is an interesting piece of software because of some common Android programming tricks it employs. The discovery simulator is located in the BtDetectSimulatorService class that the main activity launches with a startService call (it is therefore the other type of service, not the one seen at the service invocation entry). Normally, the discovery would just be started with a method call on org.bluez.IBluetoothService but the implementation is not that ready. The service abuses the half-implemented Bluetooth classes (like the android.server.BluetoothService class, don't ever do what I did here!), starts the Bluetooth service and sends out intent messages. These intent messages are captured by an intent receiver (BtIntentReceiver) and are used to update the UI of the main activity.

Two small details are interesting here. The intent receiver and the main activity call each other like ordinary Java objects. The code exploits the fact that the main activity is a singleton and just connects the activity and the intent receiver instances by Java references. This is possible because these two entities are part of the same package, hence they run in the same VM instance. Here is the proof (619 is the PID of the VM process):

D/BTINTENTRECEIVER( 619): org.bluez.intent.action.DISCOVERY_STARTED
D/BTDETECT( 619): Action = org.bluez.intent.action.DISCOVERY_STARTED

The other interesting bit is the way BtDetectSimulatorService delivers the events. There is a delay among the intent broadcasts (Bluetooth discovery may be a lengthy process). This delay could not be coded with the good old Thread.sleep call in onStart method because onStart would have run too long and the Android application manager would kill the process. In addition, no broadcasts would be delivered until onStart ends which means that all the broadcasts would be delivered at once. Instead, observe how an android.os.Handler instance is used to schedule Runnable tasks after a certain delay.

And at last, the fun part. The image below shows, how Android's own Phone application crashes terribly when our application stops the Bluetooth service (it was us who started it, so we stop it nicely). That characterizes pretty much the readiness of the Bluetooth support in the current emulator.

Image
paller
Developer
Developer
 
Posts: 29
Joined: Mon Dec 31, 2007 2:33 am
Location: London

Top

Postby xayide » Fri Feb 15, 2008 10:58 am

Hello!

I have used your code and it´s very useful. I hoped that the new sdk had a good bluetooth support, but it seems that it isn´t so.

I have created a service, as you do in BTdetectSimulatorService. I just call it from my "main" page. I have implemented the onStart method, similar to yours.
I tryed to do that funcionality but using the sdk´s functions, but i have a problem to get the default adapter. It always returns null.

I put here the code, maybe someone can tell me what i am doing wrong.

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public void onStart(int startId, Bundle args){
  2.  
  3.                 super.onStart( startId, args );
  4.  
  5.                 try{
  6.  
  7.                
  8.  
  9.                 IBluetoothService ibtservice = BluetoothServiceNative.getBluetoothService();
  10.  
  11.                 if( ibtservice == null ) {                       
  12.  
  13.                           stopSelf();
  14.  
  15.                           return;
  16.  
  17.                         }
  18.  
  19.                
  20.  
  21.                 manager=ibtservice.getManager();
  22.  
  23.                         if( manager == null ) {                
  24.  
  25.                                 stopSelf();
  26.  
  27.                         }
  28.  
  29.            
  30.  
  31.                 if(! ibtservice.isBluetoothStarted()){
  32.  
  33.                                 ibtservice.startBluetooth();
  34.  
  35.                         //stopSelf();                          
  36.  
  37.                         }
  38.  
  39.                 miadapter=manager.getDefaultAdapter();
  40.  
  41.                 miadapter.startDiscovery();
  42.  
  43.                        
  44.  
  45.                 String[] dispositivos=miadapter.listRemoteDevices();
  46.  
  47.                
  48.  
  49.                 if (dispositivos.length==0){
  50.  
  51.                         //showAlert("Error","No devices found","ok",null,false,null);
  52.  
  53.                         Toast.makeText(this, R.string.no_devices, Toast.LENGTH_SHORT).show();
  54.  
  55.                 }else{
  56.  
  57.                         for (int i=0; i<dispositivos.length;i++){
  58.  
  59.                                    
  60.  
  61.                         }
  62.  
  63.                 }
  64.  
  65.                 }catch(Exception e){
  66.  
  67.                         System.out.println(e.getMessage());
  68.  
  69.                        
  70.  
  71.                 }
  72.  
  73.  
  74.  
  75.                
  76.  
  77.         }
Parsed in 0.034 seconds, using GeSHi 1.0.8.4


thank you very much!
xayide
Junior Developer
Junior Developer
 
Posts: 20
Joined: Tue Feb 05, 2008 1:23 pm

Postby paller » Fri Feb 15, 2008 11:54 am

xayide wrote:Hello!
I tryed to do that funcionality but using the sdk´s functions, but i have a problem to get the default adapter. It always returns null.
[/syntax]


You did everything well. :-) It is not by chance, however, that my Bluetooth hack does not call the getDefaultAdapter() method but goes on simulating the discovery process. That method does not work in m3-rc37a and it seems it does not work in m5-r14 either (although I have not tried it myself).
paller
Developer
Developer
 
Posts: 29
Joined: Mon Dec 31, 2007 2:33 am
Location: London

Postby xayide » Sat Feb 16, 2008 11:37 am

ok, thank you!

Just one question. I use your code to emulate the bluetooth. I want to send a file to every device found. How can I know using your code which are the devices found?. I´ve been looking for a way to have those devices returned, but I don´t know how to do this... I don´t know if you understand my question.
I push a button and connect to bluetooth, the discovery process starts and shows me the devices it has found. And how can I do know to send a file to every found device?

thank you very much again!
xayide
Junior Developer
Junior Developer
 
Posts: 20
Joined: Tue Feb 05, 2008 1:23 pm

Postby sjtcool » Wed Feb 20, 2008 8:19 am

The 2 web links are not available, who can help, thanks.
Best regards,
sjt.
----------------------------------
good good study,day day up
sjtcool
Junior Developer
Junior Developer
 
Posts: 11
Joined: Wed Dec 19, 2007 3:18 am
Location: Nanjing

Postby plusminus » Wed Feb 20, 2008 10:21 am

sjtcool wrote:The 2 web links are not available, who can help, thanks.

They work with me. That was perhaps a temporary server issue...

Regards,
plusminus
Image
Image | Android Development Community / Tutorials
User avatar
plusminus
Site Admin
Site Admin
 
Posts: 2688
Joined: Wed Nov 14, 2007 8:37 pm
Location: Schriesheim, Germany

Top

Postby ababaei2000 » Wed Feb 20, 2008 7:05 pm

Hi
thanks for your code,i have a question like Xayide,how can i send my data to every device that i found?and please learn how can i work with IR module(send and recieve data to any device that i found)
thank you
ababaei2000
Freshman
Freshman
 
Posts: 5
Joined: Tue Feb 12, 2008 9:19 am

Top

Return to Advanced Tutorials

Who is online

Users browsing this forum: No registered users and 6 guests