24

このアプリケーションは、ユーザーに USB と Bluetooth の 2 つの接続オプションを提供します。USBは正常に動作します。Bluetooth接続のサンプルコードを入手しましたが、アクティビティとして動作するように設計されています。Service で実行しようとしましたが、失敗しました。

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

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

すでにペアリングされていて、その MAC アドレスがわかっているデバイスとの Bluetooth 通信を確立する必要があります。そのため、検出とペアリングのフェーズをスキップできます。接続しようとしているデバイスは常に検出可能で、接続を待機しています。サービスクラスからこれを行い、他のアクティビティを通じてその接続を維持する方法はありますか?

私は使用BluetoothChatServiceしていますDeviceListActivity

4

1 に答える 1

36

バックグラウンドで実行され、Messenger http://developer.android.com/guide/components/bound-services.htmlを使用してアプリケーション内の任意のアクティビティと通信できる Bluetooth サービスを作成しました。

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;
}
于 2013-02-23T08:50:34.353 に答える