I am trying to capture an image and save cropped image instead of original image with specified name.
At the moment I am able to crop and show on imageview but I need to know how to save cropped image instead of original, Here is the code.
final int CAMERA_CAPTURE = 1;
final int CROP_PIC = 2;
private Uri picUri;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button captureBtn = (Button) findViewById(R.id.capture_btn);
captureBtn.setOnClickListener(this);
}
public void onClick(View v) {
if (v.getId() == R.id.capture_btn) {
try {
// use standard intent to capture an image
Intent captureIntent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
// we will handle the returned data in onActivityResult
startActivityForResult(captureIntent, CAMERA_CAPTURE);
} catch (ActivityNotFoundException anfe) {
Toast toast = Toast.makeText(this, "This device doesn't support the crop action!",
Toast.LENGTH_SHORT);
toast.show();
}
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == CAMERA_CAPTURE) {
// get the Uri for the captured image
picUri = data.getData();
performCrop();
}
// user is returning from cropping the image
else if (requestCode == CROP_PIC) {
// get the returned data
Bundle extras = data.getExtras();
// get the cropped bitmap
Bitmap thePic = extras.getParcelable("data");
ImageView picView = (ImageView) findViewById(R.id.picture);
picView.setImageBitmap(thePic);
}
}
}
/**
* this function does the crop operation.
*/
private void performCrop() {
// take care of exceptions
try {
// call the standard crop action intent (the user device may not
// support it)
Intent cropIntent = new Intent("com.android.camera.action.CROP");
// indicate image type and Uri
cropIntent.setDataAndType(picUri, "image/*");
// set crop properties
cropIntent.putExtra("crop", "true");
// indicate aspect of desired crop
cropIntent.putExtra("aspectX", 2);
cropIntent.putExtra("aspectY", 1);
// indicate output X and Y
cropIntent.putExtra("outputX", 256);
cropIntent.putExtra("outputY", 256);
// retrieve data on return
cropIntent.putExtra("return-data", true);
// start the activity - we handle returning in onActivityResult
startActivityForResult(cropIntent, CROP_PIC);
}
// respond to users whose devices do not support the crop action
catch (ActivityNotFoundException anfe) {
Toast toast = Toast
.makeText(this, "This device doesn't support the crop action!", Toast.LENGTH_SHORT);
toast.show();
}
}
I am new to android and I really want to know how I can do this, any kind of help is much appriciated.
So the question is: How to save a bitmap
Sometimes saving bitmaps takes a long time. I suggest you to use AsyncTask in order to avoid annoying lags in your app.
public class saveFile extends AsyncTask<Void, Void, File>{
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);//Show user that app is working in backgrind
}
#Override
protected File doInBackground(Void... params) {
String file_path = Environment.getExternalStorageDirectory().getAbsolutePath() +
"/CropedImage";
File dir = new File(file_path);
if(!dir.exists())
dir.mkdirs();
String format = new SimpleDateFormat("yyyyMMddHHmmss",
java.util.Locale.getDefault()).format(new Date());
File file = new File(dir, format + ".png");
FileOutputStream fOut;
try {
fOut = new FileOutputStream(file);
thePic.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
}
catch (Exception e) {
e.printStackTrace();
}
return file;
}
#Override
protected void onPostExecute(File result) {
progressBar.setVisibility(View.INVISIBLE);
String respath=result.getPath().toString();
Toast.makeText(MainActivity.this, "Saved at "+respath, Toast.LENGTH_LONG).show();
MediaScannerConnection.scanFile(MainActivity.this, new String[] { result.getPath() }, new String[] { "image/jpeg" }, null);
}
}
And then call AsyncTask:
new saveFile().execute();
Android does not have any crop intent you can download crop libraries Click here
Related
I am facing a problem where in when I am trying to crop an image after it has picked from Gallery or Camera.
When I choose the image from gallery it gets cropped correctly without any problem. When I choose image from camera, the cropping is done properly but it shows me an "intermediate" screen as seen below without taking me directly to the crop screen.
Note: Picture above is just for representation purposes to show the "intermediate" Recent screen.
I don't want this "intermediate" Recent screen to be displayed. Instead I want to directly navigate to the crop intent. In apps like Whatsapp this behavior is not seen when someone changes his/her profile pic. It directly navigates to crop intent without showing "intermediate" screen.
Can someone help solve this problem?
Here is my complete code
/**
* This activity is used to display profile picture and update the same
*
*/
public class ChangeProfilePhotoActivity extends BaseActivity implements
View.OnClickListener {
private TextView mTvTitle;
private ImageView mBtnChangePhoto;
private ImageView mIvProfileImage;
public static final int CROP_PIC_REQUEST_CODE = 3;
public static final int TAKE_PICTURE = 1;
public static final int GALLERY_IMAGE = 2;
public static final int IMAGE_CHOOSER_INTENT = 4;
int PERMISSION_ALL = 10;
String[] PERMISSIONS = { Manifest.permission.CAMERA};
//private Uri mImageUri;
//private Uri mCropImageUri;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile_photo);
initUI();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
private void initUI() {
mBtnChangePhoto = (ImageView) findViewById(R.id.btnChangePhoto);
mIvProfileImage = (ImageView) findViewById(R.id.profile_image);
mBtnChangePhoto.setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnChangePhoto:
//launch intent chooser
getPickImageIntent(this);
break;
default:
break;
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case IMAGE_CHOOSER_INTENT:
if(data!=null){
String action = data.getAction();
Uri selectedImageUri = data.getData();
//send image for cropping
doCrop(selectedImageUri);
}
break;
case CROP_PIC_REQUEST_CODE:
if(data!=null){
Bundle extras = data.getExtras();
if(extras != null) {
Bitmap bmp = (Bitmap) extras.get("data");
mIvProfileImage.setImageBitmap(bmp);
}
}
break;
default:
break;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void doCrop(Uri picUri) {
try {
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(picUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
cropIntent.putExtra("outputX", 128);
cropIntent.putExtra("outputY", 128);
cropIntent.putExtra("return-data", true);
startActivityForResult(cropIntent, CROP_PIC_REQUEST_CODE);
}
// respond to users whose devices do not support the crop action
catch (ActivityNotFoundException anfe) {
// display an error message
String errorMessage = "Your device doesn't support the crop action!";
Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
toast.show();
}
}
public void getPickImageIntent(Context context) {
Intent chooserIntent = null;
List<Intent> intentList = new ArrayList<>();
Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
//startActivityForResult(pickIntent, GALLERY_IMAGE);
Intent takePhotoIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
/* String imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/crop_image.jpg";
File imageFile = new File(imageFilePath);
Uri picUri = Uri.fromFile(imageFile); // convert path to Uri
takePhotoIntent.putExtra( MediaStore.EXTRA_OUTPUT, picUri );*/
//takePhotoIntent.putExtra("return-data", false);
//startActivityForResult(takePhotoIntent, TAKE_PICTURE);
intentList = addIntentsToList(context, intentList, pickIntent);
intentList = addIntentsToList(context, intentList, takePhotoIntent);
if (intentList.size() > 0) {
chooserIntent = Intent.createChooser(intentList.remove(intentList.size() - 1),
context.getString(R.string.pick_image_intent_text));
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new Parcelable[intentList.size()]));
}
startActivityForResult(chooserIntent, IMAGE_CHOOSER_INTENT);
}
private static List<Intent> addIntentsToList(Context context, List<Intent> list, Intent intent) {
try {
List<ResolveInfo> resInfo = context.getPackageManager().queryIntentActivities(intent, 0);
for (ResolveInfo resolveInfo : resInfo) {
String packageName = resolveInfo.activityInfo.packageName;
Intent targetedIntent = new Intent(intent);
targetedIntent.setPackage(packageName);
list.add(targetedIntent);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return list;
}
}
You're launching an intent. That means you're handing control off to another app. After that, you have no control over what happens. Of course what happens will be different on every device, as some OEMs will use their own Gallery app or Camera app that may behave completely differently.
So no, there's no way to prevent them from doing that extra screen. If you want total control, take the picture yourself via the camera or camera2 apis instead of calling an Intent. (Note: I don't actually suggest this, but if you want control its the only way).
I am new to Android App development. And I want to implement the snapshot in the google map triggered by the info window on the map, then I need to return the image and crop it.
Here is my code, but it doesn't work every time I touch the info window.
Here is the code of snapshot. When I debug it, I found that it jumped over the snapshot method, so I think that maybe my usage of snakshotReadyCallback is wrong.
public void takeSnapShot(){
mMap.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
//final ImageView snapshotHolder = (ImageView) findViewById(R.id.picture);
final GoogleMap.SnapshotReadyCallback callback = new GoogleMap.SnapshotReadyCallback() {
#Override
public void onSnapshotReady(Bitmap snapshot) {
//snapshotHolder.setImageBitmap(snapshot);
try {
FileOutputStream out = new FileOutputStream("test.png");
snapshot.compress(Bitmap.CompressFormat.PNG, 90, out);
Toast.makeText(MapsActivity.this, "Capture OK", Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
};
mMap.snapshot(callback);
}
});
}
And here is the code of crop.
//crop the image
public void performCrop(){
try{
Intent cropIntent= new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(picUri,"map/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 2);
cropIntent.putExtra("aspectY", 1);
cropIntent.putExtra("outputX", 256);
cropIntent.putExtra("outputY", 256);
cropIntent.putExtra("return-data", true);
startActivityForResult(cropIntent, CROP_PIC);
}catch (ActivityNotFoundException anfe){
Toast.makeText(this, "this device doesn't support crop", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CROP_PIC) {
Bundle extras = data.getExtras();
Bitmap thePic = extras.getParcelable("data");
ImageView picView = (ImageView) findViewById(R.id.picture);
picView.setImageBitmap(thePic);
}
}
Welcome on stackoverflow.
By implementing PlaceAutocompleteFragment and PlaceAutocompleteActivity , you can able to get google place.
See my question and answer which helps you.
I'm working on an app which allows user to choose a picture from gallery and then I start a activity to crop it.
I want to send the cropped image back to calling activity.
Both activities extend AppCompatActivity.
Calling activity:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
// start image crop activity
String dataString = data.getDataString();
Intent intent=new Intent(this, CropPhotoActivity.class);
intent.putExtra("SELECTED_PICTURE_FOR_CROP", dataString);
startActivityForResult(intent, CROP_PICTURE);
}
else if(requestCode == CROP_PICTURE) {
// get cropped bitmap
Bitmap bitmap = (Bitmap) data.getParcelableExtra("CROPPED_IMAGE");
profilePhoto.setImageBitmap(bitmap);
}
}
}
In the crop image activity, I have a button, which on click should return back to calling activity:
Button okButton = (Button)findViewById(R.id.ok_button);
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent returnIntent = new Intent();
returnIntent.putExtra("CROPPED_IMAGE", cropped_bitmap);
setResult(RESULT_OK, returnIntent);
finish(); // sometimes restarts app
}
});
Sometimes the bitmap gets returned correctly whereas sometimes it does not and the app gets restarted without error. Why is this happening? Does putExtra have anything to do with bitmap size or anything else?
You could try substituting
AppcompatActivity.this.finish()
(where AppcompatActivity is your class name)
for:
finish(); // sometimes restarts app
Or, create a method in the calling Activity:
public static void cropComplete(Activity activity)
{
activity.startActivity(activity, AnotherActivity.class);
activity.finish();
}
Theres's a limit for data length passed as extra in a intent. Try not passing the dataString value; instead you should save the image as a temporary file, pass the path in the intent and then load the image from your calling activity (or you can just save the dataString in a static helper class).
In the crop activity (saving bitmap code from Save bitmap to location):
// Save bitmap
String filename = "tempImage.png";
File sd = Environment.getExternalStorageDirectory();
File dest = new File(sd, filename);
FileOutputStream out = null;
try {
out = new FileOutputStream(dest);
bmp.compress(Bitmap.CompressFormat.PNG, 100, out); // bmp is your Bitmap instance
// PNG is a lossless format, the compression factor (100) is ignored
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// Get image file path
String path = dest.getAbsolutePath();
// Set result with image path
Intent returnIntent = new Intent();
returnIntent.putExtra("CROPPED_IMAGE_PATH", path);
setResult(RESULT_OK, returnIntent);
finish();
In the caller activity:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if(requestCode == CROP_PICTURE) {
// Get image file path
String imagePath = data.getStringExtra("CROPPED_IMAGE_PATH");
// Load image
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
}
}
I have two text fields and a button to capture image,on click of camera button it will capture image but entered text in text fields will be refreshed,
i have a method which will clear text and images(from the SD card).I have called this method in onCreate method.I dont want to clear those text fields upto capturing image,how to handle this?
Here is my code to capture image:
btnCapture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
captureIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(captureIntent, CAMERA_CAPTURE);
} catch (ActivityNotFoundException anfe) {
String errorMessage = "Device doesn't support capturing images!";
}
}
});
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
// user is returning from capturing an image using the camera
if (requestCode == CAMERA_CAPTURE) {
Bundle extras = data.getExtras();
Bitmap thePic = extras.getParcelable("data");
DateFormat dateFormat = new SimpleDateFormat("HH-mm-ss");
Date date = new Date();
String imgcurTime = dateFormat.format(date);
File imageDirectory = new File(ImagePath);
if (!imageDirectory.exists()) {
imageDirectory.mkdirs();
}
String _path = ImagePath + imgcurTime + ".jpg";
try {
FileOutputStream out = new FileOutputStream(_path);
thePic.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.close();
out.flush();
} catch (FileNotFoundException e) {
e.getMessage();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
In low memory situations the android will kill the background activities. In your situation when camera activity started the background activity which starting the camera is may be destroying. And when you came back from camera it is recreated. So persist your edit text data same them in onSavedInstance() method and reassign them in the onRetoreInstance() method.
I hope this may works.
I am developing an application in which I have an image gallery and when I click on any image, it opens in full mode. But I want the set As Wallpaper functionality like android default gallery:
I know it can be done by custom code (setting wallpaper and cropping image). But I want to pass that image to android default wallpaper setter so that android will manage the cropping and setting wallpaper task. How can I do that? How can I pass that image to android default walpaper setter?
You can launch Crop intent by start activity for result and retrieve it in result and then use wallpaper manager class.
like this
Uri imgUri=Uri.parse("android.resource://your.package.name/"+R.drawable.image);
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(imgUri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 80);
intent.putExtra("outputY", 80);
intent.putExtra("return-data", true);
startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
and use Wallpaper manager in your onResult function
Also keep in mind that It depends on the device whether that device is support it or not. This Intent action is not part of the internal API. Some manufacturers provide their own Gallery apps and so there is no way of knowing whether or not the user's device will recognize the Intent.
This is my code which downloads a image from a URL.You can find it useful.Don't forget to add the required permissions for storage,wallpaper and internet.
#Override
public void onClick(View v) {
setWall(v);
}
});
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (shouldShowRequestPermissionRationale(
Manifest.permission.READ_EXTERNAL_STORAGE)) {
// Explain to the user why we need to read the contacts
}
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
// MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
// app-defined int constant that should be quite unique
return;
}
}
public void setWall(View view) {
new SetWallpaperTask().execute();
}
public class SetWallpaperTask extends AsyncTask <String, Void, Bitmap> {
String image = getIntent().getStringExtra("image");
ProgressDialog progressDialog;
#TargetApi(Build.VERSION_CODES.KITKAT)
#Override
protected Bitmap doInBackground(String... params) {
Bitmap result= null;
try {
result = Picasso.with(getApplicationContext())
.load(image)
.get();
} catch (IOException e) {
e.printStackTrace();
}
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
//new Intent(wallpaperManager.getCropAndSetWallpaperIntent(getImageUri(result,getApplicationContext())));
return result;
}
#TargetApi(Build.VERSION_CODES.KITKAT)
#Override
protected void onPostExecute (Bitmap result) {
super.onPostExecute(result);
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getBaseContext());
{
startActivity(new Intent(wallpaperManager.getCropAndSetWallpaperIntent(getImageUri(result,getApplicationContext()))));
// wallpaperManager.setBitmap(result);
progressDialog.dismiss();
// Toast.makeText(getApplicationContext(), "Set wallpaper successfully", Toast.LENGTH_SHORT).show();
}}
#Override
protected void onPreExecute () {
super.onPreExecute();
progressDialog = new ProgressDialog(Wallpaper_activity.this);
progressDialog.setMessage("Please wait...");
progressDialog.setCancelable(false);
progressDialog.show();
}
}
private Uri getImageUri(Bitmap inImage, Context inContext) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(),
inImage, "Title", null);
return Uri.parse(path);
}