5

I have device which sends data via Bluetooth using OBEX Object Push Profile (OPP).

Using adb logcat i see that my android device receives a connection (but abort this connection?)

08-22 11:14:37.939: I/BtOppRfcommListener(22586): Accepted connectoin from 00:07:CF:5F:52:A0
08-22 11:14:37.939: I/BtOpp Service(22586): Start Obex Server
08-22 11:14:38.109: D/Obex ServerSession(22586): java.io.IOException: Software caused connection abort
08-22 11:14:38.109: D/PowerManagerService(180): @PowerManagement: 'BtOppObexServer' releaseWakeLock when screen locked
08-22 11:14:39.219: D/BluetoothEventLoop(180): Device property changed: 00:07:CF:5F:52:A0 property: Connected value: false

When I install Bluetooth File Transfer (Free application from market) then i'm able to receive files. But I wouldn't like to install other application.

David O'Meara
  • 2,983
  • 25
  • 38
wwawrzy
  • 95
  • 2
  • 7
  • Could you post the code in question so the android experts on SO can have a look at the issue? – Tanzeel Kazi Jan 03 '13 at 06:58
  • Does this help? http://stackoverflow.com/questions/3625959/android-rfcomm-with-obex-push-not-working – domsom Jan 08 '13 at 16:35
  • @domsom I had already tried similar code without success. IMO the problem appears to be that the native Bluetooth is still accepting the incoming OPP data and custom code does not get triggered. Hence the solution would involve not just listening for incoming connections but also to 'register' with the native Bluetooth so that the custom OPP handler is called. – David O'Meara Jan 09 '13 at 03:49
  • @DavidO'Meara I agree: If the listening Bluetooth socket/channel is bound to the system service, you can't re-register it to your own code (it can only bind once, and you can't kill a system service from your unrooted app). As far as I know (but haven't searched actually) you can't register to "incoming OBEX transfer" events with the system service either. That's why the guy in the link came up with the workaround which works for his specific scenario (namely knowing the remote device). – domsom Jan 09 '13 at 08:14

1 Answers1

2

I believe I have (at least a partial) solution which should then allow files to be intercepted via OPP and custom code added. The first step is to go to settings > apps > running > Bluetooth Share and kill the BluetoothOppService

Then I used reflection to access a method on BluetoothAdapter (code below) which allows listening on a specific port. After which we can intercept the incoming OPP communication and interact with the input and output streams. This SO thread will help with the OPP communication part, but as an initial step I read the data stream and reponded with an OPP 'OK' message ie os.writeByte(ObexSession.OBEX_SUCCESS | ObexSession.OBEX_FINAL_BIT);

// simplified exception handling
public class BluetoothAdapterProxy
{
    public static final int CHANNEL_OPP = 12;

    final BluetoothAdapter target;
    static final Class<?> targetClass = BluetoothAdapter.class;
    Method listenOn;

    public BluetoothAdapterProxy(BluetoothAdapter target)
    {
        this.target = target;
        Class<?>[] args = new Class[] { int.class };
        try
        {
            this.listenOn = targetClass.getDeclaredMethod(
                "listenUsingRfcommOn", args);
        }
        catch (NoSuchMethodException e)
        {
            e.printStackTrace();
        }
    }

    public BluetoothServerSocket listenUsingRfcommOn(int channel)
    {
        try
        {
            return (BluetoothServerSocket) (listenOn.invoke(target, 
                new Object[] { channel }));
        }
        catch (Exception e)
        {
            // complain loud, complain long
            throw new RuntimeException(ex);
        }
    }
}

Usage: initialise using

serverSocket = new BluetoothAdapterProxy(BluetoothAdapter.getDefaultAdapter())
    .listenUsingRfcommOn(BluetoothAdapterProxy.CHANNEL_OPP);

After which, use the following from a separate Thread (to prevent blocking) and remote devices can connect via socket = serverSocket.accept();

Community
  • 1
  • 1
David O'Meara
  • 2,983
  • 25
  • 38
  • I don't see why you need a wrapper class for this, but anyway: You might be able to use the public `BluetoothDevice.listenUsingRfcommWithServiceRecord()` method using the OPP UUID `00001105-0000-1000-8000-00805f9b34fb`. The key to your issue probably is that another (system) service is already listening on the OBEX channel. So either you can live with the "kill" solution you stated, or you use the system service and monitor it like here: http://stackoverflow.com/questions/3625959/android-rfcomm-with-obex-push-not-working – domsom Jan 08 '13 at 16:46
  • the wrapper class is used to access a method from the 'hidden android api', code which is visible at runtime but excluded from the published API and android.jar. I have large amounts of test code probing the published API - listening is not a problem however none of the trials have enabled custom code to respond to external OPP data. – David O'Meara Jan 09 '13 at 03:31
  • I should also mention that the sample code posted is not a full solution, as I have found that it still behaves differently on different devices. It is able to receive data via OPP on my HTC One X, but behaves differently and not entirely successfully on the Samsung Nexus S and Galaxy Tab 2. – David O'Meara Jan 09 '13 at 03:33
  • What do you mean with "not entirely successful"? Did you take a look at the stock Bluetooth OPP sources (e.g. http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/2.3.7_r1/com/android/bluetooth/opp/BluetoothOppTransfer.java)? – domsom Jan 09 '13 at 08:23
  • @domsom ignore that, I did more testing yesterday and it appears that the inconsistency in the above solution was caused by older firmware on the remote device. After updating the firmware I was able to verify that the above solution worked with all of our available devices. – David O'Meara Jan 10 '13 at 01:33
  • how can i write a listener to block receiving some file types? – Shloime Rosenblum Oct 10 '18 at 17:56