4

Я создаю приложение для Android, которое обменивается данными с платой Arduino через Bluetooth, у меня есть код Bluetooth в своем классе под названием BlueComms. Для подключения к устройству Я использую следующий Methord:Удержание соединения Bluetooth с помощью нескольких действий

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

Большое спасибо, Rozz

ответ

9

Где вы храните экземпляра класса 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" > 

Access база приложение с любого из ваших мероприятий, как этот

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

Когда вы выбираете устройство для подключения и когда вы нажимаете на элементе списка устройства для запроса соединения с использованием устройства 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(); 
        } 


       } 
      }); 


      } 

     }); 
0

Я в настоящее время имеющий точно такой же вопрос, и я думал об открытии/закрытие сокета Bluetooth каждый раз, когда Activity запрашивает его. Каждая активность имеет собственный экземпляр BlueComms.

Поскольку мое приложение станет немного сложным, и будут выполняться запросы с поддержкой Bluetooth с разных видов деятельности, я думаю, что этот способ станет очень трудным в использовании и устранении неполадок.

Другой способ, которым я наткнулся, читая здесь ... https://developer.android.com/guide/components/services.html

служба может быть создана на фоне, имеющем разъем Bluetooth всегда. Все запросы Bluetooth могут быть сделаны с использованием Intent для этой службы. Это также создает некоторую значительную сложность, но чувствует себя более аккуратным и организованным.

У меня сейчас есть эта дилемма, чтобы использовать поток для каждого вида деятельности или использовать службу. Я не знаю, какой путь на самом деле лучше.

+1

Эй, это было некоторое время, так как я смотрел на этот код, но я в конечном итоге решить мою проблему с помощью служб - не стесняйтесь, чтобы просмотреть код на GitHub, хотя она должна быть чудовищно из к настоящему времени. https://github.com/RoryCrispin/toroCamAndroid/blob/Local-Camera-/src/com/rozzles/torocam/core/BlueComms.java –

+1

Чтобы добавить, вы можете увидеть, где действия привязываются к сервису здесь: https: //github.com/RoryCrispin/toroCamAndroid/blob/Local-Camera-/src/com/rozzles/torocam/core/toroCamTrigger.java#L84 –

2

Что я сделал, создал одноэлементный класс для BluetoothConnection. Таким образом, создание сокетов происходит только один раз.

Когда метод onCreate любой активности создан, он сначала извлекает экземпляр класса BluetoothConnection.

Обработчик используется для отправки сообщений из потока в классе BluetoothConnection в соответствующее действие с помощью настроек Handler.

Как:

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