Here's the problem:
In eclipse, create an OSGI bundle that uses Android API, to display a Log Message. Then, install and start the OSGI bundle in an Android app which embeds Felix framework.
Work done so far:
1- Preparing the Android bundle called android
which exports android.util
. I did this by the following: File->New->Project->Plugin From existing jar Archieves ->Next->Add External->android.jar
which resulted in an OSGI bundle having the android API.
MANIFEST.MF:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Android
Bundle-SymbolicName: android
Bundle-Version: 1.0.0
Bundle-ClassPath: .
Export-Package: android,
android.util,
............etc
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
2- Creating the OSGI Bundle called AndroidAPI_Bundle
that will import android.util
and display a Log Message.
Activator class:
package androidapi_bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import android.util.Log;
public class Activator implements BundleActivator {
private static BundleContext context;
static BundleContext getContext() {
return context;
}
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
System.out.println("This is a java message inside the start method of AndroidAPI_Bundle");
Log.d("Zitona Log","This is android message inside the start method of AndroidAPI_Bundle");
}
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
Log.d("Zitona Log","AndroidAPI_Bundle stopped!");
}
}
MANIFEST.MF:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: AndroidAPI_Bundle
Bundle-SymbolicName: AndroidAPI_Bundle
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: androidapi_bundle.Activator
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: android.util,
org.osgi.framework;version="1.3.0"
Now it's time to dexify both bundles in order to install them and use them in Felix.
I used this:
dx --dex --output=classes.dex JAR_file.jar
aapt add JAR_file.jar classes.dex
The bundle AndroidAPI_Bundle
(which uses the Android API), was dexified successfully, but when I try to dexify android
bundle, I get this error:
trouble processing "java/awt/font/NumericShaper.class":
Ill-advised or mistaken usage of a core class (java.* or javax.*)
when not building a core library.
This is often due to inadvertently including a core library file
in your application's project, when using an IDE (such as
Eclipse). If you are sure you're not intentionally defining a
core class, then this is the most likely explanation of what's
going on.
However, you might actually be trying to define a class in a core
namespace, the source of which you may have taken, for example,
from a non-Android virtual machine project. This will most
assuredly not work. At a minimum, it jeopardizes the
compatibility of your app with future versions of the platform.
It is also often of questionable legality.
If you really intend to build a core library -- which is only
appropriate as part of creating a full virtual machine
distribution, as opposed to compiling an application -- then use
the "--core-library" option to suppress this error message.
If you go ahead and use "--core-library" but are in fact
building an application, then be forewarned that your application
will still fail to build or run, at some point. Please be
prepared for angry customers who find, for example, that your
application ceases to function once they upgrade their operating
system. You will be to blame for this problem.
If you are legitimately using some code that happens to be in a
core package, then the easiest safe alternative you have is to
repackage that code. That is, move the classes in question into
your own package namespace. This means that they will never be in
conflict with core system classes. JarJar is a tool that may help
you in this endeavor. If you find that you cannot do this, then
that is an indication that the path you are on will ultimately
lead to pain, suffering, grief, and lamentation.
1 error; aborting
First: Am I going in the right direction? Is this how I should solve the problem?
Second: How can I solve the error that I got above when dexifying android
bundle?
Update 1:
I deleted some packages from android.jar
which was preventing the dexification and which I won't need currently (this is a temporary solution), and by doing that I was able to dexify android.jar
.
Next, I installed and started both android.jar
and AndroidAPI_Bundle.jar
on Apache Felix. android.jar
was installed OK. However, at the installation of AndroidAPI_Bundle.jar
which imports android.util
from android.jar
, I got these errors:
08-18 14:42:05.470: W/System.err(1318): org.osgi.framework.BundleException: Activator start error in bundle AndroidAPI_Bundle [2].
08-18 14:42:05.478: W/System.err(1318): at org.apache.felix.framework.Felix.activateBundle(Felix.java:2196)
08-18 14:42:05.478: W/System.err(1318): at org.apache.felix.framework.Felix.startBundle(Felix.java:2064)
08-18 14:42:05.478: W/System.err(1318): at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)
08-18 14:42:05.478: W/System.err(1318): at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:942)
08-18 14:42:05.478: W/System.err(1318): at com.example.apache_felix_android.MainActivity.onCreate(MainActivity.java:93)
08-18 14:42:05.478: W/System.err(1318): at android.app.Activity.performCreate(Activity.java:5104)
08-18 14:42:05.478: W/System.err(1318): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
08-18 14:42:05.508: W/System.err(1318): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
08-18 14:42:05.508: W/System.err(1318): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
08-18 14:42:05.508: W/System.err(1318): at android.app.ActivityThread.access$600(ActivityThread.java:141)
08-18 14:42:05.508: W/System.err(1318): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
08-18 14:42:05.508: W/System.err(1318): at android.os.Handler.dispatchMessage(Handler.java:99)
08-18 14:42:05.508: W/System.err(1318): at android.os.Looper.loop(Looper.java:137)
08-18 14:42:05.518: W/System.err(1318): at android.app.ActivityThread.main(ActivityThread.java:5041)
08-18 14:42:05.518: W/System.err(1318): at java.lang.reflect.Method.invokeNative(Native Method)
08-18 14:42:05.528: W/System.err(1318): at java.lang.reflect.Method.invoke(Method.java:511)
08-18 14:42:05.528: W/System.err(1318): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
08-18 14:42:05.538: W/System.err(1318): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
08-18 14:42:05.538: W/System.err(1318): at dalvik.system.NativeStart.main(Native Method)
08-18 14:42:05.548: W/System.err(1318): Caused by: java.lang.RuntimeException: Stub!
08-18 14:42:05.558: W/System.err(1318): at android.util.Log.d(Log.java:7)
08-18 14:42:05.558: W/System.err(1318): at androidapi_bundle.Activator.start(Activator.java:24)
08-18 14:42:05.578: W/System.err(1318): at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:645)
08-18 14:42:05.588: W/System.err(1318): at org.apache.felix.framework.Felix.activateBundle(Felix.java:2146)
08-18 14:42:05.588: W/System.err(1318): ... 18 more
I understand from the error that android.util.Log has only "stub", not the real implementation of the methods. How can I solve this issue?!
Update 2:
@Neil suggested in the answer below that the bundle android.jar
is not needed, once you compile AndroidAPI_Bundle.jar
. So I only installed AndroidAPI_Bundle.jar
into Felix. But that does NOT work. I tried this several times. I do understand that the platform alreayd has the Android API so no need for android.jar, but that's the theory, in practice, this did not work with me. Below is the error that I get:
08-18 18:58:44.307: W/System.err(7898): org.osgi.framework.BundleException: Unresolved constraint in bundle AndroidAPI_Bundle [1]: Unable to resolve 1.0: missing requirement [1.0] osgi.wiring.package; (osgi.wiring.package=android.util)
08-18 18:58:44.317: W/System.err(7898): at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3974)
08-18 18:58:44.317: W/System.err(7898): at org.apache.felix.framework.Felix.startBundle(Felix.java:2037)
08-18 18:58:44.317: W/System.err(7898): at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)
08-18 18:58:44.327: W/System.err(7898): at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:942)
08-18 18:58:44.327: W/System.err(7898): at com.example.apache_felix_android.MainActivity.onCreate(MainActivity.java:93)
08-18 18:58:44.327: D/dalvikvm(7898): GC_CONCURRENT freed 387K, 19% free 2774K/3388K, paused 22ms+5ms, total 131ms
08-18 18:58:44.337: W/System.err(7898): at android.app.Activity.performCreate(Activity.java:5104)
08-18 18:58:44.337: W/System.err(7898): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
08-18 18:58:44.337: W/System.err(7898): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
08-18 18:58:44.337: W/System.err(7898): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
08-18 18:58:44.337: W/System.err(7898): at android.app.ActivityThread.access$600(ActivityThread.java:141)
08-18 18:58:44.337: W/System.err(7898): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
08-18 18:58:44.347: W/System.err(7898): at android.os.Handler.dispatchMessage(Handler.java:99)
08-18 18:58:44.347: W/System.err(7898): at android.os.Looper.loop(Looper.java:137)
08-18 18:58:44.347: W/System.err(7898): at android.app.ActivityThread.main(ActivityThread.java:5041)
08-18 18:58:44.347: W/System.err(7898): at java.lang.reflect.Method.invokeNative(Native Method)
08-18 18:58:44.347: W/System.err(7898): at java.lang.reflect.Method.invoke(Method.java:511)
08-18 18:58:44.347: W/System.err(7898): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
08-18 18:58:44.357: W/System.err(7898): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
08-18 18:58:44.357: W/System.err(7898): at dalvik.system.NativeStart.main(Native Method)
Reading the error, It's clearly saying that android.util package is missing since this bundle imports it. It has to be there.
I even removed any import in the MANIFEST.MF of AndroidAPI_Bundle
, and rather than importing, I added the android.jar to my extra-dependencies section. It compiled fine, but when I run the bundle separately (not on android app), it shows java.lang.NoClassDefFoundError: android/util/Log
, and when I install it in Felix in my android application, it shows:
08-18 19:13:22.666: I/dalvikvm(12325): Could not find method android.util.Log.d, referenced from method androidapi_bundle.Activator.start
My Requirement is simple: What's the right procedure for creating bundle that uses Android API, and then successfully install that bundle into Android app. But I just don't see any implementation for it online. If anyone has any idea, please help.
It seems like you keep asking the same question with only slight variations. The answer is the same as before: you don't need to do this.
First, android.jar only contains stub methods so it won't actually work even if you manage to dexify it. Second, you don't need to get this jar onto the device because the APIs are already present there.
The JAR is only intended for compiling against. Assuming you have successfully compiled your bundle then you just install your bundle (and not android.jar) onto the device.
UPDATE
In order to import the package android.util
, somebody needs to export that package. The package is available from the base runtime -- i.e. the Android equivalent of the JRE boot classpath. These packages are normally exported by the system bundle, i.e. the special bundle that represents the OSGi Framework itself. Except of course OSGi doesn't know anything about Android! It only exports the packages that are defined by standard Java. So if there are additional packages from the base runtime that you need to access, you simply add them the system bundle exports by setting the org.osgi.framework.system.packages.extra
property. This property is passed using the configuration map that you give to FrameworkFactory.newFramework
when launching OSGi.