3

我有一个显示传感器值并将它们从onSensorChanged方法发送到同步队列的活动。我对发布到队列有一个超时,以便onSensorChanged在队列阻塞时该方法不会阻塞。然后我期望onPause按下后退按钮时会调用该方法,但事实并非如此,并且屏幕只是挂起而不返回到前一个屏幕。知道为什么会这样吗?

顺便说一句,当队列没有阻塞(数据被订阅者删除)时,一切都按预期工作,onPause当按下后退按钮时调用。

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

}
4

2 回答 2

0

尽管我不太确定我是如何做到的,但这似乎已解决,因此已包含代码供其他人使用。我做了很多重组以确保正确清理连接资源,现在当按下后退按钮时调用 onPause 和 onDestroy 方法。

仅供参考,此活动打开蓝牙连接并将传感器数据发送到另一台计算机以用于控制 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;
        }

    }

}
于 2013-05-28T16:11:57.003 回答
0

如果您使用其他操作阻塞 UI(当您在主线程上执行某些操作时),那么后退按钮将不起作用,您应该在后台线程上执行任何需要时间的操作。

于 2013-05-27T14:52:02.180 回答