动态加载来自另一个apk的资源(布局)

时间:2012-11-04 13:13:52

标签: android layout dynamic resources

我设法拉出布局,然后将其添加到我的viewflipper中,然而,它被加载为空白。

代码是,

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;
   }
}

我没有错误,我调试和检查。布局ID是正确的。但是,在我的viewFlipper中它只是空白。没有我能找到的警告或错误。

3 个答案:

答案 0 :(得分:4)

终于搞定了......它实际上很简单!!!!

这就是我做的......

  1. 在目标apk中,只有资源和布局没有应用程序或活动代码。我创建了一个类,

    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;
        }
     }
    
  2. 然后在我当前的应用程序中,我修改了我的早期代码。一旦验证包存在,就会进行修改。

            // 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();
            }   
    

答案 1 :(得分:2)

您没有给布局充气。您正在创建一个空View并将其添加到ViewFlipper

答案 2 :(得分:1)

我目前正在这样做。只有当知道应该提供布局层次结构的.apk中的活动或片段的packageName时,它才有效(我称之为外部上下文)。你需要知道你要膨胀的布局的名称(例如R.layout.mylayout - &gt;“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