-2

I've two things I want to ask about. I'm ready to eat this laptop at this stage. My location permissions seem to be working as I haven't had a crash or a dialogue saying I haven't permission for it, (although I haven't seen the dialogue requesting permissions either...) but the setText() to the textView doesn't seem to be doing the job either. My latest problem is retrieving the image to encode for image upload after the picture is taken.

Here is my code. The permissions are requested in the manifest. I will drive this laptop across the garden with a boot if I'm looking at this for much longer. Stuck on this for 3 days with a project due in two weeks with a months worth of work left in it. Save me stackoverflow!

package com.example.gary.natureallv2;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.Manifest;


import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderApi;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class CameraPicActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    public static final int CAMERA_REQUEST = 10;
    public static final int IMAGE_GALLERY_REQUEST = 20;
    private ImageView ivPicSelected;
    private FusedLocationProviderApi locationProviderApi = LocationServices.FusedLocationApi;
    private GoogleApiClient googleApiClient;
    private LocationRequest locationRequest;
    public final static int MILLISECONDS_PER_SECOND = 1000;
    public final static int MINUTE = 60 * MILLISECONDS_PER_SECOND;
    private static final int MY_PERMISSION_REQUEST_FINE_LOCATION = 101;
    private static final int MY_PERMISSION_REQUEST_COARSE_LOCATION = 102;
    private boolean permissionIsGranted = false;
    private TextView tvLatValue;
    private TextView tvLongValue;
    private double longitude;
    private double latitude;
    private String encoded_string, image_name;
    private Bitmap bitmap;
    private  File file;
    private Uri file_uri;
    private Button btnUploadPic;
    private Parcelable picUri;


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

        googleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        //initialise the location request with the accuracy and frequency with which we want location updates
        locationRequest = new LocationRequest();
        locationRequest.setInterval(MINUTE);
        locationRequest.setFastestInterval(15 * MILLISECONDS_PER_SECOND);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        ivPicSelected = (ImageView) findViewById(R.id.ivPicSelected);
        tvLatValue = (TextView) findViewById(R.id.tvLatValue);
        tvLongValue = (TextView) findViewById(R.id.tvLongValue);
        btnUploadPic = (Button) findViewById(R.id.btnUploadPic);
        btnUploadPic.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                getFileUri();
            }
        });
    }




    /**
     * Method called when btnFromCamera is clicked.
     * @param view
     */
    public void btnFromCameraClicked(View view){
        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File pictureDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);//
//        String pictureName = getPictureName();//
//        File imageFile = new File(pictureDirectory, pictureName);//
//        Uri pictureUri = Uri.fromFile(imageFile);//
//        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,pictureUri);//
        startActivityForResult(cameraIntent, CAMERA_REQUEST);

    }

    /**
     * This method is invoked when the user presses the From Gallery button.
     * @param view
     */
    public void onBtnGalleryClicked(View view){
        //Invoke the image gallery with an implicit intent.
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
        //Where to find the data.
        File pictureDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        String pictureDirectoryPath = pictureDirectory.getPath();
        //get a Uri representation.
        Uri data = Uri.parse(pictureDirectoryPath);
        //set the data and type/get all image types.
        photoPickerIntent.setDataAndType(data, "image/*");
        startActivityForResult(photoPickerIntent, IMAGE_GALLERY_REQUEST);


    }

    private String getPictureName() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
        String timeStamp = sdf.format(new Date());
        return "natureall" + timeStamp +".jpg";
    }

    private void getFileUri() {
        image_name = "testing123.jpg";
        file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
                + File.separator + image_name);
        file_uri = Uri.fromFile(file);



    }

    public void onBtnUploadClick(View view){
        Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        getFileUri();
        i.putExtra(MediaStore.EXTRA_OUTPUT, file_uri);
        startActivityForResult(i, 10);

    }





    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK){
            if (requestCode == CAMERA_REQUEST){
                Bitmap cameraImage = (Bitmap) data.getExtras().get("data");
                ivPicSelected.setImageBitmap(cameraImage);


            }
            if (requestCode == IMAGE_GALLERY_REQUEST){
                Uri imageUri = data.getData();
                //declare a stream to read the image data.
                InputStream inputStream;
                try {
                    inputStream = getContentResolver().openInputStream(imageUri);

                    Bitmap image = BitmapFactory.decodeStream(inputStream);
                    ivPicSelected.setImageBitmap(image);
                } catch (FileNotFoundException e) {
                    Toast.makeText(this, "Unable to open the image",Toast.LENGTH_LONG ).show();
                }

            }
            if(requestCode == 10 && resultCode == RESULT_OK) {
                new Encode_image().execute();
            }
        }
    }
/*Possible way to recover pics after saving to external storage*/
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);


        outState.putParcelable("picUri", picUri);
    }

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

        picUri= savedInstanceState.getParcelable("picUri");

    }
    /*End of/Possible way to recover pics after saving to external storage*/

    private class Encode_image extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... voids) {
            bitmap = BitmapFactory.decodeFile(file_uri.getPath());
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);

            byte [] array = stream.toByteArray();
            encoded_string = Base64.encodeToString(array, 0);
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            makeRequest();
        }
    }

    private void makeRequest() {
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        StringRequest request = new StringRequest(Request.Method.POST, "http://192.168.1.15/myDocs/mainProject/res/connection.php",
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {

                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        }){
            @Override
            protected Map<String, String> getParams ()throws AuthFailureError {
                HashMap<String, String> map = new HashMap<>();
                map.put("encoded_string", encoded_string);
                map.put("image_name", image_name);
                return map;
            }

        };
        requestQueue.add(request);
    }



    @Override
    public void onConnected(Bundle bundle){requestLocationUpdates();}

    private void requestLocationUpdates(){
          if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSION_REQUEST_FINE_LOCATION);
                }
                return;
            }
        LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
        }




    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {

    }

    @Override
    protected void onStart() {
        super.onStart();
        if (permissionIsGranted) {
            googleApiClient.connect();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (permissionIsGranted) {
            googleApiClient.disconnect();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case MY_PERMISSION_REQUEST_FINE_LOCATION:
                if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    permissionIsGranted = true;
                    Toast.makeText(this, "Permission Granted", Toast.LENGTH_LONG).show();
                }
                else{
                    permissionIsGranted = false;
                    Toast.makeText(getApplicationContext(), "This app requires location permissions to be granted", Toast.LENGTH_SHORT).show();
                    tvLatValue.setText("Lat permission denied");
                    tvLongValue.setText("Long permission denied");
                }
                break;

        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (permissionIsGranted){
        if (googleApiClient.isConnected())
            requestLocationUpdates();
    }}


    @Override
    protected void onPause() {
        super.onPause();
        if(permissionIsGranted) {
            LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        if (permissionIsGranted){
    //Toast.makeText(this, "Location Changed:" + location.getLatitude() + " " + location.getLongitude(), Toast.LENGTH_LONG).show();
            longitude = location.getLongitude();
            latitude = location.getLatitude();
            tvLongValue.setText(Double.toString(longitude));
            tvLatValue.setText(Double.toString(latitude));



        }
    }

}

The image is saved to external storage but I'm getting this error:

                                                                               java.lang.RuntimeException: An error occurred while executing doInBackground()
                                                                              at android.os.AsyncTask$3.done(AsyncTask.java:309)
                                                                              at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                                                                              at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                                                                              at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                                                                              at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
                                                                              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                              at java.lang.Thread.run(Thread.java:818)
                                                                           Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getPath()' on a null object reference
                                                                              at com.example.gary.natureallv2.CameraPicActivity$Encode_image.doInBackground(CameraPicActivity.java:217)
                                                                              at com.example.gary.natureallv2.CameraPicActivity$Encode_image.doInBackground(CameraPicActivity.java:214)

2 Answers2

0

It seems like file_url is null in Encode_image class.
it should be initialized before calling new Encode_image().execute(); in onActivityResult.
Have you called getFileUri() somewhere in your code?

isamirkhaan1
  • 749
  • 7
  • 19
  • I'm just after seeing the file_uri was using image_name in getPictureName() earlier in the code in the but I had to comment out this code in order to avoid the null pointer exception when the btnFromCamera() is used. After it stored the image to external storage there would be know image to display in the imageView. Does anyone know a work around to retrieve the taken image from the storage automatically without having to go back and click into the gallery? – Javaiskillingme Aug 16 '16 at 11:31
  • sorry, could you make it clear? – isamirkhaan1 Aug 16 '16 at 12:13
0

Dont Access the global variable in the async task . Please pass them as arguments instead of Void AsyncTask Uri as Input and return String as output . also provide check if (passed_uri != null).Please check ur code on Android v 21 in emulator to check that you do not have any permission issues

Gaurav Maan
  • 339
  • 1
  • 2
  • 14