Search code examples
javaandroidfirebasematerialdrawer

How to load image from firebase to the navigation material drawer icon


I can't add the image from firebase to the navigation drawer I'm getting the url of the image after the navigation drawer has been created because of the async method of getting url from firebase the method to get the url is called after the navigation drawer has been created hence can't update it.

I'm getting the url of the image after the navigation drawer has been created because of the async method of getting url from firebase the method to get the url is called after the navigation drawer has been created hence can't update it. I have tried to create a class and method that does that but then they are called after the onCreate method has executed of which thats where im trying to get the image url

if (profileImageUrlRef != null)
{
profileImageUrlRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                @Override
                public void onSuccess(Uri uri)
                {
                    urlImage=uri.toString();
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception exception) {
                    // Handle any errors
                }
            });
}
 DrawerImageLoader.init(new AbstractDrawerImageLoader() {
            @Override
            public void set(ImageView imageView, Uri uri, Drawable placeholder, String tag) {
                Glide.with(imageView.getContext()).load(uri).placeholder(placeholder).into(imageView);
            }

            @Override
            public void cancel(ImageView imageView) {
                Glide.with(Client_Services.this).clear(imageView);

            }

            @Override
            public Drawable placeholder(Context ctx, String tag) {
                //define different placeholders for different imageView targets
                //default tags are accessible via the DrawerImageLoader.Tags
                //custom ones can be checked via string. see the CustomUrlBasePrimaryDrawerItem LINE 111
                if (DrawerImageLoader.Tags.PROFILE.name().equals(tag)) {
                    return DrawerUIUtils.getPlaceHolder(ctx);
                } else if (DrawerImageLoader.Tags.ACCOUNT_HEADER.name().equals(tag)) {
                    return new IconicsDrawable(ctx).iconText(" ").backgroundColorRes(com.mikepenz.materialdrawer.R.color.primary).sizeDp(56);
                } else if ("customUrlItem".equals(tag)) {
                    return new IconicsDrawable(ctx).iconText(" ").backgroundColorRes(R.color.md_red_500).sizeDp(56);
                }

                //we use the default one for
                //DrawerImageLoader.Tags.PROFILE_DRAWER_ITEM.name()

                return super.placeholder(ctx, tag);
            }
        });
final AccountHeader headerResult = new AccountHeaderBuilder()
                .withActivity(this)
                .withHeaderBackground(R.drawable.background)
                .addProfiles(

                        new ProfileDrawerItem().withName("Ceo AtRalk").withEmail("info@atralk.co.zam").withIcon(urlImage)
                )
                .withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
                    @Override
                    public boolean onProfileChanged(View view, IProfile profile, boolean currentProfile) {

                        return false;

                    }
                })
                .build();

Im expecting the urlImage variable to be populated with the url when its passed to withIcon method


Solution

  • I've once wrote an AsyncTask which caches the profile image to SD card:

    /**
     * AsyncTask: Profile Image
     * @author Martin Zeitler
    **/
    public class ProfileImageTask extends AsyncTask<String, Void, Uri> {
    
        private static final String LOG_TAG = ProfileImageTask.class.getSimpleName();
    
        private static final boolean mDebug = BuildConfig.DEBUG;
    
        private String fileName = "photo.jpg";
    
        private boolean enforce = false;
    
        private String sdPath;
    
        private String url;
    
        /** {@link IProfileImageTask} listener */
        private IProfileImageTask listener;
    
        /** Constructor */
        @RequiresPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        public ProfileImageTask(@NonNull Context context, @NonNull String url, @NonNull IProfileImageTask listener) {
            this.sdPath = context.getExternalFilesDir(context.getResources().getString(R.string.app_name)) + "/";
            this.listener = listener;
            this.url = url;
        }
    
        @Override
        protected void onPreExecute() {
    
            /* setup destination directory */
            File directory = new File(this.sdPath + Constants.FILESYSTEM_DIRECTORY_IMAGES);
            if (! directory.exists()) {
                //noinspection ResultOfMethodCallIgnored
                directory.mkdirs();
            }
    
            /* setup file name */
            String[] parts = this.url.split("/");
            this.fileName = parts[parts.length - 1];
        }
    
        @Override
        protected Uri doInBackground(String... arguments) {
    
            File file = new File(this.sdPath + Constants.FILESYSTEM_DIRECTORY_IMAGES, this.fileName);
            if(file.exists() && this.enforce) {
                if(mDebug) {
                    Log.d(LOG_TAG, "delete profile image: " + file.getPath() + ", size: " + file.length() + " bytes.");
                }
                //noinspection ResultOfMethodCallIgnored
                file.delete();
            }
    
            if (! file.exists()) {
                try {
                    URLConnection conn = new URL(this.url).openConnection();
                    conn.connect();
                    InputStream in = conn.getInputStream();
                    FileOutputStream out = new FileOutputStream(file);
                    byte[] b = new byte[1024]; int c;
                    while ((c = in.read(b)) != -1) {out.write(b, 0, c);}
                    out.close();
                    in.close();
                } catch (IOException e) {
                    if(mDebug) {Log.e(LOG_TAG, "" + e.getMessage());}
                } finally {
                    if(mDebug) {
                        Log.d(LOG_TAG, "new cached profile image: "  + file.getPath() + ", size: " + file.length() + " bytes.");
                    }
                }
            } else if(mDebug) {
                Log.d(LOG_TAG, "existing profile image: " + file.getPath() + ", size: " + file.length() + " bytes.");
            }
            return Uri.fromFile(file);
        }
    
        @Override
        protected void onPostExecute(Uri uri) {
            if (listener != null && uri != null) {
                this.listener.OnImageAvailable(uri);
            }
        }
    }
    

    Usage example:

    if (this.currentUser != null && this.currentUser.getPhotoUrl() != null) {
        new ProfileImageTask(this, this.currentUser.getPhotoUrl(), this).execute();
    }
    

    This is the callback interface, which sets the image when the task is done:

    public interface IProfileImageTask {
    
        /**
         * indicates that the operation has finished.
         * @param localUri
        **/
        void OnImageAvailable(@NonNull Uri localUri);
    }
    

    And it's implementation:

    @Override
    public void OnImageAvailable(@NonNull Uri uri) {
    
        /* the Main {@link DrawerLayout} */
        this.mDrawerLayout = this.findViewById(resIdLayout);
    
        if (! this.mDrawerLayout.isInEditMode()) {
    
            /* the {@link NavigationView} Drawer Menu */
            this.mNavigationDrawer = this.findViewById(resIdDrawer);
    
            /* the {@link NavigationView} Drawer Header */
            View header = this.mNavigationDrawer.getHeaderView(0);
            AppCompatImageView photoUrl = header.findViewById(R.id.photoUrl);
    
            /* setting the photo-url */
            if (this.currentUser != null && this.currentUser.getPhotoUrl() != null) {
                photoUrl.setImageURI(uri);
            }
        }
    }