I am developing an android app that captures images of a Google map (V2). I require the user to name those pictures. The user should be able to name the picture after he presses the snapshot button. Should i put an edit text into an alert dialog and then put the string from the edit text as the image name? Here is the code I use for capturing those images:
public void CaptureMapScreen() {
SnapshotReadyCallback callback = new SnapshotReadyCallback() {
Bitmap bitmap;
#Override
public void onSnapshotReady(Bitmap snapshot) {
bitmap = snapshot;
try {
FileOutputStream out = new FileOutputStream(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)+File.separator+"Rute"+File.separator
+ "MyMapScreen" + System.currentTimeMillis() + ".png");
// above "/mnt ..... png" => is a storage path (where image will be stored) + name of image you can customize as per your Requirement
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
}
};
map.snapshot(callback);
}
Related
I'm trying to save the frame of the image from the live stream video. So, I'm able to show live stream video from my android application as well as saving it in my local storage. Now, I want to use some sort of delay in my saveImage function so that images get saved after some specific time. I have used both Handler and TimerTask. The image is getting saved in my local directory after some delay but the length of the image that I get is sometimes very small, the other time normal. I want my saved image to exactly the length of the video stream that I am getting in my application.
I hope the question I asked is easy to understand. I am a beginner in both android and stack overflow.
P.S - I used mjpeg library for showing the video. The video I am getting is from an IP Camera.
Code for saving the images
public void saveImage(){
try {
photo =
new File(Environment.getExternalStorageDirectory(),
"Download/photos/photo" + Instant.now().getEpochSecond() + ".jpg");
if (photo.exists()) {
photo.delete();
}
System.out.println("Photo " + photo);
FileOutputStream fos = new FileOutputStream(photo.getPath());
System.out.println("Image_length" +image.length);
fos.write(image);
fos.close();
} catch (IOException e) {
Log.e("PictureDemo", "Exception in photoCallback", e);
}
}
Code where saveImage is called
final Bitmap outputImg = BitmapFactory.decodeByteArray(image, 0, image.length);
if (outputImg != null) {
if (run) {
newFrame(outputImg);
// Saving frames in internal Storage
new Timer().schedule(
new TimerTask() {
#Override
public void run() {
saveImage();
}
},5000
);
}
} else {
Log.e(tag, "Read image error");
}
I want to implement functionality for saving image in Downloads directory and after that offer to user to open this one in a directory (open directory in which user can find and open this image). But I've got one issue. Saving ends successfully, but when user clicks "OPEN" in snackbar and chooses app to perform this action another directory appears. It contains also "Downloads" directory as well, this Downloads directory does not contain saved images! It seems like in android we have two different "Downloads" directories.
Below is how i get path for save image:
private File getFileForImageSaving() {
String filename = getImageNameFromUrl(mImageUrl) + ".png";
File dest = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
filename);
int index = 1;
while (dest.exists()) {
filename = getImageNameFromUrl(mImageUrl) + "_" + index + ".png";
dest = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
filename);
index++;
}
return dest;
}
This is how i run activity for view "Download" directory and open files.
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
Uri uri = Uri.parse(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath());
intent.setDataAndType(uri, "image/png");
startActivity(Intent.createChooser(intent, "Open folder"));
This is how I save image. It is realy works, I've checked.
pri
vate void saveImageToFile() {
File dest = getFileForImageSaving();
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
FileOutputStream out = null;
try {
dest.createNewFile();
out = new FileOutputStream(dest);
Bitmap bitmap = Glide.with(ArticleImageViewActivity.this)
.load(mImageUrl)
.asBitmap()
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.get();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
Utils.showInSnackBar(
ArticleImageViewActivity.this, getString(R.string.image_has_been_successfully_saved),
Snackbar.LENGTH_LONG,
onOpenImageInDirectoryListener,
getString(R.string.open_image_in_directory));
} catch (Exception e) {
Utils.showInSnackBar(ArticleImageViewActivity.this,
getString(R.string.error_occurred_during_saving_image),
Snackbar.LENGTH_SHORT, null, null);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}.execute();
}
I partially resolve my problem by using Intent.ACTION_VIEW instead of Intent.ACTION_GET_CONTENT and " / " mime type instead of "image/png". But only partially because in this case user will be offered to choose a wide range of applications, but not only applications like filemanagers.
use MediaScannerConnection.scanFile to scan the file after saving. if you don't many/most galleries wont show your file.
https://developer.android.com/reference/android/media/MediaScannerConnection.html
I am writing tests using espresso,my app intends to phone camera, where i press the click button manually,and then it migrates to the next screen,I am not able to automate the image click button in test code,how can i access camera using code through which i can do the same.
Thanks.
You should not open the camera intent or you'll have no way of getting any resulting image back from it (without pressing the camera button manually).
Have a look at the Stubbing out the Camera section of this website:
https://guides.codepath.com/android/UI-Testing-with-Espresso#stubbing-out-the-camera
This way you test your activity by simulating an actual image "returned" to your app from the Camera.
Update
And this is the method I use to get a bitmap to test:
public static Bitmap getTestBitmap(Context context, String resourceName) {
Resources resources = context.getResources();
Bitmap ret = null;
int imageResource = resources.getIdentifier(
resourceName, "drawable", context.getPackageName());
Uri pictureUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
+ resources.getResourcePackageName(imageResource) + '/'
+ resources.getResourceTypeName(imageResource) + '/'
+ resources.getResourceEntryName(imageResource));
try {
ret = MediaStore.Images.Media.getBitmap(context.getContentResolver(), pictureUri);
} catch (Exception e) {
}
return ret;
}
And then I save the bitmap in internal storage and get the uri:
public static Uri saveToInternalStorage(Context context, Bitmap bitmapImage, String fileName) {
ContextWrapper cw = new ContextWrapper(context);
// path to /data/data/yourapp/app_data/pictures
File directory = cw.getDir("pictures", Context.MODE_PRIVATE);
// Create imageDir
File mypath = new File(directory, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (Exception e) {
}
}
return Uri.fromFile(new File(mypath.getAbsolutePath()));
}
I know this is late, but it's something I struggled with myself and I would like to post an answer to help someone else. Here is how you click the camera button from a chooser (after you set it up), you use UIAutomator, as suggested by PunitD in the comments of the original post. This will pick up from where the test is showing a chooser on the screen.
public static final int waitTimeNativeApi = 6000;
public static void await(int time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted while sleeping");
}
}
private void takePhoto() {
boolean usePixels = true;
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
UiObject titleTextUI = device.findObject(new UiSelector()
.className("android.widget.TextView")
.text("Camera")
);
try {
titleTextUI.clickTopLeft();
if (usePixels) {
takePhotoForPixels(device);
} else {
takePhotoForSamsung(device);
}
} catch (UiObjectNotFoundException unofe) {
unofe.printStackTrace();
}
}
private void takePhotoForPixels(UiDevice device) {
// close the app selector to go back to our app so we can carry on with Espresso
await(waitTimeNativeApi);
//TAP on the camera icon
device.click(device.getDisplayWidth() / 2, device.getDisplayHeight() - 100);
await(waitTimeNativeApi);
//Get the OK button
device.click(device.getDisplayWidth() / 2, device.getDisplayHeight() - 100);
await(waitTimeNativeApi);
}
private void takePhotoForSamsung(UiDevice device) throws UiObjectNotFoundException {
// close the app selector to go back to our app so we can carry on with Espresso
UiObject titleTextUI = device.findObject(new UiSelector()
.className("android.widget.TextView")
.text("Camera")
);
titleTextUI.clickTopLeft();
await(waitTimeNativeApi);
//TAP on the camera icon
device.click(device.getDisplayWidth() / 2, device.getDisplayHeight() - 50);
//Get the OK button
UiObject cameraOkUi = device.findObject(new UiSelector()
.className("android.widget.TextView")
.text("OK")
);
cameraOkUi.click();
await(waitTimeNativeApi);
}
In this way, you will take an actual photo and get the results back in onActivityResult.
I'm currently developing an Android Application. My current progress is that I successful develop custom android camera. I followed this step (http://courses.oreillyschool.com/android2/CameraAdvanced.html) The tutorial given saved the picture taken into the gallery, but I want to insert the name, description, and other information of the Image because I'm going to save the image along with the details that the user enter into my database.
Here for example on my interface:
a) Success taken Image:
b) The image that need to be pass to another Imageview (red circle):
I want the save button able to pass the image that had been taken to the ImageView(red circle) and not to store the image into the gallery. And here's are the code on the save button:
private View.OnClickListener mSaveImageButtonClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
File saveFile = openFileForImage();
if (saveFile != null) {
saveImageToFile(saveFile);
} else {
Toast.makeText(Capturingimage.this, "Unable to open file to save the image.", Toast.LENGTH_LONG).show();
}
}
};
This is save image to file method:
private void saveImageToFile(File file) {
if (mCameraBitmap != null) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(file);
if (!mCameraBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream)) {
Toast.makeText(Capturingimage.this, "Unable to save image to file.",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(Capturingimage.this, "Saved image to: " + file.getPath(),
Toast.LENGTH_LONG).show();
}
outStream.close();
} catch (Exception e) {
Toast.makeText(Capturingimage.this, "Unable to save image to file.",
Toast.LENGTH_LONG).show();
}
}
}
My ImageView(redCircle) id is :
#+id/image_view_after_capture
If you guys aren't very clear with the codes, here's the link on the full source code (http://courses.oreillyschool.com/android2/CameraAdvanced.html) on MainActivity.java. I'm sorry if my question is a lil bit messy and less explanation on the codes. I'm new to android programming, I hope you guys can teach me. I really appreciate your time and help to consider to help me.
Thank you in Advance!
when you save image than hold your captured image path and pass to another activity where you want to show
String mCaptureImagePath="";
private void saveImageToFile(File file) {
if (mCameraBitmap != null) {
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(file);
if (!mCameraBitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream)) {
Toast.makeText(Capturingimage.this, "Unable to save image to file.",
Toast.LENGTH_LONG).show();
} else {
mCaptureImagePath=file.getPath(); //**** this is your save image path
Toast.makeText(Capturingimage.this, "Saved image to: " + file.getPath(),
Toast.LENGTH_LONG).show();
}
outStream.close();
} catch (Exception e) {
Toast.makeText(Capturingimage.this, "Unable to save image to file.",
Toast.LENGTH_LONG).show();
}
}
}
After show image where you want like this
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(mCaptureImagePath,bmOptions);
yourImageView.setImageBitmap(bitmap);
I want to start the camera intent within my app to take a picture and save it to internal storage. I'm using the code of google developers page Capturing images or video.
In the processPictureWhenReady method I've implemented the following code to save the picture:
private void processPictureWhenReady(final String picturePath) {
Log.v("path processPictureWhenReady ", " " + picturePath);
final File pictureFile = new File(picturePath);
if (pictureFile.exists()) {
// The picture is ready; process it.
try {
Bitmap imageBitmap = BitmapFactory.decodeFile(picturePath);
int w = imageBitmap.getWidth();
int h = imageBitmap.getHeight();
Bitmap bm2 = Bitmap.createScaledBitmap(imageBitmap, w / 2,
h / 2, true);
imageBitmap = bm2.copy(bm2.getConfig(), true);
MediaStore.Images.Media.insertImage(getContentResolver(),
imageBitmap, "test", "Test");
} catch (Exception e) {
Log.e("Exc", e.getMessage());
}
}
The camera intent is starting and then I have "tap to accept" to take a picture. But then nothing happens. I have a log message in my onActivityResult method and noticed that the method is not beeing called.
This is a known issue. I have the same problem. I'm following the case here in the meantime
I've seen people try implementing the preview mode with SurfaceView (I haven't personally gotten it to work but it's worth a shot). Also check here for a similar problem.
I used this method it worked for me very well.
private void processPictureWhenReady(final String picturePath) {
final File pictureFile = new File(picturePath);
if(pictureFile.exists()){
}
if (pictureFile.exists()) {
} else {
final File parentDirectory = pictureFile.getParentFile();
FileObserver observer = new FileObserver(parentDirectory.getPath()) {
private boolean isFileWritten;
#Override
public void onEvent(int event, String path) {
if (!isFileWritten) {
// For safety, make sure that the file that was created in
// the directory is actually the one that we're expecting.
File affectedFile = new File(parentDirectory, path);
isFileWritten = (event == FileObserver.CLOSE_WRITE && affectedFile.equals(pictureFile));
if (isFileWritten) {
stopWatching();
// Now that the file is ready, recursively call
// processPictureWhenReady again (on the UI thread).
runOnUiThread(new Runnable() {
#Override
public void run() {
processPictureWhenReady(picturePath);
}
});
}
}
}
};
observer.startWatching();
}
}