Android 蓝牙(十一)Pan蓝牙共享网络(源码分析)

转载请注明出处:http://blog.csdn.net/vnanyesheshou/article/details/72638637

本文主要分析Andorid蓝牙共享网络的使用、连接流程等。
基于Android4.3源码


1 简介##

Bluetooth PAN全称:Bluetooth Personal Area Networking,蓝牙个人区域网,是Bluetooth技术的一种重要应用,其核心思想就是用Bluetooth无线技术取代传统的有线电缆,组建个人化信息网络,实现个人范围的资源和信息共享(也就是网络共享)。
主要应用场景:手机与手机、PC与PC、PC与手机之间的网络共享。
三种角色:

NAP(Network Access Point): 如果你的蓝牙设备支持NAP,那么你可以通过共享网络连接来给别的PAN Network内的PC提供上网功能。
GN(Group Ad-hoc Network): 使你可以在小局域网内给其它设备提供数据转发的功能。
PANU(PAN User):与NAP,GN相对的角色,使用NAP,GN提供的功能的设备。

Android上支持作为NAP和PANU角色。


2 NAP##

NAP全称NetworkAccessPoint(网络接入点)。网络接入点又称为网络访问点,是带有一个或多个蓝牙射频的装置,作为LAN、GSM等网络和蓝牙网络之间的网桥、代理或路由器的设备。网络接入点为每个相连的蓝牙设备提供了网络服务,如LAN上共享的资源。
要想蓝牙共享网络,首先设备需要连接wifi或者开启流量。然后设置中开启“蓝牙共享网络”。


蓝牙共享网络

该界面对应着TetherSettings。
路径:packages/apps/Settings/src/com/android/settings/TetherSettings.java
在其onCreate时,会获取BluetoothPan代理对象。

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
    //获取pan代理对象
    adapter.getProfileProxy(activity.getApplicationContext(), 
            mProfileServiceListener,
            BluetoothProfile.PAN);
}

getProfileProxy是异步的,获取成功、失败会回调mProfileServiceListener。代码如下:

private BluetoothProfile.ServiceListener mProfileServiceListener =
    new BluetoothProfile.ServiceListener() {
    public void onServiceConnected(int profile, BluetoothProfile proxy) {
        //获取成功
        mBluetoothPan.set((BluetoothPan) proxy);
    }
    public void onServiceDisconnected(int profile) {
        //获取失败
        mBluetoothPan.set(null);
    }
};

打开蓝牙共享会调用到startTethering()。如果蓝牙状态为关闭,则先开启蓝牙。保证蓝牙为开启状态,然后打开蓝牙共享。

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
//判断蓝牙状态
if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
    mBluetoothEnableForTether = true;
    adapter.enable(); //打开蓝牙
    mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
    mBluetoothTether.setEnabled(false);
} else {
    BluetoothPan bluetoothPan = mBluetoothPan.get();
    //打开蓝牙共享
    if (bluetoothPan != null) bluetoothPan.setBluetoothTethering(true);
    mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
}

bluetoothPan.setBluetoothTethering(true)跳到Bluetooth应用中,
代码路径:packages/apps/Bluetooth/src/com/android/bluetooth/pan/PanService.java
先调用到内部类BluetoothPanBinder的setBluetoothTethering方法。

public void setBluetoothTethering(boolean value) {
    PanService service = getService();
    if (service == null) return;
    service.setBluetoothTethering(value);
}

该方法中很明显是去调用PanService的setBluetoothTethering方法。

void setBluetoothTethering(boolean value) {
    enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
    if(mTetherOn != value) {
        mTetherOn = value;  //保存状态
        //在更改状态时,删除任何现有的panu、pan-nap连接
        List<BluetoothDevice> DevList = getConnectedDevices();
        for(BluetoothDevice dev : DevList)
            disconnect(dev);
    }
}

该函数主要是将状态值保存喜爱,然后将之前的连接都断开。
打开网络共享后就可以进行连接互联网共享了,当A设备打开网络共享后,点击互联网访问,连接B设备一直失败,这样是错误的,应该B设备主动连接该设备,而不是该设备连接其他设备。

当别的设备与NAP设备(该设备)连接成功,NAP会回调com_android_bluetooth_pan.cpp中的connection_state_callback(),然后回调PanService中的onConnectStateChanged(),然后跳到handlePanDeviceStateChange中,在该函数中由于远端设备为PANU,本地设备为NAP,则会调用enableTethering,用来配置ip地址等相关信息(具体还不是很清楚)。handlePanDeviceStateChange会向为发送广播,携带蓝牙共享的相关状态。


3 PANU##

PANU Personal Area Networking user,个人区域网用户。
要想连接别的设备的蓝牙共享网络,首先需要配对,配对成功后,在已配对界面点击“互联网访问”来连接远端设备,

互联网访问

该操作经过一系列调用,跳到PanProfile中的connect方法中。具体如何跳到PanProfile中的connect方法,可以参考如下文章。
http://blog.csdn.net/vnanyesheshou/article/details/71106622
http://blog.csdn.net/vnanyesheshou/article/details/71811288
PanProfile中的connect会跳到Bluetooth应用中的PanService中。
在PanService的connect函数中判断与该设备的连接状态是否断开,没有断开则返回false。断开着向handler发送消息,返回true。handler中处理该消息如下:

BluetoothDevice device = (BluetoothDevice) msg.obj;
//进行pan连接
if (!connectPanNative(Utils.getByteAddress(device),
        BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE)) {
    //连接失败,发送状态
    handlePanDeviceStateChange(device, null, BluetoothProfile.STATE_CONNECTING,
            BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
    handlePanDeviceStateChange(device, null,
            BluetoothProfile.STATE_DISCONNECTED, BluetoothPan.LOCAL_PANU_ROLE,
            BluetoothPan.REMOTE_NAP_ROLE);
    break;
}

调用connectPanNative进行pan的连接,返回false则表示失败,向外发送广播(CONNECTING、DISCONNECTED);返回true则表示该操作成功,等待连接状态回调。
connectPanNative函数中的参数,看出本地设备作为PANU角色,远端作为NAP角色,所以上面作为NAP时主动连接其他设备失败。
connectPanNative为native方法,其会跳到com_android_bluetooth_pan,然后向hardware层调用。

连接状态回调与上相同。都会回调到handlePanDeviceStateChange中。

//网络相关,暂不清楚是怎么回事。
LinkProperties lp = new LinkProperties();
lp.setInterfaceName(iface);             mTetherAc.sendMessage(NetworkStateTracker.EVENT_NETWORK_CONNECTED, lp);

然后向外发送连接状态的广播。该广播只能判断pan协议的连接状态,并不能代表是否能正常共享网络。因为NAP端设备可能没有连接网络,或者分配ip地址等没有成功。

public boolean isPanConnected(Context context){
    ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo btInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_BLUETOOTH);
    if(btInfo!=null){
        return btInfo.isConnected();
    }
    return false;
}

上述代码可以判断与NAP设备的网络是否连接,但并不能保证可以上网,连接成功后,NAP设备不管可不可以上网,上述代码都返回true。暂时还没有找到其他方法。

欢迎大家关注、评论、点赞
你们的支持是我坚持的动力。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容