I'm new to android. Now, i'm doing image capturing function using:
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE );
The problem is after I capture my photo, the new captured photo does not display on the image display page.
Does anyone here know where there is code that can help me refresh my android or any step that I need to do so that my image display page can be updated once I capture a new photo?
Any help would be very appreciated and many thanks to you first.
Updated answer:
I use this, may be this can help others:
mScanner = new MediaScannerConnection(
Camera.this,
new MediaScannerConnection.MediaScannerConnectionClient() {
public void onMediaScannerConnected() {
mScanner.scanFile(outputFileUri.getPath(), null /* mimeType */);
}
public void onScanCompleted(String path, Uri uri) {
//we can use the uri, to get the newly added image, but it will return path to full sized image
//e.g. content://media/external/images/media/7
//we can also update this path by replacing media by thumbnail to get the thumbnail
//because thumbnail path would be like content://media/external/images/thumbnail/7
//But the thumbnail is created after some delay by Android OS
//So you may not get the thumbnail. This is why I started new UI thread
//and it'll only run after the current thread completed.
if (path.equals(outputFileUri.getPath())) {
mScanner.disconnect();
//we need to create new UI thread because, we can't update our mail thread from here
//Both the thread will run one by one, see documentation of android
Camera.this
.runOnUiThread(new Runnable() {
public void run() {
}
});
}
}
});
mScanner.connect();
Sally, did you mean that after you take a photo you don't see it in the gallery or file-manager when you look at the directory you know the file to be in?
If so, you need to run the media-scanner like this:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
... where uri is the uri of the photo, since you know it already, although you can use the uri of the directory instead if that's easier (though it is slower - potentially very slow if the directory contains many files or nested directories).
you should take photo using below code::
Calendar cal = Calendar.getInstance();
File file = new File(Environment.getExternalStorageDirectory(),(cal.getTimeInMillis()+".jpg"));
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
selectedImageUri = Uri.fromFile(file);
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, selectedImageUri);
startActivityForResult(i, CAMERA_RESULT);
and on activity result you can use these code:::
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CAMERA_RESULT:
if (resultCode == RESULT_OK) {
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), selectedImageUri);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
You can refresh your activity with :
Intent myIntent = getIntent();
finish();
startActivity(myIntent);
Related
I am building a photo upload form which has to grab an image either from the camera or gallery or whatever other resource is available (Dropbox/Google Drive/Astro File Manager, etc.). I think I have it all working except for one small component.
When the selected image is coming from a network resource, such as Google Drive, it can take a long time to return back to the activity. I would like to make this asynchronous to avoid having the user stare at a black screen while the image downloads.
There's a lot of code that I've written to get this whole thing to work, but here's the general process of it:
The Activity starts and displays the form.
The Intent chooser automatically opens and asks the user to select an image from either the camera or another app.
The user selects some app such as Google Drive, selects an image and that app closes, returning the selected image Uri as the result.
Cache the contents of the file to workaround KitKat permissions which can block from re-reading the image if the Activity closes and needs to resume.
Asynchronously display the scaled bitmap using the cached file as the source.
The Intent chooser closes, the image is displayed in an ImageButton and the form is visible to the user to be filled out before submission.
Once the submit button is tapped, an asynchronous task starts which allows for the multipart upload to the server.
The asynchronous upload uses a callback function to notify the user of the upload progress.
I'm getting stuck in the transition between #3 and #4.
If I use a Thread or AsyncTask
The Intent chooser will remain open, but the image will also be displayed on the form.
If I simply force the user to wait (serially)
The user is stuck looking at a black screen, then the Intent Chooser closes and the image is displayed on the form.
Opening the Intent chooser
/**
* see http://stackoverflow.com/a/12347567/940217
*/
private void openImageIntent() {
// Camera.
final List<Intent> cameraIntents = new ArrayList<Intent>();
final PackageManager packageManager = getPackageManager();
Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile;
try {
uploadableImage.makeCameraTempFile();
photoFile = uploadableImage.getCameraTempFile();
uploadableImage.setCameraFilepath(photoFile.getAbsolutePath());
} catch (IOException ex) {
// Error occurred while creating the File
photoFile = null;
uploadableImage.invalidate();
Log.e(TAG, "Error while creating the temporary file needed for image capture from camera.");
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null && packageManager != null) {
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
for (ResolveInfo res : listCam) {
// Create the File where the photo should go
if (res.activityInfo == null) {
continue;
}
final String packageName = res.activityInfo.packageName;
final Intent intent = new Intent(captureIntent);
intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
intent.setPackage(packageName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
cameraIntents.add(intent);
}
} else {
Toast.makeText(this, "Could not make temporary file.", Toast.LENGTH_LONG).show();
}
// Filesystem.
final Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
// Chooser of filesystem options.
final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source");
// Add the camera options.
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[cameraIntents.size()]));
startActivityForResult(chooserIntent, REQUEST_IMAGE_CAPTURE);
}
onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) {
if (tempUpFile != null){
tempUpFile.invalidate();
}
if (data == null) {
Log.d(TAG, "Data was null -- source was from camera");
uploadableImage.preserveCameraFile();
setPic();
} else {
Uri selectedImageUri = data.getData();
if (selectedImageUri == null) {
Log.e(TAG, "An error that should never occur has occurred -- selectedImageUri was null when trying to get the data from the Image Capture activity result.");
Toast.makeText(this, "Unexpected error when trying to get an image from the gallery or file manager.", Toast.LENGTH_LONG).show();
return;
}
uploadableImage.setSourceImageUri(selectedImageUri, imageButton);
setPic(); // only do this if doing this serially.
}
} else if (resultCode == RESULT_CANCELED){
uploadableImage.invalidate();
if (tempUpFile != null){
uploadableImage = tempUpFile;
}
setPic();
}
}
UploadableImage#setSourceImageUri
public void setSourceImageUri(Uri selectedImageUri, final ImageView iView) {
// Important!! - clean up after ourselves!
deleteFile(this.cameraFile);
this.cameraFile = null;
InputStream tempInStream = null;
OutputStream tempOutStream = null;
try {
this.cacheFile = createFile();
tempInStream = context.getContentResolver().openInputStream(selectedImageUri);
tempOutStream = new FileOutputStream(this.cacheFile);
} catch (IOException e) {
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
if (tempInStream == null || tempOutStream == null){
Toast.makeText(context, "Error while trying to "+(tempInStream == null ? "read" :"store")+" the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "Error while trying to get the " + (tempInStream == null ? "input" : "output") + " stream");
return;
}
// Works, but makes the UI hang on a black screen while waiting for the resource.
try {
copy(tempInStream, tempOutStream);
}catch (IOException e){
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
/*
// Works, but leaves the IntentChooser open
final InputStream inStream = tempInStream;
final OutputStream outStream = tempOutStream;
new Thread(new Runnable() {
public void run() {
try {
copy(inStream, outStream);
// FIXME: somehow notify/display the bitmap in the UI
// --maybe use Message and Handler? callback Interface?
} catch (IOException e) {
Toast.makeText(context, "Error while trying to read the selected image.", Toast.LENGTH_LONG).show();
Log.e(TAG, "IOException while trying to copy the selected image to our cache file");
e.printStackTrace();
}
}
}).start();
*/
}
Edit:
I've found that this will/will not occur depending on API level.
Does not occur:
KitKat (Nexus 4)
ICS MR1 (emulator)
Does occur:
KitKat (emulator)
ICS MR1 (Galaxy Tab 10.1)
Edit 2:
Here are some screenshots of what should not happen; images are from KitKat emulator.
Start the Activity
Select an image from the gallery or some other resource
The onActivityResult returns and the chooser remains open
This is how it should look after onActivityResult
Feeling pretty stupid, but I found the solution.
The issue was in step two: "The Intent chooser automatically opens..."
In order to do this, I was checking to see if a bitmap was available, and if it wasn't then it should display the placeholder image and then open the Intent chooser. I had this logic inside the onStart method which normally gets run after onActivityResult. However, because this was all happening asynchronously, I could not rely on this order.
What I had to do was put in a boolean flag which could tell me if we were waiting for a bitmap, and then not open the chooser if we were.
I am developing a custom camera app in Android. My goal is to save a picture to file and open it in the fullscreen mode as soon as the file has been saved. Unfortuantely, the problem is that my main activity (ImageCapture) doesn't wait for ImageCaptureCallback results before calling the next activity (ImageDisplay).
To take a picture I am using a custom ImageCaptureCallback, which saves captured image to "tmpPicturePath" using OutputStream. Later the ImageDisplay activity is called - it reads the file saved in tmpPicturePath.
camera.takePicture(mShutterCallback, mPictureCallbackRaw, new ImageCaptureCallback(this));
// ImageCaptureCallback saves the file in tmpPicturePath
Intent intent = new Intent(ImageCapture.this, ImageDisplay.class);
intent.putExtra("tmpPicturePath", this.getTmpPicturePath());
startActivity(intent);
BUT the file that should be created in ImageCaptureCallback is not yet available at the moment of calling ImageDisplay activity. The overall effect is that not the actual but the previously taken picture is available in the ImageDisplay class. Do you have an idea how to handle this issue? In other words how to wait for callback results before calling the next activity?
Many thanks!
Sample code for taking picture from camera
void selectPhoto() {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "New Picture");
values.put(MediaStore.Images.Media.DESCRIPTION, "From your Camera");
imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, SELECT_PHOTO);
}
and in onActivityResult() method
try {
imageBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
When i do debug it didnt go to try block than catch block , this is my code please help me!
public void onClick(View v) {
try {
path = Environment.getExternalStorageDirectory()+"/audio_meena.AMR";
File newFile = new File(path);
Uri uri =Uri.fromFile(newFile);
Intent audioIntent=new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
startActivityForResult(audioIntent, RQS_RECORDING);
mr.setAudioSource(MediaRecorder.AudioSource.MIC);
mr.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mr.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
FileDescriptor PATH_NAME = null;
mr.setOutputFile(PATH_NAME);
} catch (Exception e) {
// TODO: handle exception
}
}
});
either set the "onClick" attribute to the view you wish (via the layout) , or find it right after the "setContentView" using "findViewById" and then use "setOnClickListener" for the view .
about "OnActivityResult", you need to put it in the activity itself as a stand alone method .
Is it possible to post a picture in a friend's wall?
I'm using this code :
Bundle postdata = new Bundle();
postdata.putString("message", msg);
postdata.putByteArray("picture", pic);
// this code, i found it in another questions but it doesn't
// seem to help much:
postdata.putString("target_id", usr);
// then i use the Asynchronous request.
mAsyncRunner.request(usr+"/feed", postdata, "POST",new WallRequestListener(), null);
where pic is the picture as a byteArray and usr is the friend's ID.
It just shows the message on the friend's wall but no picture at all.
This is what I use in my app. And it works.
protected void uploadPhoto() {
if (!Utility.mFacebook.isSessionValid()) {
Util.showAlert(this, "Warning", "You must first log in.");
} else {
if (targetUri != null) {
Bundle params = new Bundle();
try {
params.putByteArray("photo", Utility.scaleImage(getApplicationContext(), targetUri));
} catch (Exception e) {
e.printStackTrace();
}
params.putString("caption", txtPhotoCaption.getText().toString());
Utility.mAsyncRunner.request( "replace this with the users ID"+ "/photos&access_token=" + Utility.mFacebook.getAccessToken(),
params, "POST", new PhotoUploadListener(), null);
txtPhotoCaption.setText("");
Toast.makeText(getApplicationContext(), "Photo uploaded successfully", Toast.LENGTH_SHORT).show();
this.finish();
}
}
}
Please note, that I am using the same method as used in the sample app. Without getting into the pros or cons of scaling or not scaling the image. The "caption" attribute is being pulled from an EditText. And the actual image is in the field "targetUri", which is declared as a global variable. It's fetching the image using the default Gallery on the device. For the sake of completeness, this is the code to grab the image from the default Gallery app. (this prompts the user to select the app)
btnAddPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 0);
}
});
And it is processed in the onActivityResult() here:
NOTE: I am also setting the selected image in an ImageView as a preview to the logged in user
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
Bitmap bitmap = null;
if (resultCode == RESULT_OK) {
targetUri = data.getData();
Log.e("IMG URI", targetUri.toString());
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri));
try {
Utility.scaleImage(getApplicationContext(), targetUri);
imgDisplaySelectedImage.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
I have again tested an upload to a friends wall before I posted the code here as an answer. And it really works. Hope this helps you as well.
EDIT:
As mentioned in the latest comment, using Intent.ACTION_GET_CONTENT did not play nice with the preview image display under the onActivityResult(). Modifying the code a little worked.
What I find strange is the fact that in the "Complete action using" popup, I did not get the Astro File Manager nor the Gallery on my Galaxy S. It gives me File Manager (off the market, not the stock) and Quickoffice Pro. That being said, selections from either the two still works and photos still upload.
According to the documentation the name of the parameter for the picture is not "picture" but "source".
So your code should be:
Bundle postdata = new Bundle();
postdata.putString("message", msg);
postdata.putByteArray("source", pic);
mAsyncRunner.request(usr + "/feed", postdata, "POST", new WallRequestListener(), null);
I've got a image selector/cropper with code taken from this site
They create the image in the phone's external storage but I want to store this in my app's internal storage, a process documented here
This is what my function to retrieve the temp file looks like, however when I try to use the file returned from this function, the image does not change. In fact, looking at logcat, it seems resolveUri failed on bad bitmap uri on that file I generated. The error occurs when I try to set the Image URI, leading me to believe it was not saved properly. This is odd to me considering the original code from the site just creates a file in the SD card, and the code works fine for reading/writing to that. So I wonder where the problem arises.
#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) {
ImageView callerImage = (ImageView)findViewById(R.id.contact_image);
callerImage.setImageURI(Uri.fromFile(getTempFile()));
}
}
}
break;
}
}
private File getTempFile() {
try {
FileOutputStream fos = openFileOutput(TEMP_PHOTO_FILE, Context.MODE_WORLD_WRITEABLE);
fos.close();
File f = getFileStreamPath(TEMP_PHOTO_FILE);
return f;
} catch (FileNotFoundException e) {
// To be logged later
return null;
} catch (IOException e) {
// To be logged later
return null;
}
}
Never mind, I am so silly. When I called getTempFile, each time it recreates the file, which is a mistake. It should only create the file on the initial call and simply open it the rest of the time.