Create downloadable custom theme and apply it during run time

后端 未结 1 2037
庸人自扰
庸人自扰 2020-12-30 10:46

I\'m making an Android app that needs to allow client to maintain the resources from their server which would include strings, drawables etc.

I\'ve already created a

1条回答
  •  悲&欢浪女
    2020-12-30 11:37

    I've finally decided to solve this by making a custom system for handling drawables, strings etc so now i have a custom class called "ResourceManager" that handles what needs to be loadad and how, and themes are distributed as a zip file which app downloads, extracts and later uses.

    I had to compile nine patch images by myself before putting them in zip file, and I did that using "abrc" from here: http://forum.xda-developers.com/showthread.php?t=785012

    I've also created a simple bash script that goes recursively through custom folder and compiles all nine patch images with abrc.

    I've also created a simple helper in the ResourceManager that checks and tells me the screen density so i can normally support images in hdpi, xhdpi etc densities, and finally i don't re-create the images every time i need them, i save them in a static list of HashMap so i can reuse the ones I've already created and that way i hope to prevent wasting too much phone's memory :).

    OK that's all in short lines, if anyone has any questions please let me know, i'll be glad to share this experience with anyone.

    Cheers!

    ============ EDIT ============

    Here's the class I ended up writing for this purpose (it downloads the file, checks for it's version, loads strings from JSON file rather than strings.xml etc)

    NOTE: This is not a full class so some parts are missing, but I think it's more than enough to get the idea how I solved all this :)

    /**
     * Created by bojank on 7/28/2014.
     * Class that handles custom resources downloaded from server
     */
    public class ResourceManager {
    
        // List of ninePatchImages in the application
        private static ArrayList> ninePatchHashMaps;
        private static ArrayList> imagesHashMaps;
    
        private static ImageLoader imageLoader;
    
        // Context for methods
        public static Context ctx;
    
        // JSONObject with all strings
        private static JSONObject joString;
    
        // JSONObject with all styles
        private static JSONObject joStyles;
    
        // String with current active lang code
        private static String currentLanguage;
    
        private static String sdcardPath;
    
        // Private consturctor to prevent creating a class instance
        private ResourceManager() {
        }
    
        /**
         * Method that returns a translated string for given key
         *
         * @param key String
         * @return String
         */
        public static String getString(String module, String key) {
            String output = ""; //String.format("[%s - %s]", module, key);
    
            try {
                if (getStringsFile() != null && getStringsFile().getJSONObject(module).has(key))
                    output = getStringsFile().getJSONObject(module).getString(key);
            } catch (Exception e) {
    
                // Force some default language if proper json file is missing for newly added language
                currentLanguage = "en-US";
                Helper.saveLocale(currentLanguage, ctx);
                Helper.logError("ErrorFetchingString", e);
            }
    
            return output;
        }
    
        /**
         * Method that returns JSONObject with string resources
         * @return JSONObject
         * @throws JSONException
         */
        public static JSONObject getStringsFile() throws JSONException {
    
            if (joString == null) {
                String stringFileName = getResourcesPath() + "languages/" + getCurrentLanguage() + "/values.json";
                String languageFile = Helper.readJsonFile(stringFileName);
                if (languageFile != null) {
                    joString = new JSONObject(Helper.readJsonFile(stringFileName));
                } else {
                    return null;
                }
            }
    
            return joString.getJSONObject("strings");
        }
    
        /**
         * Method that returns current language ("sr", "en"...)
         * @return String
         */
        public static String getCurrentLanguage() {
    
            if (currentLanguage == null)
                currentLanguage = Helper.getCurrentLanguage(ctx);
    
            return currentLanguage;
        }
    
        /**
         * Method that resets joString object and currentLanguage on language change
         */
        public static void resetLanguage() {
            joString = null;
            currentLanguage = null;
        }
    
        /**
         * Method that resets joStyles object on theme change
         */
        public static void resetStyle() {
            joStyles = null;
        }
    
        /**
         * Method that deletes a directory from filesystem
         * @param path File
         * @return boolean
         */
        public static boolean deleteDirectory(File path) {
            if( path.exists() ) {
                File[] files = path.listFiles();
                for(int i=0; i>();
    
            // check if we already have this filename so we can reuse it
            for (int i = 0; i < ninePatchHashMaps.size(); i++) {
                HashMap row = ninePatchHashMaps.get(i);
    
                if(row.containsKey(filename))
                    return row.get(filename);
            }
    
            NinePatchDrawable patchy = null;
            try {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                Bitmap bitmap = BitmapFactory.decodeFile(filename, options);
                byte[] chunk = bitmap.getNinePatchChunk();
                boolean result = NinePatch.isNinePatchChunk(chunk);
                if (result)
                    patchy = new NinePatchDrawable(bitmap, chunk, new Rect(), null);
            } catch (Exception e){
                Helper.logError("NinePatchLoading",e);
            }
    
            if(patchy != null) {
    
                HashMap drawableImage = new HashMap();
                drawableImage.put(filename, patchy);
                ninePatchHashMaps.add(drawableImage);
            }
    
            return patchy;
    
        }
    
        public static Drawable loadImageFromFilesystem(String filename) {
    
            if(imagesHashMaps == null)
                imagesHashMaps = new ArrayList>();
    
            // check if we already have this filename so we can reuse it
            for (int i = 0; i < imagesHashMaps.size(); i++) {
                HashMap row = imagesHashMaps.get(i);
    
                if(row.containsKey(filename))
                    return row.get(filename);
            }
    
            Drawable image = null;
            try {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                Bitmap bitmap = BitmapFactory.decodeFile(filename, options);
    
                if(bitmap == null)
                    bitmap = BitmapFactory.decodeFile(filename.replace(ResourceConstants.getScreenDPI(ctx) + "/", ""), options);
    
                image = new BitmapDrawable(bitmap);
            } catch (Exception e){
                Helper.logError("ImageLoadingError",e);
            }
    
            if(image != null) {
                HashMap drawableImage = new HashMap();
                drawableImage.put(filename, image);
                imagesHashMaps.add(drawableImage);
            }
    
            return image;
        }
    
    }
    

    0 讨论(0)
提交回复
热议问题