4

I've a String Input that contains an Layout.xml with String Fromat.

 // String that contains the Layout.xml :

 String concat ;

 // Create the XmlPullParser from the String format

 XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

 factory.setNamespaceAware(true);

 XmlPullParser xpp = factory.newPullParser();
 xpp.setInput( new StringReader (concat) ); 

 // create le The LayoutInflater 

 LayoutInflater inflater =         (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

 View myView = inflater.inflate(xpp, null);

I've got this bug:

03-12 08:23:12.876: W/System.err(937): android.view.InflateException: START_TAG http://schemas.android.com/apk/res/android}android:orientation='vertical' {http://schemas.android.com/apk/res/android}android:layout_width='fill_parent' {http://schemas.android.com/apk/res/android}android:layout_height='fill_parent'>@1:226 in java.io.StringReader@44f50508: Error inflating class

Help please ?

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
ghost rider3
  • 448
  • 1
  • 5
  • 17

1 Answers1

3

It seems that the Inflater only accepts XmlBlock.

I have written an method to do this, you can referer to the project site: https://github.com/liudongmiao/preference-fragment-compat/blob/master/src/me/piebridge/android/preference/PreferenceFragment.java#L202

The main codes like this:

// byte[] data = ... 
// bytes of compiled xml (unzip the apk, get the bytes from res/layout*/*.xml)

// XmlBlock block = new XmlBlock(data);
Class<?> clazz = Class.forName("android.content.res.XmlBlock");
Constructor<?> constructor = clazz.getDeclaredConstructor(byte[].class);
constructor.setAccessible(true);
Object block = constructor.newInstance(data);

// XmlPullParser parser = block.newParser();
Method method = clazz.getDeclaredMethod("newParser");
method.setAccessible(true);
XmlPullParser parser = method.invoke(block);
liudongmiao
  • 455
  • 4
  • 7
  • I'm trying to use your `PreferenceFragment.getParser(String xml)` method in your repo. I see that you pass `public static final String LAYOUT` into your `getParser()` method and inflate `LAYOUT` as a `View`. How did you generate `String LAYOUT`? I'm guessing that you encoded the compiled code of your layout somehow but I want to know the details so that I can encode my own layout into the same format as you did for `LAYOUT`...? – Wess Jul 27 '18 at 13:59
  • 1
    @Wess I have written in the comments. Read again. – liudongmiao Jul 28 '18 at 13:29
  • Thanks @liudongmiao. I have followed your steps but I always get `NullPointerException: Attempt to invoke interface method 'java.lang.String org.xmlpull.v1.XmlPullParser.getPositionDescription()' on a null object reference`. My steps: unzip apk -> copy compiled layout to res/raw in project -> read layout file contents to String at runtime -> convert String to `byte[] data` and pass into `Object block = constructor.newInstance(data);`. Not sure what I'm doing wrong? Any help will be appreciated. – Wess Jul 30 '18 at 12:05
  • I implement your code but in runtime, I get InvocationTargetException. in Log one line upper than exception I see one line about XmlBlock: ```Bad XML block: header size 28024 or total size 1702240364 is larger than data size 2757``` – SamiAzar Oct 10 '18 at 12:10
  • @liudongmiao - It would be nice if you answer users' questions from above comments. I found your approach interesting, but I haven't tried it. Is this approach still valid and working? Does a binary code from pre-compiled XML files contain some pre-assigned IDs for each view? If so, that could cause conflicts with existing IDs, if such layout is inflated into another view. Could you please update your answers with more information regarding binary data, use and limitation of your approach? Thank you! – Ωmega Jun 07 '19 at 20:54