Упаковка файлов ресурсов Android в распространяемый файл Jar

StackOverflow https://stackoverflow.com/questions/1995004

  •  22-09-2019
  •  | 
  •  

Вопрос

Я работаю над повторно используемым кодом Android, который хотел бы распространить среди других разработчиков для использования в их собственных приложениях.В коде есть некоторые зависимости ресурсов (макеты, рисунки xml и png), которые я хотел бы иметь возможность включать и ссылаться на них в одном пакете (файл Jar).

Возможно ли это, и если да, то как лучше всего это сделать?

Это было полезно?

Решение

У меня нет для вас никаких оптимистичных новостей.В общем, вы не можете распространять свой собственный пакет так легко, как вы ожидаете.Основная проблема — автоматически созданный R-файл.Вы, вероятно, делаете на него какие-то ссылки — у вас есть макеты и чертежи.У пользователя вашей библиотеки будет свой собственный файл R, содержащий идентификаторы его ресурсов, а не тех, которые предоставляет ваша библиотека.

В случае доступных ресурсов вы можете прочитать их классическим способом, без R-файла.Но насколько я знаю вы не умеете надувать макеты из внешних xml файлов.

Таким образом, уродливым хаком здесь было бы распространение вашей библиотеки вместе со всеми вашими ресурсами, которые пользователю пришлось бы скопировать в свою папку «res».Честно говоря, хорошего решения вашей проблемы не существует...извини.С уважением!

Другие советы

Поскольку Android делает R класс автоматически с файлами ресурсов под /res папку, используя R класс как final static невозможно.

Я нашел хорошее решение использовать jar файл с res файлы.Вот как я это сделал:

  1. В вашем исходном коде, который будет экспортирован в jar файл, не используй R переменная, поскольку во время компиляции она будет заменена конечным статическим адресом памяти.Вместо использования R, я сделал свой собственный метод ниже:

    public static int getResourceIdByName(String packageName, String className, String name) {
        Class r = null;
        int id = 0;
        try {
            r = Class.forName(packageName + ".R");
    
            Class[] classes = r.getClasses();
            Class desireClass = null;
    
            for (int i = 0; i < classes.length; i++) {
                if (classes[i].getName().split("\\$")[1].equals(className)) {
                    desireClass = classes[i];
    
                    break;
                }
            }
    
            if (desireClass != null) {
                id = desireClass.getField(name).getInt(desireClass);
            }
    
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    
        return id;
    }
    

    Например, если у вас есть макет с именем main.xml, вы можете получить его, вызвав метод:

    int id = getResourceIdByName(context.getPackageName(), "layout", "main");
    

    Если у вас есть строка, чья id это «text1», вы можете получить его, вызвав метод

    int id = getResourceIdByName(context.getPackageName(), "string", "text1");
    

    Этот метод дает вам идентификатор ресурса во время выполнения.Он использует API отражения для получения статуса R во время выполнения.

    Используя этот метод, вы можете избежать использования R переменная.

  2. Скопируйте свой res файлы в целевой проект.

  3. Строить.


макеты:

жесткий код в исходном коде Java


xml и png:

скопируйте xml и png в папку src вашего проекта и упакуйте в jar, например

скопируйте файл .png в src/com/example/test

загрузите его как следующие коды Java:

    InputStream is = YourClassName.class.getClassLoader().getResourceAsStream("com/example/test/a.png");
    if ( null != is )
    {
          Bitmap bmp = BitmapFactory.decodeStream(is);

Я только что обнаружил, что aapt Инструмент в Android SDK позволяет использовать следующую опцию:

   --non-constant-id
       Make the resources ID non constant. This is required to make an R java class
       that does not contain the final value but is used to make reusable compiled
       libraries that need to access resources.

Звучит многообещающе, хотя я этого не пробовал и понятия не имею, работает ли это.Я подозреваю, что это делается для того, чтобы обойти проблему, описанную в сообщении @J.J.Kim выше.

Вы можете динамически получать идентификатор ресурса, используя метод Android.

int preferences = context.getResources().getIdentifier("preferences", "xml", context.getPackageName());

Позже ваши ресурсы необходимо будет включить (скопировать) в ваш новый проект.

я использовал user558185 решение, но есть более простой способ.Если ваши ресурсы находятся в проекте библиотеки (например, для плагина Cordova), вы можете получить ресурс с помощью context.getResources().getIdentifier(name, className, context.getPackageName());

Это происходит, когда файл R ресурсов проекта библиотеки не создается должным образом, а имя пакета R не соответствует требуемому имени пакета в проекте библиотеки.

Использование такое же, как и ответ user558185, но используется собственный метод Android.

Привет, я думаю, что это поздний ответ, но все же мне просто что сообщить об AAR

Android ARchive — этот файл может хранить ваши файлы res и манифеста, чтобы другие разработчики могли просто импортировать aar в свой проект и скомпилировать свой код.

Таким образом, мы можем получить ошибки слияния манифеста, исправить использование свойства replace в вашем манифесте, и это следует проверить перед распространением.

вы можете использовать абстракцию, чтобы получить значения R от реализующего класса (пользователя).

protected abstract void getMyLayoutTextBox(int myLayoutTextBox);

Затем пользователь должен расширить ваш класс (который расширяет Activity) и реализовать этот метод.В своем классе вы просто звоните getMyLayoutTextBox() и вы получите правильное значение R, предоставленное пользователем после того, как он реализует ваш распространяемый jar.

Вы можете прочитать больше о абстракция здесь.

Если вы используете Eclipse, перейдите в проект "Properties->Java Build Path".На вкладке "Source", добавьте папку res, которую хотите упаковать (например.разрешение/сырой).

Он добавит следующую строку в .classpath файл
<classpathentry kind="src" path="res/raw"/>

После завершения сборки новый файл jar будет содержать файлы в res/raw/ папка.Вы можете получить к ним доступ как user558185 предложенный.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top