Запуск пакета на Knopflerfish, встроенном в Android, не работает

Я встраиваю фреймворк Knopflerfish в приложение для Android, чтобы динамически запускать и останавливать пакеты.

Я следил за этим учебным курсом, загруженным фреймворком. jar из ссылки this и добавил ее в мой путь к классам в моем проекте eclipse.

Кроме того, ниже приведен класс Activity, который запускает фреймворк и запускает один пакет:

package com.example.knopflerfish_android;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;

import org.knopflerfish.framework.FrameworkFactoryImpl;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.launch.FrameworkFactory;
import org.osgi.service.startlevel.StartLevel;




public class MainActivity extends Activity {

private static final String TAG = "Zaid Log";
private Framework mFramework;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        System.out.println("here!");

        Map<String, String> fwprops = new Hashtable<String, String>(); //CHANGED

        // add any framework properties to fwprops
        fwprops.put("org.osgi.framework.storage", "sdcard/fwdir");

        FrameworkFactory ff = new FrameworkFactoryImpl();
        mFramework = ff.newFramework(fwprops);



        try {

            mFramework.init(); //STUCK HERE!!


        } catch (BundleException be) {
            // framework initialization failed

            Log.d(TAG, be.getStackTrace().toString());
            Log.d(TAG,"failed to initialize Framework");
        }



        setInitlevel(1);


        installBundle("Bundle_AndroidAPI_1.0.0.201308160327.jar");
        startBundle("Bundle_AndroidAPI_1.0.0.201308160327.jar");
        // install/start other bundles...


        setStartLevel(10);

        try {
            mFramework.start();
        } catch (BundleException be) {
            Log.e(TAG, be.toString());
            // framework start failed
        }

        Log.d(TAG, "OSGi framework running, state: " + mFramework.getState());


      /*  helloServiceReference= context.getServiceReference(HelloService.class.getName());
        HelloService helloService =(HelloService)context.getService(helloServiceReference);
        System.out.println(helloService.sayHello());*/
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    private void startBundle(String bundle) {
        Log.d(TAG, "starting bundle " + bundle);
        InputStream bs;
        try {
            bs = getAssets().open("bundles/" + bundle);
        } catch (IOException e) {
            Log.e(TAG, e.toString());
            return;
        }

        long bid = -1;
        org.osgi.framework.Bundle[] bl = mFramework.getBundleContext().getBundles();
        for (int i = 0; bl != null && i < bl.length; i++) {
            if (bundle.equals(bl[i].getLocation())) {
                bid = bl[i].getBundleId();
            }
        }

        org.osgi.framework.Bundle b = mFramework.getBundleContext().getBundle(bid);
        if (b == null) {
            Log.e(TAG, "can't start bundle " + bundle);

            return;
        }

        try {
            b.start(org.osgi.framework.Bundle.START_ACTIVATION_POLICY);
            Log.d(TAG, "bundle " + b.getSymbolicName() + "/" + b.getBundleId() + "/"
                    + b + " started");
            Toast.makeText(getApplicationContext(),"bundle " + b.getSymbolicName() + "/" + b.getBundleId() + "/"
                    + b + " started" , Toast.LENGTH_SHORT).show();


        } catch (BundleException be) {
            Log.e(TAG, be.toString());
        }

        try {
            bs.close();
        } catch (IOException e) {
            Log.e(TAG, e.toString());
        }
    }

    private void installBundle(String bundle) {
        Log.d(TAG, "installing bundle " + bundle);
        Toast.makeText(getApplicationContext(), "installing bundle", Toast.LENGTH_SHORT).show();

        InputStream bs;
        try {
            bs = getAssets().open("bundles/" + bundle);
        } catch (IOException e) {
            Log.e(TAG, e.toString());
            return;
        }

        try {
            mFramework.getBundleContext().installBundle(bundle, bs);
            Log.d(TAG, "bundle " + bundle + " installed");
            Toast.makeText(getApplicationContext(), "bundle " + bundle + " installed", Toast.LENGTH_SHORT).show();
        } catch (BundleException be) {
            Log.e(TAG, be.toString());
        }

        try {
            bs.close();
        } catch (IOException e) {
            Log.e(TAG, e.toString());
        }
    }

    private void setStartLevel(int startLevel) {
        ServiceReference sr = mFramework.getBundleContext()
            .getServiceReference(StartLevel.class.getName());
        if (sr != null) {
            StartLevel ss =
                (StartLevel)mFramework.getBundleContext().getService(sr);
            ss.setStartLevel(startLevel);
            mFramework.getBundleContext().ungetService(sr);
        } else {
            Log.e(TAG, "No start level service " + startLevel);
        }
    }

    private void setInitlevel(int level) {
        ServiceReference sr = mFramework.getBundleContext()
            .getServiceReference(StartLevel.class.getName());
        if (sr != null) {
            StartLevel ss =
                (StartLevel)mFramework.getBundleContext().getService(sr);
            ss.setInitialBundleStartLevel(level);
            mFramework.getBundleContext().ungetService(sr);
            Log.d(TAG, "initlevel " + level + " set");
        } else {
            Log.e(TAG, "No start level service " + level);
        }
    }


}

Как я сказал в моем предыдущем вопросе, согласно @ldx в это сообщение, «Патчи, которые я отправил для лучшей поддержки Android / Dalvik в Knopflerfish, были объединены, поэтому исправление и перекомпиляция KF больше не нужны:»

и поэтому я ничего не добавил, предполагая, что моего кода достаточно, как сейчас.

Когда я запускаю приложение для Android, я не получаю никаких ошибок, вместо этого я получаю положительные сообщения на моем LogCat о том, что мой пакет был установлен и запущен. Смотрите мой журнал ниже (я игнорирую первые 2 строки):

08-15 23:32:08.381: E/Trace(22044): error opening trace file: No such file or directory (2)
08-15 23:32:08.381: E/Trace(22044): error opening trace file: No such file or directory (2)
08-15 23:32:09.441: I/System.out(22044): here!
08-15 23:32:10.320: D/dalvikvm(22044): GC_CONCURRENT freed 172K, 10% free 2695K/2984K, paused 73ms+85ms, total 236ms
08-15 23:32:10.720: D/dalvikvm(22044): GC_CONCURRENT freed 324K, 14% free 2816K/3260K, paused 73ms+85ms, total 214ms
08-15 23:32:10.762: D/Zaid Log(22044): initlevel 1 set
08-15 23:32:10.762: D/Zaid Log(22044): installing bundle Bundle_AndroidAPI_1.0.0.201308160327.jar
08-15 23:32:11.060: D/Zaid Log(22044): bundle Bundle_AndroidAPI_1.0.0.201308160327.jar installed
08-15 23:32:11.080: D/Zaid Log(22044): starting bundle Bundle_AndroidAPI_1.0.0.201308160327.jar
08-15 23:32:11.090: D/Zaid Log(22044): bundle Bundle_AndroidAPI/4/BundleImpl[id=4] started
08-15 23:32:11.140: D/Zaid Log(22044): OSGi framework running, state: 32
08-15 23:32:12.012: D/gralloc_goldfish(22044): Emulator without GPU emulation detected.
08-15 23:32:52.941: I/Choreographer(22044): Skipped 47 frames!  The application may be doing too much work on its main thread.

Однако моя связка действительно не запускалась. Сообщение в методе запуска пакета появилось бы в LogCat, если бы мой пакет действительно запустился. Ниже приведен мой метод запуска пакета:

public void start(BundleContext bundleContext) throws Exception {
    Activator.context = bundleContext;


    System.out.println("Hello World. I am the OSGI_Android_Bundle!");


}

Обратите внимание, что мой пакет был дексифицирован, но все же он не запускается в моем приложении. Где я ошибся?

Обновление 1: я подумал, что мне следует поменять начало фреймворка на запуск пакета. Автор учебника сначала запускает пакеты, но я решил изменить это, потому что имеет смысл сначала запустить фреймворк, поэтому мой обновленный код имеет следующее:

setInitlevel(1);


// install/start other bundles...


setStartLevel(10);

try {
    mFramework.start();
} catch (BundleException be) {
    Log.e(TAG, be.toString());
    // framework start failed
}

Log.d(TAG, "OSGi framework running, state: " + mFramework.getState());


installBundle("Bundle-Test_1.0.0.201308160536.jar");
startBundle("Bundle-Test_1.0.0.201308160536.jar");

Теперь журнал не показывает мне, что мой пакет был запущен, как раньше, а скорее говорит мне, что среда выполнения не поддерживается. См. Обновленный LogCat ниже:

08-16 01:43:06.821: I/System.out(22737): here!
08-16 01:43:08.080: D/dalvikvm(22737): GC_CONCURRENT freed 191K, 11% free 2656K/2968K, paused 35ms+18ms, total 155ms
08-16 01:43:09.010: D/dalvikvm(22737): GC_CONCURRENT freed 276K, 13% free 2806K/3200K, paused 25ms+15ms, total 110ms
08-16 01:43:09.238: D/Zaid Log(22737): initlevel 1 set
08-16 01:43:09.300: D/Zaid Log(22737): OSGi framework running, state: 32
08-16 01:43:09.300: D/Zaid Log(22737): installing bundle Bundle-Test_1.0.0.201308160536.jar
08-16 01:43:09.530: D/Zaid Log(22737): bundle Bundle-Test_1.0.0.201308160536.jar installed
08-16 01:43:09.540: D/Zaid Log(22737): starting bundle Bundle-Test_1.0.0.201308160536.jar
08-16 01:43:09.550: E/Zaid Log(22737): org.osgi.framework.BundleException: Bundle#5, unable to resolve: Execution environment 'J2SE-1.5' is not supported
08-16 01:43:10.740: D/gralloc_goldfish(22737): Emulator without GPU emulation detected.

Обновление 2: я удалил эту строку из МАНИФЕСТА пакета после ответа @ Neil ниже,

Bundle-RequiredExecutionEnvironment: J2SE-1.5

но это привело к следующей ошибке:

 org.osgi.framework.BundleException: Bundle#6 start failed

Наверное, не стоило менять порядок запуска фреймворка и запуска бандла. Ниже мой обновленный LogCat.

08-16 17:02:33.855: E/Trace(28805): error opening trace file: No such file or directory (2)
08-16 17:02:35.111: I/System.out(28805): here!
08-16 17:02:35.591: D/dalvikvm(28805): GC_CONCURRENT freed 199K, 11% free 2679K/2996K, paused 76ms+93ms, total 246ms
08-16 17:02:36.153: D/dalvikvm(28805): GC_CONCURRENT freed 268K, 13% free 2814K/3200K, paused 77ms+141ms, total 297ms
08-16 17:02:36.451: D/Zaid Log(28805): initlevel 1 set
08-16 17:02:36.531: D/Zaid Log(28805): OSGi framework running, state: 32
08-16 17:02:36.531: D/Zaid Log(28805): installing bundle Bundle-Test_1.0.0.201308161323.jar
08-16 17:02:36.611: D/Zaid Log(28805): bundle Bundle-Test_1.0.0.201308161323.jar installed
08-16 17:02:36.631: D/Zaid Log(28805): starting bundle Bundle-Test_1.0.0.201308161323.jar
08-16 17:02:36.646: E/Zaid Log(28805): org.osgi.framework.BundleException: Bundle#6 start failed
08-16 17:02:36.646: E/Zaid Log(28805): More:Bundle#6 start failed
08-16 17:02:36.681: W/System.err(28805): org.osgi.framework.BundleException: Bundle#6 start failed
08-16 17:02:36.681: W/System.err(28805):    at org.knopflerfish.framework.BundleImpl.start0(BundleImpl.java:421)
08-16 17:02:36.681: W/System.err(28805):    at org.knopflerfish.framework.BundleThread.run(BundleThread.java:145)
08-16 17:02:36.681: W/System.err(28805): Caused by: java.lang.ClassNotFoundException: bundle_test.Activator
08-16 17:02:36.681: W/System.err(28805):    at org.knopflerfish.framework.BundleClassLoader.findClass(BundleClassLoader.java:218)
08-16 17:02:36.681: W/System.err(28805):    at org.knopflerfish.framework.BundleClassLoader.loadClass(BundleClassLoader.java:347)
08-16 17:02:36.681: W/System.err(28805):    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
08-16 17:02:36.694: W/System.err(28805):    at org.knopflerfish.framework.BundleImpl.start0(BundleImpl.java:382)
08-16 17:02:36.694: W/System.err(28805):    ... 1 more
08-16 17:02:37.282: I/Choreographer(28805): Skipped 34 frames!  The application may be doing too much work on its main thread.
08-16 17:02:37.551: D/gralloc_goldfish(28805): Emulator without GPU emulation detected.

person Traveling Salesman    schedule 15.08.2013    source источник


Ответы (1)


Я обращусь к ошибке только в вашем обновленном вопросе, поскольку кажется, что первая проблема была устранена (пожалуйста, подтвердите).

Ошибка означает, что в комплект входит следующее требование:

Bundle-RequiredExecutionEnvironment: J2SE-1.5

Другими словами, пакет утверждает, что для него требуется стандартная Java 5 или выше. Это известно как среда выполнения или EE. Обычно OSGi Framework определяет, на какой среде выполнения Java вы ее запустили, и публикует набор EE для соответствия этому. Например, если вы работаете на стандартной Java 5, фреймворк публикует EE с именами J2SE-1.5, J2SE-1.4 и т. Д. Вплоть до JRE-1.0, потому что Java 5 обратно совместима со всеми этими версиями. Однако, если у вас есть пакет, который утверждает Bundle-RequiredExecutionEnvironment: JavaSE-1.6, и вы пытаетесь запустить его на Java 5, он не сможет разрешиться.

Теперь вы пытаетесь запустить Android, который не является стандартной Java. Подобно стандартной Java, многие части стандартных JRE API были удалены. Поэтому пакет, для которого требуется стандартная Java 5, не должен разрешаться на Android, поскольку он может попытаться вызвать API, которых нет на этой платформе.

Вероятно, проще всего вам удалить заголовок Bundle-RequiredExecutionEnvironment из пакета, который не разрешается. Это позволит ему установить и разрешить, но, конечно, позже он может выйти из строя с ошибками времени выполнения, если ему действительно нужно вызывать методы из стандартной JRE, которых нет в Android.

person Neil Bartlett    schedule 16.08.2013
comment
спасибо @Neil, когда я удалил строку Bundle-RequiredExecutionEnvironment, на этот раз я получил эту ошибку: org.osgi.framework.BundleException: сбой при запуске Bundle # 6 - person Traveling Salesman; 16.08.2013
comment
Что касается первой проблемы, я не могу сказать, что она исправлена, но мой обновленный раздел - это попытка решить проблему: я не уверен, что это решение. Это просто предположение. - person Traveling Salesman; 16.08.2013
comment
При запуске пакета возникает исключение пакета, но трассировка стека не отображается. Вам нужно получить дополнительную информацию об этом исключении. - person Neil Bartlett; 16.08.2013
comment
Итак, ваш пакет объявляет активатор с именем bundle_test.Activator, но этот класс не существует в пакете. Вы действительно читаете эти сообщения об ошибках? - person Neil Bartlett; 16.08.2013
comment
конечно читаю ошибки. Но я уверен, что в моем комплекте есть такой класс. У меня есть пакет bundle_test, в котором есть Activator.java. Нил, если вы прочитаете мой вопрос перед любым обновлением, вы заметите, что я не получаю никаких ошибок, поэтому я начал считать, что мне не следует менять код, как я. - person Traveling Salesman; 16.08.2013
comment
Я сказал это в своем вопросе: действительно, связка не запускалась. Сообщение в методе запуска пакета было бы показано, если бы пакет действительно был запущен. Это сообщение - system.println (), которое должно появиться в LogCat, если пакет действительно запущен. - person Traveling Salesman; 17.08.2013
comment
Я не уверен, о какой отладке вы говорите, но код полон сообщений журнала для печати в случае сбоя. я буду работать над этим больше - person Traveling Salesman; 17.08.2013
comment
Я перешел на Apache Felix на android, и он работал как MAGIC !! Слава богу, очень рекомендую Феликса на Android. Кроме того, после этих трех недель кошмаров я твердо уверен, что код в этом руководстве для встраивания Knopflerfish на Android НЕ работает. nilvec.com/ - person Traveling Salesman; 17.08.2013