gpt4 book ai didi

java - 如何通过蓝牙在其他设备上显示相机预览?

转载 作者:搜寻专家 更新时间:2023-11-01 08:37:57 25 4
gpt4 key购买 nike

我正在尝试创建一个蓝牙相机应用程序,其中 2 台设备通过蓝牙连接,点击设备 1 上的开始按钮,它应该在设备 2 上启动相机 并且两个设备上都应显示相机预览。当用户在设备 1 上点击拍摄时,设备 2 应该拍摄一张照片。

Full project is here

我正在使用蓝牙聊天示例代码,我可以发出开始命令,但我不知道如何显示来自字节 [] 中的相机的预览数据流并在其他设备上显示预览

我尝试将 byte[] 转换为位图,但位图为空。

在设备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


}

在另一台设备上,它不断读取设备 1 写入的数据,处理程序将读取的数据传递到 byte[] 中,而这个 byte[] 我试图在 surfaceview 或 imageview 中显示,但两者都不起作用

蓝牙相机 fragment

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) {

}

蓝牙管理器

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

最佳答案

通常蓝牙发送图像帧的速度很慢,但您不需要发送每一帧。您将面临的一个问题是帧冲突。蓝牙套接字将您的数据(帧)作为字节数组发送。因此,大多数时候从另一端接收数据时,前一帧和当前帧的字节会发生冲突。因此,您需要确保远程移动设备接收到第一帧并成功处理。远程移动设备正在处理时创建的帧不应存储在缓冲区中以供稍后发送,而应忽略它们(不应发送)。有些帧可能会丢失,但您将作为实时源工作。现在 android 手机将根据相机分辨率创建大帧预览。所以你只需要发送小尺寸的帧,在显示器的剩余空间上你可以显示相机控制。

我已经在我的 Github 存储库中发布了一个示例项目。 Bluetooth Camera

关于java - 如何通过蓝牙在其他设备上显示相机预览?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35146652/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com