I upload an image to Firebase Storage with Android. I have an app which send image immediately after captured a photo.
But I would like to create an app which show a photo in ImageView before sending. I'd like to write some text under the photo and next, upload both of them.
Which tools should I use to do this?
I've Picasso to download from Storage. But I can't manage how to show an ImageView after capturing a photo, next write some text(like name or description) and send it to Firebase.
The second challenge is how to show particular text with this image?
IMAGE <-> TEXT.
In Firebase Storage I don't see some field to store image with a text.
MainActivity.java:
private ProgressDialog mProgress;
private Bitmap bitmap;
private Button mUploadBtn;
private Button mSendBtn;
private EditText mEditText;
private ImageView mImageView;
Uri picUri;
private StorageReference mStorage;
private static final int CAMERA_REQUEST_CODE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStorage = FirebaseStorage.getInstance().getReference();
mEditText = (EditText) findViewById(R.id.editText);
mSendBtn = (Button) findViewById(R.id.sendBtn);
mUploadBtn = (Button) findViewById(R.id.uploadBtn);
mImageView = (ImageView) findViewById(R.id.imageView);
mProgress = new ProgressDialog(this);
mUploadBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File file=getOutputMediaFile(1);
picUri = Uri.fromFile(file); // create
i.putExtra(MediaStore.EXTRA_OUTPUT,picUri); // set the image file
startActivityForResult(i, CAMERA_REQUEST_CODE);
}
});
}
public void UploadWithText(){
String name = mEditText.getText().toString().trim();
}
/** Create a File for saving an image */
private File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyApplication");
/**Create the storage directory if it does not exist*/
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return null;
}
}
/**Create a media file name*/
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == 1){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".png");
} else {
return null;
}
return mediaFile;
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK ) {
mProgress.setMessage("Uploading Image...");
mProgress.show();
Uri uri = picUri;
StorageReference filepath = mStorage.child("Photos").child(uri.getLastPathSegment());
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
mProgress.dismiss();
Uri downloadUri = taskSnapshot.getDownloadUrl();
Picasso.with(MainActivity.this).load(downloadUri).fit().centerCrop().into(mImageView);
Toast.makeText(MainActivity.this, "Uploaded Successfully.", Toast.LENGTH_LONG).show();
}
});
}
}
Maybe there is a way that I can send the image to Firebase Storage but a Text(description) is sending to Database with a Name field(from Firebase Storage) and with this I can recognize which Text belongs to a particular image?
Could somebody help me to resolve this challenge?
Regards
I can only answer broadly, since there's a bit too much code to answer specifically without doing it for you. In general, there are few ways to do this:
Add text to the image file itself, upload the new image with changes made
Store text as an image attribute, upload the file and save attributes elsewhere
You can either store the data in the Realtime Database, or
You can store the data in Storage file metadata (assuming pairs)
Related
I currently have an application with a button that takes a photo. However, when I click the button the default camera application opens, then you manually have to take a photo. How do I get the camera application to not open and just take a picture automatically and save it just by pressing the button in my application? I would like to press the button that I created and it takes a photo and saves it automatically.
MainActivity.java
public class MainActivity extends AppCompatActivity {
//for taking photos
static final int REQUEST_IMAGE_CAPTURE = 1;
String currentPhotoPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void onResume(){
super.onResume();
}
//button to start image capturing process
public void startImageCapture(View view){
dispatchTakePictureIntent();
galleryAddPic();
}
//method for taking a photo
public void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//Ensure that there is 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 e){
Log.i("ERROR","Error in trying to create file for image");
}
//continue only if the file was successfully created
if (photoFile != null){
Uri photoURI = FileProvider.getUriForFile(this,"com.example.MyProject.provider",photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,photoURI);
startActivityForResult(takePictureIntent,REQUEST_IMAGE_CAPTURE);
}
}
}
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
currentPhotoPath = image.getAbsolutePath();
return image;
}
private void galleryAddPic(){
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(currentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
}
For me the easiest solution is using camera view (your own wrapper of Camera2 API or existing CameraView) inside your application and making it invisible or placing some view above it, if you want to hide it.
CameraView API is simple (CameraView Getting Started): just add view into layout, set LifecycleOwner, set callback on taking picture and call camera.takePicture(), when you need to take picture.
Whenever I make a continuous upload to Firebase, the latest photo that I upload will replace all the other link. it's a weird error and hard to believe.
get result image
String filePath = Environment.getExternalStorageDirectory() + "/image2.jpg";
selectedImageUri = Uri.parse(filePath);
imageView.setImageURI(selectedImageUri);
ImageCompression imageCompression = new ImageCompression(this);
String oath = imageCompression.compressImage(filePath);
uriN = Uri.fromFile(new File(oath));
upload the image
private void fabSend(){
if (uriN!=null){
final StorageReference photoRef = storageRef.child(selectedImageUri.getLastPathSegment() + ".jpg");
photoRef.putFile(uriN).addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Uri downloadUrl = taskSnapshot.getDownloadUrl();
image = (downloadUrl.toString());
postRef.push().setValue(new myAdapter(image,
description ,
user.getDisplayName())).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
progress.setVisibility(View.GONE);
imageView.setImageBitmap(null);
uriN = null;
fab.setVisibility(View.VISIBLE);
}
});
}
});}
The fact is if I quit the activity and relaunch it again, this does not happen. I have tried using reCreate() but the same happens.
All links are different ie different upload tokens and different images
but the last picture that is uploaded is the one shown for all links.
That's because you're stating that all images must have the same name (image2.jpg) in this line:
String filePath = Environment.getExternalStorageDirectory() + "/image2.jpg";
What you should do instead is get the Uri from the data parameter in onActivityResult() (I assume that's were you're getting the image result:
selectedImageUri = data.getData();
imageView.setImageURI(selectedImageUri);
ImageCompression imageCompression = new ImageCompression(this);
String oath = imageCompression.compressImage(filePath);
uriN = Uri.fromFile(new File(oath));
Edit: You can change the name before sending it to Firebase Storage, maybe adding date and time. Like this:
String newName = new SimpleDateFormat("yyyy-MM-dd-HHmm").format(new Date());
final StorageReference photoRef = storageRef.child("IMG-"+newName+ ".jpg");
I am trying to capture an image and then display it on the screen using another activity. I am able to successfully capture the images and save them in my desired directory. However, even after hours of struggle, I am still unable to solve this problem. The touch listener is added to the screen though there's no image.
Here's the code:
private void takeImage(){ Intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyImages");
imagesFolder.mkdirs();
File image = new File(imagesFolder, "QR_" + timeStamp + ".png");
Uri uriSavedImage = Uri.fromFile(image);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(imageIntent, PHOTO_TAKEN); }
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PHOTO_TAKEN){
data.putExtra(SET_CAPTURED_IMAGE, true);
} else{
Log.d(MainActivity.DEBUGTAG, "Photo = null");
}
}
Now in another activity (ImageActivity):
addTouchListener() is called in onCreate() method of this activity.
Till here, the image is successfully captured and saved in the directory.
private void addTouchListener(){
ImageView imageView = (ImageView)findViewById(R.id.unlocker_image);
Bundle extras = getIntent().getExtras();
//The following if block is not executed
if (extras != null && extras.getBoolean(MainActivity.SET_CAPTURED_IMAGE)){
Uri imageUri= Uri.parse(extras.getString(MediaStore.EXTRA_OUTPUT));
imageView.setImageURI(imageUri);
} else {
imageView.setImageResource(R.drawable.unlocker_image);
//this is the default image added
}
imageView.setOnTouchListener(collector);
}
At this point, the touch listener is added but there's no image.
I have an imageView i am trying to set an image to based on the file path of an image the user selects from their gallery. I put the path into a database and then i pass that path into another activity to set the imageView to display. The path comes back at all steps as
/external/images/media/23
I have used multiple toasts to check the path in the activity before i pass the path, after receiving the path by the called method so i know the path is being sent from activity to activity correctly. However when i use the following code to set the imageView nothing appears.
File imgFile;
//Bitmap moviePic;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_view);
Bundle income = getIntent().getExtras();
if(income != null)
{
mTitle = income.getString("title");
mYear = income.getString("year");
id = income.getLong("id");
mPath = income.getString("path");
}
Toast.makeText(this, "path: " + mPath, Toast.LENGTH_SHORT).show();
imV = (ImageView) findViewById(R.id.movieImage);
//moviePic = BitmapFactory.decodeFile(mPath);
imgFile = new File(mPath);
imV.setImageURI(Uri.fromFile(imgFile));
//imV.setImageResource(R.drawable.top);
mVT = (TextView) findViewById(R.id.movieViewTitle);
mVT.setText(mTitle);
mVY = (TextView) findViewById(R.id.movieViewYear);
mVY.setText(mYear);
delete = (Button) findViewById(R.id.deleteMovie);
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent deleting = new Intent();
deleting.putExtra("Id", id);
setResult(RESULT_OK, deleting);
finish();
}
});
}
My guess is that im doing something wrong with the file path. Below is the code i use to resolve the path.
imgV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent addImage = new
Intent(android.content.Intent.ACTION_PICK);
addImage.setType("image/*");
startActivityForResult(addImage, 1);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
super.onActivityResult(requestCode, resultCode, intent);
switch(requestCode)
{
case 1:
if(resultCode == RESULT_OK)
{
Uri image = intent.getData();
imgV.setImageURI(image);
moviePath = image.getPath();
Toast.makeText(this, moviePath, Toast.LENGTH_LONG).show();
}
}
}
}
To find the image files i used the android emulator, browsed to google images and downloaded one or two. When i look in the DDMS It placed them in the mnt\sdcar\download\ folder which is obviously different than the path they are resolving to using the image.getPath() method. Is there another way i should be resolving the path? Or is there something im missing with the way the emulator file path works.
Right now I've got an app that takes a photo via an intent. After taking the photo, I want the user to be able to confirm it and push the photo to another activity where they can add details. I'm struggling to find the correct way to pass the photo from activity to activity.
Right now, confirming the photo brings the user back to the main activity.
Here's my relevant code:
Main Activity
public void takePhoto(View view) {
// create Intent to take a picture and return control to the calling application
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
Log.d("MySecondApp",fileUri.toString());// create a file to save the image
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
// start the image capture Intent
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
if (data!=null) {
// Image captured and saved to fileUri specified in the Intent
Toast.makeText(this, "Image saved to:\n" +
data.getData(), Toast.LENGTH_LONG).show();
}
} else if (resultCode == RESULT_CANCELED) {
// User cancelled the image capture
} else {
// Image capture failed, advise user
}
}
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MySecondApp");
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MySecondApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new java.util.Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
I would try something like
if(resultCode == Activity.RESULT_OK)
handleCameraPhoto(data);
handle method:
private void handleCameraPhoto(Intent intent) {
Bundle extras = intent.getExtras();
Bitmap mImageBitmap = (Bitmap) extras.get("data");
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", mImageBitmap);
startActivity(intent);
}
and then, retrieve it in your other activity
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
and assign it to your ImageView
ImageView iv = (ImageView)findViewById(R.id.myImageView);
iv.setImageBitmap(bitmap);
Make a constructor in your new class that takes an intent or even the image:
class newClass {
public newClass(Intent intent){
...
}
...
}
And then just make the intent the size of a thumbnail in this new class where you can do the confirmation in a popup or something similar and then have the information to be filled on the page for this class. This will also be better because if they wanted to retake the picture you could have this class which they are taken to after the picture is taken if not accepted go to take another picture.
Take a look at this blog post I wrote on how to take a full size image and a thumbnail version as well:
Use Camera Activity for Thumbnail and Full Size Image
after you did that you can extract the file path of the saved file from the file instance using getAbsolutePath() method and pass it to the following Activity.