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)