Android-Bluetooth

這篇文章將所有的android藍(lán)牙的東西都集合在這里,主要分一下幾個部分,所有分析都基于Bluedroid:
(1) Android Bluedroid藍(lán)牙基本框架
(2) 主要目錄及文件結(jié)構(gòu)
(3) 藍(lán)牙主要的支持的profile
(4) 藍(lán)牙基本流程分析:藍(lán)牙啟動, 藍(lán)牙搜索, 藍(lán)牙連接, 藍(lán)牙傳輸文件,藍(lán)牙通話和播放音樂

(1) Android Bluedroid藍(lán)牙基本框架


bluetooth.jpg

根據(jù)上圖,代碼調(diào)用過程一般基于下面的流程
APP->Framework---->(通過Binder)BluetoothService-->(通過JNI)調(diào)用Native Bluetooth->bluedroid->hci

(2) 模塊的主要目錄以及文件結(jié)構(gòu):
APP:
Settings

packages/apps/Settings/src/com/android/settings/bluetooth
主要文件說明:
BluetoothEnabler.java   界面上藍(lán)牙開啟、關(guān)閉的開關(guān)就是它了, 
BluetoothSettings.java  主界面,用于管理配對和連接設(shè)備
LocalBluetoothManager.java  提供了藍(lán)牙API上的簡單調(diào)用接口,這里只是開始。
CachedBluetoothDevice.java   描述藍(lán)牙設(shè)備的類,對BluetoothDevice的再封裝
BluetoothPairingDialog.java  那個配對提示的對話框

Phone

packages/apps/services/Telecom/src/com/android/server/telecom/BluetoothManager.java
這里是通話調(diào)用藍(lán)牙Audio, 
connectBluetoothAudio
disconnectBluetoothAudio

Framework:

/frameworks/base/core/java/android/bluetooth/
BluetoothA2dp.java A2DP的功能實(shí)現(xiàn)
BluetoothAdapter.java 藍(lán)牙action的定義,虛擬設(shè)備屬性以及操作方法
BluetoothAudioGateway.java 藍(lán)牙語音網(wǎng)關(guān)
BluetoothClass.java 藍(lán)牙設(shè)備類型的定義
BluetoothDevice.java 藍(lán)牙設(shè)備屬性
BluetoothDevicePicker.java 定義遠(yuǎn)程藍(lán)牙設(shè)備的特性,比如需要認(rèn)證,設(shè)備類型
BluetoothHeadset.java 定義藍(lán)牙headset功能的屬性以及接口
BluetoothInputStream.java 藍(lán)牙流接口的實(shí)現(xiàn)(輸入流)
BluetoothOutputStream.java 藍(lán)牙流接口的實(shí)現(xiàn)(輸出流)
BluetoothServerSocket.java 藍(lán)牙socket服務(wù)端具備的方法
BluetoothSocket.java 藍(lán)牙socket的封裝
BluetoothUuid.java 藍(lán)牙uuid的定義以及uuid的解析

(3) 藍(lán)牙主要的支持的profile
HFP/HSP
A2DP
AVRCP
PBAP
DUN
OPP
PAN

(4) 藍(lán)牙基本流程分析:
a. 藍(lán)牙開啟:
首先是BluetoothManagerService的啟動, 這個服務(wù)也是在SystemServer中啟動的, 在開機(jī)后,SystemServer進(jìn)程由zygote進(jìn)程fork出來后,會啟動一系列的service,這里面就有BluetoothManagerService:

frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
    BluetoothManagerService bluetooth = null;
    //初始化一個BluetoothManagerService;
    bluetooth = new BluetoothManagerService(context);
    ServiceManager.addService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE, bluetooth);
}

看一下BluetoothManagerService的構(gòu)造函數(shù)
BluetoothManagerService(Context context) {
    loadStoredNameAndAddress();  //讀取藍(lán)牙打開默認(rèn)名稱和地址
        if (isBluetoothPersistedStateOn()) {  //判斷藍(lán)牙是否打開
            mEnableExternal = true;  //如果藍(lán)牙打開,這個設(shè)為true,等boot完后,開啟enable 藍(lán)牙的過程
        }
}

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
  else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
                synchronized(mReceiver) {
                    if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
                        //Enable
                        if (DBG) Log.d(TAG, "Auto-enabling Bluetooth.");
                        sendEnableMsg(mQuietEnableExternal);
                    }
                }
}
廣播中接收Boot是否完成, 完成后調(diào)用sendEnable來開啟藍(lán)牙,mEnableExternal這個值就在這里用到了。

b. 點(diǎn)擊藍(lán)牙開關(guān)開啟藍(lán)牙流程
Settings菜單點(diǎn)擊菜單開啟藍(lán)牙:
APP層路徑packages/apps/Settings/src/com/android/settings/bluetooth
BluetoothSettings.java

     public void onActivityCreated(Bundle savedInstanceState) {
        mSwitchBar = activity.getSwitchBar();  //界面上的swtichbar控件
        mBluetoothEnabler = new BluetoothEnabler(activity, mSwitchBar);  //傳送給BluetoothEnabler, 通過BluetoothEnable控制
        mBluetoothEnabler.setupSwitchBar();
    }

BluetoothEnabler.java

     private final LocalBluetoothAdapter mLocalAdapter;   //localBluetoothAdapter
     public BlutoothEnable(){  //構(gòu)造函數(shù),定義了localBluetoothManager和LocalBluetoothAdapter
        LocalBluetoothManager manager = LocalBluetoothManager.getInstance(context);
        mLocalAdapter = manager.getBluetoothAdapter();   
     }
     public void resume(Context context) {
        // Bluetooth state is not sticky, so set it manually
        handleStateChanged(mLocalAdapter.getBluetoothState());  //設(shè)置初始狀態(tài)
        mSwitchBar.addOnSwitchChangeListener(this);             //設(shè)置switch監(jiān)聽
    }
     public void onSwitchChanged(Switch switchView, boolean isChecked) {
        if (mLocalAdapter != null) {
            mLocalAdapter.setBluetoothEnabled(isChecked);  //
        }   
    }

LocalBluetoothAdapter.java

 public void setBluetoothEnabled(boolean enabled) {
    private final BluetoothAdapter mAdapter;
    boolean success = enabled? mAdapter.enable(): mAdapter.disable();  調(diào)用BluetoothAdapter的enable/disable
}

通過調(diào)用BluetoothAdapter的函數(shù),就調(diào)用到了framework的接口:
LocalBluetoothAdapter.java

 private final IBluetoothManager mManagerService;
 public static synchronized BluetoothAdapter getDefaultAdapter() {
   IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);    //這邊會返回一個managerService的代理 
 }
 public boolean enable() {
   return mManagerService.enable(ActivityThread.currentPackageName());  //通過代理調(diào)用BluetoothManagerService的enable.
  }

BluetoothManagerService

 class BluetoothManagerService extends IBluetoothManager.Stub{
    private final BluetoothHandler mHandler;
    private IBluetooth mBluetooth;
    public boolean enable(String callingPackage) {
      //這里會獲取藍(lán)牙的權(quán)限
      synchronized(mReceiver) {
            //通過發(fā)送消息的方式enable
            sendEnableMsg(false);     
      }  
    }

    private void sendEnableMsg(boolean quietMode) {
        //這邊回去發(fā)送消息, quietMode決定打開后是否需要AutoConnect,這邊是false
        mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE,
                             quietMode ? 1 : 0, 0));
    }
   //Handler是BluetoothManagerService的內(nèi)部類,這邊處理接收的命令
    private class BluetoothHandler extends Handler {
    public void handleMessage(Message msg) {
        case MESSAGE_ENABLE:
        //調(diào)用handleEnable函數(shù)處理
        handleEnable(msg.arg1 == 1);  
        break;
        case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
            mBluetooth = IBluetooth.Stub.asInterface(service);
         break;
    }
    }

private void handleEnable(boolean quietMode) {
    synchronized(mConnection) {
                try {
                    //傳進(jìn)來是false,所以走enable,即開啟會重新連接
                    if (!mQuietEnable) {
                        //調(diào)用mBluetooth的enable,mBluetooth上面有定義,是IBluetooth的代理, server端在package/apps/Bluetooth里面
                        if(!mBluetooth.enable()) { 
                        }
                    }
                    else {
                        if(!mBluetooth.enableNoAutoConnect()) {
                        }
                    }
                } catch (RemoteException e) {
                    Log.e(TAG,"Unable to call enable()",e);
                }
      }
    }
}

之前調(diào)用IBluetooth的service端的部分:
AdapterService.java

 static {  //這里添加了so庫,并定義了一些 native函數(shù)
        System.load("/system/lib/libbluetooth_jni.so");
        classInitNative();
 }
 private static class AdapterServiceBinder extends IBluetooth.Stub {
    public boolean enable() {
        return service.enable(); //這邊又要看這個service,這個service即是 AdapterService
    }
}

boolean enable() {
        return enable (false);
}
public synchronized boolean enable(boolean quietMode) {
   //這邊會發(fā)送一個消息到狀態(tài)機(jī)AdapaterState
   Message m =
                 mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
   mAdapterStateMachine.sendMessage(m);
}

void processStart() {
  //啟動藍(lán)牙的部分, 如果是第一次開啟的話, 走下面的路徑, 繼續(xù)想state狀態(tài)機(jī)發(fā)送AdapterState.STARTED狀態(tài)
        if (!mProfilesStarted && supportedProfileServices.length >0) {
            //Startup all profile services
            setProfileServiceState(supportedProfileServices,BluetoothAdapter.STATE_ON);
        }else {
            debugLog("processStart() - Profile Services alreay started");
            mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
        }
}


AdapterState.java 狀態(tài)機(jī)文件,負(fù)責(zé)跟AdapterService的溝通

 private class OffState extends State {
        public boolean processMessage(Message msg) {
                switch(msg.what) {
                   case USER_TURN_ON:
                     adapterService.processStart();  //adpaterService調(diào)用processStart函數(shù)
                   break;
  }
}

最后,看一下狀態(tài)機(jī)里面的函數(shù)

 private class PendingCommandState extends State {
        public boolean processMessage(Message msg) {
    boolean ret = adapterService.enableNative(); //這邊就調(diào)用到j(luò)ni的地方了
}

看一下簡單的流程圖, 大體一致,但也稍微有不同的地方


Bluetooth_on.jpg

這邊只到了JNI,下面JNI如何調(diào)用CPP的呢~
這邊調(diào)用packages/apps/Bluetooth/jni下面的jni文件:
com_android_bluetooth_btservice_AdapterService.cpp

static jboolean enableNative(JNIENv* env, jobject obj){
  int ret = sBluetoothInterface->enable();
}

在然后好像真的沒有了, 后面進(jìn)入到hal,調(diào)用Bluedroid協(xié)議棧了
hardware/libhardware/include/hardware/bluetooth.h

typedef struct{
  int(*enable)(void);
}bt_interface_t;

Bluedroid協(xié)議棧位于external/bluetooth/bluedroid
bluetooth.c

static int enable(void){
  return btif_enable_bluetooth(); 
}

btif_core.c

bt_status_t btif_enable_bluetooth(void)
{
    bte_main_enable();
}

bte_main.c
void bte_main_enable(){
BTE_Init();
GKI_create_task(); //創(chuàng)建GKI task
bte_hci_enable();
GKI_run();
}

c. 藍(lán)牙搜索:
APP測:
BluetoothSettings.java

//藍(lán)牙狀態(tài)改變監(jiān)聽
public void onBluetoothStateChanged(int bluetoothState) { 
    super.onBluetoothStateChanged(bluetoothState);
    updateContent(bluetoothState);     
}

private void updateContent(int bluetoothState) {
    case BluetoothAdapter.STATE_ON:  //藍(lán)牙開啟完成后,開始掃描
        if (!mInitialScanStarted) {
          startScanning();
        }
    break;
    case BluetoothAdapter.STATE_TURNING_ON:  //藍(lán)牙開啟中,將scanStart設(shè)置為false
        mInitialScanStarted = false;
    break;
}
這邊的BluetoothAdapter.STATE有4個狀態(tài):
STATE_OF  =  10;
STATE_TURNING_ON = 11;
STATE_ON = 12;
STATE_TURNING_OFF = 13;

private void startScanning() {
        mLocalAdapter.startScanning(true);//調(diào)用localAdapter的startScanning函數(shù)
}

LocalBluetoothAdapter.java

void startScanning(boolean force) {
    // If we are playing music, don't scan unless forced.
    //這里回去判斷a2dp profile,如果正在a2dp存在,則不能掃描
    A2dpProfile a2dp = mProfileManager.getA2dpProfile();
    if (a2dp != null && a2dp.isA2dpPlaying()) {
      return;
    }
    A2dpSinkProfile a2dpSink = mProfileManager.getA2dpSinkProfile();
     if ((a2dpSink != null) && (a2dpSink.isA2dpPlaying())){
      return;
      }
     if (mAdapter.startDiscovery()) {  //調(diào)用framwork的接口
        mLastScan = System.currentTimeMillis();
      }
}

Framework:
BluetoothAdapter.java

private IBluetooth mService;  //這么快就用到IBluetooth了。。。
BluetoothAdapter(IBluetoothManager managerService) {
        try {
            //構(gòu)造函數(shù)里直接就獲取mService,這個mService跟managerService是一樣一樣的,是IBluetooth的客戶端代理,跟Service(AdapterService)通訊
            mService = managerService.registerAdapter(mManagerCallback);
        } catch (RemoteException e) {Log.e(TAG, "", e);}
}

public boolean startDiscovery() {
    if (mService != null) return mService.startDiscovery();  //開始掃描
}

還是來看一下mService是如何獲取的
BluetoothManagerService.java

public IBluetooth registerAdapter(IBluetoothManagerCallback callback){
        synchronized(mConnection) {
            return mBluetooth;  //就是返回BluetoothManagerService的mBluetooth
        }
}

Service (Service的目錄在packages/apps/bluetooth里面)
AdapterService.java

private static class AdapterServiceBinder extends IBluetooth.Stub {
    public boolean startDiscovery() {
        AdapterService service = getService();
        return service.startDiscovery();
    }
}
這里有個內(nèi)部類AdapterServiceBinder,是遠(yuǎn)程通訊的服務(wù)端:
直接調(diào)用了AdapterService的startDiscovery函數(shù)
boolean startDiscovery() {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                       "Need BLUETOOTH ADMIN permission");
        //do not allow new connections with active multicast
        A2dpService a2dpService = A2dpService.getA2dpService();
        if (a2dpService != null &&
                a2dpService.isMulticastOngoing(null)) {
            Log.i(TAG,"A2dp Multicast is Ongoing, ignore discovery");
            return false;
        }
        return startDiscoveryNative();
}
這邊也是簡單粗暴的,直接返回startDiscoveryNative(),調(diào)用JNI函數(shù)

JNI
JNI的文件需要到packages/apps/bluetooth/jni下面,adapterservice對應(yīng)的jni文件為
com_android_bluetooth_btservice_AdapterService.cpp

static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
    int ret = sBluetoothInterface->start_discovery();
}

HAL
hal主要看hanrdware/libhardware/include/hardware/bluetooth.h

int (*start_discovery)(void);

//Bluedroid協(xié)議棧部分
bluetooth.c

static int statrt_discovery(void){
   retun btif_dm_start_discovery();
}

btif_dm.c

這個函數(shù)start device discovery/inquiry
bt_status_t btif_dm_start_discovery(void){
  /*find nearby devices*/
BTA_DmSearch(...);
}

d. 藍(lán)牙掃描結(jié)果返回
掃描結(jié)果反饋到上層則是從協(xié)議棧->hal->bluetoothService->APP
external/bluetooth/bluedroid/btif/src/
btif_dm.c

static void btif_dm_search_devices_evt (UINT16 event, char *p_param)
{
        case BTA_DM_INQ_RES_EVT:
                /* Callback to notify upper layer of device */
                //調(diào)用注冊的callback, device_found_cb
                HAL_CBACK(bt_hal_cbacks, device_found_cb,num_properties, properties);
    break;
}

HAL
bluetooth.h

//
typedef void (*device_found_callback)(int num_properties,
                                         bt_property_t *properties);

JNI
com_android_bluetooth_btservice_AdapterService.cpp

 static void device_found_callback(int num_properties, bt_property_t *properties) {
    if (sJniCallbacksObj) {
        callbackEnv->CallVoidMethod(sJniCallbacksObj, method_deviceFoundCallback, addr);
    }
}

Service

 //deviceFoundCallback
RemoteDevices.java
    void deviceFoundCallback(byte[] address) {
        Intent intent = new Intent(BluetoothDevice.ACTION_FOUND);    //send broadcast
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothDevice.EXTRA_CLASS,
                new BluetoothClass(Integer.valueOf(deviceProp.mBluetoothClass)));
        intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi);
        intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName);

        mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
    }
這里調(diào)用發(fā)送廣播,Action_Found給到上層

APP(Settings)
BluetoothEventManager.java

     BluetoothEventManager(LocalBluetoothAdapter adapter,
            CachedBluetoothDeviceManager deviceManager, Context context) {
        mLocalAdapter = adapter;
        mDeviceManager = deviceManager;
        mAdapterIntentFilter = new IntentFilter();
        mProfileIntentFilter = new IntentFilter();
        mHandlerMap = new HashMap<String, Handler>();
        mContext = context;

        // Bluetooth on/off broadcasts
        addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());

        // Discovery broadcasts
        addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
        addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
        addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
        addHandler(BluetoothDevice.ACTION_DISAPPEARED, new DeviceDisappearedHandler());
        addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());

        // Pairing broadcasts
        addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler());
        addHandler(BluetoothDevice.ACTION_PAIRING_CANCEL, new PairingCancelHandler());

        // Fine-grained state broadcasts
        addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());
        addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());

        // Dock event broadcasts
        addHandler(Intent.ACTION_DOCK_EVENT, new DockEventHandler());

        mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter);

        setDefaultBtName();
    }
這邊注冊廣播接收器
addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());

private class DeviceFoundHandler implements Handler {
        public void onReceive(Context context, Intent intent,
                BluetoothDevice device) {
            if (cachedDevice == null) {
                cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
                Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
                        + cachedDevice);
                // callback to UI to create Preference for new device
                dispatchDeviceAdded(cachedDevice);
            }
        }
    }
DeviceFoundHandler接收廣播,并調(diào)用dispatchDeviceAdded(cachedDevice);刷新上層顯示

private void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
        synchronized (mCallbacks) {
            for (BluetoothCallback callback : mCallbacks) {
                callback.onDeviceAdded(cachedDevice);
            }
        }
}
調(diào)用callback.onDeviceAdded(cachedDevice); 回調(diào)返給上層

ListFragment DeviceListPreferenceFragment.java

public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
  、、、
}
DeviceListPreferenceFragment繼承BluetoothCallback接口,重寫onDeviceAdded.

藍(lán)牙連接:

藍(lán)牙OPP文件傳輸:
起點(diǎn)自函數(shù)packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java

if (action.equals(Intent.ACTION_SEND) || action.equals(Intent.ACTION_SEND_MULTIPLE)) {
    if (!isBluetoothAllowed()) {
        Intent in = new Intent(this, BluetoothOppBtErrorActivity.class);
        in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        in.putExtra("title", this.getString(R.string.airplane_error_title));
        in.putExtra("content", this.getString(R.string.airplane_error_msg));
        startActivity(in);
        finish();
        return;
    }
    if (action.equals(Intent.ACTION_SEND)) {
        Thread t = new Thread(new Runnable() {
            public void run() {
                BluetoothOppManager.getInstance(BluetoothOppLauncherActivity.this)
                    .saveSendingFileInfo(type,stream.toString(), false);
                //Done getting file info..Launch device picker and finish this activity
                launchDevicePicker();
                finish();
            }
        });
        t.start();
        return;
    }
}
isBluetoothAllowed()判斷Bluetooth是否允許,如果不允許,彈出Error.
如果返回true,則開啟個線程, 
launchDevicePicker 加載藍(lán)牙列表

 private final void launchDevicePicker() {
        if (!BluetoothOppManager.getInstance(this).isEnabled()) {
            if (V) Log.v(TAG, "Prepare Enable BT!! ");
            Intent in = new Intent(this, BluetoothOppBtEnableActivity.class);
            in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(in);
        } else {
            if (V) Log.v(TAG, "BT already enabled!! ");
            Intent in1 = new Intent(BluetoothDevicePicker.ACTION_LAUNCH);
            in1.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
            in1.putExtra(BluetoothDevicePicker.EXTRA_NEED_AUTH, false);
            in1.putExtra(BluetoothDevicePicker.EXTRA_FILTER_TYPE,
                    BluetoothDevicePicker.FILTER_TYPE_TRANSFER);
            in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE,
                    Constants.THIS_PACKAGE_NAME);
            in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS,
                    BluetoothOppReceiver.class.getName());
            if (V) {Log.d(TAG,"Launching " +BluetoothDevicePicker.ACTION_LAUNCH );}
            startActivity(in1);
        }
}
BluetoothOppManager.getInstance(this).isEnabled()判斷藍(lán)牙是否打開,如果打開,則跳轉(zhuǎn)到列表

DevicePickerFragment.java

     @Override
    void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
        mLocalAdapter.stopScanning();
        LocalBluetoothPreferences.persistSelectedDeviceInPicker(
                getActivity(), mSelectedDevice.getAddress());
        if ((btPreference.getCachedDevice().getBondState() ==
                BluetoothDevice.BOND_BONDED) || !mNeedAuth) {
            sendDevicePickedIntent(mSelectedDevice);
            finish();
        } else {
            super.onDevicePreferenceClick(btPreference);
        }
    }
    private void sendDevicePickedIntent(BluetoothDevice device) {
        mDeviceSelected = true;
        Intent intent = new Intent(BluetoothDevicePicker.ACTION_DEVICE_SELECTED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        if (mLaunchPackage != null && mLaunchClass != null) {
            intent.setClassName(mLaunchPackage, mLaunchClass);
        }
        getActivity().sendBroadcast(intent);
    }
這邊發(fā)送一個selectd的廣播,搜關(guān)鍵字查詢廣播接收。

BluetoothOppReceiver.java

public void onReceive(Context context, Intent intent) {
    else if (action.equals(BluetoothDevicePicker.ACTION_DEVICE_SELECTED)) {
    // Insert transfer session record to database
            mOppManager.startTransfer(remoteDevice);
    }
}


 public void startTransfer(BluetoothDevice device) {
        if (V) Log.v(TAG, "Active InsertShareThread number is : " + mInsertShareThreadNum);
        InsertShareInfoThread insertThread;

            insertThread = new InsertShareInfoThread(device, mMultipleFlag, mMimeTypeOfSendingFile,
                    mUriOfSendingFile, mNameOfSendingFile, mMimeTypeOfSendingFiles, mUrisOfSendingFiles,
                    mIsHandoverInitiated);

        }

        insertThread.start();
    }
private class InsertShareInfoThread extends Thread {
    public void run() {
        insertSingleShare();
    }
}
上面步驟即是接收廣播后的操作~最終調(diào)用insertSingleShare來操作,后面的步驟略掉。

藍(lán)牙接電話與聽音樂:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容