【问题标题】:How to move Bluetooth activity into a Service如何将蓝牙活动移动到服务中
【发布时间】:2013-02-08 04:04:13
【问题描述】:

该应用程序为用户提供 2 个连接选项,USB 和蓝牙。 USB 工作正常。我已经获得了蓝牙连接的示例代码,但是它们被设计为活动。我尝试在 Service 中执行此操作,但失败了。

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
startService(new Intent(this, MyService.class));

<service android:enabled="true" android:name=".MyService" />
enter code here

我需要与已配对且其 MAC 地址已知的设备建立蓝牙通信。所以我可以跳过发现和配对阶段。我尝试连接的设备始终处于可发现状态并正在等待连接。有没有办法从服务类做到这一点,并通过其他活动保持这种连接?

我正在使用BluetoothChatServiceDeviceListActivity

【问题讨论】:

    标签: android service android-activity bluetooth


    【解决方案1】:

    我编写了一个蓝牙服务,它在后台运行,可以使用 Messenger http://developer.android.com/guide/components/bound-services.html 与应用程序中的任何 Activity 进行通信。

    public class PrinterService extends Service {
    private BluetoothAdapter mBluetoothAdapter;
    public static final String BT_DEVICE = "btdevice";
    public static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
    public static final int STATE_NONE = 0; // we're doing nothing
    public static final int STATE_LISTEN = 1; // now listening for incoming
                                                // connections
    public static final int STATE_CONNECTING = 2; // now initiating an outgoing
                                                    // connection
    public static final int STATE_CONNECTED = 3; // now connected to a remote
                                                    // device
    private ConnectThread mConnectThread;
    private static ConnectedThread mConnectedThread;
    // public mInHangler mHandler = new mInHangler(this);
    private static Handler mHandler = null;
    public static int mState = STATE_NONE;
    public static String deviceName;
    public Vector<Byte> packdata = new Vector<Byte>(2048);
    public static Device device = null;
    
    @Override
    public void onCreate() {
        Log.d("PrinterService", "Service started");
        super.onCreate();
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        mHandler = ((MyAplication) getApplication()).getHandler();
        return mBinder;
    }
    
    public class LocalBinder extends Binder {
        PrinterService getService() {
            return PrinterService.this;
        }
    }
    
    
    
    private final IBinder mBinder = new LocalBinder();
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("PrinterService", "Onstart Command");
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter != null) {
            device = (Device) intent.getSerializableExtra(BT_DEVICE);
            deviceName = device.getDeviceName();
            String macAddress = device.getMacAddress();
            if (macAddress != null && macAddress.length() > 0) {
                connectToDevice(macAddress);
            } else {
                stopSelf();
                return 0;
            }
        }
        String stopservice = intent.getStringExtra("stopservice");
        if (stopservice != null && stopservice.length() > 0) {
            stop();
        }
        return START_STICKY;
    }
    
    private synchronized void connectToDevice(String macAddress) {
        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
        if (mState == STATE_CONNECTING) {
            if (mConnectThread != null) {
                mConnectThread.cancel();
                mConnectThread = null;
            }
        }
    
        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        mConnectThread = new ConnectThread(device);
        mConnectThread.start();
        setState(STATE_CONNECTING);
    }
    
    private void setState(int state) {
        PrinterService.mState = state;
        if (mHandler != null) {
            mHandler.obtainMessage(AbstractActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
        }
    }
    
    public synchronized void stop() {
        setState(STATE_NONE);
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
    
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        if (mBluetoothAdapter != null) {
            mBluetoothAdapter.cancelDiscovery();
        }
        stopSelf();
    }
    
    @Override
    public boolean stopService(Intent name) {
        setState(STATE_NONE);
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
    
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
        mBluetoothAdapter.cancelDiscovery();
        return super.stopService(name);
    }
    
    private void connectionFailed() {
        PrinterService.this.stop();
        Message msg = mHandler.obtainMessage(AbstractActivity.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(AbstractActivity.TOAST, getString(R.string.error_connect_failed));
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }
    
    private void connectionLost() {
        PrinterService.this.stop();
        Message msg = mHandler.obtainMessage(AbstractActivity.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(AbstractActivity.TOAST, getString(R.string.error_connect_lost));
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }
    
    private static Object obj = new Object();
    
    public static void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;
        // Synchronize a copy of the ConnectedThread
        synchronized (obj) {
            if (mState != STATE_CONNECTED)
                return;
            r = mConnectedThread;
        }
        // Perform the write unsynchronized
        r.write(out);
    }
    
    private synchronized void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
        // Cancel the thread that completed the connection
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
    
        // Cancel any thread currently running a connection
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
            mConnectedThread = null;
        }
    
        mConnectedThread = new ConnectedThread(mmSocket);
        mConnectedThread.start();
    
        // Message msg =
        // mHandler.obtainMessage(AbstractActivity.MESSAGE_DEVICE_NAME);
        // Bundle bundle = new Bundle();
        // bundle.putString(AbstractActivity.DEVICE_NAME, "p25");
        // msg.setData(bundle);
        // mHandler.sendMessage(msg);
        setState(STATE_CONNECTED);
    
    }
    
    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
    
        public ConnectThread(BluetoothDevice device) {
            this.mmDevice = device;
            BluetoothSocket tmp = null;
            try {
                tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID));
            } catch (IOException e) {
                e.printStackTrace();
            }
            mmSocket = tmp;
        }
    
        @Override
        public void run() {
            setName("ConnectThread");
            mBluetoothAdapter.cancelDiscovery();
            try {
                mmSocket.connect();
            } catch (IOException e) {
                try {
                    mmSocket.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                connectionFailed();
                return;
    
            }
            synchronized (PrinterService.this) {
                mConnectThread = null;
            }
            connected(mmSocket, mmDevice);
        }
    
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e("PrinterService", "close() of connect socket failed", e);
            }
        }
    }
    
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
    
        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e("Printer Service", "temp sockets not created", e);
            }
            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }
    
        @Override
        public void run() {
            while (true) {
                try {
                    if (!encodeData(mmInStream)) {
                        mState = STATE_NONE;
                        connectionLost();
                        break;
                    } else {
                    }
                    // mHandler.obtainMessage(AbstractActivity.MESSAGE_READ,
                    // bytes, -1, buffer).sendToTarget();
                } catch (Exception e) {
                    e.printStackTrace();
                    connectionLost();
                    PrinterService.this.stop();
                    break;
                }
    
            }
        }
    
        private byte[] btBuff;
    
    
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);
    
                // Share the sent message back to the UI Activity
                mHandler.obtainMessage(AbstractActivity.MESSAGE_WRITE, buffer.length, -1, buffer).sendToTarget();
            } catch (IOException e) {
                Log.e("PrinterService", "Exception during write", e);
            }
        }
    
        public void cancel() {
            try {
                mmSocket.close();
    
            } catch (IOException e) {
                Log.e("PrinterService", "close() of connect socket failed", e);
            }
        }
    
    }
    
    public void trace(String msg) {
        Log.d("AbstractActivity", msg);
        toast(msg);
    }
    
    public void toast(String msg) {
        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
    }
    
    @Override
    public void onDestroy() {
        stop();
        Log.d("Printer Service", "Destroyed");
        super.onDestroy();
    }
    
    private void sendMsg(int flag) {
        Message msg = new Message();
        msg.what = flag;
        handler.sendMessage(msg);
    }
    
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {//
            if (!Thread.currentThread().isInterrupted()) {
                switch (msg.what) {
                case 3:
    
                    break;
    
                case 4:
    
                    break;
                case 5:
                    break;
    
                case -1:
                    break;
                }
            }
            super.handleMessage(msg);
        }
    
    };
    }
    

    更新

    你需要在你的 MyApplication 类中使用 Handler

    Handler.Callback realCallback = null;
    Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (realCallback != null) {
                realCallback.handleMessage(msg);
            }
        };
    };
    public Handler getHandler() {
        return handler;
    }
    public void setCallBack(Handler.Callback callback) {
        this.realCallback = callback;
    }
    

    【讨论】:

    • 能否也链接 AbstractActivity 类?
    • AbstractActivity 只不过是您所有活动的基本活动,因此只需创建一个扩展Activity 的抽象类,然后在所有活动中扩展您的基本活动而不是Activity跨度>
    • 酷,我已经有这样的课了。您能解释一下如何从 MyApplication 类中获取 Handler 吗? mHandler = ((MyAplication) getApplication()).getHandler(); 我也有一个 MyApplication 类,但不知道如何将 Handler 传递给它。
    • 您需要在 MyApplication 类中定义一个处理程序,并为此定义 geter seter,我已经更新了我的帖子
    • MyAplication 包含什么?或者它是什么类,启动服务的类?谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    • 2017-05-24
    • 1970-01-01
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多