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);
}
Related
So I am developing an android app for a school project, it allows the user to either take a picture or load an image from the gallery, and then it runs k-means clustering algorithm on the image to output the most dominant colors (https://buzzrobot.com/dominant-colors-in-an-image-using-k-means-clustering-3c7af4622036) However, when the image is chosen the android app either turns to black, or it freezes. I do not know what the error is or how to correct it, and there is no error it seems in the debugger, and I do not know enough about the android platform to have intuition for such a problem. Any help would be much appreciated!
this is the button functions:
public void loadFromGallery(View view) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, RESULT_LOAD_IMG);
}
public void takePhoto(View view){
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null){
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
and this is the function called when the photo is returned:
, and the line which calls K-Means is:
ArrayList<Point> colors = c.getColors(selectedImage, 4, 10);
and as you can probably see, without this line the app works perfectly but with it breaks. The code for this function does work, and occasionally the app will work fine and output the colors, but rarely. Therefore I think this has something to do with a resource limit or a time limit?
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK){
try {
final Uri imageUri = data.getData();
final InputStream imageStream = getContentResolver().openInputStream(imageUri);
//get and shrink bitmap
final Bitmap selectedImage = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(imageStream), 100, 100, true);
//run kmeans
ColorFinder c = new ColorFinder();
ArrayList<Point> colors = c.getColors(selectedImage, 4, 10);
//colors of points in android color format
ArrayList<Integer> cs = new ArrayList<Integer>(4);
for (Point color : colors){
cs.add(hexToColor(color));
}
image.setImageBitmap(selectedImage);
ColorDrawable drawable1 = (ColorDrawable) color1.getDrawable();
drawable1.setColor(cs.get(0));
textView1.setText(c.RGBtoHex(colors.get(0)));
ColorDrawable drawable2 = (ColorDrawable)color2.getDrawable();
drawable2.setColor(cs.get(1));
textView2.setText(c.RGBtoHex(colors.get(1)));
ColorDrawable drawable3 = (ColorDrawable)color3.getDrawable();
drawable3.setColor(cs.get(2));
textView3.setText(c.RGBtoHex(colors.get(2)));
ColorDrawable drawable4 = (ColorDrawable)color4.getDrawable();
drawable4.setColor(cs.get(3));
textView4.setText(c.RGBtoHex(colors.get(3)));
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(MainScreen.this, "Something went wrong", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(MainScreen.this, "You havent picked image", Toast.LENGTH_LONG).show();
}
}
You are doing IO operation on your main thread, use asynctask inside your on activity result to get rid of black screen
private class AsyncTaskRunner extends AsyncTask<String, String, String> {
private String resp;
ProgressDialog progressDialog;
#Override
protected String doInBackground(String... params) {
try {
final Uri imageUri = data.getData();
final InputStream imageStream = getContentResolver().openInputStream(imageUri);
//get and shrink bitmap
final Bitmap selectedImage = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(imageStream), 100, 100, true);
//run kmeans
ColorFinder c = new ColorFinder();
ArrayList<Point> colors = c.getColors(selectedImage, 4, 10);
//colors of points in android color format
ArrayList<Integer> cs = new ArrayList<Integer>(4);
for (Point color : colors){
cs.add(hexToColor(color));
}
image.setImageBitmap(selectedImage);
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(MainScreen.this, "Something went wrong", Toast.LENGTH_LONG).show();
}
}
#Override
protected void onPostExecute(String result) {
// execution of result of Long time consuming operation
progressDialog.dismiss();
ColorDrawable drawable1 = (ColorDrawable) color1.getDrawable();
drawable1.setColor(cs.get(0));
textView1.setText(c.RGBtoHex(colors.get(0)));
ColorDrawable drawable2 = (ColorDrawable)color2.getDrawable();
drawable2.setColor(cs.get(1));
textView2.setText(c.RGBtoHex(colors.get(1)));
ColorDrawable drawable3 = (ColorDrawable)color3.getDrawable();
drawable3.setColor(cs.get(2));
textView3.setText(c.RGBtoHex(colors.get(2)));
ColorDrawable drawable4 = (ColorDrawable)color4.getDrawable();
drawable4.setColor(cs.get(3));
textView4.setText(c.RGBtoHex(colors.get(3)));
}
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(MainActivity.this,
"ProgressDialog",
"Loading");
}
}
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
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 want to Select Image from gallery and crop it,then upload the image to server.If upload success,change view,if upload fail,them give a message;
I Use onActivityResult to manage this,and I use AsyncTask to make http post, dismiss the progressDialog,and save Image,Then i ran to this error
java.lang.RuntimeException: Failure delivering result ResultInfo...
and it caused by
Caused by: java.lang.NullPointerException
in my AsyncTask codes;
Here is my button to crop
avatarButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent,1);
}
});
and onActivityResult code
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 1:
if (data != null) {
Uri uri = data.getData();
crop(uri);
}
case 2:
if (data != null) {
final Bitmap bitmap = data.getParcelableExtra("data");
new UploadAvatar(UserProfileActivity.this, bitmap).execute();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
Crop method
private void crop(Uri uri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 100);
intent.putExtra("outputY", 100);
intent.putExtra("outputFormat", "PNG");
intent.putExtra("noFaceDetection", true);
intent.putExtra("return-data", true);
startActivityForResult(intent, 2);
}
and AsyncTask class
class UploadAvatar extends AsyncTask<Void,Integer,Boolean> {
private Context context;
private String avatarString;
private ProgressDialog progressDialog;
private ImageView avatarImage;
private Bitmap avatar;
public UploadAvatar(Context contextin,Bitmap bitmap){
this.context = contextin;
this.avatar = bitmap;
View rootView = ((Activity)contextin).getWindow().getDecorView().findViewById(android.R.id.content);
this.avatarImage = (ImageView)rootView.findViewById(R.id.setavatar);
}
#Override
protected void onPreExecute(){
progressDialog = new ProgressDialog(context);
progressDialog.setMessage("正在上传头像");
progressDialog.setCancelable(true);
progressDialog.show();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
if(avatar == null){
Log.d("222","Null");
}
//Here i Got error,that avatar is null;
avatar.compress(Bitmap.CompressFormat.PNG,90,baos);
byte[] b=baos.toByteArray();
avatarString= new String(b);
}
#Override
protected Boolean doInBackground(Void... param){
//try upload Image to server
}
#Override
protected void onPostExecute(Boolean result){
...//do some work
}
}
It totally confused me,because i got this Error when i click on a Image in gallery,trying to call Crop(),I didn't finish my crop,so the Bitmap data is obvious Null,it seems execute AsyncTask before i finish my crop.It's quite confusing,in the crop() method i start intent to crop like this:startActivityForResult(intent, 2);
But onActivityResult executed the codes before the Result is deliver back.
Please help, Thanks in advance.This really draw me crazy. :(
Update:
Here is some more NullPointerObject stack trace code:
at com.example.allen.bubbles001.Activity.UploadAvatar.onPreExecute(UserProfileActivity.java:229)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:587)
at android.os.AsyncTask.execute(AsyncTask.java:535)
at com.example.allen.bubbles001.Activity.UserProfileActivity.onActivityResult(UserProfileActivity.java:168)
at android.app.Activity.dispatchActivityResult(Activity.java:5423)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3347)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3394)
The first entry point at
avatar.compress(Bitmap.CompressFormat.PNG,90,baos);
in UploadAvatar.onPreExcute
The fourth entry point at
new UploadAvatar(UserProfileActivity.this, bitmap).execute();
in onActivityResult
It's probably the bitmap that is null. You seem to be pulling it out of the "data" Intent, which is probably not a good idea in the first place. Intents have a maximum size limit for extras, and if the Bitmap is large, you will easily go over the limit. Instead, I would recommend saving it to disk and putting the filename in the Intent as an extra so you can read it from the file instead.
I'm using a photo picker intent to choose an image and write it to an application-private file. Most of my important source code is shown below. Once I press a button and perform the first image selection intent, then it successfully updates the image view. However, once I press the image selection button again (in the same activity), then the image view does NOT update, unless I exit and restart the activity. So I know the image is getting successfully saved, but why would the ImageView in the layout not refresh or update?
public void onResume() {
super.onResume();
ImageView myImageView = (ImageView)findViewById(R.id.contact_image);
if (hasImage) {
myImageView.setImageURI(Uri.fromFile(getFileStreamPath(TEMP_PHOTO_FILE)));
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case PHOTO_PICKED:
if (resultCode == RESULT_OK) {
if (data != null) {
Bundle extras = data.getExtras();
if (extras != null) {
hasImage = true;
bmp = (Bitmap) extras.get("data");
}
}
}
break;
}
}
private OnClickListener mChooseImage = new OnClickListener() {
#Override
public void onClick(View v) {
try {
// Launch picker to choose photo for selected contact
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", ICON_SIZE);
intent.putExtra("outputY", ICON_SIZE);
intent.putExtra("scale", true);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(getTempFile()));
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(intent, PHOTO_PICKED);
} catch (ActivityNotFoundException e) {
// LOG THIS
}
}
};
private File getTempFile() {
try {
if (!hasImage) {
FileOutputStream fos = openFileOutput(TEMP_PHOTO_FILE, MODE_WORLD_WRITEABLE);
fos.close();
}
return getFileStreamPath(TEMP_PHOTO_FILE);
} catch (FileNotFoundException e) {
// To be logged later
return null;
} catch (IOException e) {
// To be logged later
return null;
}
}
upon activity result, I set the ImageView's image URI to this file.
When it first completes, the ImageView changes to reflect this. However, if I attempt to choose the image again (same activity), the ImageView will not update until I exit and re-enter the activity. I'm not sure why this happens, is it because I'm trying to write to the temp.jpg everytime? Or do I need to refresh my layout somehow to reflect changes in the ImageView?
Judging by the ImageView source code, the ImageView won't reload the image if you call setImageURI with the same URI. You could try changing the URI by writing your image to another file.
ImageView will not redraw if "new" URI is the same like old one. "View.invalidate()" will not work. To "force" update you can do:
public void onResume() {
super.onResume();
ImageView myImageView = (ImageView)findViewById(R.id.contact_image);
if (hasImage) {
myImageView.setImageDrawable(null); // <--- added to force redraw of ImageView
myImageView.setImageURI(Uri.fromFile(getFileStreamPath(TEMP_PHOTO_FILE)));
}
}
invalidate() not worked. Try hack :
imageView.setImageURI(null);
imageView.setImageURI(newUri);
To force redrawing your widget/View just call View.invalidate();
I had a similar problem where I was using the devices camera to take a picture and then wanting the imageView in the original screen to refresh when I returned to it. The solution was to call View.invalidate() in onResume().
For me, it refreshed my ImageView with this
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_PHOTO && resultCode == RESULT_OK && data != null && data.getData() != null) {
filePath = data.getData();
try {
mProfilePic.setImageURI(null);
mProfilePic.setImageURI(filePath);
Bitmap imageBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath);
mProfilePic.setImageBitmap(imageBitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I would suggest this thing solution. After trying lot of solutions i found this one worked for me.
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 1000ms
ivProfilePic.setImageBitmap(bitImage);
}
}, 1000);
UIView.transition(with: bannerImageView, duration: 0.3, options: [.transitionCrossDissolve], animations: { [weak self] in
self?.exampleImageView.image = newImage
})
Use this func in your view controller
If you are also setting the image using Glide then check if the url is setting up the image or not. If the Glide fails and sets the error Image then setImageURI won't change the image.
This happened in one of my projects. I though this might help someone.