I have an app where it is possible to create an user and this work perfectly and I am happy!
In a simple way, here is a method that adds the user to the Firebase database:
public void addUserInfoToDatabase(){
String user_id = mAuth.getCurrentUser().getUid();
final DatabaseReference the_user_database = FirebaseDatabase.getInstance().getReference().child("UserRegistraion").child(user_id);
Map userAttributes = new HashMap();
userAttributes.put("user_id", user_id);
userAttributes.put("username", userName);
userAttributes.put("name", name);
userAttributes.put("e-mail", email);
the_user_database.setValue(userAttributes);
if (mRegistrationListener != null)
mRegistrationListener.onRegistrationComplete(true); // Assumes success
}
And here is how the table looks when the user is registered:
What I want to do now is that I want the possibility to add a profile picture which belongs to each user: e,g a profile picture, family-picture etc.
The question is: how can i do this in Firebase? I am not asking anyone to do this for me, but just to give me a good tip or provide a guide/video for how to do this.
Thank you.
I usually create a separate activity for setting up a profile photo. Maybe instead of calling onRegistrationComplete call an onCompleteListener after setValue(userAttributes) like this:
the_user_database.setValue(userAttributes).addOnCompleteListener(new OnCompleteListener...){
Intent intent = new Intent(context, AddProfileActivity.class);
startActivity(intent);
In the next activity it could be a simple XML layout with a button and an ImageView.
This code can open your gallery, select an image, and place it in your imageview in the onActivityResult method:
private void selectPhotoFromGallery(){
Log.d(TAG, "selectPhotoFromGallery: started");
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, GALLERY_PICK);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == GALLERY_PICK){
if (resultCode == RESULT_OK && data != null){
contentUri = data.getData();
try{
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), contentUri);
profile_photo.setImageBitmap(bitmap);
}catch (IOException e){
Toast.makeText(mContext, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
}
You would then need a method to upload your image to FirebaseStorage and capture the downloadUrl to add to the desired node. In this case because you are adding to an existing node you call updateChildren() when adding the profile photo. I use a method like this:
private void uploadProfileImage(){
Log.d(TAG, "uploadProfileImage: uploading image....");
if (contentUri != null){
//from gallery
final StorageReference reference = FirebaseStorage.getInstance().getReference().child(currentUserID).child("profile_photo");
reference.putFile(contentUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
reference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String profilePhotoUri = uri.toString();
DatabaseReference publicUserReference = FirebaseDatabase.getInstance().getReference().child("public_user")
.child(currentUserID);
HashMap hashMap = new HashMap();
hashMap.put("profile_photo", profilePhotoUri);
publicUserReference.updateChildren(hashMap).addOnCompleteListener(new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()){
Intent intent = new Intent(mContext, CompleteProfileActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
}
});
}
});
}
});
}
}
You would need to adjust this for your specific needs obviously. The thing you are really trying to do is to save an image to Storage and get the http://... string location where it is stored and then insert that information into the same location as the previous information you provided.
I hope this counts as a helpful tip. https://www.youtube.com/watch?v=mPOhnTnLcSY That's a link to a video about uploading images to Firebase storage for more information if you need it. Good luck!
Related
I'm currently learning how to use android studio in java and am trying to make a social media app. I am currently creating an edit profile page where the user would update their details and upload a profile picture.
I have been following tutorials online and all of the ones I have come across use the startActivityForResult method. It has been crossed out and wont call the method as it is deprecated. But I don't know what to use instead.
`ProfileImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//open gallery
Intent OpenGalleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(OpenGalleryIntent, 1000);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #androidx.annotation.Nullable Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1000){
if(resultCode == Activity.RESULT_OK){
Uri imageUri = data.getData();
ProfileImage.setImageURI(imageUri);
UploadImageToFirebase(imageUri);
}
}
}
private void UploadImageToFirebase(Uri image){
StorageReference fileRef = storageReference.child("Profile.jpg");
fileRef.putFile(image).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(Edit_Profile.this, "Image Uploaded", Toast.LENGTH_SHORT).show();
}
});![enter image description here](https://i.stack.imgur.com/padRc.jpg)`
I know there is an alternative but I don't understand how it works.
startActivityForResult is indeed deprecated in later versions of AndroidX Activity and Fragment APIs (while I believe you can still use it despite of warning). New way to get result from activity is registerForActivityResult.
In your code you would need to create a launcher, which will handle result (selected image)
private final ActivityResultLauncher<Intent> launcher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
result -> {
if (result.getResultCode() == Activity.RESULT_OK
&& result.getData() != null) {
Uri photoUri = result.getData().getData();
//use photoUri here
}
}
);
and then launch this launcher in onClickListener
profileImage.setOnClickListener(view -> {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
launcher.launch(intent);
});
Yes startActivityForeResult is deprecated.
Now you can use ActivityResultLauncher for the callbacks
https://developer.android.com/training/basics/intents/result#java
Please help! I am unable to push the photo to the Firebase Storage and consequently can't display in my app. This code is reference to the Udacity Firebase in a Weekend Course.
I want to push the selected photo to the firebase storage and display in my app.
The first picture shows the chat activity, 2nd picture shows intent to the picture gallery when the picture icon is clicked, and third picture shows the result where it fails to push the selected photo to firebase storage and also doesn't display in app.
I want to push the selected photo to firebase storage and display in the chat section
Link for the official documentation for upload the image to firebase storage -> https://firebase.google.com/docs/storage/android/upload-files?authuser=0
I tried the official documentation code but it also doesn't work
Link for the course which i followed -> https://classroom.udacity.com/courses/ud0352/lessons/fab5bf81-cfe5-4071-9afe-b6eb324a6257/concepts/27c52d47-50cd-4be1-8d3d-95e3fccebda5
public class MainActivity extends AppCompatActivity {
private static final int RC_PHOTO_PICKER = 2;
private FirebaseStorage mFirebaseStorage;
private StorageReference mChatPhotosStorageReference;`
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUsername = ANONYMOUS;
mFirebaseDatabase = FirebaseDatabase.getInstance();
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseStorage = FirebaseStorage.getInstance();
mMessagesDatabaseReference = mFirebaseDatabase.getReference().child("messages");
mChatPhotosStorageReference = mFirebaseStorage.getReference().child("photos");
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
if (resultCode == RESULT_OK) {
// Sign-in succeeded, set up the UI
Toast.makeText(this, "Signed In!", Toast.LENGTH_SHORT).show();
} else if (resultCode == RESULT_CANCELED) {
// Sign in was canceled by the user, finish the activity
Toast.makeText(this, "Sign In Cancelled!", Toast.LENGTH_SHORT).show();
finish();
} else if (requestCode == RC_PHOTO_PICKER && resultCode == RESULT_OK) {
Uri selectedImageUri = data.getData();
// Get a reference to store file at chat_photos/<FILENAME>
StorageReference photoRef =
mChatPhotosStorageReference.child(selectedImageUri.getLastPathSegment());
// Upload file to Firebase Storage
photoRef.putFile(selectedImageUri);
mChatPhotosStorageReference.putFile(selectedImageUri).continueWithTask(task -> {
if (!task.isSuccessful()) {
throw task.getException();
}
return mChatPhotosStorageReference.getDownloadUrl();
}).addOnCompleteListener(task -> {
if (task.isSuccessful()) {
Uri downloadUri = task.getResult();
FriendlyMessage friendlyMessage = new FriendlyMessage(null, mUsername,
downloadUri.toString());
mMessagesDatabaseReference.push().setValue(friendlyMessage);
}
});
}
}
}[Chat Activity[After Clicking Picture icon[No response][1]
I can't get the normal taken picture by my phone in java. Everything is working while I choose picture from the gallery which is screenshot but when It's normal taken picture it's not returning anything. I will give you some parts of the code where u can see how I'm getting picture.
#Override
public void onActivityResult(int reqCode, int resultCode, final Intent data) {
super.onActivityResult(reqCode, resultCode, data);
if (reqCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
final Uri imageUri = data.getData();
final String path = getPath(getActivity(), imageUri);
if (path != null) {
try {
File f1 = new File(path);
final AsyncHttpClient client = new AsyncHttpClient(true, 80, 443);
client.addHeader("accept", "application/json");
final RequestParams params = new RequestParams();
params.put("id", id);
params.put("token", token);
params.put("avatar", f1);
And also this
add_avatar.setOnClickListener(new View.OnClickListener() {
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onClick(View view) {
// filePickUtils.requestImageGallery(STORAGE_PERMISSION_IMAGE, true, true);
if (getActivity().checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (shouldShowRequestPermissionRationale(
android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
// Explain to the user why we need to read the contacts
}
requestPermissions(new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE},
1);
// MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
// app-defined int constant that should be quite unique
return;
}
if (getActivity().checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (shouldShowRequestPermissionRationale(
android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// Explain to the user why we need to read the contacts
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
// MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE is an
// app-defined int constant that should be quite unique
return;
}
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoPickerIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
photoPickerIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, PICK_IMAGE);
}
});
What would you suggest?
Thanks for your help
Given that you only need to read the image, and upload the data to your backend server, I'd suggest if you use Intent.ACTION_GET_CONTENT instead of Intent.ACTION_PICK.
Why
Your problem might related to what Intent.ACTION_PICK needs to have. The documentation stated:
Input: getData() is URI containing a directory of data (vnd.android.cursor.dir/*) from which to pick an item.
So it means, if you want to use Intent.ACTION_PICK, you need to provide the directory of the data.
Meanwhile if you use Intent.ACTION_GET_CONTENT, you can just set the MIME type of the file that you want to search (just as what you are doing now), and use Context.startActivity(intent).
Additional note from the documentation that you might want to read:
Input: getType() is the desired MIME type to retrieve. Note that no URI is supplied in the intent, as there are no constraints on where the returned data originally comes from. You may also include the CATEGORY_OPENABLE if you can only accept data that can be opened as a stream. You may use EXTRA_LOCAL_ONLY to limit content selection to local data. You may use EXTRA_ALLOW_MULTIPLE to allow the user to select multiple items.
Output: The URI of the item that was picked. This must be a content: URI so that any receiver can access it.
Add a comment here, if you need further information.
Sample Code:
In your activity
private searchImageFile() {
Intent intent = new Intent(Intent.GET_CONTENT);
// Filter to only show results that can be "opened"
intent.addCategory(Intent.CATEGORY_OPENABLE);
// Filter to show only images, using the image MIME data type.
// it would be "*/*".
intent.setType("image/*");
startActivityForResult(intent, READ_REQUEST_CODE);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
final Uri imageUri = resultData.getData();
//Do something with your Uri.
}
}
I'am try to use start Activity for result to pick photo from gallery but it does not called on fragment
I checked most solutions but no one work for me
please help me
newsImg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
intent=new Intent(Intent.ACTION_PICK);
intent.setType("image*//*");
getActivity().startActivityForResult(intent,GALLERY_INTENT);
}
});
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==GALLERY_INTENT && resultCode== Activity.RESULT_OK){
Uri uri=data.getData();
StorageReference filePath=mStorage.child("Photos").child(uri.getLastPathSegment());
filePath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
downloadUri=taskSnapshot.getDownloadUrl();
Picasso.with(getActivity().getApplicationContext()).load(downloadUri).fit().centerCrop().into(newsImg);
Toast.makeText(getActivity().getApplicationContext(),"success",Toast.LENGTH_SHORT).show();
publishBtn.setEnabled(true);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getActivity().getApplicationContext(),"fail",Toast.LENGTH_SHORT).show();
}
});
}
Try using this and then find out, before giving my answer I would suggest you to be please do some research or search the exact thing in short form like you want to use the use the gallery intent, just use the image picker in android or gallery intent in android. For going from the fragment we use the getContext() rather than using ActivityIntent like MainActivity.this.
For Calling the startActivity for result do like this :
private final int REQUEST_CODE = 1
class ImagePicker extends Fragment{
/*here we are calling the start activity for result
supposing you know how to use the gallery intent so just giving you
the answer what you want */
Intent intent = new Intent(getContext(), YourClass.class);
startActivityForResult(intent, REQUEST_CODE);
}
And in onActivityResult() you get the result in the same Fragment or Activity after finishing this.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
//get your gallery image uri data here
}
}
Hope it helps and please refer to this link to read more about the how to get the data in the same Activity.
About startAcitivityForResult in android
Hope that helps! Thanks
EDITS
Since your code seems fine for gallery intent but I think there is problem with your gallery intent. Try this also and see if it works.
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, RESULT_CODE;
Here specifically I have used the inten.setType("image/*") and one more thing, make this simple, do not use getActivity.startActivityForResult() just make it simple, startAcitivityForResult() will also work fine and use getContext() despite of doing getActivity().getApplicationContext(). Try amending this thins things and tell me whether it works or not!
I have a MultiplePhotoSelectActivity.java which let user select multiple photo and store the path in an ArrayList.
public void btnChoosePhotosClick(View v){
ArrayList<String> selectedItems = imageAdapter.getCheckedItems();
if (selectedItems!= null && selectedItems.size() > 0) {
//Toast.makeText(MultiPhotoSelectActivity.this, "Total photos selected: " + selectedItems.size(), Toast.LENGTH_SHORT).show();
Log.d(MultiPhotoSelectActivity.class.getSimpleName(), "Selected Items: " + selectedItems.toString());
Intent intent = new Intent(MultiPhotoSelectActivity.this,PreuploadActivity.class);
intent.putStringArrayListExtra("selectedItems", selectedItems);
setResult(RESULT_OK, intent);
startActivity(intent);
}
}
This is ArrayList<String> selectedItems come from imageAdapter
ArrayList<String> getCheckedItems() {
ArrayList<String> mTempArry = new ArrayList<>();
for(int i=0;i<mImagesList.size();i++) {
if(mSparseBooleanArray.get(i)) {
mTempArry.add(mImagesList.get(i));
}
}
return mTempArry;
}
After user choose the photo,the following result will appear in logcat
D/MultiPhotoSelectActivity: Selected Items: [/storage/emulated/0/Pictures/Screenshot_1486795867.png, /storage/emulated/0/Pictures/15592639_1339693736081458_1539667284_n.jpg, /storage/emulated/0/15592639_1339693736081458_1539667284_n.jpg]
The problem now is,I want to display the image in my another activity using the file path in the array list,after the user choose the image
Here is PreuploadActivity.java that should be receive the intent data.
This is the button to let user choose photo in MultiplePhotoSelectActivity.java
//this button will open gallery,and select photo
addPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(PreuploadActivity.this,MultiPhotoSelectActivity.class);
startActivityForResult(intent,PICK_IMAGE_REQUEST);
}
});
This is the onActivityResult() which should receive the Intent data from MultiplePhotoSelectActivity.java
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data.getData() !=null){
ArrayList<String> selectedItems = data.getStringArrayListExtra("selectedItems");
for(String selectedItem : selectedItems){
Uri filePath = Uri.parse(selectedItem);
try{
// bimatp factory
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
bitmap = BitmapFactory.decodeFile(filePath.getPath(),
options);
//Setting image to ImageView
ImageView imageView = new ImageView(getApplicationContext());
LinearLayout.LayoutParams layoutParams =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
imageView.setLayoutParams(layoutParams);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setPadding(0, 0, 0, 10);
imageView.setAdjustViewBounds(true);
imageView.setImageBitmap(bitmap);
linearMain.addView(imageView);
}catch (Exception e) {
e.printStackTrace();
}
}
So now in onActivityResult() of PreuploadActivity.java I cant display back the image in the ArrayList which sent from MultiplePhotoSelectActivity.java.I suspect is something wrong when putExtra in the intent,what I tried so far but still no different.
The answer of this Stackoverflow question
putParcelable or putSerializable like the answer
How to transfer a Uri image from one activity to another?
So what I need to know,
1) How should I putExtra and getExtra in the intent in both Activity in order send and receive the ArrayList of the image?
2) Is my handle to display the image correct?If no,please tell me what I doing wrong.
EDIT:Try for Aslam Hossin solution
After I tried this
ArrayList<String> myList = (ArrayList<String>) getIntent().getSerializableExtra("selectedItems ");
I got the following error
After looking at some documentation I figure out I make a few mistake
MultiPhotoSelectActivity.java
Intent intent = new Intent(MultiPhotoSelectActivity.this,PreuploadActivity.class);
intent.putStringArrayListExtra("selectedItems", selectedItems);
setResult(RESULT_OK, intent);
startActivity(intent);
I figure out,there are 3 mistake at above code,
1)In MultiPhotoSelectActivity.java should not a new intent,but it should be send the data back to PreuploadActivity.java
2) I should setResult like this
setResult(Activity.RESULT_OK, data);
3) According to the documentation as below ,so I add finish() after setResult()
Data is only returned once you call finish(). You need to call setResult() before calling finish(), otherwise, no result will be returned.
I solve it by setting result code in PreuploadActivity.java like below
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == PICK_IMAGE_REQUEST && resultCode == Activity.RESULT_OK ){
//setting Activity.RESULT_OK
ArrayList<String> selectedItems = data.getStringArrayListExtra("selectedItems");
This is MultiPhotoSelectActivity.java I do the following changes
ArrayList<String> selectedItems = imageAdapter.getCheckedItems();
if (selectedItems!= null && selectedItems.size() > 0) {
//Toast.makeText(MultiPhotoSelectActivity.this, "Total photos selected: " + selectedItems.size(), Toast.LENGTH_SHORT).show();
Log.d(MultiPhotoSelectActivity.class.getSimpleName(), "Selected Items: " + selectedItems.toString());
final Intent data = new Intent();
data.putStringArrayListExtra("selectedItems", selectedItems);
setResult(Activity.RESULT_OK, data);
finish();
}
}