How to show camera preview on another device via Bluetooth?

I am trying to create an application for a Bluetooth camera in which 2 devices are connected via Bluetooth and when I press the start button on device 1 it should launch the camera on device 2 and the camera’s preview should be displayed on both devices. When the user clicks capture on device 1, device 2 should take a picture.

Full project here

I am using a bluetooth chat code sample, I can give a start command, but I don’t get how to show the preview data stream from the camera which is in byte [], and show the preview on another device

I tried converting byte [] to a bitmap, but the bitmap is null.

Preview data on device 1

camera.setPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {

                  //Here I am writing data through connected channel
                  //tried to convert byte[] to bitmap here also but its showing null
             BitmapFactory.Options options = new BitmapFactory.Options();
            bitmap = BitmapFactory.decodeByteArray(image, 0, image.length, options); 
               //setting bitmap to imageview but bitmap itself is null


            }

On another device, it continuously reads the data written by device 1, and the handler transfers the read data in byte [], and this byte [] I try to show either in the surface view or in the image, but both of them do not work

BluetoothCameraFragment

public class BluetoothCameraFragment extends Fragment implements SurfaceHolder.Callback{


TextView testView;
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
Camera.PictureCallback rawCallback;
Camera.ShutterCallback shutterCallback;
Camera.PictureCallback jpegCallback;
private final String tag = "tagg";

Button start, stop, capture;

private static final String TAG = "BluetoothCamera";


private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
private static final int REQUEST_ENABLE_BT = 3;


private ListView mConversationView;
private EditText mOutEditText;
private Button mSendButton;
private ImageView imageview;


private String mConnectedDeviceName = null;


private ArrayAdapter<String> mConversationArrayAdapter;


private StringBuffer mOutStringBuffer;


private BluetoothAdapter mBluetoothAdapter = null;


private BluetoothCameraManager mCameraService = null;
private boolean isCameraRunning = false;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);

    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();


    if (mBluetoothAdapter == null) {
        FragmentActivity activity = getActivity();
        Toast.makeText(activity, "Bluetooth is not available", Toast.LENGTH_LONG).show();
        activity.finish();
    }
}


@Override
public void onStart() {
    super.onStart();


    if (!mBluetoothAdapter.isEnabled()) {
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent, REQUEST_ENABLE_BT);

    } else if (mCameraService == null) {
        setup();
    }
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (mCameraService != null) {
        mCameraService.stop();
    }
}

@Override
public void onResume() {
    super.onResume();




    if (mCameraService != null) {

        if (mCameraService.getState() == BluetoothCameraManager.STATE_NONE) {

            mCameraService.start();
        }
    }
}

@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                         @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_bluetooth_camera, container, false);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {

    mSendButton = (Button) view.findViewById(R.id.button_send);
    stop = (Button) view.findViewById(R.id.stop);
    capture = (Button) view.findViewById(R.id.capture);
    imageview = (ImageView) view.findViewById(R.id.previewImage);
}


private void setup() {
    Log.d(TAG, "setup()");












    mSendButton.setOnClickListener(new Button.OnClickListener()
    {
        public void onClick(View arg0) {

            sendMessage("start-camera".getBytes());

        }
    });

    View view = getView();
    if (null != view) {
        stop = (Button)view.findViewById(R.id.stop);
        capture = (Button) view.findViewById(R.id.capture);
    }

    stop.setOnClickListener(new Button.OnClickListener()
    {
        public void onClick(View arg0) {
            sendMessage("stop-camera".getBytes());
        }
    });
    capture.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            sendMessage("take-picture".getBytes());
        }
    });

    surfaceView = (SurfaceView)view.findViewById(R.id.surfaceview);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    rawCallback = new Camera.PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.d("Log", "onPictureTaken - raw");
        }
    };


    shutterCallback = new Camera.ShutterCallback() {
        public void onShutter() {
            Log.i("Log", "onShutter'd");
        }
    };
    jpegCallback = new Camera.PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            FileOutputStream outStream = null;
            try {
                outStream = new FileOutputStream(String.format(
                        "/sdcard/%d.jpg", System.currentTimeMillis()));
                outStream.write(data);
                outStream.close();
                Log.d("Log", "onPictureTaken - wrote bytes: " + data.length);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
            }
            Log.d("Log", "onPictureTaken - jpeg");
        }
    };



    mCameraService = new BluetoothCameraManager(getActivity(), mHandler);


    mOutStringBuffer = new StringBuffer("");
}


private void ensureDiscoverable() {
    if (mBluetoothAdapter.getScanMode() !=
            BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
        Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
        startActivity(discoverableIntent);
    }
}


private void sendMessage(byte[] preview) {

    if (mCameraService.getState() != BluetoothCameraManager.STATE_CONNECTED) {
        Toast.makeText(getActivity(), R.string.not_connected, Toast.LENGTH_SHORT).show();
        return;
    }


    Log.d("sttatt","sending data");
        mCameraService.write(preview);



}


private TextView.OnEditorActionListener mWriteListener
        = new TextView.OnEditorActionListener() {
    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {

        if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
            String message = view.getText().toString();

        }
        return true;
    }
};


private void setStatus(int resId) {
    FragmentActivity activity = getActivity();
    if (null == activity) {
        return;
    }
    final ActionBar actionBar = activity.getActionBar();
    if (null == actionBar) {
        return;
    }
    actionBar.setSubtitle(resId);
}


private void setStatus(CharSequence subTitle) {
    FragmentActivity activity = getActivity();
    if (null == activity) {
        return;
    }
    final ActionBar actionBar = activity.getActionBar();
    if (null == actionBar) {
        return;
    }
    actionBar.setSubtitle(subTitle);
}


private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        FragmentActivity activity = getActivity();
        switch (msg.what) {
            case Constants.MESSAGE_STATE_CHANGE:
                switch (msg.arg1) {
                    case BluetoothCameraManager.STATE_CONNECTED:
                        setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));

                        break;
                    case BluetoothCameraManager.STATE_CONNECTING:
                        setStatus(R.string.title_connecting);
                        break;
                    case BluetoothCameraManager.STATE_LISTEN:
                    case BluetoothCameraManager.STATE_NONE:
                        setStatus(R.string.title_not_connected);
                        break;
                }
                break;
            case Constants.START_CAMERA_SERVICE:

                byte[] readBuf = (byte[]) msg.obj;
                String command  = new String(readBuf).toString();
                Log.d("cammy", "" + command);
                if(command.equals("start-camera")){
                    Log.d("cammy","Startcam");
                    start_camera();
                    Toast.makeText(getActivity(),"starting camera",Toast.LENGTH_LONG).show();

                }else if(command.equals("stop-camera")){
                    Log.d("cammy","Stopcam");
                    stop_camera();
                    Toast.makeText(getActivity(),"stopping camera",Toast.LENGTH_LONG).show();
                }else if(command.equals("take-picture")){
                    Log.d("cammy","takepic");
                    captureImage();
                    Toast.makeText(getActivity(),"Take picture",Toast.LENGTH_LONG).show();
                }else {
                    Log.d("cammy","No trigger");
                }



                break;
            case Constants.STOP_CAMERA:

                break;
            case Constants.TAKE_PICTURE:

                break;
            case Constants.MESSAGE_WRITE:

                mSendButton.setClickable(false);


                Log.d("sttatt","writing data");





                break;
            case Constants.MESSAGE_READ:








                break;
            case Constants.MESSAGE_DEVICE_NAME:

                mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
                if (null != activity) {
                    Toast.makeText(activity, "Connected to "
                            + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                }
                break;
            case Constants.MESSAGE_TOAST:
                if (null != activity) {
                    Toast.makeText(activity, msg.getData().getString(Constants.TOAST),
                            Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
};

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_CONNECT_DEVICE_SECURE:

            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, true);
            }
            break;
        case REQUEST_CONNECT_DEVICE_INSECURE:

            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data, false);
            }
            break;
        case REQUEST_ENABLE_BT:

            if (resultCode == Activity.RESULT_OK) {

                setup();
            } else {

                Log.d(TAG, "BT not enabled");
                Toast.makeText(getActivity(), R.string.bt_not_enabled_leaving,
                        Toast.LENGTH_SHORT).show();
                getActivity().finish();
            }
    }
}


private void connectDevice(Intent data, boolean secure) {

    String address = data.getExtras()
            .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);

    BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);

    mCameraService.connect(device, secure);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.bluetooth_camera, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.secure_connect_scan: {

            Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
            return true;
        }
        case R.id.insecure_connect_scan: {

            Intent serverIntent = new Intent(getActivity(), DeviceListActivity.class);
            startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
            return true;
        }
        case R.id.discoverable: {

            ensureDiscoverable();
            return true;
        }
    }
    return false;
}


private void captureImage() {
    camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}

private void start_camera(){
    try{
        camera = Camera.open();
        isCameraRunning=true;
    }catch(RuntimeException e){
        Log.e(tag, "init_camera: " + e);
        return;
    }
    Camera.Parameters param;
    param = camera.getParameters();

    param.setPreviewFrameRate(20);
    param.setPreviewSize(176, 144);
    camera.setParameters(param);
    try {
        camera.setPreviewDisplay(surfaceHolder);
        camera.setPreviewCallback(new Camera.PreviewCallback() {
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) {




            }
        });
        camera.startPreview();

    } catch (Exception e) {
        Log.e(tag, "init_camera: " + e);
        return;
    }
}

private void stop_camera()
{
        camera.stopPreview();
        camera.release();
}

public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {

}

public void surfaceCreated(SurfaceHolder holder) {

}

public void surfaceDestroyed(SurfaceHolder holder) {

}

}

Bluetoothmanager

 public class BluetoothCameraManager {

private static final String TAG = "rolf";

private static final String NAME_SECURE = "BluetoothCameraSecure";
private static final String NAME_INSECURE = "BluetoothCameraInsecure";


private static final UUID MY_UUID_SECURE =
        UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final UUID MY_UUID_INSECURE =
        UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");


private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mSecureAcceptThread;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;


public static final int STATE_NONE = 0;       
public static final int STATE_LISTEN = 1;     
public static final int STATE_CONNECTING = 2; 
public static final int STATE_CONNECTED = 3;  


public BluetoothCameraManager(Context context, Handler handler) {
    mAdapter = BluetoothAdapter.getDefaultAdapter();
    mState = STATE_NONE;
    mHandler = handler;
}


private synchronized void setState(int state) {
    Log.d(TAG, "setState() " + mState + " -> " + state);
    mState = state;


    mHandler.obtainMessage(Constants.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}


public synchronized int getState() {
    return mState;
}


public synchronized void start() {
    Log.d(TAG, "start");


    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }


    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;
    }

    setState(STATE_LISTEN);


    if (mSecureAcceptThread == null) {
        mSecureAcceptThread = new AcceptThread(true);
        mSecureAcceptThread.start();
    }
    if (mInsecureAcceptThread == null) {
        mInsecureAcceptThread = new AcceptThread(false);
        mInsecureAcceptThread.start();
    }
}


public synchronized void connect(BluetoothDevice device, boolean secure) {
    Log.d(TAG, "connect to: " + device);


    if (mState == STATE_CONNECTING) {
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }
    }


    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;
    }


    mConnectThread = new ConnectThread(device, secure);
    mConnectThread.start();
    setState(STATE_CONNECTING);
}


public synchronized void connected(BluetoothSocket socket, BluetoothDevice
        device, final String socketType) {
    Log.d(TAG, "connected, Socket Type:" + socketType);


    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }


    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;
    }


    if (mSecureAcceptThread != null) {
        mSecureAcceptThread.cancel();
        mSecureAcceptThread = null;
    }
    if (mInsecureAcceptThread != null) {
        mInsecureAcceptThread.cancel();
        mInsecureAcceptThread = null;
    }


    mConnectedThread = new ConnectedThread(socket, socketType);
    mConnectedThread.start();


    Message msg = mHandler.obtainMessage(Constants.MESSAGE_DEVICE_NAME);
    Bundle bundle = new Bundle();
    bundle.putString(Constants.DEVICE_NAME, device.getName());
    msg.setData(bundle);
    mHandler.sendMessage(msg);

    setState(STATE_CONNECTED);
}


public synchronized void stop() {
    Log.d(TAG, "stop");

    if (mConnectThread != null) {
        mConnectThread.cancel();
        mConnectThread = null;
    }

    if (mConnectedThread != null) {
        mConnectedThread.cancel();
        mConnectedThread = null;
    }

    if (mSecureAcceptThread != null) {
        mSecureAcceptThread.cancel();
        mSecureAcceptThread = null;
    }

    if (mInsecureAcceptThread != null) {
        mInsecureAcceptThread.cancel();
        mInsecureAcceptThread = null;
    }
    setState(STATE_NONE);
}


public void write(byte[] out) {

    ConnectedThread r;

    synchronized (this) {
        if (mState != STATE_CONNECTED) return;
        r = mConnectedThread;
    }

    r.write(out);
}


private void connectionFailed() {

    Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString(Constants.TOAST, "Unable to connect device");
    msg.setData(bundle);
    mHandler.sendMessage(msg);


    BluetoothCameraManager.this.start();
}


private void connectionLost() {

    Message msg = mHandler.obtainMessage(Constants.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString(Constants.TOAST, "Device connection was lost");
    msg.setData(bundle);
    mHandler.sendMessage(msg);

    BluetoothCameraManager.this.start();
}


private class AcceptThread extends Thread {

    private final BluetoothServerSocket mmServerSocket;
    private String mSocketType;

    public AcceptThread(boolean secure) {
        BluetoothServerSocket tmp = null;
        mSocketType = secure ? "Secure" : "Insecure";


        try {
            if (secure) {
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
                        MY_UUID_SECURE);
            } else {
                tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
                        NAME_INSECURE, MY_UUID_INSECURE);
            }
        } catch (IOException e) {
            Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
        }
        mmServerSocket = tmp;
    }

    public void run() {
        Log.d(TAG, "Accept thread: " + mSocketType +
                "BEGIN mAcceptThread" + this);
        setName("AcceptThread" + mSocketType);

        BluetoothSocket socket = null;


        while (mState != STATE_CONNECTED) {
            try {


                socket = mmServerSocket.accept();
            } catch (IOException e) {
                Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
                break;
            }


            if (socket != null) {
                synchronized (BluetoothCameraManager.this) {
                    switch (mState) {
                        case STATE_LISTEN:
                        case STATE_CONNECTING:

                            connected(socket, socket.getRemoteDevice(),
                                    mSocketType);
                            break;
                        case STATE_NONE:
                        case STATE_CONNECTED:

                            try {
                                socket.close();
                            } catch (IOException e) {
                                Log.e(TAG, "Could not close unwanted socket", e);
                            }
                            break;
                    }
                }
            }
        }
        Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);

    }

    public void cancel() {
        Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
        try {
            mmServerSocket.close();
        } catch (IOException e) {
            Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
        }
    }
}



private class ConnectThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
    private String mSocketType;

    public ConnectThread(BluetoothDevice device, boolean secure) {
        mmDevice = device;
        BluetoothSocket tmp = null;
        mSocketType = secure ? "Secure" : "Insecure";



        try {
            if (secure) {
                tmp = device.createRfcommSocketToServiceRecord(
                        MY_UUID_SECURE);
            } else {
                tmp = device.createInsecureRfcommSocketToServiceRecord(
                        MY_UUID_INSECURE);
            }
        } catch (IOException e) {
            Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
        }
        mmSocket = tmp;
    }

    public void run() {
        Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
        setName("ConnectThread" + mSocketType);


        mAdapter.cancelDiscovery();


        try {


            mmSocket.connect();
        } catch (IOException e) {

            try {
                mmSocket.close();
            } catch (IOException e2) {
                Log.e(TAG, "unable to close() " + mSocketType +
                        " socket during connection failure", e2);
            }
            connectionFailed();
            return;
        }


        synchronized (BluetoothCameraManager.this) {
            mConnectThread = null;
        }


        connected(mmSocket, mmDevice, mSocketType);
    }

    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {
            Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
        }
    }
}


private class ConnectedThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final InputStream mmInStream;
    private final OutputStream mmOutStream;

    public ConnectedThread(BluetoothSocket socket, String socketType) {
        Log.d(TAG, "create ConnectedThread: " + socketType);
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;


        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {
            Log.e(TAG, "temp sockets not created", e);
        }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

    public void run() {
        Log.d(TAG, "BEGIN mConnectedThread");
        byte[] buffer = new byte[1024];
        int bytes;


        while (true) {
            try {

                bytes = mmInStream.read(buffer);
                mHandler.obtainMessage(Constants.START_CAMERA_SERVICE, bytes, -1, buffer)
                        .sendToTarget();




                Log.d(TAG, "Reading");



            } catch (IOException e) {
                Log.e(TAG, "disconnected", e);
                connectionLost();

                BluetoothCameraManager.this.start();
                break;
            }
        }
    }


    public void write(byte[] buffer) {
        try {
            mmOutStream.write(buffer);


        } catch (IOException e) {
            Log.e(TAG, "Exception during write", e);
        }
    }

    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) {
            Log.e(TAG, "close() of connect socket failed", e);
        }
    }
}
}
+2
source share
1 answer

bluetooth , . , , . Bluetooth () . , , . , . , , , ( ). , . Android- . , .

Github. Bluetooth-

+3

Source: https://habr.com/ru/post/1531401/


All Articles