Search code examples
androidsocketsandroid-studiogoogle-glassgoogle-glass-camera

Android Studio Send string over socket after taking a picture [Google Glass]


What I'm trying to do:

User says "find my keys" Google glass takes a picture and stores a string of what you said in a socket to be sent on a port. A second socket is created to send the picture, so the receiver has the voice string and picture in order for further processing.

The problem:

After the picture is taken, I have some Toast.makeText messages along with the socket creation, which is being ignored for some reason.

All of the socket creation is happening under onActivityResult The voice detection happens on onCreate

Code is as follows:

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.FileObserver;
import android.provider.MediaStore;
import android.speech.RecognizerIntent;
import android.util.Log;
import android.widget.Toast;
import com.google.android.glass.content.Intents;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

public class CameraActivity extends Activity {

    private CameraSurfaceView cameraView;


    private static final int TAKE_PICTURE_REQUEST = 1;

    //Take the picture only if the string take_picture from voice control allows for it.
    private void takePicture() {

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(intent, TAKE_PICTURE_REQUEST);
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(resultCode != RESULT_CANCELED)
        {


            if (requestCode == TAKE_PICTURE_REQUEST && resultCode == RESULT_OK) {
                String thumbnailPath = data.getStringExtra(Intents.EXTRA_THUMBNAIL_FILE_PATH);
                String picturePath = data.getStringExtra(Intents.EXTRA_PICTURE_FILE_PATH);

                processPictureWhenReady(picturePath);
                Toast.makeText(getApplicationContext(), "Proceeding to Socket creation.", Toast.LENGTH_LONG).show();

                //Create the java socket and send the file to the android device
                //Need to send out the voice command to the Android phone and the picture
                //for now, send the voice data

                try {

                    Toast.makeText(getApplicationContext(), "Socket created on port 40404", Toast.LENGTH_LONG).show();

                    try {
                        //Define the socket:
                        //Firewall problem.
                        Socket skt = new Socket(InetAddress.getLocalHost(), 40404);
                        //Send the voice data
                        OutputStream outstream = skt.getOutputStream();
                        PrintWriter out = new PrintWriter(outstream);
                        Toast.makeText(getApplicationContext(), "Sending data to Android Device", Toast.LENGTH_LONG).show();
                        out.print(voiceglobal);

                        //The commented out code below will eventually send the picture that you take with the device over a socket
                        //to a recieving device.You can ignore this for now.


                        //long length = pictureToSend.length();

                        //Create a new socket for sending the picture.
                            /*
                            Socket pic_socket = new Socket(InetAddress.getLocalHost(), 50505);
                            byte bytes[];
                            ObjectInputStream ois = new ObjectInputStream(pic_socket.getInputStream());
                            FileOutputStream fos = null;
                            try {
                                bytes = (byte[])ois.readObject();
                                fos = new FileOutputStream(pictureToSend);
                                fos.write(bytes);
                            } catch (ClassNotFoundException e)
                            {
                                e.printStackTrace();

                            } finally {
                                if(fos!= null)
                                {
                                    fos.close();
                                }
                            }
                            */
                        //////////////////////////////////////////////
                        //////////////////


                    } catch (UnknownHostException e) {

                        //Handle this.
                        System.err.print(e);
                    }
                } catch (IOException v) {
                   // handle this.
                    System.err.print(v);
                    }
            }

            //Define the socket:

            //Make sure this works and then write the code for


            /////////////////////////////////////////////////////////////////////////
            //////////////////////////////////////////////////////////////////////


        } //if resultCode != RESULT_CANCELED

        super.onActivityResult(requestCode, resultCode, data);
    }

    //Define global path to picture file.
    //Test the path by using the recieving connection.
    File pictureToSend;


    private void processPictureWhenReady(final String picturePath) {
        final File pictureFile = new File(picturePath);
        ////////////////////////////////////////////////////////
        //////
        pictureToSend = pictureFile; //Global for sending the picture.
        ////////////////////////////////////////////////////////
        /////

        if (pictureFile.exists()) {
            // The picture is ready; process it.

        } else {
            // The file does not exist yet. Before starting the file observer, you
            // can update your UI to let the user know that the application is
            // waiting for the picture (for example, by displaying the thumbnail
            // image and a progress indicator).

            final File parentDirectory = pictureFile.getParentFile();
            FileObserver observer = new FileObserver(parentDirectory.getPath(),
                    FileObserver.CLOSE_WRITE | FileObserver.MOVED_TO) {
                // Protect against additional pending events after CLOSE_WRITE
                // or MOVED_TO is handled.
                private boolean isFileWritten;

                @Override
                public void onEvent(int event, String path) {
                    if (!isFileWritten) {
                        // For safety, make sure that the file that was created in
                        // the directory is actually the one that we're expecting.
                        File affectedFile = new File(parentDirectory, path);
                        isFileWritten = affectedFile.equals(pictureFile);

                        if (isFileWritten) {
                            stopWatching();

                            // Now that the file is ready, recursively call
                            // processPictureWhenReady again (on the UI thread).
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    processPictureWhenReady(picturePath);
                                }
                            });
                        }
                    }
                }
            };
            observer.startWatching();
        }
    }


    public byte[] imgbyte;
    public String voiceglobal;




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

        //Initiate CameraView
        cameraView = new CameraSurfaceView(this); //Calls CameraSurfaceView

        // Set the view
        this.setContentView(cameraView);



        //VOICE DETECTION HAPPENS HERE.
        ArrayList<String> voiceRes = getIntent().getExtras().getStringArrayList(RecognizerIntent.EXTRA_RESULTS);
        String Voicedata = voiceRes.toString();
        Log.d("Voicedata was ", Voicedata);
        voiceglobal = Voicedata;


        // "Dynamic" voice detection ...
        if((Voicedata.equals("[take a picture]")) || (Voicedata.equals("[find my cup]")) || (Voicedata.equals("[find my keys]")))
        {
            //Then take the picture.
             takePicture();

        } // if voicedata equals

        else if(!Voicedata.equals("take a picture"))
        {
            //Make a toast that says it's wrong.
            Toast.makeText(getApplicationContext(), "Try again", Toast.LENGTH_LONG).show();
        }

    }

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

        // Do not hold the camera during onResume
        if (cameraView != null) {
            cameraView.releaseCamera();
        }


    }

    @Override
    protected void onPause() {
        super.onPause();

        // Do not hold the camera during onPause
        if (cameraView != null) {
            cameraView.releaseCamera();
        }
    }






}

Thanks very much in advance. I will post the whole project once it is working for users to play with.


Solution

    1. Check, if you have Internet permission in your manifest <uses-permission android:name="android.permission.INTERNET" />

    2. Move all networking code off the main UI thread. Otherwise, you'll be getting android.os.NetworkOnMainThreadException in the logs. More info here.