Bluetooth Connection (Android Sockets)

A little bit about my current setup:

Currently I have a Android program split into a bunch of different fragments. The home fragment scans for a Bluetooth connection with a specific MAC Address, and socket UUID. This connection works fine (no problem yet).

The broadcasting Bluetooth server is a beaglebone black that is running ubuntu and is utilizing bluez to broadcast a specific service with a specific UUID.

Problem: When I switch to the gallery fragment, I then attempt to use the already connected Bluetooth service to send data (pictures).

Where I run into trouble is with the command outputStream.write(msgBuffer);. It returns with a "null" error.

So far for debugging I have done the following:

I was curious to see if the original connection ever worked (in the home fragment), so after I connected to the Bluetooth server with a call to connect(), I then tested it with a call to socket.getConnected(). This returned true, meaning the Bluetooth socket must be connected to the Bluetooth server.

I then wanted to see what was happening in the gallery fragment. Before sending my data with the outputStream.write(msgBuffer); command, I ran socket.getConnected() which returned false. Thus meaning the socket must be disconnected.... Why is the bluetooth server now disconnected? Do I have to do anything special to keep the bluetooth connection open? Do I have to do anything special to keep the connection alive when switching fragments?

What would be causing my connection to disconnect in the time between these two events?

Below are my two fragments.

Home Fragment

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

Gallery Fragment

 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;

    }
}

As always thank you!

Edits:

Tried to clean this up a bit. If you don't understand this, can you tell me what you don't understand so I can provide more information?

Answers


I wasn't passing the sockets correctly between the fragments, and therefore opened up multiple sockets.......needed to take a break from the project to realize such a silly mistake.


Need Your Help

Android Instrumentation Testing how to tell if current Activity is Home (Launcher) Screen?

android instrumentation launcher robotium

I am trying to test drive an application feature using Robotium. One of the features is that when my initial activity is launched from a view on top of the activity stack it should clear the top o...

Angular variables not updating outside loop

javascript angularjs loops angularjs-scope models

So I'm running into a weird issue with Angular where I created a raw predefined object to loop through card stats for a card game I am working on.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.