I am facing an issue which I do not understand. I am taking a picture then creating a PNG image file as per code that follows but somewhere down the line a random string is being added to the filename which causes me all sorts of issues. For example (as per tutorials I have found): I create an image called dimage_(generated timestamp) and save the string to shared preferences and the image in getExternalFilesDir(Environment.DIRECTORY_PICTURES). In shared preferences the string is correct but the file has the above mentioned string appended.
Eg:
The generated filename string saved in shared prefs:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="driver_picture">dimage_20190610_065509</string>
</map>
Whereas the file checked with adb results as:
127|generic_x86:/storage/emulated/0/Android/data/africa.mykagovehicledrivers/files/Pictures $ ls
dimage_20190610_0655091215099619.png
generic_x86:/storage/emulated/0/Android/data/africa.mykagovehicledrivers/files /Pictures $
I have no clue where the 1215099619 extra part comes from!
This is the code of the activity:
package africa.mykagovehicledrivers;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.yalantis.ucrop.UCrop;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class RegisterDriverImage extends AppCompatActivity {
String currentPhotoPath;
final int REQUEST_TAKE_PHOTO = 1;
final int CAMERA_PERMISSIONS = 3;
Activity activity = this;
ImageView imgTakePicture, imgDriver;
Button btnContinueDriver;
ProgressBar prgImage;
SharedPreferences prefs;
SharedPreferences.Editor edit;
String imageFileName;
Tools t;
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == CAMERA_PERMISSIONS) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// All good so launch take picture from here
dispatchTakePictureIntent();
} else {
// Permission denied. Warn the user and kick out of app
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.permsDeniedCameraTitle);
builder.setMessage(R.string.permsDeniedCameraMessage);
builder.setCancelable(false);
builder.setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finishAffinity();
}
});
builder.create().show();
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_TAKE_PHOTO && resultCode == RESULT_OK) {
Uri starturi = Uri.fromFile(new File(currentPhotoPath));
Uri destinationuri = Uri.fromFile(new File(currentPhotoPath));
UCrop.Options options = AppConstants.setUcropOptions(activity);
UCrop.of(starturi, destinationuri).withOptions(options).start(activity);
}
// On result from cropper add to image view
if (resultCode == RESULT_OK && requestCode == UCrop.REQUEST_CROP) {
prgImage.setVisibility(View.VISIBLE);
final Uri resultUri = UCrop.getOutput(data);
assert resultUri != null;
File imgFile = new File(resultUri.getPath());
Picasso.Builder builder = new Picasso.Builder(getApplicationContext());
builder.listener(new Picasso.Listener() {
#Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
exception.printStackTrace();
}
});
builder.build().load(imgFile).into(imgDriver, new Callback() {
#Override
public void onSuccess() {
Log.d("-------->", "onSuccess: CROPPED!");
prgImage.setVisibility(View.INVISIBLE);
btnContinueDriver.setEnabled(true);
}
#Override
public void onError(Exception e) {
e.printStackTrace();
}
});
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register_driver_image);
prefs = getSharedPreferences("mykago-driver", Context.MODE_PRIVATE);
edit = prefs.edit();
imgTakePicture = findViewById(R.id.imgTakePicture);
imgDriver = findViewById(R.id.imgDriver);
btnContinueDriver = findViewById(R.id.btnContinueDriver);
prgImage = findViewById(R.id.prgImage);
t = new Tools(getApplication(), getApplicationContext(), this);
imgTakePicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dispatchTakePictureIntent();
}
});
imgDriver.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dispatchTakePictureIntent();
}
});
btnContinueDriver.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
edit.putString("driver_picture", imageFileName);
edit.putString("nextstep", "drivinglicense");
edit.apply();
Intent drivinglicense = new Intent(getApplicationContext(), RegisterDrivingLicense.class);
startActivity(drivinglicense);
finish();
}
});
// Always ask for camera permissions
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{ Manifest.permission.CAMERA }, CAMERA_PERMISSIONS);
}
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
Log.d("IMAGE CREATION FAILED", ex.toString());
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"africa.mykagovehicledrivers.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date());
imageFileName = "dimage_" + timeStamp;
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName,
".png",
storageDir
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
}
As per code I am using String imageFileName; to save the path and then use it in the button click action to save it into shared preferences.
Thanks!
Found out the reasin. createTempFile does this. Switched to new File() and this solved the issue.
Related
i'm having issue doing image center crop to a specific size after taking a still photo by calling MediaStore.ACTION_IMAGE_CAPTURE.
Action Image Capture currently stores the image to image directory, how do i crop image automatically according to my pre-set size and save it to the same path and filename?
appreciate if can give some guidance. im new to android
i do have the URI of the image, just wondering if there's any way to center crop, resize to a specific size eg: 456x456 and save the image to the same URI by overwriting.
below is my code under MainActivity:
package com.example.android_take_photos_and_save_gallery;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
public static final int CAMERA_PERM_CODE = 101;
public static final int CAMERA_REQUEST_CODE = 102;
ImageView selectedImage;
Button cameraBtn;
String currentPhotoPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
selectedImage = findViewById(R.id.displayImageView);
cameraBtn = findViewById(R.id.cameraBtn);
// Open Camera
cameraBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
verifyPermissions();
}
});
}
private void verifyPermissions(){
String[] permissions = {Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA};
if(ContextCompat.checkSelfPermission(this.getApplicationContext(),
permissions[0]) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this.getApplicationContext(),
permissions[1]) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this.getApplicationContext(),
permissions[2]) == PackageManager.PERMISSION_GRANTED){
dispatchTakePictureIntent();
}else{
ActivityCompat.requestPermissions(this,
permissions,
CAMERA_PERM_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == CAMERA_PERM_CODE){
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
dispatchTakePictureIntent();
}else {
Toast.makeText(this, "Camera Permission is Required to Use camera.", Toast.LENGTH_SHORT).show();
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == CAMERA_REQUEST_CODE){
if(resultCode == Activity.RESULT_OK){
File f = new File(currentPhotoPath);
selectedImage.setImageURI(Uri.fromFile(f));
Log.d("tag", "ABsolute Url of Image is " + Uri.fromFile(f));
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
// File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
}
I'm trying to build a MainActivity that comprises two Buttons, one for taking a picture with the camera and uploading it to Firebase Storage, and the other one to download the image from Firebase Storage and show it on an ImageView.
Right now, I'm stuck with the upload function. I can take the picture and save it into the app directory. I would like to upload the saved picture into Firebase Storage.
My MainActivity.java (based on the Firebase developers tutorial) is the following:
package com.example.mathi.image;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.UploadTask;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
static final int REQUEST_TAKE_PHOTO = 1;
String mCurrentPhotoPath;
private Button btn_upload;
private Button btn_download;
//Firebase
FirebaseStorage storage;
StorageReference storageReference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_upload = (Button)findViewById(R.id.btn_upload);
btn_download = (Button)findViewById(R.id.btn_download);
btn_upload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dispatchTakePictureIntent();
}
});
btn_download.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.mathi.image.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
upload_photo();
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void upload_photo(){
Uri file = Uri.fromFile(new File(mCurrentPhotoPath));
UploadTask uploadTask = storageReference.putFile(file);
// Register observers to listen for when the download is done or if
it fails
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, etc.
// ...
}
});
}
}
In the debugger I have the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.storage.UploadTask com.google.firebase.storage.StorageReference.putFile(android.net.Uri)' on a null object reference
at com.example.mathi.image.MainActivity.upload_photo(MainActivity.java:112)
Line 112 is the following line:
UploadTask uploadTask = storageReference.putFile(file);
The file is created on the local dir when I remove the upload() method. However, with the upload() method, the app crashes.
Does anyone knows what I am missing?
Try this code
btn_upload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CaptureImageFromCamera();
}
});
private void CaptureImageFromCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, 200);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
try {
if (requestCode == 200) {
Uri imageUri = data.getData();
sendImage(imageUri);
}
}
catch (Exception e) {
}
}else{
Toast.makeText(this, "Cancelled", Toast.LENGTH_SHORT).show();
}
}
private void sendImage(Uri imageUri){
UploadTask uploadTask = storageReference.putFile(imageUri);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
}
});
}
In my project, I am capturing image from the camera. I am taking the full-size image from the app (instead of taking thumbnail). Captured image is of very big size which is 7 to 18 mb. When I have taken image from my default camera app, the size was roughly 2.5 mb only. As well as it's taking lot of time(6-10 seconds) to load and save to the folder. This happening only when I am using the android device, on emulator it's working good. This is my code:
package com.stegano.strenggeheim.fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.stegano.strenggeheim.BuildConfig;
import com.stegano.strenggeheim.R;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;
public class FragmentEncode extends Fragment {
private static final String MESSAGE_IMAGE_SAVED = "Image Saved!";;
private static final String MESSAGE_FAILED = "Failed!";
private static final String IMAGE_DIRECTORY = "/StrengGeheim";
private static final int GALLERY = 0, CAMERA = 1;
private File capturedImage;
TextView imageTextMessage;
ImageView loadImage;
public FragmentEncode() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
private void galleryIntent() {
Intent galleryIntent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent, GALLERY);
}
private void cameraIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri fileUri = getOutputMediaFileUri();
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, CAMERA);
}
private Uri getOutputMediaFileUri() {
try {
capturedImage = getOutputMediaFile();
return FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", capturedImage);
}
catch (IOException ex){
ex.printStackTrace();
Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
}
return null;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_encode, container, false);
imageTextMessage = view.findViewById(R.id.imageTextMessage);
loadImage = view.findViewById(R.id.loadImage);
loadImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
showPictureDialog();
}
});
return view;
}
private void showPictureDialog(){
AlertDialog.Builder pictureDialog = new AlertDialog.Builder(getContext());
pictureDialog.setTitle("Select Action");
String[] pictureDialogItems = {
"Select photo from gallery",
"Capture photo from camera",
"Cancel"
};
pictureDialog.setItems(pictureDialogItems,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
galleryIntent();
break;
case 1:
cameraIntent();
break;
case 2:
dialog.dismiss();
break;
}
}
});
pictureDialog.show();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == getActivity().RESULT_CANCELED) {
return;
}
try {
if (requestCode == GALLERY && data != null) {
Bitmap bitmap = getBitmapFromData(data, getContext());
File mediaFile = getOutputMediaFile();
String path = saveImage(bitmap, mediaFile);
Log.println(Log.INFO, "Message", path);
Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
loadImage.setImageBitmap(bitmap);
imageTextMessage.setVisibility(View.INVISIBLE);
} else if (requestCode == CAMERA) {
final Bitmap bitmap = BitmapFactory.decodeFile(capturedImage.getAbsolutePath());
loadImage.setImageBitmap(bitmap);
saveImage(bitmap, capturedImage);
Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
imageTextMessage.setVisibility(View.INVISIBLE);
}
} catch (Exception ex) {
ex.printStackTrace();
Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
}
}
private Bitmap getBitmapFromData(Intent intent, Context context){
Uri selectedImage = intent.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver()
.query(selectedImage,filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
return BitmapFactory.decodeFile(picturePath);
}
private String saveImage(Bitmap bmpImage, File mediaFile) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bmpImage.compress(Bitmap.CompressFormat.PNG, 50, bytes);
try {
FileOutputStream fo = new FileOutputStream(mediaFile);
fo.write(bytes.toByteArray());
MediaScannerConnection.scanFile(getContext(),
new String[]{mediaFile.getPath()},
new String[]{"image/png"}, null);
fo.close();
return mediaFile.getAbsolutePath();
} catch (IOException ex) {
ex.printStackTrace();
}
return "";
}
private File getOutputMediaFile() throws IOException {
File encodeImageDirectory =
new File(Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
if (!encodeImageDirectory.exists()) {
encodeImageDirectory.mkdirs();
}
String uniqueId = UUID.randomUUID().toString();
File mediaFile = new File(encodeImageDirectory, uniqueId + ".png");
mediaFile.createNewFile();
return mediaFile;
}
}
Something you could do is download an available API online, or, if need be, dowload the source code of some online compressor. Then you could use it as a model. Never directly use the source code. One that is widely supported across languages is: https://optimus.keycdn.com/support/image-compression-api/
I am taking the image from the camera and getting the File. So, I am saving the image directly in file location which I generated using getOutputMediaFile() method. For that I am overloading saveImage() method like this:
private void saveImage(File mediaImage) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(mediaImage);
mediaScanIntent.setData(contentUri);
getContext().sendBroadcast(mediaScanIntent);
}
This method will put the image in the desired file location and also accessible to the Gallery for other apps. This method is same as galleryAddPic() method on this link Taking Photos Simply
But In the case of picking a photo from the Gallery, I will have to create the File in the desired location and write the bytes of the picked image into that file, so the old saveImage() method will not change.
In onActivityResult method, this is how I used overloaded saveImage() method:
else if (requestCode == CAMERA) {
saveImage(imageFile);
Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath());
loadImage.setImageBitmap(bitmap);
Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
imageTextMessage.setVisibility(View.INVISIBLE);
}
This question already has answers here:
android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()
(27 answers)
Closed 3 years ago.
MainActivity
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Parcelable;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mBtn;
private Context context;
private static final int SELECT_PICTURE_CAMARA = 101, SELECT_PICTURE = 201, CROP_IMAGE = 301;
private Uri outputFileUri;
String mCurrentPhotoPath;
private Uri selectedImageUri;
private File finalFile = null;
private ImageView imageView;
private PermissionUtil permissionUtil;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBtn = (Button) findViewById(R.id.btn_img);
imageView = (ImageView) findViewById(R.id.img_photo);
permissionUtil = new PermissionUtil();
mBtn.setOnClickListener(this);
context = this;
}
#Override
public void onClick(View view) {
selectImageOption();
}
private void selectImageOption() {
final CharSequence[] items = {"Capture Photo", "Choose from Gallery", "Cancel"};
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Add Photo!");
builder.setItems(items, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
if (items[item].equals("Capture Photo")) {
if (permissionUtil.checkMarshMellowPermission()) {
if (permissionUtil.verifyPermissions(MainActivity.this, permissionUtil.getCameraPermissions()))
onClickCamera();
else
ActivityCompat.requestPermissions(MainActivity.this, permissionUtil.getCameraPermissions(), SELECT_PICTURE_CAMARA);
} else
onClickCamera();
} else if (items[item].equals("Choose from Gallery")) {
if (permissionUtil.checkMarshMellowPermission()) {
if (permissionUtil.verifyPermissions(MainActivity.this, permissionUtil.getGalleryPermissions()))
onClickGallery();
else
ActivityCompat.requestPermissions(MainActivity.this, permissionUtil.getGalleryPermissions(), SELECT_PICTURE);
} else
onClickGallery();
} else if (items[item].equals("Cancel")) {
dialog.dismiss();
}
}
});
builder.show();
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
selectedImageUri = data.getData();
cropImage(selectedImageUri);
} else if (requestCode == CROP_IMAGE) {
/*if (data != null) {
// get the returned data
Bundle extras = data.getExtras();
// get the cropped bitmap
Bitmap selectedBitmap = extras.getParcelable("data");
imageView.setImageBitmap(selectedBitmap);
}*/
Uri imageUri = Uri.parse(mCurrentPhotoPath);
File file = new File(imageUri.getPath());
try {
InputStream ims = new FileInputStream(file);
imageView.setImageBitmap(BitmapFactory.decodeStream(ims));
} catch (FileNotFoundException e) {
return;
}
} else if (requestCode == SELECT_PICTURE_CAMARA && resultCode == Activity.RESULT_OK) {
cropImage(Uri.parse(mCurrentPhotoPath));
}
}
}
private void onClickCamera() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
}
if (photoFile != null) {
Uri photoURI;
if (Build.VERSION.SDK_INT >= 24) {
photoURI = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", photoFile);
} else {
photoURI = Uri.fromFile(photoFile);
}
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, SELECT_PICTURE_CAMARA);
}
}
}
private void onClickGallery() {
List<Intent> targets = new ArrayList<>();
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_PICK);
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
List<ResolveInfo> candidates = getApplicationContext().getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo candidate : candidates) {
String packageName = candidate.activityInfo.packageName;
if (!packageName.equals("com.google.android.apps.photos") && !packageName.equals("com.google.android.apps.plus") && !packageName.equals("com.android.documentsui")) {
Intent iWantThis = new Intent();
iWantThis.setType("image/*");
iWantThis.setAction(Intent.ACTION_PICK);
iWantThis.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
iWantThis.setPackage(packageName);
targets.add(iWantThis);
}
}
if (targets.size() > 0) {
Intent chooser = Intent.createChooser(targets.remove(0), "Select Picture");
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[targets.size()]));
startActivityForResult(chooser, SELECT_PICTURE);
} else {
Intent intent1 = new Intent(Intent.ACTION_PICK);
intent1.setType("image/*");
startActivityForResult(Intent.createChooser(intent1, "Select Picture"), SELECT_PICTURE);
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
if (Build.VERSION.SDK_INT >= 24) {
mCurrentPhotoPath = String.valueOf(FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider", image));
} else {
mCurrentPhotoPath = String.valueOf(Uri.fromFile(image));
}
return image;
}
private void cropImage(Uri selectedImageUri) {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(selectedImageUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1.5);
cropIntent.putExtra("return-data", true);
outputFileUri = Uri.fromFile(createCropFile());
cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cropIntent, CROP_IMAGE);
}
private File createCropFile() {
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
// path = path + (timeStamp + "1jpg");
File file = null;
try {
file = File.createTempFile(timeStamp, ".jpg", storageDir);
} catch (IOException e) {
e.printStackTrace();
}
mCurrentPhotoPath = String.valueOf(Uri.fromFile(file));
return file;
}
}
PermissionUtil.java
package com.example.shwetachauhan.imagecropasoebi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.v4.app.ActivityCompat;
public class PermissionUtil {
private String[] galleryPermissions = {
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE"
};
private String[] cameraPermissions = {
"android.permission.CAMERA",
"android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE"
};
public String[] getGalleryPermissions(){
return galleryPermissions;
}
public String[] getCameraPermissions() {
return cameraPermissions;
}
public boolean verifyPermissions(int[] grantResults) {
if(grantResults.length < 1){
return false;
}
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
public boolean verifyPermissions(Context context, String[] grantResults) {
for (String result : grantResults) {
if (ActivityCompat.checkSelfPermission(context, result) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
public boolean checkMarshMellowPermission(){
return(Build.VERSION.SDK_INT> Build.VERSION_CODES.LOLLIPOP_MR1);
}
public boolean checkJellyBean(){
return(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN);
}
}
This code is for pick image for crop from Camera or Gallery
This code is works for all android OS but when I try to run On Android N device it crash when I open Camera. It works fine in Android N with Gallery.
I have also faced the same issue in Android N devices. But i resolved it.
Here is my code which can solve the issue:
public void launchCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
intent.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoFileUri());
} else {
File file = new File(getPhotoFileUri().getPath());
Uri photoUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
}
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (intent.resolveActivity(getApplicationContext().getPackageManager()) != null) {
startActivityForResult(intent, REQUEST_CAMERA);
}
}
After this you need to create a XML folder in res, and in that folder you need to create a xml labeled provider_paths.xml
Code in provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Later in manifest you need to add the following inside the application tag and make sure that the compileSdkVersion >=24
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
Here are the two reference links which can guide you better for better understanding.
Links:
link1 - from medium cooperation
link2 - from inthecheesefactory
If you've are not touching other apps in the system just put
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
in your Application.onCreate(). It'll ignore the URI exposure and you are good to go.
You can use StrictMode, add below code to your Activity onCreate()
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
From Android N, android has changed the way you provide a file URI. Using file:// uri is prohibited and would throw this. Use the FileProvider to overcome this.
Passing file:// URIs outside the package domain may leave the receiver with an unaccessible path. Therefore, attempts to pass a file:// URI trigger a FileUriExposedException. The recommended way to share the content of a private file is using the FileProvider.
More info can be found here
change ur buildToolsVersion
buildToolsVersion "25.0.1"
to
buildToolsVersion "23.0.1"
My app is to open the built in camera and save it into sd card then start a new activity and preview the captured image on it.
This is the loginActivity that start a new AsynTask to open the camera :
package com.android.grad;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import com.Camera.R;
public class LoginActivity extends Activity {
private final int MEDIA_TYPE_IMAGE = 1;
private CheckBox rememberMe;
private EditText userName, passWord;
private Button loginBtn;
private final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private String path;
private Uri fileUri;
private OnClickListener loginOnClick = new OnClickListener() {
public void onClick(View v) {
new LoginTask(LoginActivity.this, fileUri).execute();
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
path = fileUri.getPath();
loginBtn = (Button) findViewById(R.id.signInBtn);
loginBtn.setOnClickListener(loginOnClick);
rememberMe = (CheckBox) findViewById(R.id.keepMe);
userName = (EditText) findViewById(R.id.userNameID);
passWord = (EditText) findViewById(R.id.passwordID);
}
#Override
protected void onResume() {
super.onResume();
SharedPreferences sp = getSharedPreferences("user", MODE_PRIVATE);
try {
userName.setText(sp.getString("username", ""));
passWord.setText(sp.getString("password", ""));
rememberMe.setChecked(sp.getBoolean("rememberMe", false));
} catch (ClassCastException ex) {
}
}
#Override
protected void onPause() {
super.onPause();
SharedPreferences sp = getSharedPreferences("user", MODE_PRIVATE);
Editor editor = sp.edit();
if (rememberMe.isChecked()) {
editor.putString("username", userName.getText().toString());
editor.putString("password", passWord.getText().toString());
} else {
editor.putString("username", "");
editor.putString("password", "");
}
editor.putBoolean("rememberMe", rememberMe.isChecked());
editor.commit();
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Intent intent = new Intent(LoginActivity.this,
PreviewActivity.class);
intent.putExtra("path", path);
startActivity(intent);
} else if (resultCode == RESULT_CANCELED) {
// User cancelled the image capture
Toast.makeText(getApplicationContext(),
"User cancelled the image capture", Toast.LENGTH_LONG)
.show();
} else {
// Image capture failed, advise user
}
}
}
/** Create a file Uri for saving an image or video */
private Uri getOutputMediaFileUri(int type) {
File f = getOutputMediaFile(type);
if (f == null) {
Toast.makeText(LoginActivity.this, "MyCameraApp File not found",
Toast.LENGTH_LONG);
return null;
}
return Uri.fromFile(f);
}
/** Create a File for saving an image or video */
private File getOutputMediaFile(int type) {
// Check if SD card is mounted
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File externalFilesDir = LoginActivity.this
.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File outFile = new File(externalFilesDir, "IDOCR");
if (!outFile.exists())
outFile.mkdirs();
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
String path = outFile.getPath() + File.separator + "IMG"
+ timeStamp + ".jpg";
File mediaFile = new File(path);
return mediaFile;
}
Toast.makeText(LoginActivity.this, "SD card unmounted",
Toast.LENGTH_LONG);
return null;
}
}
And this is the AsynTask :-
package com.android.grad;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.MediaStore;
public class LoginTask extends AsyncTask<Void, Void, Boolean> {
private Activity activity;
private ProgressDialog pd;
private Uri fileUri;
private final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
public LoginTask(Activity activity, Uri fileUri) {
this.activity = activity;
this.fileUri = fileUri;
}
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(activity, "Signing in",
"Please wait while we are signing you in..");
}
#Override
protected Boolean doInBackground(Void... arg0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return true;
}
#Override
protected void onPostExecute(Boolean result) {
pd.dismiss();
pd = null;
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
activity.startActivityForResult(intent,
CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
}
and this is the previewActivity:-
package com.android.grad;
import java.io.File;
import java.io.IOException;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import com.Camera.R;
import com.OCR.ID.AndroidImage;
import com.OCR.ID.Segement;
public class PreviewActivity extends Activity {
private ImageView previewIV;
private final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private String path;
private boolean crop = true;
private boolean resample = true;
private ProgressDialog pd;
OnClickListener processOnClickListener = new OnClickListener() {
public void onClick(View v) {
try {
createProgressDialog();
pd.show();
new Segement(PreviewActivity.this, pd).execute(path);
} catch (IOException e) {
}
}
};
private void createProgressDialog() {
pd = new ProgressDialog(PreviewActivity.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setTitle("Extract ID");
pd.setMessage("Processing...");
pd.setIcon(R.drawable.ic_launcher);
pd.setProgress(0);
pd.setCancelable(false);
}
private OnClickListener backOnClickListener = new OnClickListener() {
public void onClick(View v) {
startActivityForResult(
new Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(
MediaStore.EXTRA_OUTPUT,
Uri.fromFile(new File(path))),
CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
};
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
previewIV.setImageBitmap(BitmapFactory.decodeFile(path));
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.preview);
path = getIntent().getExtras().getString("path");
previewIV = (ImageView) findViewById(R.id.previewPicID);
previewIV.setImageBitmap(AndroidImage.decodeSampledBitmapFromSDcard(
path, 150, 150));
// previewIV.setImageBitmap(AndroidImage.readImage(path));
Button process = (Button) findViewById(R.id.processID);
process.setOnClickListener(processOnClickListener);
Button back = (Button) findViewById(R.id.back);
back.setOnClickListener(backOnClickListener);
}
}
The error that appear that sometimes when take picture it appear in the previewActivity and
sometime doesn't appear ?
Why that error
??