Enable bluetooth tethering android programmatically
Asked Answered
M

4

7

I am trying to make an application like "Bluetooth auto tethering" on play store. I read on the forum that Android is very security-aware and will not enable this setting without user interaction.

I need some explanations about how enable bluetooth tethering.

Thank you

Militate answered 4/4, 2014 at 13:48 Comment(0)
X
8

I don't know if this is still an issue or not, but I found that using the connect method in the reflection call works. Working off of the code that pmont used from the link in Lorelorelore's answer:

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Class<?> classBluetoothPan = null;
Constructor<?> BTPanCtor = null;
Object BTSrvInstance = null;
Method mBTPanConnect;

try {
    classBluetoothPan = Class.forName("android.bluetooth.BluetoothPan");
    mBTPanConnect = classBluetoothPan.getDeclaredMethod("connect", BluetoothDevice.class);
    BTPanCtor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class);
    BTPanCtor.setAccessible(true);
    BTSrvInstance = BTPanCtor.newInstance(myContext, new BTPanServiceListener(myContext));
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}

Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
    // Loop through paired devices
    for (BluetoothDevice device : pairedDevices) {
        try{
            mBTPanConnect.invoke(BTSrvInstance, device);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Of course, this assumes that the bluetooth is enabled, and you only have one paired device. But enabling bluetooth is pretty straightforward using standard (not reflection) calls, and you can just check for the paired device that you want to connect to in the for loop. Also, don't forget the BTPanServiceListener class from the other answer as well.

Hope this helps.

Xe answered 2/7, 2014 at 18:53 Comment(1)
This works for standard devices. However, I'm on a T-mobile S7 edge, and crappy Tmobile removes support for Bluetooth tethering. Even after running this code, I've no BT tethering. Can anyone suggest an alternate? May be create a virtual VPN or something over BT?Fosterfosterage
B
6

The solution above required some modification in order to work for me. Specifically, the code to enable tethering needs to be in the OnServiceConnected() method. Also I have the following permissions set in the manifest:

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />

Here is my solution:

public class BluetoothTethering extends ActionBarActivity {

    Object instance = null;
    Method setTetheringOn = null;
    Method isTetheringOn = null;
    Object mutex = new Object();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bluetooth_tethering);
        String sClassName = "android.bluetooth.BluetoothPan";

        try {

            Class<?> classBluetoothPan = Class.forName(sClassName);

            Constructor<?> ctor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class);
            ctor.setAccessible(true);
            //  Set Tethering ON
            Class[] paramSet = new Class[1];
            paramSet[0] = boolean.class;

            synchronized (mutex) {
                setTetheringOn = classBluetoothPan.getDeclaredMethod("setBluetoothTethering", paramSet);
                isTetheringOn = classBluetoothPan.getDeclaredMethod("isTetheringOn", null);
                instance = ctor.newInstance(getApplicationContext(), new BTPanServiceListener(getApplicationContext()));
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public class BTPanServiceListener implements BluetoothProfile.ServiceListener {

        private final Context context;

        public BTPanServiceListener(final Context context) {
            this.context = context;
        }

        @Override
        public void onServiceConnected(final int profile,
                                       final BluetoothProfile proxy) {
            //Some code must be here or the compiler will optimize away this callback.

            try {
                synchronized (mutex) {
                    setTetheringOn.invoke(instance, true);
                    if ((Boolean)isTetheringOn.invoke(instance, null)) {
                        Toast.makeText(getApplicationContext(), "BT Tethering is on", Toast.LENGTH_LONG).show();
                    }
                    else {
                        Toast.makeText(getApplicationContext(), "BT Tethering is off", Toast.LENGTH_LONG).show();
                    }
                }
            }
            catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(final int profile) {
        }
    }
}
Breastwork answered 17/6, 2016 at 11:58 Comment(2)
Does this work on N? Do you have a published app for the lazy among us? :)Coadjutor
Thank you so much! Works on Android 4.4Fineable
J
4

The below code works perfectly for me

String sClassName = "android.bluetooth.BluetoothPan";

try {  

    Class<?> classBluetoothPan = Class.forName(sClassName);

    Constructor<?> ctor = classBluetoothPan.getDeclaredConstructor(Context.class, BluetoothProfile.ServiceListener.class);
    ctor.setAccessible(true);
    Object instance = ctor.newInstance(getApplicationContext(), new BTPanServiceListener(getApplicationContext()));                 
    //  Set Tethering ON
    Class[] paramSet = new Class[1];
    paramSet[0] = boolean.class;

    Method setTetheringOn = classBluetoothPan.getDeclaredMethod("setBluetoothTethering", paramSet);

    setTetheringOn.invoke(instance,true);

} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (Exception e) {
    e.printStackTrace();
}

public class BTPanServiceListener implements BluetoothProfile.ServiceListener {

    private final Context context;

    public BTPanServiceListener(final Context context) {
        this.context = context;
    }

    @Override
    public void onServiceConnected(final int profile,
            final BluetoothProfile proxy) {
        //Some code must be here or the compiler will optimize away this callback.
        Log.e("MyApp", "BTPan proxy connected");

    }

    @Override
    public void onServiceDisconnected(final int profile) {
    }
}
Jerilynjeritah answered 27/8, 2014 at 7:46 Comment(0)
G
2

Here you find a similar question: Bluetooth question

Just replace "isTetheringOn" with "setBluetoothTethering" in the reflection call and pass in a boolean parameter. It should work.

Glans answered 4/4, 2014 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.