Je travaille sur un code Android réutilisable que je souhaiterais distribuer à d'autres développeurs pour l'utiliser dans leurs propres applications. Le code comporte des dépendances de ressources (mises en forme, tirages xml et png) que je voudrais pouvoir inclure et référencer dans un seul package (fichier Jar).
Est-ce possible et, dans l'affirmative, quelle est la meilleure méthode pour le faire?
Je n'ai aucune nouvelle optimiste pour vous. En général, vous ne pouvez pas distribuer votre propre paquet aussi facilement que prévu. Le problème principal est le fichier R auto-généré. Vous en faites probablement des références - vous avez vos mises en page et vos tirables. L'utilisateur de votre bibliothèque aura son propre fichier R - contenant les identifiants pour ses ressources, pas pour ceux fournis par votre bibliothèque.
Dans le cas de ressources extractibles, vous pouvez les lire de manière classique, sans le fichier R. Mais pour autant que je sache, vous n'êtes pas en mesure de gonfler les mises en page à partir de fichiers XML externes.
Donc, le vilain piratage ici serait de distribuer votre bibliothèque avec toutes vos ressources, quel utilisateur devrait copier dans son dossier "res" Pour être honnête, il n’ya pas de bonne solution à votre problème ... désolé . Amicalement!
Étant donné qu'Android crée automatiquement la classe R
avec des fichiers de ressources dans le dossier /res
, il est impossible d'utiliser la classe R
en tant que final static
.
J'ai trouvé une solution intéressante pour utiliser un fichier jar
avec les fichiers res
. Voici comment je l'ai fait:
Dans votre code source qui sera exporté dans le fichier jar
, n’utilisez pas de variable R
car elle sera remplacée par une adresse mémoire statique finale au moment de la compilation ..__ Au lieu d’utiliser R
, j’ai créé méthode ci-dessous:
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;
}
Par exemple, si vous avez une disposition nommée main.xml
, vous pouvez l'obtenir en appelant la méthode suivante:
int id = getResourceIdByName(context.getPackageName(), "layout", "main");
Si vous avez une chaîne dont id
est "text1", vous pouvez l'obtenir en appelant la méthode
int id = getResourceIdByName(context.getPackageName(), "string", "text1");
Cette méthode vous donne votre identifiant de ressource au moment de l'exécution. Il utilise l'API de réflexion pour obtenir le statut de R
au moment de l'exécution.
En utilisant cette méthode, vous pouvez éviter d'utiliser la variable R
.
Copiez vos fichiers res
dans votre projet cible.
Construire.
mises en page:
code dur dans votre source Java
xml & png:
copier xml & png dans le dossier src de votre projet et le package dans jar, par exemple
copier a.png vers src/com/exemple/test
chargez-le sous les codes Java suivants:
InputStream is = YourClassName.class.getClassLoader().getResourceAsStream("com/example/test/a.png");
if ( null != is )
{
Bitmap bmp = BitmapFactory.decodeStream(is);
Je viens de constater que l'outil aapt
du SDK Android permet l'option suivante:
--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.
Cela semble prometteur, bien que je n’aie pas essayé cela et que je ne sache pas si cela fonctionne. Je suppose que cela a pour but de résoudre le problème traité par le message de @ J.J.Kim ci-dessus.
Vous pouvez obtenir de manière dynamique un identifiant de ressource à l'aide de la méthode Android.
int preferences = context.getResources().getIdentifier("preferences", "xml", context.getPackageName());
Plus tard, vos ressources doivent être incluses (copiées) dans votre nouveau projet.
Bonjour, je pense que la réponse est tardive, mais j’ai encore de quoi informer sur AAR.
Android ARchive - ce fichier peut contenir vos fichiers res et manifestes, de sorte que les autres développeurs puissent simplement importer le fichier aar dans leur projet et compiler leur code.
De cette façon, nous pourrions obtenir des erreurs de fusion de manifeste, le correctif qui lui permettrait d'utiliser la propriété de remplacement dans votre manifeste, ce qui devrait être vérifié avant la distribution.
J'utilisais user558185 solution mais voici un moyen plus simple. Si vos ressources sont dans un projet de bibliothèque (pour un plugin Cordova par exemple), vous pouvez obtenir une ressource avec context.getResources().getIdentifier(name, className, context.getPackageName());
Cela se produit lorsque le fichier R des ressources du projet de bibliothèque n'est pas généré correctement et que le package R ne correspond pas au packageName requis par le projet de bibliothèque.
L'utilisation est la même que la réponse user558185, mais il utilise une méthode Android native.
Si vous utilisez Eclipse, accédez au projet "Properties->Java Build Path"
. Sous l'onglet "Source"
, ajoutez le dossier res que vous voulez emballer (par exemple, res/raw).
Il va ajouter la ligne suivante dans le fichier .classpath
<classpathentry kind = "src" chemin = "res/raw" />
Une fois la construction terminée, le nouveau fichier JAR contiendra les fichiers du dossier res/raw/
. Vous pouvez y accéder en tant que user558185 suggéré.
vous pouvez utiliser l'abstraction pour obtenir les valeurs R de la classe d'implémentation (l'utilisateur).
protected abstract void getMyLayoutTextBox(int myLayoutTextBox);
Ensuite, l'utilisateur doit étendre votre classe (qui étend Activity
) et implémenter cette méthode. Dans votre classe, vous appelez simplement getMyLayoutTextBox()
et vous obtiendrez la valeur R correcte fournie par l'utilisateur après la mise en œuvre de votre jar distribuable.
Vous pouvez en savoir plus sur abstraction ici .