When trying Picasso on the runtime onStart() method it normally loads the image from Firebase using the download link from the console.
But when I try to load an image inside StorageReference onSuccess method it just won't work.
This class is extending Fragment:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == GALLERY_IN && resultCode == Activity.RESULT_OK) {
isGranted = true;
String path = FireStorage.retUID() + "/";
showIndProgress();
Uri uri = data.getData();
StorageReference childPathRef = FireStorage.storageRef.child(path + uri.getLastPathSegment());
childPathRef.putFile(uri)
.addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if(task.isSuccessful()) {
Picasso.with(mContext).load(task.getResult().getDownloadUrl())
.into(profView);
Picasso.Builder build = new Picasso.Builder(mContext);
build.listener(new Picasso.Listener() {
#Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
Toast.makeText(mContext, "exception\n" + exception.toString(), Toast.LENGTH_SHORT).show();
}
});
progressDialog.dismiss();
} else {
//failed
}
}
});
}
}
This is my FirebaseStorage instance on another Class:
public static FirebaseStorage storage = FirebaseStorage.getInstance();
public static StorageReference storageRef =
storage.getReferenceFromUrl("gs://myurl.appspot.com/");
Manifest:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
My XML layout:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#drawable/gcover"
android:id="#+id/relativeLayout">
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/profPhoto"
android:clickable="true"
android:layout_width="120dp"
android:layout_height="120dp"
android:padding="20dp"
android:src="#drawable/default_prof"
android:scaleType="centerCrop"
app:civ_border_color="#color/trans"
app:civ_border_width="2dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
My views initialization:
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_prof, container, false);
profView = (CircleImageView) view.findViewById(R.id.profPhoto);
btn1 = (Button) view.findViewById(R.id.btn_1);
btn2 = (Button) view.findViewById(R.id.btn_2);
btn3 = (Button) view.findViewById(R.id.btn_3);
return view;
}
Update 2:
While the code I posted works for me, you indicate that it fails for you. My test does not use a fragment, I don't know what version of the libraries you are using, it's now known how the fragment is being added to the layout, etc. There are too many possible causes of the different behavior to effectively debug it on SO.
As an experiment, you can try using Glide and FirebaseUI to perform the download instead of Picasso. The code is shown below and works for me. Because the download is from the storage reference and not the URL, this approach requires read access to the storage. You also need to add these lines to your build dependencies:
// FirebaseUI 2.0.1 is the version to use for Firebase SDK version 11.0.1
// SDK/Firebase version compatibility is important.
// See the FirebaseUI docs for a table of compatible versions.
compile 'com.firebaseui:firebase-ui-storage:2.0.1'
compile 'com.github.bumptech.glide:glide:3.8.0'
.
childPathRef.putFile(Uri.fromFile(file))
.addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Upload: SUCCESS");
Glide.with(mContext)
.using(new FirebaseImageLoader())
.load(childPathRef)
.dontAnimate()
.listener(new RequestListener<StorageReference, GlideDrawable>() {
#Override
public boolean onException(Exception e, StorageReference model,
Target<GlideDrawable> target, boolean isFirstResource) {
Log.e(TAG, "Download: FAILED: ", e);
return false;
}
#Override
public boolean onResourceReady(GlideDrawable resource,
StorageReference model, Target<GlideDrawable> target,
boolean isFromMemoryCache, boolean isFirstResource) {
Log.d(TAG, "Download: SUCCESS");
return false;
}
})
.into(mCircleImageView);
} else {
Log.e(TAG, "Upload: FAILED: " + task.getException().getMessage());
}
}
});
Update:
Additional debugging showed that the upload and download were both completing sucessfully. The problem was with the rendering of the downloaded image. The documentation for CircleImageView indicates that noFade() must be used when downloading from Picasso:
If you use an image loading library like Picasso or Glide, you need to
disable their fade animations to avoid messed up images. For Picasso
use the noFade() option, for Glide use dontAnimate().
It was also found that small images were rendered but large images were displayed as black. fit() was added to cause Picasso to resize the image.
To detect both upload success and failure, use a completion listener instead of just a success listener, and test task.isSuccessful(). The upload is probably failing because of security rules, or invalid StorageReference:
StorageReference childPathRef = Class.storageRef.child(path + uri.getLastPathSegment());
childPathRef.putFile(uri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Upload: SUCCESS");
Picasso.with(mContext)
.load(task.getResult().getDownloadUrl())
.noFade()
.fit()
.into(profView, new Callback() {
#Override
public void onSuccess() {
Log.d(TAG, "Download: SUCCESS");
Toast.makeText(mContext, "download done" , Toast.LENGTH_SHORT).show(); }
#Override
public void onError() {
Log.d(TAG, "Download: FAILED");
}
});
Toast.makeText(mContext, "upload done" , Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "Upload: FAILED: " + task.getException().getMessage());
}
progressDialog.dismiss();
}
});
Limitations for de.hdodenhof.circleimageview.CircleImageView
The ScaleType is always CENTER_CROP and you'll get an exception if you try to change it. This is (currently) by design as it's perfectly fine for profile images.
Enabling adjustViewBounds is not supported as this requires an unsupported ScaleType
If you use an image loading library like Picasso or Glide, you need to disable their fade animations to avoid messed up images. For Picasso use the noFade() option, for Glide use dontAnimate(). If you want to keep the fadeIn animation, you have to fetch the image into a Target and apply a custom animation yourself when receiving the Bitmap.
Using a TransitionDrawable with CircleImageView doesn't work properly and leads to messed up images.
I just switched from CircleImageView to a normal ImageView and it suddenly worked.
It is possible that in this line of code:
Picasso.with(mContext).load(task.getResult().getDownloadUrl())
.into(profView);
profView is recreating with fragment, and Picasso.into(View view) keeps week reference to view.
From docs:
public void into(android.widget.ImageView target) Asynchronously
fulfills the request into the specified ImageView. Note: This method
keeps a weak reference to the ImageView instance and will
automatically support object recycling.
Try to use:
public void into(#NotNull ImageView target,
Callback callback)
Maybe it's a conflict with the CircleImageView.
Try to change it with an ImageView or define the CircleImageView like an ImageView.
Try :
ImageView profView = (ImageView) view.findViewById(R.id.profPhoto);
Related
I am trying to download an image from Firebase storage into imageView on an android studio app using Java. I have looked through stackoverflow for over 6 hours so I have most likely read any "similiar" questions. I have tried various methods but the most suggested and what appeared to be the most simplest is using glide. I can't get it to work and I can't find the error. I even put in a regular google images link to try and it still shows blank.
the dependencies I have added
implementation'com.firebaseui:firebase-ui-storage:6.4.0'
implementation'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor'com.github.bumptech.glide:compiler:4.12.0'
The code I have used
ImageView imageView = findViewById(R.id.resultImage);
Glide.with(this).load("string of image").into(imageView);
I also tried this code
StorageReference ref = storage.getReferenceFromUrl("urlforimage");
// ImageView in your Activity
ImageView imageView = findViewById(R.id.uploadedImage);
// Download directly from StorageReference using Glide
Glide.with(this /* context */)
.load(ref)
.into(imageView);
And this code
public class Breed_Search_Page1Activity extends AppCompatActivity {
ImageView rImage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_breed__search__page1);
rImage = findViewById(R.id.rImage);
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference databaseReference = firebaseDatabase.getReference();
DatabaseReference getImage = databaseReference.child("image");
getImage.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String link = dataSnapshot.getValue(String.class);
Picasso.get().load(link).into(rImage);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
// we are showing that error message in toast
Toast.makeText(Breed_Search_Page1Activity.this, "Error Loading Image", Toast.LENGTH_SHORT).show();
}
});
}
}
Update - I have it working with the code below but wondering is there a way to display it from Firebase Storage using just the name of the file? As I am uploading an image from my laptop that I want to display in the app as quickly as possible so if I could code it so that it has the file name that I am going to use when uploading it would display once uploaded without having to manually change anything
ImageView image = (ImageView) findViewById(R.id.rImage);
String url = "https//...";
Glide.with(getApplicationContext()).load(url).into(image);
My logcat after adding listeners
2021-04-27 10:35:01.780 14347-14576/com.example.woofsapp E/StorageException:
StorageException has occurred.
Object does not exist at location.
Code: -13010 HttpResult: 404
2021-04-27 10:35:01.781 14347-14576/com.example.woofsapp E/StorageException:
{ "error": { "code": 404, "message": "Not Found. Could not get
object", "status": "GET_OBJECT" }}
java.io.IOException: { "error": { "code": 404, "message": "Not
Found. Could not get object", "status": "GET_OBJECT" }}
at com.google.firebase.storage.network.NetworkRequest.parseResponse(NetworkRequest.java:434)
at com.google.firebase.storage.network.NetworkRequest.parseErrorResponse(NetworkRequest.java:451)
at com.google.firebase.storage.network.NetworkRequest.processResponseStream(NetworkRequest.java:442)
at com.google.firebase.storage.network.NetworkRequest.performRequest(NetworkRequest.java:272)
at com.google.firebase.storage.network.NetworkRequest.performRequest(NetworkRequest.java:286)
at com.google.firebase.storage.internal.ExponentialBackoffSender.sendWithExponentialBackoff(ExponentialBackoffSender.java:70)
at com.google.firebase.storage.internal.ExponentialBackoffSender.sendWithExponentialBackoff(ExponentialBackoffSender.java:62)
at com.google.firebase.storage.GetDownloadUrlTask.run(GetDownloadUrlTask.java:76)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
The code that gives the logcat errors - note I do have the MyAppGlideModule copied directly from documentation
ImageView image = findViewById(R.id.rImage);
StorageReference storageReference =
FirebaseStorage.getInstance().getReference("Images/dogs.jpg");
storageReference.child("dogs.jpg").getDownloadUrl().addOnSuccessListener(new
OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
// Got the download URL for 'users/me/profile.png'
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle any errors
}
});
In my app, I've something like this:
StorageReference storageReference = FirebaseStorage.getInstance().getReference("FolderName/photoName.format");
I'm using the path with file's name.
For reference, check the official documentation - Download files with Cloud Storage on Android.
I want to get image from Firebase Storage and than show at Image View. I trying this code but not working. Always I getting my "ERROR" toast message.
App is opening but I dont see my JPEG.
** I found one way but it is not enough for me.
If I delete 'com.google.firebase:firebase-auth:19.3.2' from build gradle, this code working.
I need FirebaseAuth because I have User login and logout page.
Do you know another way for Firebase storage and image ?
Thank you for help.
enter image description here
private StorageReference mStorageReference;
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vardiya);
mStorageReference=FirebaseStorage.getInstance().getReference().child("vardiyaandroid.jpeg");
final File localfile;
try {
localfile = File.createTempFile("vardiyaandroid","jpeg");
mStorageReference.getFile(localfile).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() {
#Override
public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(vardiya.this,"Resim Hazır",Toast.LENGTH_LONG).show();
Bitmap bitmap = BitmapFactory.decodeFile(localfile.getAbsolutePath());
(imageView=findViewById(R.id.imageView)).setImageBitmap(bitmap);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(vardiya.this,"ERROR",Toast.LENGTH_LONG).show();
}
});
} catch (IOException e) {
e.printStackTrace();
}
I found my false.
You will change this code
mStorageReference=FirebaseStorage.getInstance().getReference().child("vardiyaandroid.jpeg");
with
mStorageReference=FirebaseStorage.getInstance().getReferenceFromUrl("gs://YOURAPPID.appspot.com/vardiyaandroid.jpeg");
StorageReference pathreferance =mStorageReference.child("vardiyaandroid.jpeg");
and the storege rules must be this:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, writ, auth: if true;
}
}
}
I'm using a recycler view to load a list of posts made by and organization. I've used firestore as the backend.
For loading the image I'm first getting the download Url from storage reference and then using Glide to load image in to the image view.
The issue i'm facing is that since a call to the storage reference is an asynchronous one, by the time it gets the download uri from the server the position of the adapter in OnBindviewHolder is already changed Therefore image gets mixed up.
I've provided the OnBindViewHolder code and the method where i get the download url
#Override
public void onBindViewHolder(#NonNull final studentFavouriteUniversityPosts.MyViewHolder holder, int position) {
if(postsList.get(holder.getAdapterPosition()).getImageUrl()!=null &&
!postsList.get(holder.getAdapterPosition()).getImageUrl().isEmpty()){
holder.setPostImage(holder.getAdapterPosition());
}
}
public void setPostImage(int position) {
postImage.setVisibility(View.VISIBLE);
placeholder.placeholder(R.color.white);
//Getting the download uri from the Fire store storage and displaying it using glide.
storageReference.child(postsList.get(position).getImageUrl())
.getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
// Log.d("URI",uri.toString());
Glide.with(context).applyDefaultRequestOptions(placeholder).load(uri).into(postImage);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("ERROR","err loading image file");
}
});
}
Can anyone of you help me out on this?
EDIT
I changed the structure a bit. So instead of running the storage reference task in adapter, i'm storing the dowload url in the object. Thus the setPostImage method only has the Glide part.
So the method looks like this
public void setPostImage(String downloadURL) {
postImage.setVisibility(View.VISIBLE);
Glide.with(context).applyDefaultRequestOptions(placeholder).load(downloadURL).into(postImage);
}
Still i'm getting this issue. I dont know how to resolve it
First get the list of urls from firestore from the activity or fragment where you are
setting the adapter
1. public void getImages() { storageReference.child("the child name")
.getDownloadUrl()
.addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
// Log.d("URI",uri.toString());
adapter.imagesRetrieved();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("ERROR","err loading image file");
}
});
}
2. Then inside on success listener pass the group of values to the adapter method from the success listener and define the method inside the adapter
public void imagesRetreived() {
notifyDataChanged(images);
}
private void notifyDataChanged(Images images) {
this.images = images;
notifydatasetchanged(); //this one is recycler view inbuilt method
}
i am new in android java programming and i need to create an activity which will help a user to send media like image,video, audio,.. to another user or to the group of users so that the action of sending would be super fast like whatsapp does , but i don't know which way i can follow and what i am required to know and to have . i am using android studio 2.if there is some tutorials or source codes please share with me the link. thanks for yr highest consideration to my question.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText MyText=(EditText) findViewById(R.id.text);
Button send=(Button) findViewById(R.id.button1);
ImageView attach =(ImageView) findViewById(R.id.attach);
button.setOnClickListener(new OnClickListener() {
#SuppressWarnings("deprecation")
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
String txt =MyText.getText().toString();
...
AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create();
...
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
Try Firebase https://firebase.google.com/
Use Firebase Storage and also Firebase Realtime Database
See https://firebase.google.com/docs/storage/android/upload-files
Small sample code from above link
Upload from a local file
You can upload local files on the device, such as photos and videos from the camera, with the putFile() method. putFile() takes a File and returns an UploadTask which you can use to manage and monitor the status of the upload.
Uri file = Uri.fromFile(new File("path/to/images/rivers.jpg"));
StorageReference riversRef = storageRef.child("images/"+file.getLastPathSegment());
uploadTask = riversRef.putFile(file);
// Register observers to listen for when the download is done or if it fails
uploadTask.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
}
}).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();
}
});
ImageView imgview = (ImageView)findViewById(R.id.image);
Drawable drawable = LoadImage("http://192.168.172.1/myproject/images/st1.jpg");
imgview.setImageDrawable(drawable);
...
...
public Drawable LoadImage(String url)
{
try
{
InputStream is = (InputStream) new URL(url).getContent();
Drawable b = Drawable.createFromStream(is, url);
return b;
}catch(Exception e){
System.out.println(e);
return null;
}
}
.java
...
...
<ImageView
android:id="#+id/image"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
.xml
getting the image from wamp server as a Url and display it onto my xml but image doesn't shown
I use the following code to get an image from url and add it to an ImageView:
ImageRequest imgRequest = new ImageRequest(url,
new Response.Listener<Bitmap>() {
#Override
public void onResponse(Bitmap response) {
mImageView.setImageBitmap(response);
Toast.makeText(MainActivity.this, "Succes", Toast.LENGTH_SHORT).show();
}
}, 0, 0, ImageView.ScaleType.FIT_XY, Bitmap.Config.ARGB_8888, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, error.getMessage(), Toast.LENGTH_SHORT).show();
mImageView.setBackgroundColor(Color.parseColor("#ff0000"));
error.printStackTrace();
}
});
Volley.newRequestQueue(this).add(imgRequest);
All you need to do is to use Volley Library made by google developers(trusted source). More info here
Hope it helps!
Use http://square.github.io/picasso/ it's really easy to implement, follow the following steps:-
1- If you haven’t done it already. If you are using eclipse as your development IDE, then just copy the downloaded picasso-2.5.2.jar file into your application lib folder. If you are using Android Studio IDE, then you have to add below dependency in build.gradle file.
dependencies {
...
compile "com.squareup.picasso:picasso:2.5.2"
...
}
2- Now let us download the image and display on imageView:-
//Loading image from below url into imageView
Picasso.with(this)
.load("YOUR IMAGE URL HERE")
.into(imageView);//Your image view
That's all, Hope this will help you !!
Are you given internet permission on manifest
and running this code in background such as asyn task
class LoadImageLoader extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
drawable = LoadImage("http://i.imgur.com/DvpvklR.png");
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
imgview.setImageDrawable(drawable);
}
}
Use Picasso works great and is easy to use.
There are many third party libraries that can help you with that.
Their use is strongly recommended, ie. don't create your own tool for that.
Picasso by guys from Square
Glide used in sample apps by Google