手机蓝牙与mac pro传送文件失败问题解决

 mac  手机蓝牙与mac pro传送文件失败问题解决已关闭评论
9月 162021
 

使用手机与已经蓝牙配对的mac pro机器传送文件,却总提示失败。 解决方法如下:

mac机器还需要打开共享的权限:

打开“系统偏好设置”  -> 选择“共享”  -> 勾选左边的“蓝牙共享”,也可以在右侧界面做一些接收文件存放默认路径等的设置。

DONE!

android蓝牙开发入门

 android, bluetooth, java, 开发  android蓝牙开发入门已关闭评论
4月 062016
 

网上找到的一些开发资料,挺有意思的,整理汇总下。

一:什么是蓝牙

1:Bluetooth是目前使用最广泛的无线通讯协议,近距离无线通讯的标准。传说瑞典有个国王特别爱吃蓝莓导致自己的牙齿天天都是蓝色的,在他执政期间这位国王非常善于交际,能说会到,和邻国的搞得关系非常好,这个Bluetooth的发明者觉得蓝牙它的作用就是在近距离沟通周围的设备,跟这个国王很类似,于是起名叫蓝牙。

2:主要针对短距离设备通讯(10米)

3:无线耳机,无线鼠标,无线键盘

蓝牙标志

 

二:蓝牙工作流程图

首先两个设备上都要有蓝牙设备或者专业一点叫蓝牙适配器,以手机和电脑为例我画了如下流程图。其次在手机上进行扫描,扫描周围蓝蓝牙设备,先找到手机附近的电脑,然后给它发出一个信号需要进行蓝牙的配对,再次返回一个信号说明手机和电脑已经配对成功了,最后配对成功后可以进行文件传输了。这是一个最基本的一个流程。

三:与蓝牙相关的最重要的两个API

1:BuletoothAdapter

这个类的对象代表了本地的蓝牙适配器,相当于蓝牙工作流程图中的手机里的蓝牙适配器,也就是说比如这个应用程序是运行在手机上,那么手机上的蓝牙适配器就是本地蓝牙适配器。

2:BuletoothDevice

这个类的对象代表了远程的蓝牙设备,相当于蓝牙工作流程图中的计算机里的蓝牙适配器,也就是说比如这个应用程序是运行在手机上,那么BuletoothDevice代表了你要连接的远程的那个设备上面的蓝牙适配器。

四:硬件准备

今天这个示例必须运行在具有安卓2.0SDK以上的手机上面,不能运行在模拟器上面,因为现在的模拟器是不能模拟蓝牙的,所以必须有个安卓的手机,另外要有台具有蓝牙适配器的电脑。手机和电脑来进行配对,只能通过手动来进行,不可能通过代码是实现配对,因为安全性的问题不能通过应用程序自动的来进行配对,一旦配对成功就可以进行文件的传输了。如何配对在这里就不讲解了。

     五:如何蓝牙配对

           本来是要拿手机和电脑作为调试的,但是我的电脑上面没有蓝牙适配器,所以就用蓝牙笔代替了。

           1:插入手机

            如果发现没有驱动系统会提示安装驱动

            

           2 :下载豌豆荚

           豌豆荚会自动安装手机对应型号的USB驱动,USB调试默认是打开的(一定要开启手机的USB调试),等待安装完成。

          

          3 :打开在eclipse的DDMS视图里的Devices这一区域出现了你的手机设备的数字名称了。

          

         4:打开手机上的“设置”

         

      5:选择“无线和网络”

          给蓝牙打上勾,此时手机头部的蓝牙小图标已打开,表示开启了蓝牙

          

          

      6:扫描配对

         拿起蓝牙笔,打开它的开关,点击手机上面的“扫描查找设备”

         

    7:请求配对       

       输入密钥请求配对,然后等待配对成功

        

        

  六:实现效果

          扫描已配对的远程蓝牙设备

          代码步骤

1:需要在AndroidMainfest.xml里声明蓝牙权限

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

2:获得BluetoothAdapter对象

3:判断当前设备中是否拥有蓝牙设备

4:判断当前设备中的蓝牙设备是否已经打开

5:得到所有已经配对的蓝牙设备对象

七:代码

1:布局文件main.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android
              android:orientation=”vertical”
              android:layout_width=”fill_parent”
              android:layout_height=”fill_parent”
       >
<TextView  
       android:layout_width=”fill_parent” 
       android:layout_height=”wrap_content” 
       android:text=”@string/hello”
      />
      <Button
     android:layout_width=”fill_parent”
     android:layout_height=”wrap_content”
   android:text=”扫描周围的蓝牙设备”
     android:id=”@+id/btn2″
/>
</LinearLayout>

2:代码文件MainActivity.java

package com.szy.bluetooth;

import java.util.Iterator;
import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

    public class MainActivity extends Activity {
      private Button mybutton = null;
      public void onCreate(Bundle savedInstanceState) 
      {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
          //得到按钮
          mybutton = (Button)findViewById(R.id.btn2);
          //绑定监听器
          mybutton.setOnClickListener(new ButtonListener());
     }
 

//监听器匿名类
     private class ButtonListener implements OnClickListener
     {
        public void onClick(View v)
      {
         //得到BluetoothAdapter对象
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         //判断BluetoothAdapter对象是否为空,如果为空,则表明本机没有蓝牙设备
         if(adapter != null)
         {
            System.out.println(“本机拥有蓝牙设备”);
            //调用isEnabled()方法判断当前蓝牙设备是否可用
            if(!adapter.isEnabled())
            {     
               //如果蓝牙设备不可用的话,创建一个intent对象,该对象用于启动一个Activity,提示用户启动蓝牙适配器
               Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
               startActivity(intent);
            }
            //得到所有已经配对的蓝牙适配器对象
            Set<BluetoothDevice> devices = adapter.getBondedDevices();
            if(devices.size()>0)    
            {
               //用迭代
               for(Iterator iterator = devices.iterator();iterator.hasNext();)
               {
                  //得到BluetoothDevice对象,也就是说得到配对的蓝牙适配器
                  BluetoothDevice device = (BluetoothDevice)iterator.next();
                  //得到远程蓝牙设备的地址
                  Log.d(“mytag”,device.getAddress());

               }     
          }
       }
       else
       {
          System.out.println(“没有蓝牙设备”);
       }
     }           
      }
}

    八:不连接安卓手机效果图

因为找不到蓝牙设备所以会在DDMS视图下的系统信息里输出“没有蓝牙设备”。

  九:调试效果图

        我们得到了蓝牙笔的蓝牙适配器的地址,我们接下来用MAC地址建立通讯的通道进行文件的传输。

      

图十

一:修改本机蓝牙设置的可见性

每一个蓝牙设备都会有一个可见性的设置,什么叫可见性呢?你把你的蓝牙设备设置为可见,那么别人的蓝牙设备就可以扫描到你手机上的这个蓝牙设备,如果你把你的蓝牙设备设置为不可见,那么别人的蓝牙设备就无法扫描到你手机上的蓝牙设备的,一般的我们不会把蓝牙设备可见性设置为永久可见,它总会有一个时间段,比如蓝牙设备在未来300秒内是可见的,过了300秒又回归到不可见状态,这样做主要是为了考虑到手机里数据的安全性。

1:通过”设置“来达到修改蓝牙可见性

点击“蓝牙设置”选项,勾选“可检测”,如果不勾选那么现在手机上的蓝牙设备处于不可见的状态,也就是说别人扫描的时候是扫描不到我的蓝牙设备的,勾选“可检测”后,发现时间开始是117秒可检测到,刷新一下变成111秒可检测到,它在不断的倒计时也就是说手机上的这个蓝牙设备不是总是可见的,默认是120秒这个蓝牙是可见的,过了这120秒这个蓝牙设备又变成不可见状态了,之前说到是为了安全性的问题。

2:通过代码来达到修改蓝牙可见性

2.1:需要在AndroidMainfest.xml里声明蓝牙权限和蓝牙管理权限

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

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

2.2:布局文件main.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android
               android:orientation=”vertical”
               android:layout_width=”fill_parent”
               android:layout_height=”fill_parent”
           >
         <TextView  
                android:layout_width=”fill_parent” 
                android:layout_height=”wrap_content” 
                android:text=”@string/hello”
          />
         <Button
              android:layout_width=”fill_parent”
              android:layout_height=”wrap_content”
              android:text=”设置可见性”
              android:id=”@+id/btnkejianxing”
         />
           <Button
              android:layout_width=”fill_parent”
              android:layout_height=”wrap_content”
              android:text=”开始扫描”
              android:id=”@+id/btnsaomiao”
         />
</LinearLayout>

                      

3:代码文件MainActivity.java

package com.szy.bluetooth2;

import java.util.Iterator;
import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity<BluetoothReceiver> extends Activity

{

private Button btn_saomiao = null;

           public void onCreate(Bundle savedInstanceState)

 {
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.main);
                  //得到可见性按钮
                  btn_kejianxing = (Button)findViewById(R.id.btnkejianxing);
                  //绑定可见性按钮监听器
                  btn_kejianxing.setOnClickListener(new KeJianXingButtonListener());

}

 

             //可见性按钮监听器,该监听器用于修改蓝牙设备可见性
            private class KeJianXingButtonListener implements OnClickListener
            {
            @Override
            public void onClick(View v)
            {
               //创建一个Intent对象,并且将其action的值设置为BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE也就是蓝牙设备设置为可见状态
               Intent kejianxingIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
               //将一个键值对存放到Intent对象当中,主要用于指定可见状态的持续时间,大于300秒,就认为是300秒
               kejianxingIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 500);
               //这个Activity实际上是安卓自带的一个Activity
               startActivity(kejianxingIntent);
   
            }           
                  }

}

4:通过代码设置手机可见性效果图

我们先通过手机的设置关闭它的可检测性,然后运行代码后发现手机的可检测性打开了。

 

二:扫描周围可用的且没配对的蓝牙设备

在蓝牙操作(一)中我们讲到扫描已经配对的蓝牙设备,其实已经配对的蓝牙设备的信息都已经被存储在你的手机里面了,所以即使你不打开蓝牙适配器,你也可以得到你的这个手机以前配对过的那些蓝牙设备的那些信息。今天我们要讲的操作,只要是你的手机的蓝牙信号能够覆盖到的地方,我们都可以去扫描所有的可见的蓝牙设备,都可以得到这些蓝牙设备的基本信息,进行通讯还不行,需要先配对在通过一个协议来进行数据的交换,我们先实现第一步先找到周围这些蓝牙设备。

           1:布局文件与上面的main.xml一致

           2:代码文件MainActivity.java

                 package com.szy.bluetooth2;

   import java.util.Iterator;
   import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity<BluetoothReceiver> extends Activity

{

private BluetoothAdapter bluetoothAdapter = null;
                      private BluetoothReceiver bluetoothReceiver = null;

          public void onCreate(Bundle savedInstanceState)

{
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.main);
                  //得到扫描周围蓝牙设备按钮

                  btn_saomiao = (Button)findViewById(R.id.btnsaomiao);

                  //绑定扫描周围蓝牙设备按钮监听器

                 btn_saomiao.setOnClickListener(new SaoMiaoButtonListener());

                                   //得到本机蓝牙设备
                                   bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                                   //创建一个IntentFilter对象,将其action指定为BluetoothDevice.ACTION_FOUND
                                   //IntentFilter它是一个过滤器,只有符合过滤器的Intent才会被我们的BluetoothReceiver所接收
                                   IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
                                  //创建一个BluetoothReceiver对象
                                  bluetoothReceiver = new BluetoothReceiver();
                                  //注册广播接收器 注册完后每次发送广播后,BluetoothReceiver就可以接收到这个广播了
                                  registerReceiver(bluetoothReceiver, intentFilter);

}

 

         //扫描周围的蓝牙设备按钮监听器
                      private class SaoMiaoButtonListener implements OnClickListener
                      {
                                @Override
                                public void onClick(View v)
                                {   
                                           //扫描周围的可见的蓝牙设备一次要消耗12秒,废电池电量
                                           //扫描到了后结果我们怎么接收呢,扫描周围的蓝牙设备每扫描到一个蓝牙设备就会发送一个广播,我们就需要BroadcastReceiver来接收这个广播,这个函数是异步的调用,并不是扫描12之后才返回结果的,只要一调用这个函数马上返回,不会等12秒
                                            bluetoothAdapter.startDiscovery();
                                 }           
                        }

 

                   //接收广播
                   private class BluetoothReceiver extends BroadcastReceiver
                   {
                                 public void onReceive(Context context, Intent intent)
                                {
                                             String action = intent.getAction();
                                             if(BluetoothDevice.ACTION_FOUND.equals(action))
                                             {    
                                                        //只要BluetoothReceiver接收到来自于系统的广播,这个广播是什么呢,是我找到了一个远程蓝牙设备
                                                        //Intent代表刚刚发现远程蓝牙设备适配器的对象,可以从收到的Intent对象取出一些信息
                                                        BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                                                        Log.d(“mytag”,bluetoothDevice.getAddress()); 
                                              } 
                                 }
                      }

}

              3:扫描周围可用的且没配对的蓝牙设备效果图

              我们先关掉之前和蓝牙笔的配对,然后运行代码发现同样得到蓝牙笔的蓝牙适配器的地址(打开蓝牙笔)

              

              

来自:http://www.cnblogs.com/menglin2010/archive/2011/11/02/2232923.html

**********************************************************************************************************************************************************************

***********************************************************************************************************************************************************************

资料二:

1. 使用蓝牙的响应权限

复制代码代码如下:

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

2. 配置本机蓝牙模块

在这里首先要了解对蓝牙操作一个核心类BluetoothAdapter

复制代码代码如下:

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
//直接打开系统的蓝牙设置面板
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 0x1);
//直接打开蓝牙
adapter.enable();
//关闭蓝牙
adapter.disable();
//打开本机的蓝牙发现功能(默认打开120秒,可以将时间最多延长至300秒)
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//设置持续时间(最多300秒)

3.搜索蓝牙设备

使用BluetoothAdapter的startDiscovery()方法来搜索蓝牙设备

startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。

请求Discovery后,系统开始搜索蓝牙设备,在这个过程中,系统会发送以下三个广播:

ACTION_DISCOVERY_START:开始搜索

ACTION_DISCOVERY_FINISHED:搜索结束

ACTION_FOUND:找到设备,这个Intent中包含两个extra fields:EXTRA_DEVICE和EXTRA_CLASS,分别包含BluetooDevice和BluetoothClass。

我们可以自己注册相应的BroadcastReceiver来接收响应的广播,以便实现某些功能

复制代码代码如下:

// 创建一个接收ACTION_FOUND广播的BroadcastReceiver
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        // 发现设备
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            // 从Intent中获取设备对象
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            // 将设备名称和地址放入array adapter,以便在ListView中显示
            mArrayAdapter.add(device.getName() + “\n” + device.getAddress());
        }
    }
};
// 注册BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // 不要忘了之后解除绑定

4. 蓝牙Socket通信

如果打算建议两个蓝牙设备之间的连接,则必须实现服务器端与客户端的机制。当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。

服务器设备与客户端设备获取BluetoothSocket的途径是不同的。服务器设备是通过accepted一个incoming connection来获取的,而客户端设备则是通过打开一个到服务器的RFCOMM channel来获取的。

服务器端的实现

通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务器端之间的配对)

调用BluetoothServerSocket的accept()方法监听连接请求,如果收到请求,则返回一个BluetoothSocket实例(此方法为block方法,应置于新线程中)

如果不想在accept其他的连接,则调用BluetoothServerSocket的close()方法释放资源(调用该方法后,之前获得的BluetoothSocket实例并没有close。但由于RFCOMM一个时刻只允许在一条channel中有一个连接,则一般在accept一个连接后,便close掉BluetoothServerSocket)

复制代码代码如下:

private class AcceptThread extends Thread {
    private final BluetoothServerSocket mmServerSocket;

    public AcceptThread() {
        // Use a temporary object that is later assigned to mmServerSocket,
        // because mmServerSocket is final
        BluetoothServerSocket tmp = null;
        try {
            // MY_UUID is the app’s UUID string, also used by the client code
            tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
        } catch (IOException e) { }
        mmServerSocket = tmp;
    }

    public void run() {
        BluetoothSocket socket = null;
        // Keep listening until exception occurs or a socket is returned
        while (true) {
            try {
                socket = mmServerSocket.accept();
            } catch (IOException e) {
                break;
            }
            // If a connection was accepted
            if (socket != null) {
                // Do work to manage the connection (in a separate thread)
                manageConnectedSocket(socket);
                mmServerSocket.close();
                break;
            }
        }
    }

    /** Will cancel the listening socket, and cause the thread to finish */
    public void cancel() {
        try {
            mmServerSocket.close();
        } catch (IOException e) { }
    }
}

客户端的实现 
通过搜索得到服务器端的BluetoothService

调用BluetoothService的listenUsingRfcommWithServiceRecord(String, UUID)方法获取BluetoothSocket(该UUID应该同于服务器端的UUID)

调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务器端的UUID匹配,并且连接被服务器端accept,则connect()方法返回

注意:在调用connect()方法之前,应当确定当前没有搜索设备,否则连接会变得非常慢并且容易失败

复制代码代码如下:

private class ConnectThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;

    public ConnectThread(BluetoothDevice device) {
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        BluetoothSocket tmp = null;
        mmDevice = device;

        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            // MY_UUID is the app’s UUID string, also used by the server code
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e) { }
        mmSocket = tmp;
    }

    public void run() {
        // Cancel discovery because it will slow down the connection
        mBluetoothAdapter.cancelDiscovery();

        try {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            mmSocket.connect();
        } catch (IOException connectException) {
            // Unable to connect; close the socket and get out
            try {
                mmSocket.close();
            } catch (IOException closeException) { }
            return;
        }

        // Do work to manage the connection (in a separate thread)
        manageConnectedSocket(mmSocket);
    }

    /** Will cancel an in-progress connection, and close the socket */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
}

连接管理(数据通信) 
分别通过BluetoothSocket的getInputStream()和getOutputStream()方法获取InputStream和OutputStream

使用read(bytes[])和write(bytes[])方法分别进行读写操作

注意:read(bytes[])方法会一直block,知道从流中读取到信息,而write(bytes[])方法并不是经常的block(比如在另一设备没有及时read或者中间缓冲区已满的情况下,write方法会block)

复制代码代码如下:

private class ConnectedThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket) {
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the input and output streams, using temp objects because
        // member streams are final
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) { }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    public void run() {
        byte[] buffer = new byte[1024];  // buffer store for the stream
        int bytes; // bytes returned from read()

        // Keep listening to the InputStream until an exception occurs
        while (true) {
            try {
                // Read from the InputStream
                bytes = mmInStream.read(buffer);
                // Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                break;
            }
        }
    }

    /* Call this from the main Activity to send data to the remote device */
    public void write(byte[] bytes) {
        try {
            mmOutStream.write(bytes);
        } catch (IOException e) { }
    }

    /* Call this from the main Activity to shutdown the connection */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
}

引用资料:Android官方SDK、《Android/OPhone完全开发讲义》

来自:http://www.jb51.net/article/42416.htm