0

I'm trying to get a View from APKs that implement a particular interface, but my app keeps crushing. What is it that I might be getting wrong? The following is my approach:

Here is the interface that gets passed around and gets implemented by other apps:

package ca.rev.libs.core;

import android.content.Context;
import android.view.View;

public interface MyViewCreator {
    View createMyView(Context context);
}

An app that implements the interface and provides a View:

package ca.rev.service.core.rev_views;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;

public class TestView implements MyViewCreator {
    @Override
    public View createMyView(Context context) {
        LayoutInflater revInfl = LayoutInflater.from(context);
        View toolBarItemsLL = revInfl.inflate(R.layout.layout, null, false);

        Button button = (Button) toolBarItemsLL.findViewById(R.id.testButton);
        return button;
    }
}

In the main app, I crawl through all the apps installed, and check for the Dex files that have the interface's implementation:

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
PackageManager pm = getPackageManager();

for (ApplicationInfo app : pm.getInstalledApplications(0)) {
    String dexPath = app.sourceDir;
    String libraryPath = null;

    DexClassLoader dexClassLoader = null;
    try {
        dexClassLoader = new DexClassLoader(dexPath, File.createTempFile("opt", "dex", this.getCacheDir()).getPath(), libraryPath, ClassLoader.getSystemClassLoader());
    } catch (IOException e) {
        e.printStackTrace();
    }

    DexFile dexFile;
    Button myView;
    try {
        dexFile = DexFile.loadDex(dexPath, File.createTempFile("opt", "dex", this.getCacheDir()).getPath(), 0);

        for (Enumeration<String> classNames = dexFile.entries(); classNames.hasMoreElements(); ) {
            String className = classNames.nextElement();
            Class myClass = dexClassLoader.loadClass(className);
            if (myClass.isAssignableFrom(MyViewCreator.class)) {
                MyViewCreator creator = (MyViewCreator) myClass.getConstructor().newInstance();
                myView = (Button) creator.createMyView(this);
                // add myView wherever you want
                navigationView.addView(myView);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

UPDATE

Thanks to @JesusFreke, I managed to get the stack-trace:

 --------- beginning of crash
08-03 22:57:38.067 4864-4864/ca.rev.revcore E/AndroidRuntime: FATAL EXCEPTION: main
                                                              Process: ca.rev.revcore, PID: 4864
                                                              java.lang.IllegalAccessError: Class android.support.v4.app.NotificationCompat$BuilderExtender extended by class android.support.v7.app.NotificationCompat$IceCreamSandwichExtender is inaccessible (declaration of 'android.support.v7.app.NotificationCompat$IceCreamSandwichExtender' appears in /system/app/PrebuiltBugle/PrebuiltBugle.apk)
                                                                  at dalvik.system.DexFile.defineClassNative(Native Method)
                                                                  at dalvik.system.DexFile.defineClass(DexFile.java:296)
                                                                  at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:289)
                                                                  at dalvik.system.DexPathList.findClass(DexPathList.java:418)
                                                                  at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:54)
                                                                  at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
                                                                  at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
                                                                  at ca.rev.revcore.MainActivity.onCreate(MainActivity.java:108)
                                                                  at android.app.Activity.performCreate(Activity.java:6679)
                                                                  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                                  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
                                                                  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
                                                                  at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                                  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
                                                                  at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                  at android.os.Looper.loop(Looper.java:154)
                                                                  at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

at ca.rev.revcore.MainActivity.onCreate(MainActivity.java:108) is at Class myClass = dexClassLoader.loadClass(className);

Program-Me-Rev
  • 6,184
  • 18
  • 58
  • 142
  • 5
    and the stacktrace is? – Marcin Orlowski Aug 03 '17 at 19:11
  • No errors are thrown – Program-Me-Rev Aug 03 '17 at 19:17
  • 2
    Then your app is not crashing. If your app is crashing, there will be a stacktrace in LogCat. – CommonsWare Aug 03 '17 at 19:31
  • 1
    Why are you calling e.printStackTrace()? You should be logging to logcat instead. – JesusFreke Aug 03 '17 at 19:53
  • Thanks to JesusFreke I've managed to get Stack-trace printed. I, however, still haven't got a clue on how to get it working. @CommonsWare – Program-Me-Rev Aug 03 '17 at 20:06
  • Well, I will be surprised if you get it working for anything that's practical. That being said, perhaps your hosting app does not have the identical set of dependencies (e.g., `support-compat`) as does the app that is supplying your DEX. – CommonsWare Aug 03 '17 at 20:27
  • Hi @CommonsWare. This question is an offspring of a problem I have, [How to add a View to an app from another app](https://stackoverflow.com/questions/45407532/how-to-add-a-view-to-an-app-from-another-app). Would you mind looking at it and possibly advising on the suggested approach by lelloman, [in an answer HERE](https://stackoverflow.com/a/45454679/3663765)? I would be really grateful. Thank you. – Program-Me-Rev Aug 03 '17 at 20:50
  • As he states, "I wouldn't recommend to do this for a commercial project". – CommonsWare Aug 03 '17 at 20:58

0 Answers0