2012-02-22 3 views
1

В моем приложении я хочу сделать Bluetooth-чат. У меня проблема с потоками. В моем приложении мой андроид телефон будет работать как сервер, который имеет блокирующее заявлениеПолучение принудительной ошибки закрытия в android при использовании потоковой передачи

socket=mServerSocket.accept(); 

для этой цели я создал дочерний поток так, что он будет работать отдельно. Но до завершения этой дочерней нити основная нить идет вниз, давая Force Close, и если я использую метод .join(), он вешает мой UI.

Каково решение для параллельной работы обоих потоков?

это мой код Основной активности

package com.my.bluechat_2_1; 

import android.app.Activity; 
import android.bluetooth.BluetoothAdapter; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 
import android.widget.Toast; 

public class BlueChat extends Activity { 
/** Called when the activity is first created. */ 
private BlueHandler btHandler=null; 
private BluetoothAdapter btAdapter = null; 
private Context context=this; 
TextView chatWindow=null; 


    @Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    chatWindow=(TextView)findViewById(R.id.textView1); 
    doStart(); 
} 

private void doStart(){ 
    Button btnStart=(Button)findViewById(R.id.button1); 
    btnStart.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View arg0) { 

       // Get local Bluetooth adapter 
       btAdapter = BluetoothAdapter.getDefaultAdapter(); 
       // If the adapter is null, then Bluetooth is not supported 
       if(btAdapter == null) 
       { 
        Toast.makeText(context, "Device does not support Bluetooth", Toast.LENGTH_LONG).show(); 
       } 
       if (!btAdapter.isEnabled()) { 
        Intent discoverableIntent = new 
        Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); 
        discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); 
        startActivity(discoverableIntent); 
       } 

       chatWindow.append("Waiting for connection...\n"); 
       btHandler=new BlueHandler(context,chatWindow,btAdapter); 
       Thread acceptThread=new Thread(btHandler); 
       acceptThread.start(); 



      } 
     }); 
} 

} 

BlueHandler

package com.my.bluechat_2_1; 

    import java.io.IOException; 
    import java.io.InputStream; 
    import java.io.OutputStream; 
    import java.util.UUID; 

    import android.bluetooth.BluetoothAdapter; 
    import android.bluetooth.BluetoothServerSocket; 
    import android.bluetooth.BluetoothSocket; 
    import android.content.Context; 
    import android.widget.TextView; 
    import android.widget.Toast; 

public class BlueHandler implements Runnable{ 
    // Name for the SDP record when creating server socket 
    private static final String SMARTCAM_BT_SERVICE_NAME = "SmartCam"; 

    // Unique UUID for this application 
    private static final UUID SMARTCAM_BT_SERVICE_UUID = UUID.fromString("95b82690-4c94-11e1-b86c-0800200c9a66"); 

    private BluetoothAdapter btAdapter = null; 
    private BluetoothServerSocket btServerSocket = null; 
    private BluetoothSocket btSocket = null; 
    private InputStream btInputStream=null; 
    private Context contextObj=null; 
    private TextView textView; 



    public BlueHandler(Context contextObj,TextView textView,BluetoothAdapter btAdapter){ 
     this.contextObj=contextObj; 
     this.btAdapter=btAdapter; 
     this.textView=textView; 

     try { 
      btServerSocket=this.btAdapter.listenUsingRfcommWithServiceRecord(SMARTCAM_BT_SERVICE_NAME, SMARTCAM_BT_SERVICE_UUID); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      Toast.makeText(this.contextObj, "Service not created", Toast.LENGTH_LONG); 
     } 
    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     textView.append("Inside child thread.\n"); 
     textView.append(btServerSocket+"\n"); 

     while (true) { 
       try { 
        btSocket = btServerSocket.accept(); 
       } catch (IOException e) { 
        break; 
       } 
       // If a connection was accepted 
       if (btSocket != null) { 
        // Do work to manage the connection (in a separate thread) 
        try { 
         btServerSocket.close(); 
        } catch (IOException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
        break; 
       } 
      } 

     textView.append("Connected.\n"); 

     try { 
      btInputStream=btSocket.getInputStream(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     byte[] buffer = new byte[1024]; // buffer store for the stream 
     String s; 
     int bytes; // bytes returned from read() 

     // Keep listening to the InputStream until an exception occurs 
     while (true) { 
      try { 
       // Read from the InputStream 

       bytes=btInputStream.read(buffer); 
       s= new String(buffer); 
       // Send the obtained bytes to the UI Activity 
       textView.append("received ::" +s+"\n"); 
      } catch (IOException e) { 
       break; 
      } 
     } 

    } 

    } 
+2

У вас есть выход logcat, который вы можете отправить в свой вопрос? –

ответ

0

Вы выполняете длительную работу в конструкторе ваших детей нить? Каждая длинная операция должна выполняться в методе run().

+0

Я добавил код..plz пройти через него. –

+0

Как говорит Джереми, вы должны ** ТОЛЬКО ** обновлять пользовательский интерфейс (например, содержимое TextView) из потока пользовательского интерфейса = основной поток. – Sly

+0

Кроме того, требуется ли длительное время метод в конструкторе? Обратите внимание, что я еще не использовал bluetooth API. Вы можете добавлять журналы до и после следующей строки: btServerSocket = this.btAdapter.listenUsingRfcommWithServiceRecord (SMARTCAM_BT_SERVICE_NAME, SMARTCAM_BT_SERVICE_UUID); – Sly

1

Возможно, вы столкнулись с крахом, потому что вы обращаетесь к текстовому элементу рабочего потока. Вам нужно будет использовать TextView.post(Runnable), чтобы этого не произошло.

В действительности вы должны использовать связующий Service для выполнения такого рода работ. Вы можете отправить обратно в пользовательский интерфейс посредством трансляции или методов обратного вызова. Таким образом, вам не нужно беспокоиться о ошибках вращения.

Смежные вопросы