So i'm trying to get the user to pick an image from their photo gallery then upload it to Firebase Storage...so far my code looks as follows:
#Override
protected void onActivityResult(int requestCode,int resultcode, Intent data){
super.onActivityResult(requestCode,resultcode,data);
if(requestCode == REQUEST_IMAGE_CAPTURE && resultcode == RESULT_OK) {
final Uri uri = data.getData();
if (uri != null){
Bitmap bmp = null;
try {
bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
} catch (IOException e){
e.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 25, baos);
byte[] fileInBytes = baos.toByteArray();
bmp.recycle();
FirebaseAuth auth = FirebaseAuth.getInstance();
FirebaseStorage storage = FirebaseStorage.getInstance();
String imageString = "";
if(clickPhoto ==1){imageString = "Image 1"; }
else if(clickPhoto ==2){imageString = "Image 2"; }
else if (clickPhoto ==3){imageString = "Image 3"; }
else if (clickPhoto ==4){imageString = "Image 4"; }
final StorageReference storageReference = storage.getReference().child("Images").child("users").child(auth.getCurrentUser().getUid()).child(imageString);
storageReference.putBytes(fileInBytes).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
storageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String downloadUrl = uri.toString();
String urlString ="";
if(clickPhoto ==1){ urlString = "photo1URI";}
if(clickPhoto ==2){ urlString = "photo2URI";}
else if (clickPhoto ==3){ urlString = "photo3URI";}
else if (clickPhoto ==4){urlString = "photo4URI";}
toMap.put(urlString, downloadUrl);
updatedb();
toMap.clear();
Log.d("uriii",downloadUrl);}
});
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("UploadFailure",e.getMessage());
}
});
}
else {
Toast.makeText(this,"Didn't work",Toast.LENGTH_LONG).show();
}
}
}
My problem is that the image that is uploaded changes orientation...seeminly at random....how do i maintain orientation? I've looked at Exif interface but can't see an answer for uploading it as a ByteArrayOutputStream?
Any help would be appreciated.
Issue is that EXIF information from image (including orientation) is removed after compressing. You need to copy EXIF info from original image to compressed one. Solution explained here.
Related
The application attempts to capture an image using the device's camera and upload it to FireBase. However, after an image is captured, the app crashes.
It shows the error: java.lang.NullPointerException: Attempt to invoke virtual method 'android.net.Uri android.content.Intent.getData()' on a null object reference
Functions in MainActivity:
private File createImageFile() throws IOException {
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 */
);
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
Log.e("MainActivity", "Error creating file", e);
}
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
storage = FirebaseStorage.getInstance().getReference();
take_pic = (Button) findViewById(R.id.take_pic);
imageView = (ImageView) findViewById(R.id.pic_view);
progressDialog = new ProgressDialog(this);
take_pic.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dispatchTakePictureIntent();
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
progressDialog.setMessage("Uploading...");
progressDialog.show();
StorageReference filepath;
Uri uri = data.getData();
filepath = storage.child("Photos").child(uri.getLastPathSegment());
filepath.putFile(photoURI).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(MainActivity.this, "Upload Successful!", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivity.this, "Upload Failed!", Toast.LENGTH_SHORT).show();
}
});
}
}
You are getting that errror because your intent.getData is null. It happened to me too, your onActivityResult when using the take picture intent always brings the data as null. As a workaround I made the photoURI a global variable in the activity and onActivityResult called it again. It would be something like this:
First you declare the variable
Uri myPhotoUri = null;
Then, you initiate it in your dispatchTakePictureIntent function:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
Log.e("MainActivity", "Error creating file", e);
}
if (photoFile != null) {
//you are adding initializing the uri
myPhotoUri = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
And on your onActivityResult, you use that uri to call to your firebase function. It will now have the information necessary to upload it:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
progressDialog.setMessage("Uploading...");
progressDialog.show();
StorageReference filepath;
//you delete the Uri uri = data.getData();
filepath = storage.child("Photos").child(uri.getLastPathSegment());
//here you call it
filepath.putFile(myPhotoUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(MainActivity.this, "Upload Successful!", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivity.this, "Upload Failed!", Toast.LENGTH_SHORT).show();
}
});
}
}
First check that you have permission for using the camera, then
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQ);
Then onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQ && resultCode == Activity.RESULT_OK) {
bitmap = (Bitmap) data.getExtras().get("data");
Bitmap.createScaledBitmap(bitmap, 150, 150, true);
}
}
then from bitmap to byte[]
public static byte[] getByteArrayFromBitmap(Bitmap bitmap) {
if(bitmap == null) return null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
You can now do whatever you want with the bitmap or byte[]
I wrote a program where a user can click a TextView (editPhoto) and select an image (profile picture) and display on the profile and also save it on my database with the rest of the profile details, but as soon as I leave the page the picture disappears from the CircleImageView although it's still saved on my database. I am able to save the rest of the users information on the profile like name, username, email etc using .setText() so how can I do the same with the CircleImageView for the profile picture? Thanks in advance
CODE:
private TextView editPhoto;
CircleImageView profilePic;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_profile);
profilePic = findViewById(R.id.profilepic);
editPhoto = findViewById(R.id.txtEditPP);
editPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
chooseFile();
}
});
}
private void chooseFile(){
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Choose Photo"),1);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null){
Uri filepath = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filepath);
profilePic.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
UploadPicture(getId, getStringImage(bitmap));
}
}
//UPLOAD PROFILE PICTURE
private void UploadPicture(final String id, final String photo) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL_UPLOAD, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i(TAG, response.toString());
try {
JSONObject jsonObject = new JSONObject(response);
String success = jsonObject.getString("success");
if (success.equals("1")){
Toast.makeText(EditProfile.this, "Photo Uploaded", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(EditProfile.this, "Error Uploading Image!", Toast.LENGTH_SHORT).show();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(EditProfile.this, "Error Uploading Image!", Toast.LENGTH_SHORT).show();
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("ID", id);
params.put("photo", photo);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
public String getStringImage(Bitmap bitmap){
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
byte[] imageByteArr = byteArrayOutputStream.toByteArray();
String encodedImage = Base64.encodeToString(imageByteArr, Base64.DEFAULT);
return encodedImage;
}
In onResume can you reload imageView using bitmap object?
Also make bitmap object as class variable reloading image will work for you in this case.
I am trying to call the Camera app twice as described here: https://developer.android.com/training/camera/photobasics
Now when I was using this without creating a temp file this worked and I was able to call the camera twice but after adding the temp file I am only able to take one file before crashing. it is very frustrating because I can see that it is returning a full size image before crashing.
I have tried doing a second .putExtras() before the get but that is not working. I have also tried assert not null, same results.
private void takePictureAndUpload() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.provider",
photoFile);
startActivityForResult(takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
, REQUEST_IMAGE_CAPTURE);
}
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if ((requestCode == REQUEST_IMAGE_CAPTURE) && (resultCode == Activity.RESULT_OK)){
count++;
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
assert imageBitmap != null;
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
final byte[] imageData = stream.toByteArray();
setuId(user);
final String path = "posts/" + UUID.randomUUID() + ".jpg";
FirebaseStorage storage = FirebaseStorage.getInstance();
final StorageReference storageRef = storage.getReference();
final StorageReference imageRef = storageRef.child(path);
UploadTask uploadTask = imageRef.putBytes(imageData);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
String ex = e.getLocalizedMessage();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
imageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>()
{
#Override
public void onSuccess(Uri downloadUrl)
{
final String url = downloadUrl.toString();//do something with downloadurl
data.putExtra(MediaStore.EXTRA_OUTPUT, url);
addPhotoUrlToDatabase(post.getImageUrl_1(), post.getImageUrl_2(), path);
}
});
}
});
}
}
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;
}
This should open the camera take a picture then after accepting the first picture it should reopen camera for a second picture. However so far all it does is open camera, take a picture then when I hit accept it crashes with a nullPointerException.
LogCat:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android, PID: 21689
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=null} to activity {com.example.android/com.example.android.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Bundle android.content.Intent.getExtras()' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:4491)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4534)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1752)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.os.Bundle android.content.Intent.getExtras()' on a null object reference
at com.example.android.MainActivity.onActivityResult(MainActivity.java:257)
at android.app.Activity.dispatchActivityResult(Activity.java:7547)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4487)
Edit
This is the guide that I am following:
https://developer.android.com/training/camera/photobasics.html#TaskPath
Make your activity result like this as using the same named parameters are confusing.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
}
Your Bundle seems like it's null.
Found an answer here:https://stackoverflow.com/a/37628687/10941659. It is not made clear on the android developer training site, but when you want to get a full size image you don't use the intent that you pass to onActivityResult. You need to use the path that you generate for your image, for example:
private void takePictureAndUpload() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
photoURI = FileProvider.getUriForFile(this,
"com.example.android.provider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
protected void onActivityResult(int requestCode, int resultCode, final Intent data){
super.onActivityResult(requestCode, resultCode, data);
if ((requestCode == REQUEST_IMAGE_CAPTURE) && (resultCode == Activity.RESULT_OK)){
count++;
Bitmap imageBitmap = null;
try {
imageBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),photoURI);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
final byte[] imageData = stream.toByteArray();
setuId(user);
final String path = "posts/" + UUID.randomUUID() + ".jpg";
FirebaseStorage storage = FirebaseStorage.getInstance();
final StorageReference storageRef = storage.getReference();
final StorageReference imageRef = storageRef.child(path);
UploadTask uploadTask = imageRef.putBytes(imageData);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
String ex = e.getLocalizedMessage();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
imageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>()
{
#Override
public void onSuccess(Uri downloadUrl)
{
final String url = downloadUrl.toString();//do something with downloadurl
addPhotoUrlToDatabase(post.getImageUrl_1(), post.getImageUrl_2(), path);
}
});
}
});
}
}
I'm trying to create an app where you can add profile images from your mobile device, then save it to firebase, and retrieve it from firebase as well, as efficiently as possible.
A few questions:
1: How do these big dating apps such as bumble/tinder create the edit profile image UI where you upload your profile images and rearrange them? Do they place cardviews into a gridview, seeing as how these cards have the ability to be dragged to rearrange the position? Also they normally have a small x button attached to delete the image, so it would be a cardview, right?
I'm currently using ImageViews for testing and wanted to incorporate the ability to add more, but my code is horrible and it overwrites the images in the firebase DB if I return to the page and add a new image.
LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SettingsActivity"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/back"
android:text="Back"
android:layout_marginBottom="20sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20sp"
android:orientation="horizontal">
<ImageView
android:layout_width="100sp"
android:layout_height="100sp"
android:id="#+id/image1"
android:src="#mipmap/ic_launcher"
android:layout_margin="20sp"
android:layout_gravity="start"
/>
<ImageView
android:layout_width="100sp"
android:layout_height="100sp"
android:id="#+id/image2"
android:src="#mipmap/ic_launcher"
android:layout_margin="20sp"
android:layout_gravity="center_horizontal"
/>
<ImageView
android:layout_width="100sp"
android:layout_height="100sp"
android:id="#+id/image3"
android:src="#mipmap/ic_launcher"
android:layout_margin="20sp"
android:layout_gravity="end"
/>
</LinearLayout>
public class SettingsActivity extends AppCompatActivity {
private Button mBack;
private ImageView mImage1, mImage2, mImage3;
private FirebaseAuth mAuth;
private DatabaseReference mUserDb, mTagsDb;
private String userId, phone, image1Url, image2Url, image3Url, userSex;
private Uri resultUri1, resultUri2, resultUri3;
private ArrayList<Uri> resultUri = new ArrayList<Uri>();
private ArrayList<ImageView> imageViewsList = new ArrayList<ImageView>();
final int MaxTags = 5;
final int MaxImages = 3;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
mImage1 = findViewById(R.id.image1);
mImage2 = findViewById(R.id.image2);
mImage3 = findViewById(R.id.image3);
mBack = findViewById(R.id.back);
mAuth = FirebaseAuth.getInstance();
userId = mAuth.getCurrentUser().getUid();
mUserDb = FirebaseDatabase.getInstance().getReference().child("Users").child(userId);
getUserInfo();
mImage1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 1);
}
});
mImage2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 2);
}
});
mImage3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 3);
}
});
mBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
saveUserInformation();
finish();
}
});
private void saveUserInformation() {
phone = mPhoneField.getText().toString();
Map userInfo = new HashMap();
userInfo.put("phone", phone);
mUserDb.updateChildren(userInfo);
if(resultUri != null){
for(int i = 0; i < resultUri.size(); i++)
{ String num = String.valueOf(i);
final StorageReference filePath = FirebaseStorage.getInstance().getReference().child("profileImages").child(userId).child(num);
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplication().getContentResolver(), resultUri.get(i));
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, baos);
byte[] data = baos.toByteArray();
UploadTask uploadTask = filePath.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
finish();
}
});
final int finalI = i+1;
uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
filePath.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Map newImage = new HashMap();
newImage.put("image"+ finalI +"Url", uri.toString());
mUserDb.updateChildren(newImage);
finish();
return;
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
finish();
return;
}
});
}
});
}
}else{
finish();
}
}
ArrayAdapter<String> values;
private void getUserInfo() {
mUserDb.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists() && dataSnapshot.getChildrenCount()>0){
Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();
if(map.get("phone") != null){
phone = map.get("phone").toString();
mPhoneField.setText(phone);
}
if(map.get("sex") != null){
userSex = map.get("sex").toString();
}
Glide.clear(mImage1);
Glide.clear(mImage2);
Glide.clear(mImage3);
if(MaxImages == 3) {
imageViewsList.add(mImage1);
imageViewsList.add(mImage2);
imageViewsList.add(mImage3);
}
for(int i = 0; i < MaxImages; i ++)
{
int b = i+1;
if(map.get("image"+b+"Url") != null){
String url = map.get("image"+b+"Url").toString();
switch(url){
case "default":
imageViewsList.get(i).setImageResource(R.mipmap.ic_launcher);
//Glide.with(getApplication()).load(R.mipmap.ic_launcher).into(mImage1);
break;
default:
Glide.with(getApplication()).load(url).into(imageViewsList.get(i));
break;
}
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1 && resultCode == Activity.RESULT_OK){
final Uri imageUri = data.getData();
resultUri1 = imageUri;
mImage1.setImageURI(resultUri1);
resultUri.add(resultUri1);
}
if(requestCode == 2 && resultCode == Activity.RESULT_OK){
final Uri imageUri = data.getData();
resultUri2 = imageUri;
mImage2.setImageURI(resultUri2);
resultUri.add(resultUri2);
}
if(requestCode == 3 && resultCode == Activity.RESULT_OK){
final Uri imageUri = data.getData();
resultUri3 = imageUri;
mImage3.setImageURI(resultUri3);
resultUri.add(resultUri3);
}
}
}
Currently I can upload images to the imageviews fine and save them to firebase, but for example if I upload 2 images, then save and return to upload a 3rd image, that image overwrites image 1. Does anyone have a simpler way of doing this?
So after looking at the other apps at my disposal again, I've realized that it seems they upload the image to firebase after the onResultActivity of the image selection of your phone gallery. So i've simplified my code to do the same and it works much better. Code now works but I just need to resize the images to fit the imageviews properly, other than that no complaints.
If you have a better and more efficient way of writing this code, please comment, efficiency is key and I would appreciate your input.
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_settings);
mImage1 = findViewById(R.id.image1);
mImage2 = findViewById(R.id.image2);
mImage3 = findViewById(R.id.image3);
mAuth = FirebaseAuth.getInstance();
userId = mAuth.getCurrentUser().getUid();
mUserDb = FirebaseDatabase.getInstance().getReference().child("Users").child(userId);
getUserInfo();
getUserTags();
mImage1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 1);
}
});
mImage2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 2);
}
});
mImage3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 3);
}
});
private void getUserInfo() {
mUserDb.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists() && dataSnapshot.getChildrenCount()>0){
Glide.clear(mImage1);
if(map.get("image1Url") != null){
image1Url = map.get("image1Url").toString();
switch(image1Url){
case "default":
mImage1.setImageResource(R.mipmap.ic_launcher);
//Glide.with(getApplication()).load(R.mipmap.ic_launcher).into(mImage1);
break;
default:
Glide.with(getApplication()).load(image1Url).into(mImage1);
break;
}
}
if(map.get("image2Url") != null){
image2Url = map.get("image2Url").toString();
switch(image2Url){
case "default":
mImage2.setImageResource(R.mipmap.ic_launcher);
//Glide.with(getApplication()).load(R.mipmap.ic_launcher).into(mImage1);
break;
default:
Glide.with(getApplication()).load(image2Url).into(mImage2);
break;
}
}
if(map.get("image3Url") != null){
image3Url = map.get("image3Url").toString();
switch(image3Url){
case "default":
mImage3.setImageResource(R.mipmap.ic_launcher);
//Glide.with(getApplication()).load(R.mipmap.ic_launcher).into(mImage1);
break;
default:
Glide.with(getApplication()).load(image3Url).into(mImage3);
break;
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1 && resultCode == Activity.RESULT_OK){
final Uri imageUri = data.getData();
final Uri resultUri = imageUri;
if(resultUri != null){
final StorageReference filePath = FirebaseStorage.getInstance().getReference().child("profileImages").child(userId).child("image1");
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplication().getContentResolver(), resultUri);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, baos);
byte[] databytes = baos.toByteArray();
UploadTask uploadTask = filePath.putBytes(databytes);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Failed! Please try again", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
});
uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
filePath.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Map newImage = new HashMap();
newImage.put("image1Url", uri.toString());
mUserDb.updateChildren(newImage);
mImage1.setImageURI(resultUri);
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Successful!", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Failed! Please try again", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
});
}
});
}else{
finish();
}
}
if(requestCode == 2 && resultCode == Activity.RESULT_OK){
final Uri imageUri = data.getData();
final Uri resultUri = imageUri;
if(resultUri != null){
final StorageReference filePath = FirebaseStorage.getInstance().getReference().child("profileImages").child(userId).child("image2");
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplication().getContentResolver(), resultUri);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, baos);
byte[] databytes = baos.toByteArray();
UploadTask uploadTask = filePath.putBytes(databytes);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Failed! Please try again", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
});
uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
filePath.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Map newImage = new HashMap();
newImage.put("image2Url", uri.toString());
mUserDb.updateChildren(newImage);
mImage2.setImageURI(resultUri);
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Successful!", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Failed! Please try again", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
});
}
});
}else{
finish();
}
}
if(requestCode == 3 && resultCode == Activity.RESULT_OK){
final Uri imageUri = data.getData();
final Uri resultUri = imageUri;
if(resultUri != null){
final StorageReference filePath = FirebaseStorage.getInstance().getReference().child("profileImages").child(userId).child("image3");
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getApplication().getContentResolver(), resultUri);
} catch (IOException e) {
e.printStackTrace();
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 20, baos);
byte[] databytes = baos.toByteArray();
UploadTask uploadTask = filePath.putBytes(databytes);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Failed! Please try again", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
});
uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
filePath.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Map newImage = new HashMap();
newImage.put("image3Url", uri.toString());
mUserDb.updateChildren(newImage);
mImage3.setImageURI(resultUri);
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Successful!", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast toast = Toast.makeText(SettingsActivity.this, "Upload Failed! Please try again", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
});
}
});
}else{
finish();
}
}
}
I am allowing users to take pictures and store them to Firebase. Below is my code that contains the intent to load the camera application, save the image, and then upload to the Firebase storage. The problem I am having is each subsequent upload to the Firebase Storage is overriding the previous upload, meaning I have 1 file in storage that keeps being overridden. I want to keep adding multiple files:
private void createAlertDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.add_image_dialog_title);
builder.setItems(new CharSequence[]
{getResources().getString(R.string.add_image_web), getResources().getString(R.string.add_image_camera), getResources().getString(R.string.add_image_gallery)},
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// The 'which' argument contains the index position
// of the selected item
switch (which) {
case 0:
Intent toImageSearch = new Intent(CreateActivity.this, NewImageActivity.class);
startActivityForResult(toImageSearch, USE_WEB);
break;
case 1:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getApplication().getPackageManager()) != null) {
startActivityForResult(takePictureIntent, TAKE_PICTURE);
} else {
Toast.makeText(getApplicationContext(), getResources().getString(R.string.camera_error), Toast.LENGTH_LONG).show();
}
break;
case 2:
Toast.makeText(getApplicationContext(), "clicked 2", Toast.LENGTH_LONG).show();
break;
case 3:
Toast.makeText(getApplicationContext(), "clicked 3", Toast.LENGTH_LONG).show();
break;
}
}
}
);
builder.create().
show();
}
OnActivityResult()
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case USE_WEB:
if (resultCode == CreateActivity.RESULT_OK) {
resultImageURL = data.getStringExtra("result");
mAddImageButton.setVisibility(View.INVISIBLE);
Picasso.with(getApplicationContext())
.load(resultImageURL)
.into(mImagePreview);
}
if (resultCode == CreateActivity.RESULT_CANCELED) {
//Write your code if there's no result
}
case TAKE_PICTURE:
if (resultCode == CreateActivity.RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImagePreview.setImageBitmap(imageBitmap);
encodeBitmapAndSaveToFirebase(imageBitmap);
}
}
}
Save to Firebase:
private void encodeBitmapAndSaveToFirebase(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] data = baos.toByteArray();
UploadTask uploadTask = mPollImageStorage.putBytes(data);
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Toast.makeText(getApplicationContext(), "Error Loading Photo", Toast.LENGTH_LONG).show();
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
// taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
Uri downloadUrl = taskSnapshot.getDownloadUrl();
mAddImageButton.setVisibility(View.INVISIBLE);
resultImageURL = downloadUrl.toString();
Picasso.with(getApplicationContext())
.load(resultImageURL)
.into(mImagePreview);
}
});
}
You need to use a separate location or separate file name for each upload.
You can create a custom location like this:
FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageRef = storage.getReferenceFromUrl("gs://myfirebaseproject.appspot.com");
StorageReference fileRef =
storageRef.child(channelId)
.child(String.valueOf(message.getSender()))
.child(String.valueOf(message.getTimestamp()));
UploadTask uploadTask = fileRef.putFile(message.getAttachmentUri());
uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
sendMessage(channelId, message.getMessageText(), taskSnapshot.getStorage().toString(), message.getAttachmentType(), callback);
}
});
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
callback.onError(e.toString());
}
});
You can see we are adding custom locations to our base storage reference so that we don't overwrite existing items.
The location that you store your image is determined by what mPollImageStorage is referencing. If mPollingStorage always references the same place, ie, in your onCreate you do something like:
StorageReference mPollingStorage = storageRef.child("polling.jpg");
Then it will keep overriding camerapic.jpg. If you don't want to override it, you could set the image name to something like the time the image was taken or generate a UUID as per this stackoverflow post : Store files with unique/random names