2009-02-21 14 views
20

Ho due progetti Android, un "progetto di libreria" contenente un layout personalizzato e un "progetto di applicazione" contenente un'applicazione che utilizza il layout.Specifica delle dipendenze del progetto Android (in Eclipse)

Tutto sembra costruire ed eseguire correttamente, tranne che l'editor del layout visivo genera una classe ClassNotFoundException (che presumo sia un bug nel plug-in), ma quando provo a iniziare a utilizzare gli attributi che ho definito per il layout personalizzato in xml, non posso più costruire. Questo è; questo funziona:

<?xml version="1.0" encoding="utf-8"?> 
<se.fnord.android.layout.PredicateLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="asdfasdf" 
    /> 
</se.fnord.android.layout.PredicateLayout> 

considerando che il presente non lo fa:

<?xml version="1.0" encoding="utf-8"?> 
<se.fnord.android.layout.PredicateLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:fnord="http://schemas.android.com/apk/res/se.fnord.android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <TextView 
    fnord:layout_horizontalSpacing="1px" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="asdfasdf" 
    /> 
</se.fnord.android.layout.PredicateLayout> 

La compilazione fallisce con un messaggio da aapt:

ERRORE Nessun identificatore di risorsa trovata per l'attributo 'layout_horizontalSpacing' a pacchetto ' se.fnord.android '

L'identificatore di risorsa fa ex ist nel file R e attrs.xml conteneva il progetto della libreria, e se inserisco il codice di layout e le risorse direttamente nel progetto dell'applicazione, tutto funziona correttamente. L'attributo layout_horizontalSpacing (e layout_verticalSpacing) è un attributo personalizzato utilizzato nella classe PredicateLayout.LayoutParam per specificare la distanza dal widget successivo.

Finora ho provato i modi eclissi standard specificando i riferimenti di progetto e le dipendenze del percorso del percorso di generazione. Mi è stato anche detto di provare il tag nel manifest dell'applicazione, il che non ha aiutato.

Quindi, cosa devo fare per far funzionare i riferimenti nel file xml?

Non so se è rilevante, ma manifesta la 'biblioteca' si presenta così:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
     package="se.fnord.android" 
     android:versionCode="1" android:versionName="1.0.0"> 
</manifest> 

L' 'applicazione' manifestare in questo modo:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
     package="se.fnord.appname" 
     android:versionCode="1" android:versionName="1.0.0"> 
    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
     <activity android:name=".AppName" 
        android:label="@string/app_name"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 
</manifest> 

(Il 'PredicateLayout' , btw, è una versione ripulita di this).

+0

Vedere anche http://stackoverflow.com/questions/8581627/android-activity-under-eclipse-adt-with-project-dependencies-failed-resolving-x http://stackoverflow.com/questions/9838069/ jar-file-issue-with-adt-r17 – jfritz42

risposta

19

Le prime versioni di sdk per Android non supportavano la condivisione a livello di codice sorgente in un modo piacevole. Potresti scomporre i tuoi file .class e aggiungerli alla cartella lib /, ma questa soluzione non consentiva la condivisione diretta del codice sorgente e altrettanto importante non supportava la condivisione di risorse o file aidl.

Quindi, nel maggio 2010, Android ha introdotto il meccanismo del progetto Biblioteca. Un progetto di libreria è strutturato in modo molto simile a un normale progetto Android, ma piuttosto che essere utilizzato per produrre un apk, serve solo a fornire codice e risorse ad altri progetti. Come un progetto ordinario, un progetto di libreria di solito contiene cartelle src e res, insieme a un file AndroidManifest.xml; tuttavia il manifest dovrebbe essere per lo più vuoto con l'eccezione dell'elemento manifest e dell'attributo del pacchetto (non più vero - ora puoi dichiarare Attività e altri componenti nel manifest del tuo Progetto Libreria). Inoltre, il file project.properties per un Progetto Biblioteche deve contenere la proprietà:

"android.library=true" 

di fare un riferimento da un progetto comune (apk-produzione) per un Progetto Biblioteche, è necessario aggiungere un "Android .library.reference.N "linea nel file project.properties del progetto ordinario. Ad esempio, se il mio progetto principale vuole puntare a due progetti di libreria, il mio file project.properties per il progetto principale dovrebbe includere i seguenti:

android.library.reference.1=../LibraryA 
android.library.reference.2=../../LibraryB 

dove il ../ e il ../../ sono i rispettivi percorsi dal progetto principale ai progetti di biblioteca (questo è solo un esempio). Nota questo elenco di riferimenti è basato su 1 e non dovrebbe contenere spazi vuoti o duplicati. Google è consapevole del fatto che questo non è un sistema perfetto ma era una soluzione ragionevole compatibile con Ant ed Eclipse. In generale, il tuo IDE tenterà di mantenere questi file per te, ma a volte potresti doverli modificare a mano.

In un primo momento progetti di libreria non hanno sostenuto quanto segue:

  1. Biblioteca Progetti che punta ad altri progetti di libreria
  2. Biblioteca Progetti contenenti file AIDL
  3. cartella Assets contenente
  4. Biblioteca Progetti

Tuttavia le versioni successive di sdk hanno risolto tutti questi problemi.

Per ulteriori informazioni sui progetti di libreria, vedere the official documentation.

+1

ADT 0.9.7 ci ottiene l'80% di ciò che vogliamo, ma ha ancora questi svantaggi: (1) un progetto di libreria non può contenere file .aidl, (2) un progetto di libreria non può dipendere da un altro progetto di libreria, (3) un progetto di biblioteca non può contenere beni –

+1

(1) non è più valido a partire da ADT 0.9.8 – neu242

+1

corretto. SDK Tools Revision 7 insieme a ADT 0.9.8 (rilasciato nel settembre 2010) risolvono i problemi (1) e (2) almeno e possibilmente (3). –

3

Esportare il progetto di libreria come JAR e fare riferimento nel "Percorso di creazione Java" del progetto dell'applicazione come JAR.

3

Il "Esportare la libreria come un barattolo di" soluzione" funziona solo se il progetto di libreria contiene solo il codice sorgente. In questo caso la domanda del PO menziona il fatto che il suo progetto biblioteca contiene roba ui-related.

Abbiamo la Esattamente lo stesso problema sul mio team di voler avere progetti di libreria che contengono sorgenti e risorse correlate agli ui. Abbiamo finito con la revisione del nostro sistema di build Ant per far sì che le applicazioni inglobassero i progetti della libreria durante il tempo di costruzione. essere compatibile con Eclipse e questa è una delle principali fonti di frustrazione per gli sviluppatori: siamo ancora in grado di utilizzare Eclipse, ma dobbiamo fare i salti mortali per farlo funzionare e dobbiamo sopportare una diminuita produttività

+0

Vedere sopra l'aggiornamento che menziona ADT 0.9.7 - risolve principalmente questo problema. –

8

Inoltre, ho ottenuto il funzionamento degli attributi, ma non nel modo in cui dovrebbe funzionare, penso.

È necessario utilizzare come spazio dei nomi nell'elemento che utilizza gli attributi personalizzati, lo spazio dei nomi della propria app principale, non quello del progetto di libreria. Quindi, nel tuo esempio, se specifichi il valore di "xmlns: fnord" lo spazio dei nomi del tuo progetto di app, funziona.

Inoltre, durante la lettura degli attributi personalizzati nel costruttore personalizzato PredicateLayout(Context,AttributeSet), è necessario specificare lo spazio dei nomi dell'app anche nelle chiamate a attributes.getAttributeValue().

Che cosa è un dolore, dal momento che quel codice è nella tua app di libreria che non deve/non deve sapere del progetto di app in cui è usato. Ho lavorato attorno all'app richiamando un metodo statico ViewUtil.setAttributeNamespace (appNamespace) nella mia app onCreate(), e le viste personalizzate della libreria usano quel namespace per recuperare gli attributi personalizzati. Il file attrs.xml può quindi rimanere anche nel progetto della libreria. Ora l'unica cosa brutta è che l'XML di layout deve utilizzare lo spazio dei nomi dell'app su visualizzazioni personalizzate, quindi non è possibile inserire tali XML di layout nel progetto di libreria.

+2

Prova a rimuovere he/apk/dal percorso dello schema come indicato qui -> http://stackoverflow.com/questions/3428784/android-how-do-i-reference-a-stylable-that-resides-in-a- library-that-my-app-refe – scottyab

12

Esportare il progetto come JAR non è il modo giusto per collegare un progetto di libreria al progetto dell'app tramite Proprietà -> Percorso build Java -> Libreria. Né è possibile collegare il progetto come progetto richiesto tramite Proprietà -> Percorso build Java -> Progetti.

Prima di tutto, leggere l'argomento progetti Biblioteca agli sviluppatori Android -> Sviluppo -> gestione dei progetti: http://developer.android.com/guide/developing/projects/index.html#LibraryProjects Dopo questo, leggere l'impostazione di un Progetto Biblioteche e fa riferimento a un tema di progetto biblioteca di nuovo a Sviluppatori Android -> Sviluppo - > Gestione dei progetti -> Da Eclipse con ADT

Quindi ... i passi sono:

  1. Crea il tuo progetto di libreria normalmente come progetto Android;
  2. Impostare "è una libreria" nelle proprietà del progetto -> Android Crea il tuo progetto in modo normale;
  3. Aggiungere un riferimento alla libreria nelle proprietà del progetto -> Android -> Aggiungi.

Dopo questo è possibile utilizzare tutte le classi, i componenti (attività, servizi, fornitori, ricevitori), risorse ecc

Es .: per fare riferimento a tutte le risorse in un layout xml, ad esempio, è necessario utilizzare @mylib: id/my_id o @mylib: layout/my_lib_layout

Obs .: se si utilizzano componenti della libreria nel progetto di app, è necessario replicarli nel manifest dell'app.

+1

C'è qualche differenza nel file APK finale a seconda se un progetto di libreria è collegato in questo modo o completamente incorporato nell'app? – Pacerier

+0

Non sono sicuro, @Pacerier, ma penso che collegando la libreria come un progetto si incorpori solo ciò che l'app utilizza e non la lib completa. Puoi verificarlo testando entrambe le soluzioni e esaminando le dimensioni e il contenuto dell'ultimo apk. Ad ogni modo, è un buon punto! – JPMagalhaes

Problemi correlati