0

I'm trying to make an app that uses the camera to take photos and sends this to my NAS, I managed to do create an app through a tutorial, which takes a picture, saves the picture and shows it onscreen. Another tutorial shows me how to upload a "selected" image by pressing an "extra" button on the screen, it's just that I want to get rid of this step and instead of showing the picture, it directly sends the picture to my NAS.

The current app I created:

package com.deshpande.camerademo;

public class MainActivity extends AppCompatActivity {

    private Button takePictureButton;
    private ImageView imageView;
    private Uri file;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        takePictureButton = (Button) findViewById(R.id.button_image);
        imageView = (ImageView) findViewById(R.id.imageview);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            takePictureButton.setEnabled(false);
            ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == 0) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                takePictureButton.setEnabled(true);
            }
        }
    }

    public void takePicture(View view) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        file = Uri.fromFile(getOutputMediaFile());
        intent.putExtra(MediaStore.EXTRA_OUTPUT, file);

        startActivityForResult(intent, 100);
    }

    private static File getOutputMediaFile(){
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), "WedCam");

        if (!mediaStorageDir.exists()){
            if (!mediaStorageDir.mkdirs()){
                Log.d("WedCam", "failed to create directory");
                return null;
            }
        }

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        return new File(mediaStorageDir.getPath() + File.separator +
                    "IMG_"+ timeStamp + ".jpg");
    }

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

            try {

                final FTPClient client = new FTPClient();
                final File image = new File(file.getPath());
                final FileInputStream fis = new FileInputStream(image);

                Thread thread = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try  {

                            client.connect("ftp://127.0.0.1:2221");
                            client.login("francis", "francis");

                            client.storeFile(image.getName(), fis);
                            client.logout();

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });

                thread.start();

            } catch (IOException e) {
                e.printStackTrace();
            }
                }
            }
        }
    }
}

Thanks to @Matthias F. I got it all working, this guy is great!

  • Just combine these two tutorials. First take an image and than upload the created file in `onActivityResult`. – Matthias F. Oct 25 '16 at 14:40
  • Both tutorial have a different approach, the upload tutorial used php and I think I preferre ftp for it. Although I can find quite some ftp example, I can't seem to get them right. I allready have a ftp server, I just need an example code that uses the created file and uploads to my ip adress. If I understand you correctly I need to replace "imageView.setImageURI(file);" – user3032387 Oct 25 '16 at 15:14
  • Yes thats right. You have the created file in the `onActivityResult`-Method. So at this point you need to initiate the upload process. [Here](https://stackoverflow.com/questions/6527664/how-do-you-upload-a-file-to-an-ftp-server) is an example how to upload a file to a ftp-server. – Matthias F. Oct 25 '16 at 15:30
  • I'm sure i'm doing it wrong, I copied the example and added it to my code. Probably the place where I create an InputStream and declare the to be uploaded file is wrong. See updated code – user3032387 Oct 26 '16 at 06:53

1 Answers1

0

You need to use your saved URI from the camera for the FileInputStream. Try it with this:

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

            try {

                final FTPClient client = new FTPClient();
                final File image = new File(file.getPath());
                final FileInputStream fis = new FileInputStream(image);

                Thread thread = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try  {

                            client.connect("127.0.0.1", 2221);
                            client.login("francis", "francis");
                            client.setFileType(FTP.BINARY_FILE_TYPE);

                            client.storeFile(image.getName(), fis);
                            client.logout();

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });

                thread.start(); 

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Now the FileInputStream points to the created image.

EDIT: The problem was that the upload was executed on the ui thread and that is not allowed in android. Now a new thead is created for the upload process. Also I forgot to say that you need to access a android permission for using network functionalities. So you need to set <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> in the AndroidManifest.xml.

Matthias F.
  • 147
  • 2
  • 13
  • Thanks, but at "client.storeFile(filename, fis);" it's can't resolve filename. – user3032387 Oct 26 '16 at 07:49
  • The app can now be installed without errors, but after I get the image and accept it, the app crashes. It does save the picture to the internal storage, so I think it is still having problems with the uploading part. Errorcode added to original post. – user3032387 Oct 26 '16 at 08:52
  • I think we are almost there, when using your code it says "fis" and "client" need to be declared final, because it is accessed from within inner class. After declaring them final, I get "Error:(101, 33) error: cannot assign a value to final variable fis" on line "fis = new FileInputStream(image);" – user3032387 Oct 26 '16 at 10:18
  • I get twice "error: cannot find symbol variable fis" and once "error: cannot find symbol variable client". It's all in the bottom piece of the code. – user3032387 Oct 26 '16 at 11:10
  • New error; "variable fis might not have been initialized" and "variable client might not have been initialized" – user3032387 Oct 26 '16 at 11:18
  • I managed to compile and install apk, i'm running a local ftp server on port 2221, i'm not sure if the code doesn't upload or that i'm using the wrong hostname, etc. I updated my code to the latest. – user3032387 Oct 26 '16 at 14:37
  • The ftp server is running on my phone (127.0.0.1) so i'm not connecting to the pc. If I use a ftp cliënt i'm able to reach my local ftp on my phone and create a folder. – user3032387 Oct 26 '16 at 14:51
  • I updated the code - the method [connect](https://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/SocketClient.html#connect(java.net.InetAddress,%20int)) can handle the host as string and port as integer – Matthias F. Oct 26 '16 at 15:05
  • With your new edit, it's uploading "something" to my ftp server, but its not exactly the photo, it has the same size as the photo that is stored on my phone, but the image consists out of alot of colored lines, while the original photo on my device is correct and viewable. http://oi65.tinypic.com/2cmu4cl.jpg – user3032387 Oct 27 '16 at 06:50
  • The standard transfer file type is ASCII but for non-text files it needs to be binary. I updated my post with the [setting file-type](https://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClient.html#setFileType(int)) equals binary. – Matthias F. Oct 28 '16 at 06:55
  • That did the job, it's working now, I only found 1 bug, which probably has something to do with lay-out? When I press the button to take a picture (phone vertical) when camera is active and I turn the phone horizontal, the app crashes when accepthing the picture. If I take the photo horizontal, but turn it back vertical before accepthing, the app doesn't crash. – user3032387 Oct 28 '16 at 12:26
  • The activity normaly recreates their layout when the screenorientation is changed. So I think the orientation change could stop the uploading process. You can [fix the screenorientation to vertical only](https://stackoverflow.com/questions/5702086/how-to-fix-layout-orientation-to-vertical) or find a solution that does not interrupt the ftp upload. – Matthias F. Oct 28 '16 at 12:36