Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Just connect to BT-PAN NAP and die
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.m2hq.pannacotta">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Translucent">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
package net.m2hq.pannacotta
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothClass
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothProfile
import android.bluetooth.BluetoothProfile.ServiceListener
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import java.lang.reflect.Method
class MainActivity : AppCompatActivity() {
companion object {
const val MY_TAG = "MainActivity"
}
var mBTPanConnect: Method? = null
var mBTSrvInstance: Any? = null
var isConnected = false
@SuppressLint("PrivateApi", "DiscouragedPrivateApi")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (BluetoothAdapter.getDefaultAdapter()?.isEnabled == false) {
Toast.makeText(applicationContext, "Bluetooth is not enabled", Toast.LENGTH_SHORT).show()
finishAndRemoveTask()
return
}
// ref: https://stackoverflow.com/questions/22864670/enable-bluetooth-tethering-android-programmatically
val classBluetoothPan = Class.forName("android.bluetooth.BluetoothPan")
mBTPanConnect = classBluetoothPan.getDeclaredMethod(
"connect",
BluetoothDevice::class.java
)
val btPanConstructor = classBluetoothPan.getDeclaredConstructor(
Context::class.java,
BluetoothProfile.ServiceListener::class.java
)
btPanConstructor.isAccessible = true
mBTSrvInstance = btPanConstructor.newInstance(applicationContext, BTPanServiceListener(applicationContext))
}
override fun onDestroy() {
super.onDestroy()
Log.d(MY_TAG, "onDestroy")
Handler().postDelayed({
android.os.Process.killProcess(android.os.Process.myPid());
}, 3000)
}
inner class BTPanServiceListener(private val context: Context) : ServiceListener {
override fun onServiceConnected(
profile: Int,
proxy: BluetoothProfile
) {
Log.d(MY_TAG,"onServiceConnected")
if (isConnected) {
// to run once
return
}
val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
if (bluetoothAdapter?.isEnabled == false) {
return
}
val bondedDevices = bluetoothAdapter.bondedDevices
bondedDevices.forEach { device ->
val btClass = device.bluetoothClass
if (btClass.hasService(BluetoothClass.Service.NETWORKING) &&
btClass.hasService(BluetoothClass.Service.TELEPHONY) &&
btClass.deviceClass == BluetoothClass.Device.PHONE_SMART) {
Log.d(MY_TAG, String.format("Name:%s, Class(Service/Device):0x%s", device.name, btClass.toString()))
val success = mBTPanConnect?.invoke(mBTSrvInstance, device) as Boolean
if (success) {
Toast.makeText(applicationContext, "Connecting to " + device.name, Toast.LENGTH_SHORT).show()
isConnected = true
} else {
Toast.makeText(applicationContext, "Something wrong with connecting to " + device.name + " (maybe already connected?)", Toast.LENGTH_SHORT).show()
}
}
}
finishAndRemoveTask()
}
override fun onServiceDisconnected(profile: Int) {
Log.d(MY_TAG,"onServiceDisconnected")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment