【问题标题】:Holding android bluetooth connection through multiple activities通过多个活动保持android蓝牙连接
【发布时间】:2013-07-08 06:06:45
【问题描述】:

我正在构建一个通过蓝牙与 Arduino 板通信的 Android 应用程序,我在它自己的一个名为 BlueComms 的类中拥有蓝牙代码。要连接到设备,我使用以下方法:

public boolean connectDevice() {
    CheckBt();
    BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
    Log.d(TAG, "Connecting to ... " + device);
    mBluetoothAdapter.cancelDiscovery();
    try {
        btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
        btSocket.connect();
        outStream = btSocket.getOutputStream();
        Log.d(TAG, "Connection made.");
        return true;

    } catch (IOException e) {
        try {
            btSocket.close();
        } catch (IOException e2) {
            Log.d(TAG, "Unable to end the connection");
            return false;
        }
        Log.d(TAG, "Socket creation failed");
    }
    return false;

}
    private void CheckBt() {
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    if (!mBluetoothAdapter.isEnabled()) {
        System.out.println("Bt dsbld");
    }

    if (mBluetoothAdapter == null) {
        System.out.println("Bt null");
    }
}

这个连接很好,但是一旦我离开我通过它连接的活动,就会断开连接,通过 LogCat 显示,

 D/dalvikvm(21623): GC_CONCURRENT freed 103K, 10% free 2776K/3056K, paused 5ms+2ms, total 35ms

我无法再连接到设备,但如果我调用 killBt(),它会引发致命错误,如果我尝试发送数据,我会收到“套接字创建失败”错误。我的发送消息代码如下:

public void sendData(String data, int recvAct) {
    try {
        outStream = btSocket.getOutputStream();
    } catch (IOException e) {
        Log.d(TAG, "Bug BEFORE Sending stuff", e);
    }

    String message = data;
    byte[] msgBuffer = message.getBytes();

    try {
        outStream.write(msgBuffer);
    } catch (IOException e) {
        Log.d(TAG, "Bug while sending stuff", e);
    }
}

当我切换不同的活动时,我应该如何防止连接被我连接的活动暂停,我正在使用以下代码切换活动:

Intent myIntent = new Intent(v.getContext(), Timelapse.class);
    startActivityForResult(myIntent, 0);

非常感谢, 罗兹

【问题讨论】:

    标签: android android-intent android-activity bluetooth onpause


    【解决方案1】:

    您将 BlueComms 类的实例存储在哪里?如果你把它放在第一个活动中,那么当你离开它并移动到下一个活动时,当那个活动被破坏时,类实例就会被杀死(NB活动也会在屏幕旋转时被破坏)

    因此,您需要找到一种方法,让 BlueComms 类的实例在您需要时一直保持活动状态。您可以通过公共属性在活动之间传递它,并在轮换期间将其存储在 onRetainNonConfigurationInstance() 中。

    一个更简单的技巧是创建一个扩展 Application 的类,将其用作应用程序的应用程序委托,并向其添加公共属性以在其中存储 BlueComms 类的实例。这样,BlueComms 类的实例将在您的应用程序的整个生命周期内一直存在。

    扩展应用程序

    import android.app.Application;
    
    public class cBaseApplication extends Application {
    
        public BlueComms myBlueComms;
    
        @Override
        public void onCreate() 
        {
            super.onCreate();
            myBlueComms = new BlueComms();
        }
    
    }
    

    让你的类成为应用清单中的应用委托

    <application
        android:name="your.app.namespace.cBaseApplication"
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
    

    像这样从您的任何活动中访问基础应用程序

    ((cBaseApplication)this.getApplicationContext()).myBlueComms.SomeMethod();
    

    【讨论】:

    • 在应用程序is frowned upon中存储状态,因为它也可以终止。
    【解决方案2】:

    我所做的是,为 BluetoothConnection 创建了一个单例类。 所以套接字的创建只发生一次。

    当任何活动的 onCreate 方法被创建时,它首先获取 BluetoothConnection 类的实例。

    Handler用于通过设置Handler将消息从BluetoothConnection类中的线程发送到对应的Activity。

    喜欢:

    Class MyBTConnection{
      private static MyBTConnection connectionObj;
    
      private Handler mHandler;
    
      public MyBTConnection() { //constructor }
    
      public static MyBTConnection getInstance() {
        if(connectionObj == null) {
            connectionObj = new MyBTConnection();
        }
         return connectionObj;
        }
      }
    
      public void setHandler(Handler handler) {
         mHandler = handler;
      }
    
    
      ..... Code for Bluetooth Connection ....
      to send message : 
      mHandler.obtainMessage(what).sendToTarget();
    
    }
    
    // in first activity
    class MainActivity extends Activity {
         private MyBTConnection connectionObj;
    
         public onCreate(....) {
    
             /*
              * Since this is first call for getInstance. A new object
              * of MyBTConnection will be created and a connection to
              * remote bluetooth device will be established.
              */
             connectionObj = MyBTConnection.getInstance();
             connectionObj.setHandler(mHandler);
         }
    
         private Handler mHandler = new Handler(){
              public void onReceive(...) {
                   /// handle received messages here 
              }
         };
    
    }
    
    // in second activity
    class SecondActivity extends Activity {
    
         private MyBTConnection connectionObj;
    
         public onCreate(....) {
    
             /*
              * Since this is second call for getInstance.
              * Object for MyBTConnection was already created in previous 
              * activity. So getInstance will return that previously
              * created object and in that object, connection to remote
              * bluetooth device is already established so you can                
              * continue your work here.
              */
             connectionObj = MyBTConnection.getInstance();
             connectionObj.setHandler(mHandler);
         }
    
         private Handler mHandler = new Handler(){
              public void onReceive(...) {
                   /// handle received messages here 
              }
         };
    }
    

    【讨论】:

      【解决方案3】:

      我目前遇到了完全相同的问题,我正在考虑每次活动请求时打开/关闭蓝牙套接字。每个 Activity 都有自己的 BlueComms 实例。

      因为我的应用程序会变得有点复杂,并且会有来自不同活动的蓝牙线程请求,我认为这种方式将变得非常难以使用和排除故障。

      我在这里阅读时遇到的另一种方式...... https://developer.android.com/guide/components/services.html

      可以在始终开启蓝牙套接字的后台创建服务。所有蓝牙请求都可以使用 Intent 向该服务发出。这也造成了相当多的复杂性,但感觉更加整洁和有条理。

      我目前处于两难境地,要么为每个活动使用线程,要么使用服务。我不知道哪种方式实际上更好。

      【讨论】:

      【解决方案4】:

      当您选择要连接的设备以​​及单击设备列表项以请求连接到设备时,请使用 AsyncTask 并将连接方法放在 AsyncTask 中,如下所示:-

       AsyncTask.execute(new Runnable() {
                          @Override
                          public void run() {
      
                              try {
      
                                  bluetoothSocket = Globals.bluetoothDevice.createRfcommSocketToServiceRecord(Globals.DEFAULT_SPP_UUID);
                                  bluetoothSocket.connect();
      
                                  // After successful connect you can open InputStream
                             } catch (IOException e) {
                               e.printStackTrace();
                             }
      
      
      **Here is the full code for the same problem that i have cracked :-**
      
      listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
      
                    lablelexconnected.setText("Connecting ...");
                    bdDevice = arrayListBluetoothDevices.get(position);
                    //bdClass = arrayListBluetoothDevices.get(position)
                    //    Toast.makeText(getApplicationContext()," " + bdDevice.getAddress(),Toast.LENGTH_SHORT).show();
                    Log.i("Log", "The dvice : " + bdDevice.toString());
      
                    bdDevice = bluetoothAdapter.getRemoteDevice(bdDevice.getAddress());
      
      
                    Globals.bluetoothDevice = bluetoothAdapter.getRemoteDevice(bdDevice.getAddress());
                    System.out.println("Device in GPS Settings : " + bdDevice);
                    //       startService(new Intent(getApplicationContext(),MyService.class));
      
                   /* Intent i = new Intent(GpsSettings.this, MyService.class);
                    startService(i);*/
                    //  finish();
      
      
                  //  connectDevice();
      
      
                   AsyncTask.execute(new Runnable() {
                       @Override
                       public void run() {
      
                           try {
      
                               bluetoothSocket = Globals.bluetoothDevice.createRfcommSocketToServiceRecord(Globals.DEFAULT_SPP_UUID);
                               bluetoothSocket.connect();
      
                               // After successful connect you can open InputStream
      
                               InputStream in = null;
                               in = bluetoothSocket.getInputStream();
                               InputStreamReader isr = new InputStreamReader(in);
                               br = new BufferedReader(isr);
      
                               while (found == 0) {
                                   String nmeaMessage = br.readLine();
                                   Log.d("NMEA", nmeaMessage);
                                   // parse NMEA messages
                                   sentence = nmeaMessage;
      
                                   System.out.println("Sentence : " + sentence);
      
      
                                   if (sentence.startsWith("$GPRMC")) {
                                       String[] strValues = sentence.split(",");
                                       System.out.println("StrValues : " + strValues[3] + " " + strValues[5] + " " + strValues[8]);
                                       if (strValues[3].equals("") && strValues[5].equals("") && strValues[8].equals("")) {
                                           Toast.makeText(getApplicationContext(), "Location Not Found !!! ", Toast.LENGTH_SHORT).show();
      
                                       } else {
      
                                           latitude = Double.parseDouble(strValues[3]);
                                           if (strValues[4].charAt(0) == 'S') {
                                               latitude = -latitude;
                                           }
                                           longitude = Double.parseDouble(strValues[5]);
                                           if (strValues[6].charAt(0) == 'W') {
                                               longitude = -longitude;
                                           }
                                           course = Double.parseDouble(strValues[8]);
      
                                           //    Toast.makeText(getApplicationContext(), "latitude=" + latitude + " ; longitude=" + longitude + " ; course = " + course, Toast.LENGTH_SHORT).show();
                                           System.out.println("latitude=" + latitude + " ; longitude=" + longitude + " ; course = " + course);
                                       //    found = 1;
      
                                           NMEAToDecimalConverter(latitude, longitude);
      
      
                                       }
                                   }
      
      
                               }
      
      
                           } catch (IOException e) {
                               e.printStackTrace();
                           }
      
      
                       }
                   });
      
      
                }
      
            });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-27
        • 1970-01-01
        • 1970-01-01
        • 2012-11-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多