dynamically update Libphonenumber metadata in pre-installed Android app
Asked Answered
C

1

11

I have an android application that uses libphonenumber by Google and every time libphonenumber has a an update for area codes and carrier numbers "metadata" I have to literally re-package the application with newer version of the library and release it.

my question is, could anyone guide or show me the way to update libphonenumber's metadata on an installed/running android app without needing to build a new release each time an update comes along.

Thank you in advance,

Ciprian answered 23/8, 2016 at 16:24 Comment(4)
Based on the source code, it looks like you use the version of createInstance() that takes a MetadataLoader, where you supply your own loader for your own copy of the metadata.Yard
Thank you, I was hoping for a ready example. but since no one seems to have went that road yet, I will look into it and write up a solution and share.Ciprian
Hi, Bassel! Any luck with this challenge?Controvert
@AlexCohn not really.. still releasing a new version with every update.. but on the positive side.. I came to a personal conclusion.. users prefer/trust apps that get updated regularly.. so will leave it at zat for nowCiprian
H
0

I have just implemented this. The code is not worth sharing since it is strongly integrated into my application, but I can summarize what I did:

  1. Since the PhoneNumberUtil class only accesses the metadata files once and then caches the data, you have to wrap it in some form of proxy to be able to replace the instance transparently for the rest of your application.

  2. In your application fetch the maven artifact metadata from maven central (our your own maven repo) and extract either the release or latest (includes snapshots) version.

  3. Then download the sources.jar from maven (e.g. this for 8.12.55) and also the corresponding GPG signature (e.g. this for 8.12.55)

  4. Verify the signature of the downloaded file against the public key (for version 8.12.55 you can fetch it e.g. using gpg --recv-keys --keyserver keyserver.ubuntu.com 42F1F5F3531B34660A81F7B05D95290D111CF7FF)

  5. From the downloaded sources.jar, extract all files within com/google/i18n/phonenumbers/data/ into some directory, possibly on a tmpfs) while keeping the folder structure intact (So the com/google/i18n/... folders exist inside the output folder as well).

  6. Create a new FilesystemMetadataLoader (see Kotlin implementation below) backed by this folder.

  7. Replace the PhoneNumberUtil instance in your proxy with a new instance created from the filesystem-backed loader. Remember to delete the previously used files.

If you wonder why I'm downloading the sources.jar from Maven:

  • It's publicly hosted
  • It's built and packaged in the exact same way as the bundled metadata
  • It provides cryptographic signatures which I can verify
  • While the download includes unnecessary things (the Java source code), most of the file size comes from the metadata
  • Compared to the main jar it is slightly smaller and contains no executable code

Instead of downloading the metadata into files you could just as well read them into memory buffers and drop them from memory once read by PhoneNumberUtil, if memory usage is a concern. You might also be able to skip downloading and unpacking the metadata if the version in maven central matches what you have already.

Implementation-wise I can recommend ktor and kotlinx.serialization together with xmlutil for fetching the maven metadata and downloading the jar, Java's ZipInputStream for extracting the files. Bouncycastle can be used for the signature verification.

class FilesystemMetadataLoader(private val path: Path) : MetadataLoader {
    override fun loadMetadata(metadataFileName: String): InputStream {
        return Files.newInputStream(path.resolve(metadataFileName.removePrefix("/")), StandardOpenOption.READ)
    }
}

Alternative you could download the sources.jar and instead of unpacking it, write a MetadataLoader that is backed directly by a ZipInputStream, that just iterates over the entries until it finds the requested one.

Headwards answered 19/9, 2022 at 20:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.