Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

  • В исходном коде, который будет экспортирован в файле 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.

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

  • Построить.

Ответ 3


макеты:

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


xml и png:

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

скопировать a.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);

Ответ 4

Я только что обнаружил, что инструмент 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 выше.

Ответ 5

Вы можете динамически получать идентификатор ресурса с помощью метода android.

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

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

Ответ 6

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

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

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

Ответ 7

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

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

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

Ответ 8

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

protected abstract void getMyLayoutTextBox(int myLayoutTextBox);

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

Подробнее о абстракции здесь.

Ответ 9

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

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

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