2013-04-26 4 views
1

Android의 HDPSample 응용 프로그램을 사용하고 있습니다. 내 삼성 Galaxy S3 ANDROID V17과 Zephyr HXM Bluetooth Heart Rate Monitor간에 Bluetooth 연결을 구성하려고합니다. 페어링에 성공했으며 로그 파일에 성공적으로 쓰고 있습니다. 그러나 나는 serversocket을 사용하여 연결하려고하므로 안드로이드 예제에서 주어진 두 클래스를 결합했습니다. ConnectThread 클래스 에서 "클라이언트로 연결"의 코드를 결합한 다음 ConnectedThread 클래스를 사용하여 연결을 관리하려고합니다. http://developer.android.com/guide/topics/connectivity/bluetooth.html#ConnectingDevices 이 두 클래스를 결합하면 전략이 좋지 않습니까? 각 클래스별로 수행되는 스레딩이 중요한가 또는 명확하게하기 위해 발생하는 두 가지 다른 동작을 보여주는 안드로이드 방식 일 뿐인가? 그건 정말 내 질문입니다. 나는 이것을 실행할 때 현재 예외를 얻는다. 감사합니다. 여기 내 코드가있다.제퍼에 연결하는 데 필요한 조언 은하 s3가있는 HXM 블루투스 장치

package com.example.bluetooth.health; 
    import java.io.BufferedWriter; 
    import java.io.File; 
    import java.io.FileInputStream; 
    import java.io.FileOutputStream; 
    import java.io.FileWriter; 
    import java.io.IOException; 
    import java.io.InputStream; 
    import java.io.InputStreamReader; 
    import java.io.OutputStream; 
    import java.io.OutputStreamWriter; 

    import java.sql.Timestamp; 
    import java.util.Date; 
    import java.util.UUID; 

    import android.app.Activity; 
    import android.app.AlertDialog; 
    import android.app.Dialog; 
    import android.app.DialogFragment; 
    import android.bluetooth.BluetoothAdapter; 
    import android.bluetooth.BluetoothDevice; 
    import android.bluetooth.BluetoothServerSocket; 
    import android.bluetooth.BluetoothSocket; 
    import android.content.BroadcastReceiver; 
    import android.content.ComponentName; 
    import android.content.Context; 
    import android.content.DialogInterface; 
    import android.content.Intent; 
    import android.content.IntentFilter; 
    import android.content.ServiceConnection; 
    import android.content.res.Resources; 
    import android.os.Bundle; 
    import android.os.Handler; 
    import android.os.IBinder; 
    import android.os.Message; 
    import android.os.Messenger; 
    import android.os.RemoteException; 
    import android.util.Log; 
    import android.view.View; 
    import android.widget.Button; 
    import android.widget.ImageView; 
    import android.widget.TextView; 
    import android.widget.Toast; 



    /** 
    * Main user interface for the Sample application. All Bluetooth health-related 
    * operations happen in {@link BluetoothHDPService}. This activity passes messages to and from 
    * the service. 
    */ 
    public class BluetoothHDPActivity extends Activity { 
     private static final String TAG = "BluetoothHealthActivity"; 

     // Use the appropriate IEEE 11073 data types based on the devices used. 
     // Below are some examples. Refer to relevant Bluetooth HDP specifications for detail. 
     //  0x1007 - blood pressure meter 
     //  0x1008 - body thermometer 
     //  0x100F - body weight scale 
     private static final int HEALTH_PROFILE_SOURCE_DATA_TYPE = 0x1007; 

     private static final int REQUEST_ENABLE_BT = 1; 
     //private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); 
     private static final UUID MY_UUID = UUID.fromString("HXM020735"); 

     public static final int MESSAGE_READ = 0; 
     private TextView mConnectIndicator; 
     private ImageView mDataIndicator; 
     private TextView mStatusMessage; 

     private BluetoothAdapter mBluetoothAdapter; 
     private BluetoothDevice[] mAllBondedDevices; 
     private BluetoothDevice mDevice; 
     //jt 
     private BluetoothServerSocket mServerSocket; 
     //jt 
     private int mDeviceIndex = 0; 
     private Resources mRes; 
     private Messenger mHealthService; 
     private boolean mHealthServiceBound; 

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

      /**/ 
      private final InputStream mmInStream = null; 
      private final OutputStream mmOutStream = null; 
      private Handler mHandler; 
      /**/ 

      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; 

       InputStream tmpIn = null; 
       OutputStream tmpOut = null; 

      } 

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

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


      } 

      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); 

       /***/ 
       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; 
        } 
       } 
       /***/ 

      } 

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

     /* private class ConnectedThread extends Thread { 
      private final BluetoothSocket mmSocket; 
      private final InputStream mmInStream; 
      private final OutputStream mmOutStream; 
      private Handler mHandler; 

      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) { } 
      } 
     }; 

     */ 

     //Added by Jason to append data to a file on the android phone 
     public void appendLog(String text) 
     {  
      File logFile = new File("/storage/sdcard0/log.txt"); 
      if (!logFile.exists()) 
      { 
       try 
       { 
       logFile.createNewFile(); 
       } 
       catch (IOException e) 
       { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
       } 
      } 
      try 
      { 
       //BufferedWriter for performance, true to set append to file flag 
       BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true)); 
       buf.append(text); 
       buf.newLine(); 
       buf.close(); 
      } 
      catch (IOException e) 
      { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     } 


     // Handles events sent by {@link HealthHDPService}. 
     private Handler mIncomingHandler = new Handler() { 
      @Override 
      public void handleMessage(Message msg) { 
       switch (msg.what) { 
        // Application registration complete. 
        case BluetoothHDPService.STATUS_HEALTH_APP_REG: 
         mStatusMessage.setText(
           String.format(mRes.getString(R.string.status_reg), 
           msg.arg1)); 
         break; 
        // Application unregistration complete. 
        case BluetoothHDPService.STATUS_HEALTH_APP_UNREG: 
         mStatusMessage.setText(
           String.format(mRes.getString(R.string.status_unreg), 
           msg.arg1)); 
         break; 
        // Reading data from HDP device. 
        case BluetoothHDPService.STATUS_READ_DATA: 
         mStatusMessage.setText(mRes.getString(R.string.read_data)); 
         //get data from here and write to a file 



         mDataIndicator.setImageLevel(1); 
         break; 
        // Finish reading data from HDP device. 
        case BluetoothHDPService.STATUS_READ_DATA_DONE: 
         mStatusMessage.setText(mRes.getString(R.string.read_data_done)); 
         mDataIndicator.setImageLevel(0); 
         break; 
        // Channel creation complete. Some devices will automatically establish 
        // connection. 
        case BluetoothHDPService.STATUS_CREATE_CHANNEL: 
         mStatusMessage.setText(
           String.format(mRes.getString(R.string.status_create_channel), 
           msg.arg1)); 
         mConnectIndicator.setText(R.string.connected); 
         break; 
        // Channel destroy complete. This happens when either the device disconnects or 
        // there is extended inactivity. 
        case BluetoothHDPService.STATUS_DESTROY_CHANNEL: 
         mStatusMessage.setText(
           String.format(mRes.getString(R.string.status_destroy_channel), 
           msg.arg1)); 
         mConnectIndicator.setText(R.string.disconnected); 
         break; 
        default: 
         super.handleMessage(msg); 
       } 
      } 
     }; 

     private final Messenger mMessenger = new Messenger(mIncomingHandler); 

     @Override 
     public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 

      // Check for Bluetooth availability on the Android platform. 
      mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
      if (mBluetoothAdapter == null) { 
       Toast.makeText(this, R.string.bluetooth_not_available, Toast.LENGTH_LONG); 
       finish(); 
       return; 
      } 
      setContentView(R.layout.console); 
      mConnectIndicator = (TextView) findViewById(R.id.connect_ind); 
      mStatusMessage = (TextView) findViewById(R.id.status_msg); 
      mDataIndicator = (ImageView) findViewById(R.id.data_ind); 
      mRes = getResources(); 
      mHealthServiceBound = false; 

      // Initiates application registration through {@link BluetoothHDPService}. 
      Button registerAppButton = (Button) findViewById(R.id.button_register_app); 
      registerAppButton.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View v) { 
        sendMessage(BluetoothHDPService.MSG_REG_HEALTH_APP, 
          HEALTH_PROFILE_SOURCE_DATA_TYPE); 
       } 
      }); 

      // Initiates application unregistration through {@link BluetoothHDPService}. 
      Button unregisterAppButton = (Button) findViewById(R.id.button_unregister_app); 
      unregisterAppButton.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View v) { 
        sendMessage(BluetoothHDPService.MSG_UNREG_HEALTH_APP, 0); 
       } 
      }); 

      // Initiates channel creation through {@link BluetoothHDPService}. Some devices will 
      // initiate the channel connection, in which case, it is not necessary to do this in the 
      // application. When pressed, the user is asked to select from one of the bonded devices 
      // to connect to. 
      Button connectButton = (Button) findViewById(R.id.button_connect_channel); 
      connectButton.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View v) { 
        mAllBondedDevices = 
          (BluetoothDevice[]) mBluetoothAdapter.getBondedDevices().toArray(
            new BluetoothDevice[0]); 

        if (mAllBondedDevices.length > 0) { 
         int deviceCount = mAllBondedDevices.length; 
         appendLog("device count = "+deviceCount); 
         /*if (mDeviceIndex < deviceCount) mDevice = mAllBondedDevices[mDeviceIndex]; 
         else { 
          mDeviceIndex = 0; 
          mDevice = mAllBondedDevices[1]; 
         }*/ 

         String first3 = "";// mAllBondedDevices[j].substring(0, Math.min(s.length(), 3)); 
         String bd; 
         for(int j=0; j < mAllBondedDevices.length;j++) 
         { 
          bd = mAllBondedDevices[j].getName(); 
          first3 = bd.substring(0, 3); 
          if(first3.equalsIgnoreCase("HXM")){ 
           appendLog("in if"); 
           mDeviceIndex = 0; 
           mDevice= mAllBondedDevices[j]; 
           break; 
          }else { 
           appendLog("not in if"); 
           appendLog("first3 is "+first3); 
            mDeviceIndex=0; 
            mDevice = mAllBondedDevices[0]; 
            } 
         } 

         String[] deviceNames = new String[deviceCount]; 
         int i = 0; 
         for (BluetoothDevice device : mAllBondedDevices) { 
          deviceNames[i++] = device.getName(); 
         } 
         SelectDeviceDialogFragment deviceDialog = 
           SelectDeviceDialogFragment.newInstance(deviceNames, mDeviceIndex); 
         deviceDialog.show(getFragmentManager(), "deviceDialog"); 
        } 
        //jt 
        appendLog("This is the name of the connected device"); 
        appendLog(mDevice.getName()); 
        appendLog(mDevice.toString()); 

        appendLog("Current bondstate value " + mDevice.getBondState()); 
        java.util.Date date= new java.util.Date(); 
        appendLog(new Timestamp(date.getTime()).toString());  
        //appendLog(mBluetoothAdapter.getBondedDevices()); 



        try { 

         mServerSocket.accept(20000);//twenty seconds or 20k milli-seconds before timeout 

        } catch (IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
        //jt 
       } 
      }); 



      // Initiates channel disconnect through {@link BluetoothHDPService}. 
      Button disconnectButton = (Button) findViewById(R.id.button_disconnect_channel); 
      disconnectButton.setOnClickListener(new View.OnClickListener() { 
       public void onClick(View v) { 
        disconnectChannel(); 
       } 
      }); 
      registerReceiver(mReceiver, initIntentFilter()); 
     } 

     // Sets up communication with {@link BluetoothHDPService}. 
     private ServiceConnection mConnection = new ServiceConnection() { 
      public void onServiceConnected(ComponentName name, IBinder service) { 
       mHealthServiceBound = true; 
       Message msg = Message.obtain(null, BluetoothHDPService.MSG_REG_CLIENT); 
       msg.replyTo = mMessenger; 
       mHealthService = new Messenger(service); 
       try { 
        mHealthService.send(msg); 
       } catch (RemoteException e) { 
        Log.w(TAG, "Unable to register client to service."); 
        e.printStackTrace(); 
       } 
      } 

      public void onServiceDisconnected(ComponentName name) { 
       mHealthService = null; 
       mHealthServiceBound = false; 
      } 
     }; 

     @Override 
     protected void onDestroy() { 
      super.onDestroy(); 
      if (mHealthServiceBound) unbindService(mConnection); 
      unregisterReceiver(mReceiver); 
     } 

     @Override 
     protected void onStart() { 
      super.onStart(); 
      // If Bluetooth is not on, request that it be enabled. 
      if (!mBluetoothAdapter.isEnabled()) { 
       Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
       startActivityForResult(enableIntent, REQUEST_ENABLE_BT); 
      } else { 
       initialize(); 
      } 
     } 

     /** 
     * Ensures user has turned on Bluetooth on the Android device. 
     */ 
     @Override 
     protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
      switch (requestCode) { 
      case REQUEST_ENABLE_BT: 
       if (resultCode == Activity.RESULT_OK) { 
        initialize(); 
       } else { 
        finish(); 
        return; 
       } 
      } 
     } 

     /** 
     * Used by {@link SelectDeviceDialogFragment} to record the bonded Bluetooth device selected 
     * by the user. 
     * 
     * @param position Position of the bonded Bluetooth device in the array. 
     */ 
     public void setDevice(int position) { 
      mDevice = this.mAllBondedDevices[position]; 
      mDeviceIndex = position; 
     } 

     private void connectChannel() { 
      sendMessageWithDevice(BluetoothHDPService.MSG_CONNECT_CHANNEL); 
     } 

     private void disconnectChannel() { 
      sendMessageWithDevice(BluetoothHDPService.MSG_DISCONNECT_CHANNEL); 
     } 

     private void initialize() { 
      // Starts health service. 
      Intent intent = new Intent(this, BluetoothHDPService.class); 
      startService(intent); 
      bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 
     } 

     // Intent filter and broadcast receive to handle Bluetooth on event. 
     private IntentFilter initIntentFilter() { 
      IntentFilter filter = new IntentFilter(); 
      filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 
      return filter; 
     } 

     private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context context, Intent intent) { 
       final String action = intent.getAction(); 
       if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { 
        if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) == 
         BluetoothAdapter.STATE_ON) { 
         initialize(); 
        } 
       } 
      } 
     }; 

     // Sends a message to {@link BluetoothHDPService}. 
     private void sendMessage(int what, int value) { 
      if (mHealthService == null) { 
       Log.d(TAG, "Health Service not connected."); 
       return; 
      } 

      try { 
       mHealthService.send(Message.obtain(null, what, value, 0)); 
      } catch (RemoteException e) { 
       Log.w(TAG, "Unable to reach service."); 
       e.printStackTrace(); 
      } 
     } 

     // Sends an update message, along with an HDP BluetoothDevice object, to 
     // {@link BluetoothHDPService}. The BluetoothDevice object is needed by the channel creation 
     // method. 
     private void sendMessageWithDevice(int what) { 
      if (mHealthService == null) { 
       Log.d(TAG, "Health Service not connected."); 
       return; 
      } 

      try { 
       mHealthService.send(Message.obtain(null, what, mDevice)); 
      } catch (RemoteException e) { 
       Log.w(TAG, "Unable to reach service."); 
       e.printStackTrace(); 
      } 
     } 

     /** 
     * Dialog to display a list of bonded Bluetooth devices for user to select from. This is 
     * needed only for channel connection initiated from the application. 
     */ 
     public static class SelectDeviceDialogFragment extends DialogFragment { 

      public static SelectDeviceDialogFragment newInstance(String[] names, int position) { 
       SelectDeviceDialogFragment frag = new SelectDeviceDialogFragment(); 
       Bundle args = new Bundle(); 
       args.putStringArray("names", names); 
       args.putInt("position", position); 
       frag.setArguments(args); 
       return frag; 
      } 

      @Override 
      public Dialog onCreateDialog(Bundle savedInstanceState) { 
       String[] deviceNames = getArguments().getStringArray("names"); 
       int position = getArguments().getInt("position", -1); 
       if (position == -1) position = 0; 
       return new AlertDialog.Builder(getActivity()) 
         .setTitle(R.string.select_device) 
         .setPositiveButton(R.string.ok, 
          new DialogInterface.OnClickListener() { 
           public void onClick(DialogInterface dialog, int which) { 
            ((BluetoothHDPActivity) getActivity()).connectChannel(); 
           } 
          }) 
         .setSingleChoiceItems(deviceNames, position, 
          new DialogInterface.OnClickListener() { 
           public void onClick(DialogInterface dialog, int which) { 
            ((BluetoothHDPActivity) getActivity()).setDevice(which); 
           } 
          } 
         ) 
         .create(); 
      } 
     } 
    } 
+0

가 그냥 궁금해서 예외 무엇 :

난 그냥 유용 할 수 있습니다 예를 들어 응용 프로그램을 찾았나요? 문제를 해결할 수 있었습니까? – Scalarr

답변

1

AFAIK 제퍼 HxM 모니터는 HDP가 아니며 SPP를 통한 독점 프로토콜을 사용합니다. 디바이스에 액세스하기위한 API를 제공하는 2 진 JAR이 있습니다. https://github.com/woody2/PulseTrainer