我必须在哪里初始化处理程序?

问题描述 投票:0回答:1

我正在android studio中使用Java开发第一个蓝牙应用程序。它是一个国际象棋游戏,我想将当前的场地信息从一个设备发送到另一个设备。我查看了https://developer.android.com/guide/topics/connectivity/bluetooth.html处的概述和介绍,在我想连接两个设备之前,它的工作效果很好。我可以在listView中显示另一个设备,当我单击listView中的项目时,我想连接两个设备,但是两个设备都崩溃了,并且出现此异常:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

我已经将初始化从Service类移动到Manager类,也将其移动到Activity,因为我认为我需要在UI线程中进行初始化,但无济于事

这是Bluetoothmanager-Class女巫启动蓝牙并启动接收器以监听设备

public class BluetoothManager extends Observable {
    private BluetoothAdapter adapter;
    private Context context;
    private UUID uuid;
    private BluetoothService service;
    private BluetoothDevice connectedDevice;



    public BluetoothManager(Context c){
         adapter = BluetoothAdapter.getDefaultAdapter();
         context = c;
         uuid = UUID.fromString("1c0bbc73-ae02-4272-b528-752b6b0977c4");
    }

    public boolean supportBluetooth(){

        if(adapter == null){
            return false;
        }else{
            return true;
        }

    }
    public void isEnabled(){
        if(!adapter.isEnabled()){
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            ((Activity) context).startActivityForResult(intent, 1);

            //registerReceiver();
        }
        enableDiscoverability();
    }


    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(action.equals(BluetoothDevice.ACTION_FOUND)){
                setChanged();
                notifyObservers(intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE));
            }
        }
    };

    public BroadcastReceiver getReceiver() {
        return receiver;
    }

    public void enableDiscoverability(){
        Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        context.startActivity(intent);
        AcceptThread acceptThread = new AcceptThread();
        acceptThread.start();
    }

    public Set<BluetoothDevice> getPaired(){
        return adapter.getBondedDevices();
    }

    public void manageSocket(BluetoothSocket socket){


            Handler handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    System.out.println(msg.toString());
                }
            };
        service = new BluetoothService(socket, handler);
        service.write();
    }

    public void connect(BluetoothDevice device){
        ConnectThread thread = new ConnectThread(device);
        thread.start();
    }

    private class AcceptThread extends Thread{
        private final BluetoothServerSocket serverSocket;

        private AcceptThread() {
            BluetoothServerSocket tmp = null;
            try{
                tmp = adapter.listenUsingInsecureRfcommWithServiceRecord(context.getString(R.string.app_name), uuid);
            }catch (IOException e){
                System.out.println("FAILED");
            }
            serverSocket = tmp;
        }

        @Override
        public void run() {
            BluetoothSocket socket = null;
            while (true){
                try{
                    socket = serverSocket.accept();

                    if(socket != null){
                        manageSocket(socket);
                        serverSocket.close();
                        break;
                    }
                }catch (IOException e){
                    System.out.println("FAILED");
                    break;
                }
            }


        }

        public void cancel(){
            try {
                serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private class ConnectThread extends Thread {
        private final BluetoothSocket socket;
        private final BluetoothDevice device;

        public ConnectThread(BluetoothDevice mdevice) {

            BluetoothSocket tmp = null;
            device = mdevice;

            try {
                tmp = device.createRfcommSocketToServiceRecord(uuid);
            } catch (IOException e) {
                System.out.println("FAILED");
            }
            socket = tmp;
        }

        public void run() {
            adapter.cancelDiscovery();

            try {
                socket.connect();
            } catch (IOException connectException) {
                // Unable to connect; close the socket and return.
                try {
                    socket.close();
                } catch (IOException closeException) {
                    System.out.println("FAILED");
                }
                return;
            }

            // The connection attempt succeeded. Perform work associated with
            // the connection in a separate thread.
            manageSocket(socket);
        }

        // Closes the client socket and causes the thread to finish.
        public void cancel() {
            try {
                socket.close();
            } catch (IOException e) {
                System.out.println("FAILED");
            }
        }
    }

}

这是我要在设备之间传输数据的BluetoothService-Class:

public class BluetoothService {
        private static final String TAG = "MY_APP_DEBUG_TAG";
        private Handler handler;
        private BluetoothSocket socket;
        private ConnectedThread thread;

    public BluetoothService(BluetoothSocket socket, Handler handler){
            this.socket = socket;
            this.handler = handler;
            thread = new ConnectedThread();
            thread.start();
        }


        private interface MessageConstants {
            public static final int MESSAGE_READ = 0;
            public static final int MESSAGE_WRITE = 1;
            public static final int MESSAGE_TOAST = 2;


        }

        private class ConnectedThread extends Thread {
            private final BluetoothSocket mmSocket;
            private final InputStream mmInStream;
            private final OutputStream mmOutStream;
            private byte[] mmBuffer;

            public ConnectedThread() {
                mmSocket = socket;
                InputStream tmpIn = null;
                OutputStream tmpOut = null;

                try {
                    tmpIn = socket.getInputStream();
                } catch (IOException e) {
                    Log.e(TAG, "Error occurred when creating input stream", e);
                }
                try {
                    tmpOut = socket.getOutputStream();
                } catch (IOException e) {
                    Log.e(TAG, "Error occurred when creating output stream", e);
                }

                mmInStream = tmpIn;
                mmOutStream = tmpOut;

            }


            public void run() {
                mmBuffer = new byte[1024];
                int numBytes;

                while (true) {
                    try {

                        numBytes = mmInStream.read(mmBuffer);
                        Message readMsg = handler.obtainMessage( MessageConstants.MESSAGE_READ, numBytes, -1,mmBuffer);
                        readMsg.sendToTarget();

                    } catch (IOException e) {
                        Log.d(TAG, "Input stream was disconnected", e);
                        break;
                    }
                }
            }



            public void write(byte[] bytes) {
                try {
                    mmOutStream.write(bytes);
                    Message writtenMsg = handler.obtainMessage(MessageConstants.MESSAGE_WRITE, -1, -1, mmBuffer);
                    writtenMsg.sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "Error occurred when sending data", e);

                    // Send a failure message back to the activity.
                    Message writeErrorMsg = handler.obtainMessage(MessageConstants.MESSAGE_TOAST);
                    Bundle bundle = new Bundle();
                    bundle.putString("toast",  "Couldn't send data to the other device");
                    writeErrorMsg.setData(bundle);
                    handler.sendMessage(writeErrorMsg);
                }
            }

            public void cancel() {
                try {
                    mmSocket.close();
                } catch (IOException e) {
                    Log.e(TAG, "Could not close the connect socket", e);
                }
            }
        }

    public Handler getHandler() {
        return handler;
    }
    public void write(){
        String s = "HALLO WELT";
        byte[] bytes = s.getBytes();
        thread.write(bytes);
    }

    public void setHandler(Handler handler) {
        this.handler = handler;
    }
}

这是MainActivtiy,我在其中创建对象

public class ChessActivity extends AppCompatActivity implements Observer {


    private RelativeLayout layout;
    private Game game;
    private ChessCanvas canvas;
    private BluetoothManager manager;
    private List<BluetoothDevice> devices;
    private ListView deviceList;
    private DeviceListAdapter adapter;
    private TextView status;



    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chess);
        Persister.init(this);
        layout = findViewById(R.id.layout);
        deviceList = findViewById(R.id.deviceList);
        status = findViewById(R.id.status);
        devices = new ArrayList<>();
        adapter = new DeviceListAdapter(this, android.R.layout.simple_list_item_1, (List) devices);
        deviceList.setAdapter(adapter);


        canvas = new ChessCanvas(this);
        layout.addView(canvas);
        game = new Game(canvas);

        deviceList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                manager.connect((BluetoothDevice) parent.getItemAtPosition(position));
            }
        });


        canvas.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (game.getPoints() == null || game.getPoints().isEmpty() || game.touchedOther(motionEvent)) {
                    game.getFigure(motionEvent);

                } else {
                    game.turn(motionEvent);
                }
                Persister.persist(game.getField());
                game.update();
                return false;
            }
        });


        start();
    }


    private void start() {
        startBluetooth();

        if(Persister.getGame() == null) {
            game.createField();
            Persister.setGame(game.getField());
            Persister.persist(game.getField());
        }else{
            game.setField(Persister.getGame());
        }
        game.update();



    }

    private void startBluetooth() {
        manager = new BluetoothManager(this);
        if(manager.supportBluetooth()){
            manager.isEnabled();
            devices.addAll(manager.getPaired());
            registerReceiver(manager.getReceiver(), new IntentFilter(BluetoothDevice.ACTION_FOUND));
        }else{
            System.out.println("KEIN BLUETOTH");
        }
        displayBluetoothList();
    }



    @Override
    public void update(Observable o, Object arg) {
        BluetoothDevice device = (BluetoothDevice) arg;
        devices.add(device);
        displayBluetoothList();
    }

    private void displayBluetoothList() {
        adapter.notifyDataSetChanged();
        deviceList.setVisibility(View.VISIBLE);
        layout.removeView(deviceList);

        AlertDialog adb = new AlertDialog.Builder(this).create();
        adb.setTitle("Bluetooth Geräte");
        adb.setView(deviceList);
        adb.show();

    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(manager.getReceiver());
    }


}

我应该在哪里创建并初始化处理程序对象?感谢您的帮助!

java android android-bluetooth
1个回答
0
投票

错误消息并不表示您必须移动代码。它说您必须在创建新处理程序之前调用Looper.prepare()

© www.soinside.com 2019 - 2024. All rights reserved.