android android-activity osgi apache-felix osgi-bundle

Actividad de Android en paquete OSGI



android-activity apache-felix (3)

Estoy trabajando en el desarrollo de paquetes OSGI que tienen un soporte completo para Android. Hasta el momento, según mis preguntas anteriores, pude usar la API de Android dentro del paquete OSGI. Funciona bien y lo intenté. Estoy usando el marco de Felix.

Sin embargo, estoy estancado ahora en la misión de hacer un paquete OSGI para tener una actividad de Android y comenzar esa actividad. También necesito estas actividades para poder solicitar permisos, así que supongo que necesitaré un AndroidManifest.xml en el paquete OSGI.

Mientras hacía una investigación, pude encontrar a solo una persona que describía su experiencia para lograr esto. Lamentablemente, los pasos que mencionó son ambiguos para mí.

En su pregunta "Soporte completo de Android para OSGI" , esto es lo que dijo:

I have found a way to start activities owned by android bundles: •the android bundle MUST be an APK which can be created using Eclipse Android Project •add a Reference Library entry to the project Build Path for your OSGi framework (in my case framework.jar) •edit bundle.manifest describing the bundle. The file is not part of the APK but will be used on build •the bundle''s code, especially the Activator class, MUST be in the same package as defined in AndroidManifest.xml AND the symbolic name of the bundle MUST be the package name as well. If these conditions are met then all of the classes will be correctly loaded. If not, it will result in seeing java.lang.NoClassDefFoundError on runtime •Use Android Tools > Export Unsigned Android Package •copy bundle.manifest in the unsigned APK as META-INF/MANIFEST.MF •sign the APK using whatever certificate you want •install the signed APK like any standard android application. Installation is required in order to have the Activity resolved. Without this the activity won''t resolve and the bundle will fail •have the OSGi framework load the bundle APK

Donde él dice:

•edit bundle.manifest describing the bundle. The file is not part of the APK but will be used on build

Todo lo que hice fue crear un proyecto de Android (APK) y seguir los dos primeros pasos. Pero en este tercer paso anterior, no pude encontrar "bundle.manifest" para editarlo. No está allí en absoluto, ¿cómo es que dice que lo edite?

Además, cuando Export Unsigned Android Package , ¿desde dónde debo copiar el archivo de manifiesto?

Finalmente, ¿el archivo APK final firmado es mi paquete que debe ser cargado por el framework? Esto parece extraño porque ni siquiera es un archivo jar.

Si estos pasos no me ayudaran, ¿alguien me puede guiar en la dirección correcta? Gracias.

ACTUALIZAR:

Nadie responde mi pregunta, así que hice lo siguiente:

1- En mi proyecto de aplicación de Android (que estoy tratando de hacer que actúe como un paquete), incluí mi clase Activator en el mismo paquete mencionado en AndroidManifest.xml. Aquí está mi clase Activator.java :

package com.example.patient; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { private static BundleContext context; static BundleContext getContext() { return context; } public void start(BundleContext bundleContext) throws Exception { Activator.context = bundleContext; //I WOULD LIKE TO START THE ACTIVITY HERE TO DISPLAY THE TOAST MESSAGE System.out.println("Android APK Bundle Started"); } public void stop(BundleContext bundleContext) throws Exception { Activator.context = null; } }

y aquí está mi AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.patient" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.patient.View_Patient_File_Activity" android:label="View Patient File" > </activity> <activity android:name="com.example.patient.Enter_Patient_ID_Activity" android:label="View Patient File" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>

2- Agregué una entrada de la Biblioteca de Referencia a la Ruta de compilación del proyecto para mi marco OSGi (felix.jar)

3- Genere una copia sin firmar de mi proyecto con las herramientas de Android.

4- Agregué una carpeta al directorio raíz de la copia sin firmar llamada META-INF , y dentro de esa carpeta, agregué un archivo llamado MANIFEST.MF , a continuación se muestra el contenido de ese archivo:

Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Patient Bundle-SymbolicName: com.example.patient Bundle-Version: 1.0.0.qualifier Bundle-Activator: com.example.patient.Activator Import-Package: org.osgi.framework;version="1.3.0" Bundle-RequiredExecutionEnvironment: OSGi/Minimum-1.0

5- Firmé manualmente la copia sin firmar usando la línea de comando y la herramienta de firma de jar. Algo como:

jarsigner -verbose -keystore /path_to_keystore/mykeystore.keystore my_application.apk my_keystore_alias

6- Instalé la copia firmada en mi PC y en mi pestaña.

7- Finalmente, ejecuto mi aplicación y dejo que el marco OSGI cargue el mismo archivo apk firmado.

NO USE , aunque el estado del paquete está activo, pero NO veo el mensaje en el método de activación de inicio (), lo que significa que mi paquete no está cargado correctamente. ¿Dónde fui a worng? Por favor ayuda.

ACTUALIZACIÓN 25-11-2013

Me aseguré de hacer los pasos correctamente, y ahora tengo esto:

11-25 17:54:08.600: W/System.err(2714): org.osgi.framework.BundleException: Not found: com.example.patient.Activator 11-25 19:22:36.590: W/System.err(6652): Caused by: java.lang.ClassNotFoundException: com.example.patient.Activator not found by com.example.patient

Lo que significa que mi paquete no contiene la clase Activator, pero estoy seguro de que sí. ¿Qué podría estar mal?

ACTUALIZACIÓN 26-11-2013

Abrí la APK firmada usando WinZip. Noté que a diferencia de los paquetes que solía compilar, el APK firmado no contiene los archivos .class, incluido el "Activator.class", así que copié el directorio com que contiene todos los archivos .class del proyecto y lo pegué. en el APK firmado. A continuación, firmé ese APK nuevamente. Ahora, cuando instalo el APK, obtengo el siguiente registro que contiene muchos errores:

11-25 23:16:25.651: D/dalvikvm(5617): DexOpt: --- BEGIN ''bundle.jar'' (bootstrap=0) --- 11-25 23:16:26.271: D/dalvikvm(5617): DexOpt: --- END ''bundle.jar'' (success) --- 11-25 23:16:26.271: D/dalvikvm(5617): DEX prep ''/sdcard/felix-cache-1472376252.tmp/bundle1/version0.0/bundle.jar'': unzip in 102ms, rewrite 620ms 11-25 23:16:26.271: W/dalvikvm(5617): Class resolved by unexpected DEX: Lcom/example/patient/Activator;(0x4074fa08):0x18a7b8 ref [Lorg/osgi/framework/BundleActivator;] Lorg/osgi/framework/BundleActivator;(0x40714410):0xbd630 11-25 23:16:26.271: W/dalvikvm(5617): (Lcom/example/patient/Activator; had used a different Lorg/osgi/framework/BundleActivator; during pre-verification) 11-25 23:16:26.271: I/dalvikvm(5617): Failed resolving Lcom/example/patient/Activator; interface 902 ''Lorg/osgi/framework/BundleActivator;'' 11-25 23:16:26.271: W/dalvikvm(5617): Link of class ''Lcom/example/patient/Activator;'' failed 11-25 23:16:26.271: E/dalvikvm(5617): ERROR: defineClass(0x4074fa08, com.example.patient.Activator, 0x4079d468, 0, 955, 0x4073e918) 11-25 23:16:26.271: E/Zaid Log(5617): Problem installing the bundle :s 11-25 23:16:26.271: W/System.err(5617): org.osgi.framework.BundleException: Activator start error in bundle com.example.patient [1]. 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.Felix.activateBundle(Felix.java:2196) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.Felix.startBundle(Felix.java:2064) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:942) 11-25 23:16:26.271: W/System.err(5617): at com.example.patient_application.MainActivity.onCreate(MainActivity.java:136) 11-25 23:16:26.271: W/System.err(5617): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1048) 11-25 23:16:26.271: W/System.err(5617): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1715) 11-25 23:16:26.271: W/System.err(5617): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1767) 11-25 23:16:26.271: W/System.err(5617): at android.app.ActivityThread.access$1500(ActivityThread.java:122) 11-25 23:16:26.271: W/System.err(5617): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1005) 11-25 23:16:26.271: W/System.err(5617): at android.os.Handler.dispatchMessage(Handler.java:99) 11-25 23:16:26.271: W/System.err(5617): at android.os.Looper.loop(Looper.java:132) 11-25 23:16:26.271: W/System.err(5617): at android.app.ActivityThread.main(ActivityThread.java:4028) 11-25 23:16:26.271: W/System.err(5617): at java.lang.reflect.Method.invokeNative(Native Method) 11-25 23:16:26.271: W/System.err(5617): at java.lang.reflect.Method.invoke(Method.java:491) 11-25 23:16:26.271: W/System.err(5617): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) 11-25 23:16:26.271: W/System.err(5617): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) 11-25 23:16:26.271: W/System.err(5617): at dalvik.system.NativeStart.main(Native Method) 11-25 23:16:26.271: W/System.err(5617): Caused by: java.lang.UnsupportedOperationException: can''t load this type of class file 11-25 23:16:26.271: W/System.err(5617): at java.lang.VMClassLoader.defineClass(Native Method) 11-25 23:16:26.271: W/System.err(5617): at java.lang.ClassLoader.defineClass(ClassLoader.java:319) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.findClass(BundleWiringImpl.java:2279) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1501) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:75) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1955) 11-25 23:16:26.271: W/System.err(5617): at java.lang.ClassLoader.loadClass(ClassLoader.java:500) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.BundleWiringImpl.getClassByDelegation(BundleWiringImpl.java:1374) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.Felix.createBundleActivator(Felix.java:4329) 11-25 23:16:26.271: W/System.err(5617): at org.apache.felix.framework.Felix.activateBundle(Felix.java:2141) 11-25 23:16:26.271: W/System.err(5617): ... 17 more


Finalmente, ¿el archivo APK final firmado es mi paquete que debe ser cargado por el framework? Esto parece extraño porque ni siquiera es un archivo jar . Sí lo es. Como APK, sigue siendo un JAR compatible, excepto que también contiene archivos dex.

Los pasos que has seguido me parecen legítimos. De acuerdo con mi experiencia, debería haber funcionado. ¿Tiene algún registro que podamos explotar? La consola Knopflerfish le permite ver el stacktrace al iniciar y detener los paquetes manualmente. Es extremadamente valioso aquí.


el código del paquete, especialmente la clase Activator, DEBE estar en el mismo paquete definido en AndroidManifest.xml Y el nombre simbólico del paquete DEBE ser también el nombre del paquete. Si se cumplen estas condiciones, todas las clases se cargarán correctamente. Si no, dará como resultado ver java.lang.NoClassDefFoundError en el tiempo de ejecución

No es necesario que el nombre simbólico del paquete y el código del paquete estén en el mismo paquete que la aplicación de Android, siempre que el paquete de exportación y el paquete de importación en manifest.mf estén configurados correctamente. Puede usar bndtools ( http://bndtools.org ) para ayudar a generar el manifiesto.mf correcto automáticamente (para una aplicación de Android, bndtool no parece funcionar. Tengo que usar su obsoleto uno bnd.jar para hacer el job. bnd.jar se puede descargar aquí: http://www.java2s.com/Code/Jar/b/Downloadbndjar.htm )


Hubo dos problemas, y al resolverlos logré finalmente instalar mi paquete de APK y comencé con Felix.

1- A diferencia de los paquetes OSGI, el APK final firmado no contiene los archivos .class . Es por eso que recibí: Not found: com.example.patient.Activator . Al copiar manualmente el directorio com de mi proyecto Android a la APK firmada y luego volver a firmarlo, logré resolver este problema.

2- El segundo paso mencionado por @ slash33 que es:

•add a Reference Library entry to the project Build Path for your OSGi framework

me estaba causando el siguiente error:

(Lcom/example/patient/Activator; had used a different Lorg/osgi/framework/BundleActivator; during pre-verification)

Con la ayuda de esta publicación, simplemente eliminé la referencia a la biblioteca y felix.jar de mi ruta de compilación. Luego hice esto: Build Path-> Configure Build Path-> Projects, y luego agregué mi proyecto de aplicación que cargará el paquete, y que ya tiene felix.jar en su ruta de compilación. Hasta donde yo entiendo, la aplicación y el paquete APK usarán el mismo felix.jar . (En lugar de mantener uno diferente en ambos, lo que hace que Dalvik se queje).

Por lo tanto, creo que los pasos correctos para crear un paquete APK de Android, y luego cargarlo en el marco serían:

  • Crea una APK regular, por ejemplo creando Eclipse Android Project.
  • Haga que su paquete use la misma biblioteca de marcos OSGI utilizada por su aplicación mediante: Build Path-> Configure Build Path-> Projects, y luego agregue su proyecto de aplicación que cargará el paquete. Su proyecto de aplicación debe contener el archivo jar OSGI framework en su ruta de compilación (en mi caso, felix.jar ).
  • Crea el archivo de manifiesto del paquete que describe el paquete. Puedes llamarlo bundle.manifest .
  • Supongamos que el paquete de su aplicación es com.acme.helloworld (este valor se establece con manifest: package en AndroidManifest.xml), la clase Activator de su paquete OSGI DEBE colocarse en el paquete com.acme.helloworld y usted DEBE establecer Bundle-SymbolicName: com.acme.helloworld en el manifiesto del paquete. Si no se cumple alguna de estas condiciones, se generará java.lang.NoClassDefFoundError en el tiempo de ejecución.
  • Usa las herramientas de Android> Exportar paquete de Android sin firmar
  • Copie bundle.manifest en el directorio raíz de la APK sin firmar generada como META-INF/MANIFEST.MF . Puede usar Winzip para abrir la APK sin firmar y agregar la carpeta META-INF .
  • Firme el APK usando el comando: jarsigner -verbose -keystore /path_to_keystore/mykeystore.keystore my_application.apk my_keystore_alias .
  • Copie su directorio que contiene todos los archivos .class de su proyecto de Android en el directorio raíz de su apk firmado. En mi caso: es el directorio com .
  • Firme su APK una vez más.
  • Instala el paquete de APK.
  • Haga que el marco OSGi cargue e inicie el paquete APK (el mismo archivo APK)