关于我当前的设置的一点点:
目前我有一个Android程序分成一堆不同的片段。主片段扫描具有特定 MAC 地址和套接字 UUID 的蓝牙连接。此连接工作正常(还没有问题)。
广播蓝牙服务器是运行 ubuntu 并使用 bluez 广播具有特定 UUID 的特定服务的 beaglebone black。
问题:当我切换到图库片段时,我尝试使用已连接的蓝牙服务发送数据(图片)。
我遇到麻烦的地方是 command outputStream.write(msgBuffer);
。它返回一个“null”错误。
到目前为止,我已经完成了以下调试:
我很想知道原始连接是否有效(在 home 片段中),所以在我通过调用 connect() 连接到蓝牙服务器后,我通过调用 socket.getConnected() 对其进行了测试。这返回 true,意味着蓝牙套接字必须连接到蓝牙服务器。
然后我想看看画廊片段中发生了什么。在使用 outputStream.write(msgBuffer); 发送我的数据之前 命令,我运行了返回 false 的 socket.getConnected()。因此意味着必须断开套接字....为什么蓝牙服务器现在断开连接?我需要做一些特别的事情来保持蓝牙连接打开吗?在切换片段时,我是否需要做任何特别的事情来保持连接处于活动状态?
什么会导致我的连接在这两个事件之间断开?
下面是我的两个片段。
家庭片段
package edu.umass.ecs.chalkmaster3000;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Fragment;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import java.io.IOException;
import java.util.UUID;
/**
* Created by Oskoss on 11/16/13.
*/
public class HomeFragment extends Fragment {
public static final int BT_ACTIVITY = 5;
public int i;
ActivityCommunication activityCallback;
public interface ActivityCommunication{
public void updateColors(int color);
public String getAddress();
public UUID getUUID();
public BluetoothSocket getBTSocket();
public BluetoothAdapter getBTAdapter();
public void setConnectionStatus(boolean status);
public boolean getConnectionStatus();
public View getView(int viewID);
public Context getContext();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
activityCallback = (ActivityCommunication) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement ActivityCommunication");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View V = inflater.inflate(R.layout.home_fragment,container,false);
ImageView robotImage = (ImageView) V.findViewById(R.id.robotStatus);
ImageButton staticRobotImage = (ImageButton) V.findViewById(R.id.button);
TextView status = (TextView) V.findViewById(R.id.textView_Status);
if(activityCallback.getConnectionStatus()){
V.setBackgroundColor(getResources().getColor(R.color.blue));
activityCallback.updateColors(1);
activityCallback.setConnectionStatus(true);
status.setText("Bluetooth Connected to Dusty!");
robotImage.setImageResource(R.drawable.happy_dusty);
Animation pulse = AnimationUtils.loadAnimation(activityCallback.getContext(), R.anim.pulse);
robotImage.startAnimation(pulse);
}
else{
//checkBTStates();
if(BluetoothAdapter.getDefaultAdapter()==null){
V.setBackgroundColor(getResources().getColor(R.color.orange));
staticRobotImage.setImageResource(R.drawable.sad_dusty);
//robotImage.setImageResource(R.drawable.sad_dusty);
status.setText("Your phone has no Bluetooth :/!");
activityCallback.updateColors(0);
activityCallback.setConnectionStatus(false);
}
else{
V.setBackgroundColor(getResources().getColor(R.color.red));
staticRobotImage.setImageResource(R.drawable.sad_dusty);
//robotImage.setImageResource(R.drawable.sad_dusty);
activityCallback.updateColors(2);
activityCallback.setConnectionStatus(false);
}
final ImageButton button = (ImageButton) V.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
checkBTStates();
}
});
}
return V;
}
private void checkBTStates() {
BluetoothAdapter btAdapter = activityCallback.getBTAdapter();
View currentView = activityCallback.getView(R.id.home_fragment);
ImageButton staticRobotImage = (ImageButton) getView().findViewById(R.id.button);
TextView status = (TextView) getView().findViewById(R.id.textView_Status);
// Check for Bluetooth support and then check to make sure it is turned on
if(btAdapter==null) {
status.setText("Fatal Error: Bluetooth doesn't seem to be supported on your device! :(");
staticRobotImage.setImageResource(R.drawable.sad_dusty);
//Toast toast = Toast.makeText(activityCallback.getContext(), "Fatal Error: Bluetooth doesn't seem to be supported on your device! :(", Toast.LENGTH_LONG);
//toast.show();
currentView.setBackgroundColor(getResources().getColor(R.color.orange));
activityCallback.updateColors(0);
activityCallback.setConnectionStatus(false);
//robotImage.setImageResource(R.drawable.sad_dusty);
}
else {
if (btAdapter.isEnabled()) {
connectBT();
}
else {
//Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, BT_ACTIVITY);
}
}
}
public String address = "00:02:72:3F:86:B3";
final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
public BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = btAdapter.getRemoteDevice(address);
BluetoothSocket btSocket = null;
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void connectBT(){
ImageButton staticRobotImage = (ImageButton) getView().findViewById(R.id.button);
TextView status = (TextView) getView().findViewById(R.id.textView_Status);
try {
btSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
status.setText("Fatal Error in onResume() and socket create failed");
//Toast toast = Toast.makeText(activityCallback.getContext(), "Fatal Error in onResume() and socket create failed: " + e.getMessage() + ".", Toast.LENGTH_LONG);
//toast.show();
}
View currentView = activityCallback.getView(R.id.home_fragment);
ImageView robotImage = (ImageView) activityCallback.getView(R.id.robotStatus);
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. In this case we are using the
// UUID for SPP.
// Discovery is resource intensive. Make sure it isn't going on
// when you attempt to connect and pass your message.
btAdapter.cancelDiscovery();
// Establish the connection. This will block until it connects.
try {
btSocket.connect();
if(btSocket.isConnected()){
Toast toast = Toast.makeText(activityCallback.getContext(), "socket is connected", Toast.LENGTH_LONG);
toast.show();
}
currentView.setBackgroundColor(getResources().getColor(R.color.blue));
activityCallback.updateColors(1);
activityCallback.setConnectionStatus(true);
ImageButton connect = (ImageButton) getView().findViewById(R.id.button);
ViewGroup layout = (ViewGroup) connect.getParent();
status.setText("Bluetooth Connected to Dusty!");
robotImage.setImageResource(R.drawable.happy_dusty);
Animation pulse = AnimationUtils.loadAnimation(activityCallback.getContext(), R.anim.pulse);
robotImage.startAnimation(pulse);
if(null!=layout) //for safety only as you are doing onClick
layout.removeView(connect);
} catch (IOException e) {
try {
staticRobotImage.setImageResource(R.drawable.sad_dusty);
currentView.setBackgroundColor(getResources().getColor(R.color.orange));
activityCallback.updateColors(0);
//robotImage.setImageResource(R.drawable.sad_dusty);
status.setText("No Bluetooth server broadcasting to connect to....");
activityCallback.setConnectionStatus(false);
//Toast toast = Toast.makeText(activityCallback.getContext(),"No Bluetooth server broadcasting to connect to....", Toast.LENGTH_LONG);
//toast.show();
btSocket.close();
} catch (IOException e2) {
status.setText("Fatal Error in onResume() and unable to close socket during connection failure");
//Toast toast = Toast.makeText(activityCallback.getContext(),"Fatal Error in onResume() and unable to close socket during connection failure" + e2.getMessage() + ".", Toast.LENGTH_LONG);
//toast.show();
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
TextView status = (TextView) getView().findViewById(R.id.textView_Status);
ImageButton staticRobotImage = (ImageButton) getView().findViewById(R.id.button);
super.onActivityResult(requestCode, resultCode, data);
View currentView = activityCallback.getView(R.id.home_fragment);
switch(requestCode){
case BT_ACTIVITY:
if(resultCode == -1){
i = 50; //Stop asking the user to enable bluetooth
status.setText("Bluetooth is now on!");
connectBT();
Toast.makeText(activityCallback.getContext(), "Bluetooth is now on!", Toast.LENGTH_SHORT).show();
}
else if(resultCode == 0){
staticRobotImage.setImageResource(R.drawable.sad_dusty);
currentView.setBackgroundColor(getResources().getColor(R.color.red));
activityCallback.updateColors(2);
//robotImage.setImageResource(R.drawable.sad_dusty);
activityCallback.setConnectionStatus(false);
status.setText("This application requires Bluetooth...Maybe try to turn it on?! ;)");
//Toast toast = Toast.makeText(activityCallback.getContext(), "This application requires Bluetooth...Maybe try to turn it on?! ;)", Toast.LENGTH_LONG);
//toast.show();
}
break;
}
}
}
画廊片段
package edu.umass.ecs.chalkmaster3000;
import android.widget.CheckBox;
import android.widget.GridView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
public class GalleryFragment extends Fragment {
private int count;
int id;
private Bitmap[] thumbnails;
private boolean[] thumbnailsselection;
private String[] arrPath;
private ImageAdapter imageAdapter;
public OutputStream outStream = null;
public ViewGroup container1 = null;
ActivityCommunication activityCallback;
public interface ActivityCommunication{
public String getAddress();
public UUID getUUID();
public BluetoothSocket getBTSocket();
public boolean getConnectionStatus();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
activityCallback = (ActivityCommunication) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement ActivityCommunication");
}
}
/** Called when the activity is first created. */
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
container1 = container;
View V = inflater.inflate(R.layout.gallery, container, false);
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
final String orderBy = MediaStore.Images.Media._ID;
Cursor imagecursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
columns,
MediaStore.Images.Media.DATA + " like ? ",
new String[]{"%/Robo Pics/%"},
null);
int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
this.count = imagecursor.getCount();
this.thumbnails = new Bitmap[this.count];
this.arrPath = new String[this.count];
this.thumbnailsselection = new boolean[this.count];
for (int i = 0; i < this.count; i++) {
imagecursor.moveToPosition(i);
id = imagecursor.getInt(image_column_index);
int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail(
getActivity().getContentResolver(), id,
MediaStore.Images.Thumbnails.MICRO_KIND, null);
arrPath[i]= imagecursor.getString(dataColumnIndex);
}
GridView imagegrid = (GridView) V.findViewById(R.id.PhoneImageGrid);
imageAdapter = new ImageAdapter();
imagegrid.setAdapter(imageAdapter);
final Button selectBtn = (Button) V.findViewById(R.id.selectBtn);
final Button previewBtn = (Button) V.findViewById(R.id.previewBtn);
final Button deleteBtn = (Button) V.findViewById(R.id.deleteBtn);
selectBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if(activityCallback.getConnectionStatus()){
// TODO Auto-generated method stub
final int len = thumbnailsselection.length;
int cnt = 0;
String selectImages = "";
for (int i =0; i<len; i++)
{
if (thumbnailsselection[i]){
cnt++;
selectImages = selectImages + arrPath[i];
}
}
if (cnt == 0){
Toast.makeText(getActivity(),
"Dusty can't draw anything unless you select an image! Sadface",
Toast.LENGTH_LONG).show();
}
else if(cnt>1){
Toast.makeText(getActivity(),
"Dusty is amazing but he can't draw two images at one time! Sadface",
Toast.LENGTH_LONG).show();
}
else {
byte sendArray[] = readBytes(selectImages);
sendBTData(sendArray);
}
}
else
Toast.makeText(getActivity(), "You need to first connect to Dusty!", Toast.LENGTH_LONG).show();
}
});
previewBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final int len = thumbnailsselection.length;
int cnt = 0;
String selectImages = "";
for (int i =0; i<len; i++)
{
if (thumbnailsselection[i]){
cnt++;
selectImages = selectImages + arrPath[i];
}
}
if (cnt == 0){
Toast.makeText(getActivity(),
"There is nothing to preview! Sadface",
Toast.LENGTH_LONG).show();
}
else if(cnt>1){
Toast.makeText(getActivity(),
"You can't preview more than one thing! Silly",
Toast.LENGTH_LONG).show();
}
else {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + selectImages), "image/*");
startActivity(intent);
}
}
});
deleteBtn.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final int len = thumbnailsselection.length;
int cnt = 0;
String[] storage = new String[len];
for (int i =0; i<len; i++)
{
if (thumbnailsselection[i]){
cnt++;
storage[i] = arrPath[i];
}
}
if (cnt == 0){
Toast.makeText(getActivity(),
"Can't delete nothing! Silly",
Toast.LENGTH_LONG).show();
}
else{
AlertDialog diaBox = AskOption(storage);
diaBox.show();
}
}
});
return V;
}
public class ImageAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public ImageAdapter() {
mInflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return count;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(
R.layout.galleryitem, null);
holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
holder.checkbox = (CheckBox) convertView.findViewById(R.id.yup123);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.checkbox.setId(position);
holder.imageview.setId(position);
holder.checkbox.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
CheckBox cb = (CheckBox) v;
int id = cb.getId();
if (thumbnailsselection[id]){
cb.setChecked(false);
thumbnailsselection[id] = false;
} else {
cb.setChecked(true);
thumbnailsselection[id] = true;
}
}
});
holder.imageview.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
RelativeLayout row = (RelativeLayout) v.getParent();
CheckBox cb = (CheckBox) row.getChildAt(2);
id=cb.getId();
if (thumbnailsselection[id]) {
cb.setChecked(false);
thumbnailsselection[id] = false;
} else {
cb.setChecked(true);
thumbnailsselection[id] = true;
}
}
});
holder.imageview.setImageBitmap(thumbnails[position]);
holder.checkbox.setChecked(thumbnailsselection[position]);
holder.id = position;
return convertView;
}
}
class ViewHolder {
ImageView imageview;
CheckBox checkbox;
int id;
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void sendBTData(byte[] msgBuffer){
String address = activityCallback.getAddress();
UUID MY_UUID = activityCallback.getUUID();
BluetoothSocket btSocket = activityCallback.getBTSocket();
try {
btSocket.connect();
} catch (IOException e) {
try {
e.printStackTrace();
btSocket.close();
} catch (IOException e2) {
e2.printStackTrace();
}
}
// Create a data stream so we can talk to server.
Toast toast1 = Toast.makeText(getActivity(),"Sending message to server...", Toast.LENGTH_LONG);
toast1.show();
try {
outStream = btSocket.getOutputStream();
} catch (IOException e) {
Toast toast = Toast.makeText(getActivity(),"Fatal Error in onResume() and output stream creation failed:" + e.getMessage() + ".", Toast.LENGTH_LONG);
toast.show();
}
try {
if(btSocket.isConnected()){
Toast toast = Toast.makeText(getActivity(), "socket is connected", Toast.LENGTH_LONG);
toast.show();
}
else{
Toast toast = Toast.makeText(getActivity(), "NOT CONNECTEDDDDDD", Toast.LENGTH_LONG);
toast.show();
}
outStream.write(msgBuffer);
Toast.makeText(getActivity(), "Images are now being sent through outter space to Robo for drawing!" , Toast.LENGTH_LONG).show();
} catch (Throwable e) {
String msg = "In onResume() and an exception occurred during write: " + e.getMessage();
e.printStackTrace();
if (address.equals("00:00:00:00:00:00")) {
msg = msg + ".\n\nUpdate your server address from 00:00:00:00:00:00 to the correct address on line 37 in the java code";
}
else{
msg = msg + ".\n\nCheck that the SPP UUID: " + MY_UUID.toString() + " exists on server.\n\n";
}
Toast toast = Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG);
toast.show();
}
}
public byte[] readBytes(String filePath){
BitmapFactory cute = new BitmapFactory();
Bitmap picSend = cute.decodeFile(filePath);
ByteArrayOutputStream stream1 = new ByteArrayOutputStream();
picSend.compress(Bitmap.CompressFormat.PNG, 100, stream1);
byte picByteSend[] = stream1.toByteArray();
return picByteSend;
}
public AlertDialog AskOption(final String[] toBeDeleted)
{
AlertDialog myQuittingDialogBox =new AlertDialog.Builder(getActivity())
//set message, title, and icon
.setTitle("Delete Confirmation")
.setMessage("Are you sure you want to delete the selected pictures?")
.setIcon(R.drawable.new_pic)
.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
for (int i = 0; i < toBeDeleted.length; i++) {
if (toBeDeleted[i] != null) {
File f = new File(toBeDeleted[i]);
if (f.exists()) {
if (f.delete()) {
Log.w("DELETED", "file Deleted");
} else {
Log.w("NOT DELETED", "file not Deleted");
}
}
}
getActivity().sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
Uri.parse("file://" + Environment.getExternalStorageDirectory())));
FragmentManager manager = getActivity().getFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
Fragment newFragment = getFragmentManager().findFragmentByTag("gallery");;
newFragment.onDestroy();
ft.remove(newFragment);
ft.replace(container1.getId(),newFragment);
//container is the ViewGroup of current fragment
ft.addToBackStack(null);
ft.commit();
}
dialog.dismiss();
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.create();
return myQuittingDialogBox;
}
}
一如既往地谢谢你!
编辑:
试图清理一下。如果你不明白这一点,你能告诉我你不明白的地方,以便我提供更多信息吗?