mercredi 15 juillet 2015

Random image to server

I am new to Android development. I created my first app which is a camera with the ability to capture an image, query the user for a Car ID related to the image, preview the captured image, and upload that image to the server.

I am interested in sending a random image from the directory of captured images to the server without knowing exactly which image from the directory was sent out. I do NOT want the user to have the capability of selecting an image(s) to send to the server themselves such as through a gallery selection. Also, I do NOT want to send multiple images to the server--just one random, unknown, non-user selected contained within the captured image directory.

I did a lot of research on this website as well as on numerous other educational websites. I noticed that Android's built-in Random class would be of great use.

Upon greater research I wrote some additional code that extends the original camera app code. However, the bitmap is returning null. I logged a bunch of key parts surrounding the bitmap in order to attempt to grasp why, but I do not see the issue.

I appreciate any insight as to why this is occurring and if I seem to be on the right track with my interested feature. I would love to hear additional ways in which to improve my app as you see fit. Thank you so much!

Here is my code:

public class MainActivity extends Activity {

    // Activity request codes.
    private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
    public static final int MEDIA_TYPE_IMAGE = 1;

    Bitmap bitmap;
    ProgressDialog pd;

    //Directory name to store captured images.
    private static final String IMAGE_DIRECTORY_NAME = "Hello Camera";

    private Uri fileUri; //File url to store captured images.

    private ImageView imgPreview;

    private Button btnCapturePicture;

    private Button upload;

    Button mButton;
    EditText mEdit;

    /*  Initializes activity, defines UI layout, and retrieves widgets
      * to interact with.
      * @param savedInstanceState - data is caught here and saved for
      *                           future app use.
      */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

     mButton = (Button)findViewById(R.id.button);
     mEdit = (EditText)findViewById(R.id.edittext);

        mButton.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View view) {
                        Log.v("EditText", mEdit.getText().toString());
                    }
                });

        imgPreview = (ImageView) findViewById(R.id.imgPreview);

        btnCapturePicture = (Button) findViewById(R.id.btnCapturePicture);

        upload = (Button) findViewById(R.id.upload);

        upload.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if (bitmap == null) {
                    Toast.makeText(getApplicationContext(), "Please Select Image", Toast.LENGTH_LONG).show();

                } else {
                    new ImageUpload().execute();
                }

            }
        });

        /**
         * Captures image button click event in order to capture a photo.
         * @param new View.OnClickListener- call to constructor
         */
        btnCapturePicture.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                //Captures an image.
                captureImage();
            }
        });


        //Checks for camera availability.
        if (!isDeviceSupportCamera()) {
            Toast.makeText(getApplicationContext(),
                    "Sorry! Your device doesn't support camera", Toast.LENGTH_LONG).show();
            //Closes if a camera is not available on the device.
            finish();
        }
    }

    /**
     * Checks if device has camera hardware.
     *
     * @return - true or false.
     */
    private boolean isDeviceSupportCamera() {
        if (getApplicationContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            //Device has a camera.
            return true;
        } else {
            // Device does not have a camera.
            return false;
        }
    }

    /*
     * Launches camera app request image capture.
     */
    private void captureImage() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);

        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);

        //Starts the image capture Intent.
        startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
    }

    /**
     * Gets and stores the file url. Will be null after returning from camera
     * app.
     *
     * @param outState - Holds per-instance state from activity.
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        // Saves the file url in bundle. It will be null on screen orientation changes.
        outState.putParcelable("file_uri", fileUri);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        //Gets the file url.
        fileUri = savedInstanceState.getParcelable("file_uri");
    }


    /**
     * Receives activity result method. Will be called after closing the camera.
     *
     * @param requestCode - Requests to capture an image.
     * @param resultCode  - Based on success or failure of image capturing, shows
     *                    an image preview or one of two error messages.
     * @param data        - Carries the result data(successfully captured image).
     * @return - An image preview, or one of two error messages.
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //If the result is the image capturing event,
        if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                //the image was successfully captured
                // and will be displayed in the preview.
                previewCapturedImage();
            } else if (resultCode == RESULT_CANCELED) {
                //The user cancelled the image capturing.
                Toast.makeText(getApplicationContext(),
                        "User cancelled image capture", Toast.LENGTH_SHORT).show();
            } else {
                //Image capturing failed, but the user did not actually cancel it.
                Toast.makeText(getApplicationContext(),
                        "Sorry! Failed to capture image", Toast.LENGTH_SHORT).show();
            }
        }
    }


    /**
     * Displays the image from a path to ImageView.
     * Downsizes an image if necessary and throws exception
     * if the image is too large.
     */
    private void previewCapturedImage() {
        try {

            imgPreview.setVisibility(View.VISIBLE);
            upload.setVisibility(View.VISIBLE);

            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                    IMAGE_DIRECTORY_NAME);
            Log.v("Directory", mediaStorageDir.toString());

            mediaStorageDir.listFiles(new FileFilter() {
                public boolean accept(File file) {
                    return !file.isDirectory();
                }
            });
            File[] listFiles = mediaStorageDir.listFiles();
            Log.v("File listFiles", listFiles.toString());

            Random r = new Random ();
            Log.v("Random r", r.toString());

            File randomPicture = listFiles[r.nextInt(listFiles.length)];
            Log.v("Random Picture File", randomPicture.toString());

            Uri fileUri = Uri.fromFile(randomPicture);
            Log.v("fileUri", fileUri.toString());

            BitmapFactory.Options options = new BitmapFactory.Options();

            // Downsizes images. Will throw OutOfMemory Exception for larger images.
            options.inSampleSize = 8;

            Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(), options);
            Log.v("Bitmap", bitmap.toString());

            ImageView imgView = (ImageView) findViewById(R.id.imgPreview);
            Log.v("ImgView", imgView.toString());

          imgView.setImageBitmap(BitmapFactory.decodeFile(fileUri.getPath()));
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    /**
     * Creates the file uri to store an image.
     *
     * @param type - Refers to the captured image.
     * @return Uri.fromFile - The file uri to store an image.
     */
    public Uri getOutputMediaFileUri(int type) {
        return Uri.fromFile(getOutputMediaFile(type));
    }

    /**
     * Returns the captured image.
     *
     * @param type - Refers to the captured image.
     * @return null or mediaFile - mediaFile: Captured
     * image inside of timestamped file.
     */
    private static File getOutputMediaFile(int type) {

        // External sdcard location.
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                IMAGE_DIRECTORY_NAME);
        Log.v("Directory Two", mediaStorageDir.toString());

        // Create the storage directory if it does not exists
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.d(IMAGE_DIRECTORY_NAME, "Oops! Failed create " + IMAGE_DIRECTORY_NAME + " directory");
                return null;
            }
        }

        // Creates a media file name corresponding to a timestamp.
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        File mediaFile;
        if (type == MEDIA_TYPE_IMAGE) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
        } else {
            return null;
        }
        Log.v("MediaFile", mediaFile.toString());
        return mediaFile;
    }
   /*
     * Uploads the saved and captured image to the server.
     */

    public class ImageUpload extends AsyncTask<String, String,String> {
        String postUrl = "";

        public void postURL(String url) {

            postUrl = url;
        }

        /**
         * Compresses the selected gallery image and encodes
         * compressed image to a base64 string.
         *
         * @param params
         */
        @Override
        protected String doInBackground(String... params) {
          String result = null;
           try {
                HttpClient client = new DefaultHttpClient();
                String postURL = "";
                HttpPost post = new HttpPost("http://ift.tt/1J0913I");

                ArrayList<NameValuePair> nameValuePair = new ArrayList<NameValuePair>();

               String msg = mEdit.getText().toString();
               nameValuePair.add(new BasicNameValuePair("carid",msg));

                //Converts image file uri to blob base64
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
               bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
                byte[] byte_arr = stream.toByteArray();
               Log.v("ByteArray Stream", stream.toString());
               Log.v("byte from stream", byte_arr.toString());
                String image_str = new String(Base64.encode(byte_arr, Base64.DEFAULT));

                nameValuePair.add(new BasicNameValuePair("carimage", image_str));

                UrlEncodedFormEntity ent = new UrlEncodedFormEntity(nameValuePair, HTTP.UTF_8);
                post.setEntity(ent);
                HttpResponse responsePOST = client.execute(post);
                HttpEntity resEntity = responsePOST.getEntity();
               result = EntityUtils.toString(resEntity);

                if (resEntity != null) {
                    Log.i("RESPONSE", EntityUtils.toString(resEntity));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }

        @Override
        protected void onPostExecute(String result) {
            if (result != null) {
                Toast.makeText(getApplicationContext(),
                        "Successfully uploaded", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getApplicationContext(),
                        "Sorry! Failed to upload", Toast.LENGTH_SHORT).show();
            }
        }

    }
}

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://ift.tt/nIICcg"
    package="com.example.justin.myapplication" >
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk
            android:minSdkVersion="11"
            android:targetSdkVersion="22" />

    <supports-screens
        android:largeScreens="true"
        android:normalScreens="true"
        android:smallScreens="true"
        android:anyDensity="true">
    </supports-screens>


    <!-- Accessing camera hardware -->
    <uses-feature android:name="android.hardware.camera" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-feature android:name="android.hardware.screen.portrait" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

        <application
            android:allowBackup="true"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name"
                android:configChanges="orientation|keyboard|keyboardHidden"
                android:screenOrientation="portrait">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>

    </manifest>

Logcat:

07-15 16:07:36.531  22150-22150/com.example.justin.myapplication D/dalvikvm﹕ Late-enabling CheckJNI
07-15 16:07:36.664  22150-22150/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
07-15 16:07:36.664  22150-22150/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
07-15 16:07:36.672  22150-22150/com.example.justin.myapplication D/libEGL﹕ loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
07-15 16:07:36.742  22150-22150/com.example.justin.myapplication D/OpenGLRenderer﹕ Enabling debug mode 0
07-15 16:07:43.961  22150-22150/com.example.justin.myapplication V/EditText﹕ 5
07-15 16:07:45.781  22150-22150/com.example.justin.myapplication V/Directory Two﹕ /storage/emulated/0/Pictures/Hello Camera
07-15 16:07:45.789  22150-22150/com.example.justin.myapplication V/MediaFile﹕ /storage/emulated/0/Pictures/Hello Camera/IMG_20150715_160745.jpg
07-15 16:07:46.484  22150-22150/com.example.justin.myapplication W/IInputConnectionWrapper﹕ showStatusIcon on inactive InputConnection
07-15 16:07:52.859  22150-22150/com.example.justin.myapplication V/Directory﹕ /storage/emulated/0/Pictures/Hello Camera
07-15 16:07:52.906  22150-22150/com.example.justin.myapplication V/File listFiles﹕ [Ljava.io.File;@4276b448
07-15 16:07:52.906  22150-22150/com.example.justin.myapplication V/Random r﹕ java.util.Random@42777f30
07-15 16:07:52.906  22150-22150/com.example.justin.myapplication V/Random Picture File﹕ /storage/emulated/0/Pictures/Hello Camera/IMG_20150710_160840.jpg
07-15 16:07:52.906  22150-22150/com.example.justin.myapplication V/fileUri﹕ file:///storage/emulated/0/Pictures/Hello%20Camera/IMG_20150710_160840.jpg
07-15 16:07:52.937  22150-22150/com.example.justin.myapplication D/dalvikvm﹕ GC_FOR_ALLOC freed 187K, 3% free 8776K/9000K, paused 14ms, total 15ms
07-15 16:07:53.242  22150-22150/com.example.justin.myapplication V/Bitmap﹕ android.graphics.Bitmap@42754638
07-15 16:07:53.242  22150-22150/com.example.justin.myapplication V/ImgView﹕ android.widget.ImageView{42747f90 V.ED.... ......I. 0,0-0,0 #7f0c0051 app:id/imgPreview}
07-15 16:07:53.265  22150-22150/com.example.justin.myapplication D/dalvikvm﹕ GC_FOR_ALLOC freed 38K, 3% free 9080K/9308K, paused 14ms, total 14ms
07-15 16:07:53.359  22150-22150/com.example.justin.myapplication I/dalvikvm-heap﹕ Grow heap (frag case) to 28.113MB for 20155408-byte allocation
07-15 16:07:53.383  22150-22159/com.example.justin.myapplication D/dalvikvm﹕ GC_FOR_ALLOC freed <1K, 1% free 28763K/28992K, paused 19ms, total 19ms
07-15 16:07:53.398  22150-22153/com.example.justin.myapplication D/dalvikvm﹕ GC_CONCURRENT freed <1K, 1% free 28763K/28992K, paused 3ms+2ms, total 20ms




Aucun commentaire:

Enregistrer un commentaire