Search code examples
androiduniversal-image-loader

Universal-Image-Loader Custom FileNameGenerator based on local file name


I am using Universal Image Loader to display images downloaded from a URI or already available in a disk cache implementation.

I want to display music album covers, but more than one track might have the same URI for a cover (i.e. tracks from the same album). I want that even if the image is the same it's stored each time for each different track with the track name, because I want users to be able to replace the default covers with a custom one, even for each single track.

For instance

  • 01 - Track 01.mp3
  • 02 - Track 02.mp3

Belong to the same album and the cover URI is http://something/img.jpg, on disk cache I want to have

  • 01 - Track 01.jpg
  • 02 - Track 02.jpg

even if it's the same image.

So I've coded a FileNameGenerator that stores a Set of hashes for each Uri, where the hash is the SHA-1 of the absolute path of the file.

Here is my implementation:

public MyFileNameGenerator(String ext) {
    super();
    this.ext = ext;
}

HashMap<String,HashSet<String>> names = new HashMap<String, HashSet<String>>();

@Override
public String generate(String imageUri) {
    if(imageUri==null) return null;
    if (imageUri.startsWith("file:///")) {
        return FilenameUtils.removeExtension(Uri.parse(imageUri)
                .getLastPathSegment()) + "."+ext;
    }
    //How to recognize the correct hash?
    //return FilenameUtils.removeExtension(Data.currentFiles
    //      .get(names.get(imageUri)).getName()) + "." + ext;
}

public void setTrackData(String uri, String hash) {
    if(!names.containsKey(uri))
        names.put(uri, new HashSet<String>());
    names.get(uri).add(hash);
}

But I'm at a dead end, because it's impossible to understand for which file I'm displaying the image, as generate only takes imageURI as parameter and more hashes can belong to the same uri.

How could I circumvent this issue?


Solution

  • I think I've found a solution for this.

    Whenever I call my ImageLoader instance to show an image, I use

    if (uri != null && !uri.isEmpty()) {
        uri = Uri.parse(uri).buildUpon()
            .appendQueryParameter("myhashkeyparameter", "myHashValue").toString();
    }
    mImageLoader.displayImage(uri,mImageView);
    

    This code will append to a vaild uri a query parameter, the uri will become:

    http://someuri/image.jpg?myhashkeyparameter=myHashValue
    

    Then in the FileNameGenerator's generate method I can use

    String hash = Uri.parse(imageUri).getQueryParameter("myhashkeyparameter");
    

    to retrieve the wanted file without relying on using the imageUri as key.

    Full code:

    @Override
    public String generate(String imageUri) {
        if(imageUri==null||imageUri.isEmpty()) return "";
        if (imageUri.startsWith("file:///")) {
            return FilenameUtils.removeExtension(Uri.parse(imageUri)
                    .getLastPathSegment()) + "."+ext;
        }
        String hash = Uri.parse(imageUri).getQueryParameter("myhashkeyparameter");
        if(null==hash||hash.isEmpty()) return "";
        if(Data.currentFiles.containsKey(hash)){
         return FilenameUtils.removeExtension(Data.currentFiles.get(hash).getName())+".png";
        }
        else return "";
    }
    

    You just have to be careful that the string used as queryparameter is not already used in the http URL, so avoid traditional names like name,hash,h,title and so on.