蓝牙文件传输之obex层之上的分析【Android源码解析】



在上节中我们仔细分析蓝牙文件传输过程中涉及到的UI界面,最终定格在蓝牙设备扫描的界面,我们只要选择自己想要传输的蓝牙设备就可以进行蓝牙文件的传输了。那就是这样一个简单的设备选择的点击会引发哪些连锁的操作呢?本就来详细进行分析。

1.1.设备点击的action和响应

      我们来回顾一下,最后蓝牙设备的扫描界面是在DevicePickerFragment.java这个文件中实现的,目录是/packages/apps/Settings/src/com/android/settings/bluetooth/。毫无疑问,对这个界面中设备的点击所做的处理显然也是在该文件中实现的。我们来看一下具体的代码:


void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
……
//停止扫描,所以我们会看到点击设备后扫描就不再继续了
mLocalAdapter.stopScanning();
//保存选择的设备和时间
    LocalBluetoothPreferences.persistSelectedDeviceInPicker(
                getActivity(), mSelectedDevice.getAddress());
//因为mNeedAuth是false,所以这个if是肯定进了,换句会说蓝牙文件的传输并不需要先进行设备的配对
        if ((btPreference.getCachedDevice().getBondState() ==
                BluetoothDevice.BOND_BONDED) || !mNeedAuth) {
//发送BluetoothDevicePicker.ACTION_DEVICE_SELECTED的broadcast	
            sendDevicePickedIntent(mSelectedDevice);
            finish();
        } else {
            super.onDevicePreferenceClick(btPreference);
        }
}

所以,简单地来说,选择设备之后就是发送了一个BluetoothDevicePicker.ACTION_DEVICE_SELECTEDbroadcast来通知我们选择了某个设备进行文件的传输。对这个broadcast的监听就只有一个,还是和STATE_ON监听的那个是一样的,文件:/packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppReceiver.java。具体代码如下:

} else if (action.equals(BluetoothDevicePicker.ACTION_DEVICE_SELECTED)) {
	//得到选中的device
   BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
	//就是真正的传输
    mOppManager.startTransfer(remoteDevice);
	//显示一个正在向**发送文件的toast。
    String deviceName = mOppManager.getDeviceName(remoteDevice);
            String toastMsg;
            int batchSize = mOppManager.getBatchSize();
            if (mOppManager.mMultipleFlag) {
                toastMsg = context.getString(R.string.bt_toast_5, Integer.toString(batchSize),
                        deviceName);
            } else {
                toastMsg = context.getString(R.string.bt_toast_4, deviceName);
            }
            Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show();
}

所以,这里在对action的处理中,核心的部分就是这个函数:mOppManager.startTransfer(remoteDevice);该函数位于packages/apps/Bluetooth/src/com/android/bluetooth/opp/BluetoothOppManager.java这个文件中:
public void startTransfer(BluetoothDevice device) {
……
//insert的thread不能大于3,否则就启动BluetoothOppBtErrorActivity的activity。
if (mInsertShareThreadNum > ALLOWED_INSERT_SHARE_THREAD_NUMBER) {
}
//启动insert thread。
insertThread = new InsertShareInfoThread(device, mMultipleFlag, mMimeTypeOfSendingFile, mUriOfSendingFile, mMimeTypeOfSendingFiles,   mUrisOfSendingFiles);
insertThread.start();
}

这里的核心函数就是启动insert thread,这个insert thread在我们想来应该是很简单的,就是把相应的info insertBluetoothShare.CONTENT_URI中即可。事实上是否真的如此呢?我们下节来详细分析。

      至此,我们先来总结一下到目前为止设备点击之后做的工作,在点击设备之后,会发送一个ACTION_DEVICE_SELECTEDbroadcastBluetoothOppReceiver收到这个broadcast后,会启动insertThread来把需要分享的文件内容加入到对应的数据库中并引起后续的发送操作,同时在ui上显示“正在向**发送文件”的toast

1.2.insertThread的详细分析

insertThread其实并不是简单的把数据加入到dataBase就结束,或者可以理解为这个insert的操作引起了一系列的波澜。

values.put(BluetoothShare.URI, mUri);
            values.put(BluetoothShare.MIMETYPE, mTypeOfSingleFile);
            values.put(BluetoothShare.DESTINATION, mRemoteDevice.getAddress());

            final Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI,
                    values);

这里的getContentResolver是什么呢,从AndroidManifest.xml中我们可以看到,对应的provider就是BluetoothOppProvider
 <provider android:name=".opp.BluetoothOppProvider"
            android:authorities="com.android.bluetooth.opp"
            android:process="@string/process">
            <path-permission
                    android:path="/btopp"
                    android:permission="android.permission.ACCESS_BLUETOOTH_SHARE" />
        </provider>

所以,调用的就是BluetoothOppProviderinsert函数了,

public Uri insert(Uri uri, ContentValues values) {
//创建或打开一个可读/可写的database
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
	//得到对应values中的info信息
//启动BluetoothOppService这个service
context.startService(new Intent(context, BluetoothOppService.class));
//把values信息insert到uri对应的database
long rowID = db.insert(DB_TABLE, null, filteredValues);
//再次启动BluetoothOppService的service(调用onStartCommand)
context.startService(new Intent(context, BluetoothOppService.class));
//notifyChange通知database的改变
context.getContentResolver().notifyChange(uri, null);
}

因此,对insert的处理有以下几个比较重要的操作:

1)创建一个可读/可写的database

2)启动了BluetoothOppService

3)通知database的改变,调用对应的onChange函数

1.2.1.  Database的创建。

      Database的创建是整个蓝牙文件传输过程中很重要的一环。其实他的创建语句也很简单,主要就是执行以下语句:

private void createTable(SQLiteDatabase db) {
        try {
            db.execSQL("CREATE TABLE " + DB_TABLE + "(" + BluetoothShare._ID
                    + " INTEGER PRIMARY KEY AUTOINCREMENT," + BluetoothShare.URI + " TEXT, "
                    + BluetoothShare.FILENAME_HINT + " TEXT, " + BluetoothShare._DATA + " TEXT, "
                    + BluetoothShare.MIMETYPE + " TEXT, " + BluetoothShare.DIRECTION + " INTEGER, "
                    + BluetoothShare.DESTINATION + " TEXT, " + BluetoothShare.VISIBILITY
                    + " INTEGER, " + BluetoothShare.USER_CONFIRMATION + " INTEGER, "
                    + BluetoothShare.STATUS + " INTEGER, " + BluetoothShare.TOTAL_BYTES
                    + " INTEGER, " + BluetoothShare.CURRENT_BYTES + " INTEGER, "
                    + BluetoothShare.TIMESTAMP + " INTEGER," + Constants.MEDIA_SCANNED
                    + " INTEGER); ");
        } catch (SQLException ex) {
            Log.e(TAG, "couldn't create table in downloads database");
            throw ex;
        }
}

熟悉SQLite的同学应该很快就知道这个语句的意义,他其实就是创建一个表格:

表格名:DB_TABLE:bt_opp

<

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值