Load resource (layout) from another apk dynamically

I managed to pull out the layouts and I will add it to my viewflipper, however there it is loaded as empty.

Code,

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. Layout IDs are correct. However, in my opinion, this is just empty. I cannot find any warnings or errors.

+4
source share
3 answers

Finally got it .... Its really just !!!!

Here is what I did ...

  • The target apk has only resources and layouts without an 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 changed my previous code. Modification is performed as soon as the package has been checked 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(); } 
+4
source

You do not inflate the layout. You create an empty View and add it to your ViewFlipper .

+2
source

I am currently doing this. It only works if you know the name of the activity package or the fragment from .apk that should provide the layout hierarchy (I call this external context). And you need to know the name of the layout you want to inflate (for example, 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 
+1
source

Source: https://habr.com/ru/post/1443943/


All Articles