2013-05-27 186 views
2

我有一個活動,顯示傳感器值並將它們發送到同步隊列中,方法是從onSensorChanged。發佈到隊列時發生超時,因此onSensorChanged方法在隊列阻塞時不會阻塞。然後,我期待在後退按鈕被按下時調用方法,但它不是,屏幕只是掛起而沒有返回到前一個屏幕。任何想法爲什麼發生這種情況?返回按鈕不能調用暫停

順便說一句,當隊列沒有阻塞(數據被用戶刪除),那麼所有的按預期工作,當按下後退按鈕時調用。

public void onSensorChanged(SensorEvent event) { 
    TextView tvX = (TextView) findViewById(R.id.textViewRemLinAccX); 
    TextView tvY = (TextView) findViewById(R.id.textViewRemLinAccY); 
    TextView tvZ = (TextView) findViewById(R.id.textViewRemLinAccZ); 
    String x = String.format(format, event.values[0]); 
    String y = String.format(format, event.values[1]); 
    String z = String.format(format, event.values[2]); 
    tvX.setText(x); 
    tvY.setText(y); 
    tvZ.setText(z); 

    try { 
     if (btConnection.isRunning()) { 
      Log.i(TAG, "+++ queue values"); 
      queue.offer(constructData(x, y, z), 1, TimeUnit.SECONDS); 
     } 
    } catch (InterruptedException e) { 
     Log.e(TAG, "+++ err " + e.toString()); 
    } 

} 
+0

A /你是阻塞UI線程或B /要覆蓋onBackPressed或onKeyEvent – njzk2

+0

我不重寫onBackPressed或onKeyEvent。我不認爲我阻止了UI線程。 – PerceptualRobotics

回答

0

如果你是阻止與其他操作UI(當你執行主線程上的東西),然後返回按鈕將無法正常工作,你應該做的,需要時間在後臺線程上的任何操作。

+0

我不認爲我正在阻塞UI線程,因爲queue.offer超時如果消息未發佈到隊列中。 – PerceptualRobotics

+0

那是怎麼實現的?後退按鈕不響應的唯一原因是因爲UI線程被阻止。 – bogdan

+0

請參閱原始問題中的onSensorChanged代碼 – PerceptualRobotics

0

雖然我不太清楚我是怎麼做到的,但似乎已經解決了,所以已經包含了供其他人使用的代碼。爲了確保連接資源得到正確清理,我進行了大量重構,現在當按下後退按鈕時會調用onPause和onDestroy方法。

Fyi,此活動打開藍牙連接並將傳感器數據發送到另一臺計算機,用於控制LEGO NXT機器人。

package uk.co.moonsit.apps.sensors.remote; 

import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.SynchronousQueue; 
import java.util.concurrent.TimeUnit; 

import uk.co.moonsit.apps.sensors.R; 
import uk.co.moonsit.bluetooth.BluetoothConnection; 
import android.hardware.Sensor; 
import android.hardware.SensorEvent; 
import android.hardware.SensorEventListener; 
import android.hardware.SensorManager; 
import android.os.Bundle; 
import android.app.Activity; 
import android.content.Context; 
import android.util.Log; 
import android.view.Menu; 
import android.view.WindowManager; 
import android.widget.TextView; 

public class RemoteLinearAccelerationActivity extends Activity implements 
     SensorEventListener { 

    private static final String TAG = "RemoteLinearAccelerationActivity"; 

    private BlockingQueue<String> queue; 
    private SensorManager mSensorManager; 
    private Sensor mLinAcc; 
    private String format = "%.3f"; 
    private String type; 
    private BluetoothConnection btConnection; 
    private String delimiter = "|"; 
    private String cr; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_remote_linear_acceleration); 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 
     byte[] crb = new byte[1]; 
     crb[0] = 13; 
     cr = new String(crb); 
     mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 
     mLinAcc = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION); 
     queue = new SynchronousQueue<String>(); 
     type = "LinAcc"; 
     btConnection = new BluetoothConnection(queue, "00001101-0000-1000-8000-00805F9B34FB", "<MAC address here>", "11", "28,13"); 
     Log.i(TAG, "+++ onCreate "); 

    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.remote_linear_acceleration, menu); 
     return true; 
    } 

    @Override 
    public void onAccuracyChanged(Sensor arg0, int arg1) { 
    } 

    @Override 
    public void onSensorChanged(SensorEvent event) { 
     TextView tvX = (TextView) findViewById(R.id.textViewRemLinAccX); 
     TextView tvY = (TextView) findViewById(R.id.textViewRemLinAccY); 
     TextView tvZ = (TextView) findViewById(R.id.textViewRemLinAccZ); 
     String x = String.format(format, event.values[0]); 
     String y = String.format(format, event.values[1]); 
     String z = String.format(format, event.values[2]); 
     tvX.setText(x); 
     tvY.setText(y); 
     tvZ.setText(z); 

     try { 
      String msg = constructData(x, y, z); 
      if (btConnection.isRunning()) { 
       Log.i(TAG, "+++ queue values"); 
       queue.offer(msg, 10, TimeUnit.SECONDS); 
      } 
     } catch (InterruptedException e) { 
      Log.e(TAG, "+++ err " + e.toString()); 
     } 

    } 

    private String constructData(String x, String y, String z) { 
     StringBuilder sb = new StringBuilder(); 
     sb.append(type + delimiter); 
     sb.append(x + delimiter); 
     sb.append(y + delimiter); 
     sb.append(z); 
     sb.append(cr); 
     return sb.toString(); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     Log.i(TAG, "+++ onPause unregisterListener "); 
     mSensorManager.unregisterListener(this); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     Log.i(TAG, "+++ onResume registerListener "); 
     mSensorManager.registerListener(this, mLinAcc, SensorManager.SENSOR_DELAY_NORMAL); 
     Log.i(TAG, "+++ onResume start btConnection"); 
     new Thread(btConnection).start(); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     Log.i(TAG, "+++ onDestroy closing btConnection"); 
     btConnection.stop(); 
    } 

} 



package uk.co.moonsit.bluetooth; 

import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.util.UUID; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.TimeUnit; 

import uk.co.moonsit.messaging.BeginEndEnvelope; 

import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothSocket; 
//import android.os.ParcelUuid; 
import android.util.Log; 

public class BluetoothConnection implements Runnable { 
    private static final String TAG = "BluetoothConnection"; 

    private final BlockingQueue<String> queue; 
    private BluetoothAdapter mBluetoothAdapter; 
    private BluetoothDevice device; 
    private BluetoothSocket clientSocket; 
    private DataInputStream in = null; 
    private DataOutputStream out = null; 
    private String address; 
    private boolean isConnected = false; 
    private BeginEndEnvelope envelope; 
    private String uuid; 
    private boolean isRunning = true; 

    public BluetoothConnection(BlockingQueue<String> q, String ud, String a, 
      String start, String end) { 
     uuid = ud; 
     queue = q; 
     address = a; 
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     envelope = new BeginEndEnvelope(start, end); 
    } 

    private void getDevice() throws IOException { 
     device = mBluetoothAdapter.getRemoteDevice(address); 
    } 

    private void getSocket() throws IOException { 
     clientSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid)); 
     mBluetoothAdapter.cancelDiscovery(); 
    } 

    private boolean connect() { 

     if (!isConnected) { 
      Log.i(TAG, "+++ connecting"); 
      try { 
       getSocket(); 

       Log.i(TAG, "+++ b4 connect"); 
       clientSocket.connect(); 
       Log.i(TAG, "+++ connected"); 

       isConnected = true; 

       in = new DataInputStream(clientSocket.getInputStream()); 
       out = new DataOutputStream(clientSocket.getOutputStream()); 
       Log.i(TAG, "+++ streams created"); 

      } catch (IOException e) { 
       Long sleep = (long) 10000; 
       Log.e(TAG, "+++ connection failed, sleep for " + sleep); 
       try { 
        Thread.sleep(sleep); 
       } catch (InterruptedException e1) { 
        e1.printStackTrace(); 
       } 
      } 
     } 
     return isConnected; 
    } 

    public void run() { 

     try { 
      getDevice(); 
     } catch (IOException e) { 
      Log.e(TAG, "+++ device error " + e.toString()); 
     } 
     while (isRunning) { 
      try { 
       processData(); 
      } catch (Exception e) { 
       Log.e(TAG, "+++ data error " + e.toString()); 
      } 
     } 
     close(); 
     Log.i(TAG, "+++ ending bluetooth run"); 
    } 

    private void closeSocket() { 
     if (clientSocket != null) 
      try { 
       clientSocket.close(); 
       Log.d(TAG, "+++ socket closed"); 

      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
    } 

    private void closeStreams() { 
     if (in != null) 
      try { 
       in.close(); 
       Log.d(TAG, "+++ input stream closed"); 
      } catch (IOException e) { 
       Log.e(TAG, "+++ input stream not closed " + e.toString()); 
      } 

     if (out != null) 
      try { 
       out.close(); 
       Log.d(TAG, "+++ output stream closed"); 
      } catch (IOException e) { 
       Log.e(TAG, "+++ output stream not closed " + e.toString()); 
      } 
    } 

    private void close() { 
     closeStreams(); 
     closeSocket(); 

     isConnected = false; 
    } 

    public void stop() { 
     isRunning = false; 
    } 

    public boolean isRunning() { 
     return isRunning; 
    } 

    public void setRunning(boolean isRunning) { 
     this.isRunning = isRunning; 
    } 

    private void processData() throws Exception { 

     try { 

      String outData = null; 
      int timer = 0; 
      while (outData == null) { 
       if (!connect()) 
        return; 
       Log.i(TAG, "+++ waiting on queue "); 
       outData = queue.poll(1, TimeUnit.SECONDS);// .take(); 
       if (timer++ > 15) { 
        return; 
       } 
      } 
      envelope.sendMessage(outData, out); 
      String inData = envelope.receiveMessage(in); 
      Log.i(TAG, "+++ response " + inData); 
     } catch (Exception e) { 
      Log.e(TAG, "+++ processData error " + e.toString()); 
      close(); 
      throw e; 
     } 

    } 

} 
+0

更正,此代碼沒有解決問題,但我想我已經找出了問題。這就是無論什麼呼籲傳感器變化是排隊的事件。所以我的隊列正在減慢UI線程,這意味着有很多的onSensorChanged調用趕上事件。這意味着UI線程遠遠落後,並且變得沒有反應。我通過用不等待隊列另一端的LinkedList替換SynchronousQueue來解決此問題,並且讓另一端(非UI線程)處理處理速度問題。 – PerceptualRobotics