Load resource (layout) from another apk dynamicall

2020-06-04 12:46发布

I managed to pull the layouts, and i add it to my viewflipper, however, there it is loaded as blank.

The code is,

Resources packageResources;
Context packageContext;
try
{   
    packageResources = pm.getResourcesForApplication(packageName);
    packageContext = this.createPackageContext(packageName,     Context.CONTEXT_INCLUDE_CODE + Context.CONTEXT_IGNORE_SECURITY);                
 }
 catch(NameNotFoundException excep)
 {
     // the package does not exist. move on to see if another exists.
 }

 Class layoutClass;
 try
 {
       // using reflection to get the layout class inside the R class of the package
       layoutClass = packageContext.getClassLoader().loadClass(packageName + ".R$layout");
 }
 catch (ClassNotFoundException excep1)
 {
     // Less chances that class won't be there.
 }

 for( Field layoutID : layoutClass.getFields() )
 {
    try
    {
        int id = layoutID.getInt(layoutClass);
        XmlResourceParser xmlResourceLayout = packageResources.getLayout(id);

        View v = new View(this, Xml.asAttributeSet(xmlResourceLayout));

        this.viewFlipper.addView(v);                 
    }
    catch (Exception excep)
   {
    continue;
   }
}

I get no errors, and i debugged and checked. The layout IDs are correct. However, in my viewFlipper its just blank. No warnings or errors i can find.

3条回答
我欲成王,谁敢阻挡
2楼-- · 2020-06-04 13:38

Finally got it.... Its actually simple !!!!

Here is what i did...

  1. In the target apk, there is only resources and layouts with no application or activity code. I created a class,

    public final class ViewExtractor
    {
        private static final int NUMBER_OF_LAYOUTS = 5;
    
        public static View[] getAllViews(Context context)
        {
            View[] result = new View[ViewExtractor.NUMBER_OF_LAYOUTS];
    
            result[0] = View.inflate(context, R.layout.layout_0, null);
            result[1] = View.inflate(context, R.layout.layout_1, null);
            result[2] = View.inflate(context, R.layout.layout_2, null);
            result[3] = View.inflate(context, R.layout.layout_3, null);
            result[4] = View.inflate(context, R.layout.layout_4, null);
    
            return result;
        }
     }
    

Then in my current application, I modified my earlier code. The modification takes place once package has been verified to exist.

        // If the package exists then get the resources within it.
        // Use the method in the class to get the views.
        Class<?> viewExtractor;
        try
        {
            viewExtractor = packageContext.getClassLoader().loadClass(packageName + ".ViewExtractor");
        }
        catch (ClassNotFoundException excep)
        {
            continue;
        }

        View[] resultViews;
        try
        {
            Method m = viewExtractor.getDeclaredMethod("getAllViews", Context.class);

            resultViews= (View[])m.invoke(null, new Object[]{packageContext});

            for( View v : resultViews)
            {
                this.viewFlipper.addView(v);
            }
        }
        catch (Exception excep)
        {
            excep.printStackTrace();
        }   
查看更多
我只想做你的唯一
3楼-- · 2020-06-04 13:46

You are not inflating a layout. You are creating an empty View and adding it to your ViewFlipper.

查看更多
霸刀☆藐视天下
4楼-- · 2020-06-04 13:48

I am currently doing this. It only works if a know the packageName of activity or fragment from the .apk that should provide the layout hierarchy (I call this foreign context). And you need to know the name of the layout you want to inflate (e.g. R.layout.mylayout -> "mylayout")

Context c = createPackageContext(foreignPackageName,
    Context.CONTEXT_INCLUDE_CODE|Context.CONTEXT_IGNORE_SECURITY); //create foreign context
int resId = c.getResources.getIdentifier(mylayoutName,"layout",foreignPackageName); 
LayoutInflater myInflater = LayoutInflater.from(c); //Inflater for foreign context
View myLayout = myInflater.inflate(resId,null,false); //do not attach to a root view
查看更多
登录 后发表回答