Class resolved by unexpected DEX, how to avoid duplicate imports

旧城冷巷雨未停 提交于 2019-12-25 06:59:21

问题


I'm trying to build an plugin-system which is importing Fragments from other apks as described here.

Eclipse keeps telling me:

12-01 15:17:18.609: W/dalvikvm(23425): Class resolved by unexpected DEX: Lde/anthropotec/activityapp/firstplugin/UI;(0x42901520):0x57d93000 ref [Lde/anthropotec/activityapp/api/PluginAPI;] Lde/anthropotec/activityapp/api/PluginAPI;(0x428eb2b8):0x527e1000

(Lde/anthropotec/activityapp/firstplugin/UI; had used a different Lde/anthropotec/activityapp/api/PluginAPI; during pre-verification)

Which isn't a suprise, as I'm importing my PluginAPI-libary in both, the Host and the Plugin. As far as I understand, Eclipse seems to be afraid, that these libaries aren't identical. Is there a way to tell Eclipse to not import the libary, if it's already there in the other apk? Or is there any other way to go around this. Please tell me if you need more information. Here's my source:

The Host:

package de.anthropotec.activityapp.host;

import java.io.File;

import dalvik.system.DexClassLoader;
import de.anthropotec.activityapp.api.PluginAPI;
import de.anthropotec.activtiyapp.host.R;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;

public class MainActivtiy extends Activity{

    @Override
    public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    try {
        Class<?> requiredClass = null;
        final ApplicationInfo info = getPackageManager().getApplicationInfo("de.anthropotec.activityapp.firstplugin",0);
        final String apkPath = info.sourceDir;
        final File dexTemp = getDir("temp_folder", 0);
        final String fullName = "de.anthropotec.activityapp.firstplugin.UI";
        boolean isLoaded = true;

        // Check if class loaded
        try {
            requiredClass = Class.forName(fullName);
        } catch(ClassNotFoundException e) {
            isLoaded = false;
        }

        if (!isLoaded) {
            final DexClassLoader classLoader = new DexClassLoader(apkPath, dexTemp.getAbsolutePath(), null, getApplicationContext().getClassLoader());
            requiredClass = classLoader.loadClass(fullName);
        }

        if (null != requiredClass) {
            // Try to cast to required interface to ensure that it's can be cast
            final PluginAPI holder = PluginAPI.class.cast(requiredClass.newInstance());

            if (null != holder) {
                final Fragment fragment = holder.getFragment();

                if (null != fragment) {
                    final FragmentTransaction trans = getFragmentManager().beginTransaction();

                    trans.add(R.id.pluginPlace, fragment, "MyFragment").commit();
                }
            }
        }
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    }
}  

The PluginApi:

package de.anthropotec.activityapp.api;

import android.app.Fragment;


public interface PluginAPI {

    public Fragment getFragment();
}

And the Plugin-Fragment itself:

package de.anthropotec.activityapp.firstplugin;

import de.anthropotec.activityapp.api.PluginAPI;
import android.app.Fragment;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.view.View;
import android.view.LayoutInflater;
import android.view.ViewGroup;

public class UI extends Fragment implements PluginAPI{

     @Override
        public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
            // Note that loading of resources is not the same as usual, because it loaded actually from another apk
            final XmlResourceParser parser = container.getContext().getPackageManager().getXml("de.anthropotec.testplugin", R.layout.ui, null);
            return inflater.inflate(parser, container, false);
        }

        @Override
        public Fragment getFragment() {
            return this;
        }

}

Each of the above as it's own Project (PluginAPI as libary). The question isn't quite new (e.g. here), but the already given answers advice to remove on of the imports, what doesn't seem to be a option in my case, as I need the API on both sides (Plugin and Host).


回答1:


Ahww, sometimes it's so obvious. Just import the libary as extern libary in Properties->Java Build Path -> add external jar for the Plugin, and everything works just fine. Gnarf!



来源:https://stackoverflow.com/questions/27230851/class-resolved-by-unexpected-dex-how-to-avoid-duplicate-imports

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!