要开发通过蓝牙(BT)进行数据传输的Android应用程序,请从逻辑上从Android开发人员的蓝牙页面开始,该页面详细描述了所有必需的步骤:设备发现,配对,客户端/服务器套接字,RFCOMM通道,等等

但是在进入套接字和线程编程只是为了执行基本的BT操作之前,让我们考虑一个基于Android最重要功能之一的更简单的选择:给定应用程序将用户发送给另一个应用程序的能力,在这种情况下,将是设备的默认BT应用程序。 这样做将使Android OS本身为我们完成所有底层工作。

首先,一些防御性编程:

import android.bluetooth.BluetoothAdapter;
//...
// inside method
// Check if bluetooth is supported
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();

if (btAdapter == null) {
   // Device does not support Bluetooth
   // Inform user that we're done.     	
 }

以上是我们需要执行的第一项检查。 完成后,让我们看看他如何从我们自己的应用程序中启动BT。

在上一篇有关SMS编程的文章中 ,我们讨论了隐式意图 ,它基本上使我们能够指定我们希望系统为我们处理的动作。 然后,Android将在选择器列表中显示所有能够完成所需动作的活动。 这是一个例子:

// bring up Android chooser
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file_to_transfer) );
//...
startActivity(intent);

在上面的代码段中,我们让Android系统知道我们打算发送文本文件。 然后,系统显示所有能够处理该操作的已安装应用程序:

Android 手机与设备蓝牙传输 安卓app蓝牙传输_linux

我们可以看到BT应用程序在这些处理程序中。 我们当然可以让用户从列表中选择该应用程序并完成它。 但是,如果我们觉得自己应该更加人性化,那么我们需要走得更远,自己启动应用程序,而不是简单地在其他不必要的选项中显示它……但是如何?

一种方法是通过以下方式使用Android的PackageManager

//list of apps that can handle our intent
PackageManager pm = getPackageManager();
List appsList = pm.queryIntentActivities( intent, 0);

if(appsList.size() > 0 {
   // proceed
}

上面的PackageManager方法以封装了我们所需信息的ResolveInfo对象的列表的形式返回了我们之前看到的易于处理文件传输意图的所有活动的列表:

//select bluetooth
String packageName = null;
String className = null;
boolean found = false;

for(ResolveInfo info: appsList){
  packageName = info.activityInfo.packageName;
  if( packageName.equals("com.android.bluetooth")){
     className = info.activityInfo.name;
     found = true;
     break;// found
  }
}
if(! found){
  Toast.makeText(this, R.string.blu_notfound_inlist,
                 Toast.LENGTH_SHORT).show();
  // exit
}

现在,我们掌握了启动BT所需的信息:

//set our intent to launch Bluetooth
intent.setClassName(packageName, className);
startActivity(intent);

我们所做的是使用该包及其之前检索的相应类。 由于我们好奇,我们可能想知道“ com.android.bluetooth”包的类名是什么。 如果要打印出来,将得到以下结果: com.broadcom.bt.app.opp.OppLauncherActivity OPP代表对象推送配置文件,并且是允许无线共享文件的Android组件。

很好,但为了使以上所有代码都能使用,BT不仅需要设备支持 ,还需要用户启用 。 因此,我们要做的第一件事就是要求用户在我们认为必要的时间内(此处为300秒)启用BT:

import android.bluetooth.BluetoothAdapter;
//...
// duration that the device is discoverable
private static final int DISCOVER_DURATION = 300;

// our request code (must be greater than zero)
private static final int REQUEST_BLU = 1;

//...

public void enableBlu(){
// enable device discovery - this will automatically enable Bluetooth
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);

discoveryIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
                            DISCOVER_DURATION );

startActivityForResult(discoveryIntent, REQUEST_BLU);
}

一旦我们指定要使用startActivityForResult 从活动中获取结果 ,就会向用户显示以下启用对话框:

Android 手机与设备蓝牙传输 安卓app蓝牙传输_linux_02

现在,每当活动完成时,它将通过onActivityResult回调方法将已发送的请求代码 (REQUEST_BLU)以及数据和结果代码返回到我们的主活动。 我们知道必须检查哪个请求代码,但是结果代码呢? 简单:如果用户对上述权限请求回答“否”(或者发生错误),则结果代码将为RESULT_CANCELED。 另一方面,如果用户接受,则BT文档指定结果代码将等于可发现设备的持续时间(即DISCOVER_DURATION,即300)。

因此,处理上面的BT对话框的方法是:

// When startActivityForResult completes...
protected void onActivityResult (int requestCode,
                                 int resultCode,
                                 Intent data) {

  if (resultCode == DISCOVER_DURATION
       && requestCode == REQUEST_BLU) {

      // processing code goes here
  }
  else{ // cancelled or error
    Toast.makeText(this, R.string.blu_cancelled,
                   Toast.LENGTH_SHORT).show();
  }

}

Putting all our processing flow in order, here’s what we are basically doing:

Android 手机与设备蓝牙传输 安卓app蓝牙传输_java_03

我们完成了吗? 几乎。 最后但并非最不重要的一点是,我们需要在Android清单中请求BT权限:

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

我们现在准备部署。 为了测试所有这些,我们至少需要使用两个Android设备,一个是文件发送器(安装了我们的应用程序),另一个是任何支持BT的接收设备。 这是屏幕截图。 对于发件人:

Android 手机与设备蓝牙传输 安卓app蓝牙传输_python_04

以及相应的接收设备:

Android 手机与设备蓝牙传输 安卓app蓝牙传输_python_05
请注意,一旦接收器接受了连接。 接收到的文件( kmemo.dat )保存在SD卡上的BT文件夹中。 所有较低层的数据传输已由Android OS处理。