Saving photos to the SD card, automatically creating a folder for it and generating an ID for the photos

4k views Asked by At

The application I created consists of 2 activities – SimpleCamMain.java contains a camera preview window (that displays what the camera is ‘seeing’) and allows a picture to be taken, SimpleCamImageView.java will display the picture that has been taken. From SimpleCamImageView.java, I have a save image button. I want to use it to save photos to the SD card, automatically creating a folder for it and generating an ID for the photos and bringing me back to SimpleCamMain.java. Currently I can only return back to SimpleCamMain.java without successfully saving.

My SimpleCamMain.java code :

package sg.edu.tp.iit.mns;

import java.io.FileOutputStream;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;

public class SimpleCamMain extends Activity implements OnClickListener 
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ImageButton btnSnap = (ImageButton)findViewById(R.id.btn_snap);
    btnSnap.setOnClickListener(this);

    preview = (SurfaceView)findViewById(R.id.sfc_preview);
    previewHolder = preview.getHolder();
    previewHolder.addCallback(surfaceCallback);
    previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    }

    private SurfaceView preview=null;
    private SurfaceHolder previewHolder=null;
    private Camera camera=null;
    private boolean inPreview=false;
    SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
        public void surfaceCreated(SurfaceHolder holder) {
            try {
                // When surface as been created, set the camera’s
                // preview display to be this surface
                camera.setPreviewDisplay(previewHolder);
            } catch (Exception ex) {
                Log.e(this.getClass().getSimpleName(),
                    "Exception in setPreviewDisplay()", ex);
                TextView txtMessage = (TextView)findViewById(
                    R.id.txt_message);
                txtMessage.setText(ex.getMessage());
            }
        }

        public void surfaceChanged(SurfaceHolder holder, int format,
            int width, int height) {
            // Start the camera preview
            camera.startPreview();
            inPreview=true;
        }

        public void surfaceDestroyed(SurfaceHolder holder) { }
    };

    @Override
    public void onResume() {
        super.onResume();
        camera=Camera.open();
    }

    @Override
    public void onPause() {
        if (inPreview) {
            camera.stopPreview();
        }

        camera.release();
        camera=null;
        inPreview=false;

        super.onPause();
    }

    public void onClick(View v) {
        if (inPreview) {
            camera.takePicture(null, null, new Camera.PictureCallback()
            {
                public void onPictureTaken(byte[] data, Camera camera)
                {
                    // Picture successfully taken
                    TextView txtMsg = (TextView)findViewById(R.id.txt_message);
                    txtMsg.setText("Picture taken");

                    try 
                    {
                        // Save the picture to a file
                        FileOutputStream fos = openFileOutput("SimpleCam.jpg", 
                            Context.MODE_PRIVATE);
                        fos.write(data);
                        fos.close();

                        // Launching new activity to view captured image
                        Intent intent = new Intent();
                        intent.setClassName("sg.edu.tp.iit.mns", 
                            "sg.edu.tp.iit.mns.SimpleCamImageView");
                        startActivity(intent);
                    } 
                    catch (Exception ex) 
                    {
                        txtMsg.setText("Could not save picture");
                        ex.printStackTrace();
                    }
                }
            });
        }
    }
}

My SimpleCamImageView.java code :

package sg.edu.tp.iit.mns;

import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;

public class SimpleCamImageView extends Activity implements OnClickListener
{
    private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
    private Uri fileUri;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.imageview);

        ImageButton btnDelete = (ImageButton)findViewById(R.id.btn_delete);
        btnDelete.setOnClickListener(this);

        ImageButton btnSave = (ImageButton)findViewById(R.id.btn_save);
        btnSave.setOnClickListener(this);
    }

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

        try {
            FileInputStream fis = openFileInput("SimpleCam.jpg");
            Bitmap image = BitmapFactory.decodeStream(fis);
            ImageView imgImage = (ImageView)findViewById(R.id.img_image);
            imgImage.setImageBitmap(image);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
         switch(v.getId()){

         case R.id.btn_delete:
             Intent intent = new Intent();
             intent.setClassName("sg.edu.tp.iit.mns", 
                 "sg.edu.tp.iit.mns.SimpleCamMain");
             startActivity(intent);
             break;

         case R.id.btn_save: /** AlerDialog when click on Exit */
             Intent intent2 = new Intent();
             String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".jpg";
             File image_file = new File(this.getExternalFilesDir(Environment.DIRECTORY_PICTURES), timeStamp);
             Uri imageUri = Uri.fromFile(image_file); 
             intent2.setClassName("sg.edu.tp.iit.mns", 
                     "sg.edu.tp.iit.mns.SimpleCamMain");
             startActivityForResult(intent2, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE); 
             break;
         }
    }
}

My SimpleCam Manifest :

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="sg.edu.tp.iit.mns"
      android:versionCode="1"
      android:versionName="1.0">
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".SimpleCamMain"
                  android:label="@string/app_name" android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SimpleCamImageView" android:screenOrientation="landscape" android:label="@string/app_name"></activity>

    </application>
</manifest>

This is what the LogCat shows when i press save :

01-26 02:04:32.645: INFO/wpa_supplicant(194): CTRL-EVENT-SCAN-RESULTS  Ready
01-26 02:04:32.645: INFO/wpa_supplicant(194): wpa_disabled_ssid_list_clear
01-26 02:04:32.645: VERBOSE/WifiMonitor(97): Event [wpa_disabled_ssid_list_clear]
01-26 02:04:32.653: VERBOSE/AlarmManager(97): Adding Alarm{44ff9298 type 2 com.google.android.apps.maps} Dec 14 03:42:21 am
01-26 02:04:32.903: INFO/ActivityManager(97): Starting activity: Intent { cmp=sg.edu.tp.iit.mns/.SimpleCamMain }
01-26 02:04:32.914: DEBUG/AndroidRuntime(3023): Shutting down VM
01-26 02:04:32.914: WARN/dalvikvm(3023): threadid=1: thread exiting with uncaught exception (group=0x40028a00)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023): FATAL EXCEPTION: main
01-26 02:04:32.923: ERROR/AndroidRuntime(3023): java.lang.NullPointerException
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at sg.edu.tp.iit.mns.SimpleCamImageView.onClick(SimpleCamImageView.java:82)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at android.view.View.performClick(View.java:2408)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at android.view.View$PerformClick.run(View.java:8817)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at android.os.Handler.handleCallback(Handler.java:587)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at android.os.Handler.dispatchMessage(Handler.java:92)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at android.os.Looper.loop(Looper.java:143)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at android.app.ActivityThread.main(ActivityThread.java:4914)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at java.lang.reflect.Method.invokeNative(Native Method)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at java.lang.reflect.Method.invoke(Method.java:521)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
01-26 02:04:32.923: ERROR/AndroidRuntime(3023):     at dalvik.system.NativeStart.main(Native Method)
01-26 02:04:33.414: WARN/ActivityManager(97): Activity pause timeout for HistoryRecord{4516ea08 sg.edu.tp.iit.mns/.SimpleCamImageView}

My latest edit on SimpleCamImageView.java. When I click image button btn_save, it brings me back to SimpleCamMain.java with the message "The image has been successfully saved." but the photo still isn't saved to the SD card. I can't figure out whats wrong.

package sg.edu.tp.iit.mns;

import java.io.File;
import java.io.FileInputStream;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;

public class SimpleCamImageView extends Activity implements OnClickListener
{
    public static final int MEDIA_TYPE_IMAGE = 1;

    String filename = "image.png";
    String filePrefix = "image";
    String fileSuffix = ".png";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.imageview);

        ImageButton btnDelete = (ImageButton)findViewById(R.id.btn_delete);
        btnDelete.setOnClickListener(this);

        ImageButton btnSave = (ImageButton)findViewById(R.id.btn_save);
        btnSave.setOnClickListener(this);
    }

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

        try {
            FileInputStream fis = openFileInput("SimpleCam.jpg");
            Bitmap image = BitmapFactory.decodeStream(fis);
            ImageView imgImage = (ImageView)findViewById(R.id.img_image);
            imgImage.setImageBitmap(image);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
         switch(v.getId()){

         case R.id.btn_delete:
             Intent intent = new Intent();
             intent.setClassName("sg.edu.tp.iit.mns", 
             "sg.edu.tp.iit.mns.SimpleCamMain");
             startActivity(intent);
            break;

         case R.id.btn_save: 
             File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); 
                if (!path.exists()) path.mkdirs();
                File file = new File(path, filename); 
                int i = 1;
                while (file.exists()) {
                    file = new File(path, filePrefix + Integer.toString(i) + fileSuffix);
                    i++; 
                }
             Intent intent2 = new Intent();
             intent2.setClassName("sg.edu.tp.iit.mns", 
                 "sg.edu.tp.iit.mns.SimpleCamMain");
             startActivityForResult(intent2, MEDIA_TYPE_IMAGE); 




                    String msg = getString(R.string.succ_save, file.getName(), path.getAbsolutePath());
                    Toast.makeText(SimpleCamImageView.this, msg, Toast.LENGTH_LONG).show();
             break;
         }
    }
}
1

There are 1 answers

8
Chad Schultz On

It sounds to me like you want to know how to save the contents of an ImageView or Bitmap object as a file. I actually recently wrote some code to do pretty much exactly that--you should be able to adapt this to your purposes.

It will generally save to /ext/sdcard/Pictures (creating the directory if not available) and will increment the filename as often as necessary until it does not conflict with an existing filename. Then it changes the ImageView to a Bitmap, saves it, and then shows a Toast that tells the user the filename and where it was saved. You'll need to do some adaptation--such as supplying filename, filePrefix, fileSuffix--but this should help you out!

File path = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES);
        if (!path.exists()) path.mkdirs();
        File file = new File(path, filename);
        int i = 1;
        while (file.exists()) {
            file = new File(path, filePrefix + Integer.toString(i) + fileSuffix);
            i++;
        }

        Drawable d = wheelImage.getDrawable();
        Bitmap bmp=((BitmapDrawable)d).getBitmap();
        FileOutputStream fos;
        try {
            fos = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        bmp.compress(Bitmap.CompressFormat.PNG, 90, fos);

        String msg = getString(R.string.file_written, file.getName(), path.getAbsolutePath());
        Toast.makeText(WheelResultsActivity.this, msg, Toast.LENGTH_LONG).show();