TranslationsOnDemand: ViewsResearch

File ViewsResearch, 10.8 KB (added by vsantos, 2 years ago)
Line 
1Views in the codebase that use text:
2        TextView
3        Button
4        CheckBox
5        EditText
6
7Other views that use text:
8https://github.com/Aptoide/aptoide-client-v8/blob/master/v8engine/src/main/res/layout/displayable_recommended_store.xml
9https://github.com/Aptoide/aptoide-client-v8/blob/master/v8engine/src/main/res/layout/fragment_addressbook.xml
10https://github.com/Aptoide/aptoide-client-v8/blob/master/v8engine/src/main/res/layout/timeline_follows_info.xml
11        android.support.v7.widget.AppCompatButton (7 uses)
12
13https://github.com/Aptoide/aptoide-client-v8/blob/master/v8engine/src/main/res/layout/row_adult_switch.xml
14        android.support.v7.widget.SwitchCompat (2 uses)
15
16Views class hierarchy
17        View <- TextView
18        View <- TextView <- Button
19        View <- TextView <- Button <- Compound Button <- CheckBox
20        View <- TextView <- EditText
21        View <- TextView <- Button <- AppCompatButton
22        View <- TextView <- Button <- Compound Button <- SwitchCompat
23
24Main objective: Modify how TextView receives its text. If this works, every other view subclass will also work as planned.
25
26Analysing TextView: Find out how TextView defines the attribute mText, which saves the object's text.
27
28TextView has 4 constructores, each having from 1 to 4 arguments and each calls the next constructor that has one argument until the 4th constructor, where occurs the object initialization
29
30(Line 712) mText = ""
31After which getResources() is called, which is a method from the superclass View that saves an attribute Resources mResourcse
32and in its initialization mResources is either null or equal to context.getResources().
33
34In other words, it calls the resources from the context that creates the view.
35
36This resources are used to create an object (CompatibilityInfo) and get a value (getDisplayMetrics().density, a float)
37
38Lines 728 to 744 are initializations.
39
40Line 746 does something important to our objective: It creates an immutable variable Resources.Theme theme = context.getTheme(),
41which is used afterwards to convert the argument AttributeSet attrs into values.
42
43(Lines 747 to 753 are comments)
44
45Using theme, the next statement is made:
46(Line 754) TypedArray a = theme.obtainStyledAttributes(attrs,
47                com.android.internal.R.styleable.TextViewAppearance, defStyleAttr, defStyleRes);
48
49obtainStyledAttributes receives (from android docs):
50
51        set                     AttributeSet: The base set of attribute values. May be null.
52        attrs                   int: The desired attributes to be retrieved. These attribute IDs must be sorted in ascending order.
53        defStyleAttr    int: An attribute in the current theme that contains a reference to a style resource
54                                        that supplies defaults values for the TypedArray. Can be 0 to not look for defaults.
55        defStyleRes     int: A resource identifier of a style resource that supplies default values for the TypedArray,
56                                        used only if defStyleAttr is 0 or can not be found in the theme. Can be 0 to not look for defaults.
57
58Also in the docs is described how the final value of each attribute is determined:
59
60    1. Any attribute values in the given AttributeSet.
61    2. The style resource specified in the AttributeSet (named "style").
62    3. The default style specified by defStyleAttr and defStyleRes
63    4. The base values in this theme.
64
65        Each of these inputs is considered in-order, with the first listed taking precedence over the following ones. In other words,
66        if in the AttributeSet you have supplied <Button textColor="#ff000000">, then the button's text will always be black, regardless of what is specified in any of the styles.
67
68In this invocation it's intended to receive the attribute values that belong to TextViewAppearance.
69This attributes can be found in https://developer.android.com/reference/android/R.styleable.html#TextViewAppearance
70(Extra info: List of standart attributes that can be used in a theme - https://developer.android.com/reference/android/R.styleable.html#Theme)
71
72Lines 756 to 763 are initializations related to the upcoming code
73Lines 764 to 837 there is a for loop that has a switch case which receives the attributes from the TypedArray a and applies them on the TextView object.
74
75Lines 839 to 859 are initializations
76Line 861 theme.obtainStyledAttributes is called again:
77
78a = theme.obtainStyledAttributes(
79                    attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes);
80
81The difference this time is that the intent is to receive the attributes belonging to TextView (https://developer.android.com/reference/android/R.styleable.html#TextView)
82
83Now this is the important part.
84Lines 864 to 1216 there is another for loop that has a switch case which receives the attributes from the TypedArray a and applies them on the TextView object.
85Inside the switch case, Lines 1005-1007
86
87(1005)            case com.android.internal.R.styleable.TextView_text:
88(1006)                text = a.getText(attr);
89(1007)                break;
90
91This text variable is declared in line 856 (Initialization zone before the 2nd theme.obtainStyledAttributes) and it's a CharSequence initialized with "".
92
93Lines 1218 to 1440 a BufferType is created and the code deals with other object attributes
94
95Then line 1442: setText(text, bufferType). It's in this line that the object has its text defined (mText = text)
96
97After this, from line 1443 to the end (1487) there are irrelevant statements to the matter at hand.
98
99Analising what we can influence, we have Resources (from getResources), Theme (from context.getTheme()) and the arguments the class receives.
100
101From the resources, CompatibilityInfo is obtained which does: (from it's source code docs)
102        "CompatibilityInfo class keeps the information about compatibility mode that the application is running under."
103This class doesn't seem to be relevant for what we pretend and it's not part of the API so we can't alter it's behaviour.
104This object is used in three statements:
105
106(715) final CompatibilityInfo compat = res.getCompatibilityInfo();
107(719) mTextPaint.setCompatibilityScaling(compat.applicationScale);
108(722) mHighlightPaint.setCompatibilityScaling(compat.applicationScale);
109
110This doesn't affect our objective.
111
112The other value obtained from Resources is only used in one statement:
113
114(718) mTextPaint.density = res.getDisplayMetrics().density;
115
116This also doesn't affect our objective and we can conclude from the Resources class we can't influence what we want.
117
118The next candidate is also the most relevant: context.getTheme() (Line 746). Since this object is used to obtain the text, modifying this object would be a good solution.
119File Context.java:
120
121(564)   @ViewDebug.ExportedProperty(deepExport = true)
122(565)   public abstract Resources.Theme getTheme();
123
124It looks like it's the classes that inherit context that implements this.
125We could see the implementation, but first let's analyse Resources.Theme, which is the kind of object returned by the method:
126
127File Resources.java:
128
129(1353) public final class Theme {
130
131The Resources.Theme class cannot be modified. However, this class has an attribute ResourcesImpl.ThemeImpl mThemeImpl and every method from this class apply the same method on the attribute.
132This attribute is private but Resources.Theme has a method setImpl(ResourcesImpl.ThemeImpl impl) which does exactly what it implies.
133
134The TextView class calls theme.obtainStyledAttributes(set, attrs, defStyleAttr, defStyleRes) and Resources.Theme has the following code:
135
136(1493)        public TypedArray obtainStyledAttributes(AttributeSet set,
137(1494)                @StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
138(1495)            return mThemeImpl.obtainStyledAttributes(this, set, attrs, defStyleAttr, defStyleRes);
139(1496)        }
140
141At first, it looks like we can't modify Resources.Theme but can extend ResourcesImpl.ThemeImpl and after making context.getTheme().setImpl(our own impl).
142However, the problem with this is that ResourcesImpl, just like the CompatibilityInfo class, also doesn't exist in the API therefore we can't create our own implementation.
143
144The last possibility is to follow the path this implementation does and see if we can alter something from there.
145(1495) return mThemeImpl.obtainStyledAttributes(this, set, attrs, defStyleAttr, defStyleRes);
146
147File ResourcesImpl.java;
148
149(1105)  @NonNull
150        TypedArray obtainStyledAttributes(@NonNull Resources.Theme wrapper,
151                AttributeSet set,
152                @StyleableRes int[] attrs,
153                @AttrRes int defStyleAttr,
154                @StyleRes int defStyleRes) {
155            synchronized (mKey) {
156                final int len = attrs.length;
157(1113)          final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
158
159                // XXX note that for now we only work with compiled XML files.
160                // To support generic XML files we will need to manually parse
161                // out the attributes from the XML file (applying type information
162                // contained in the resources and such).
163(1119)          final XmlBlock.Parser parser = (XmlBlock.Parser) set;
164(1120)          AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
165                        parser != null ? parser.mParseState : 0,
166                        attrs, array.mData, array.mIndices);
167                array.mTheme = wrapper;
168                array.mXml = parser;
169
170                return array;
171            }
172(1128)  }
173
174Line 1113 seems interesting because it calls getResources which we can modify, however, analysing the obtain method:
175File TypedArray.java:
176
177
178(46)    static TypedArray obtain(Resources res, int len) {
179                final TypedArray attrs = res.mTypedArrayPool.acquire();
180                if (attrs != null) {
181                    attrs.mLength = len;
182                    attrs.mRecycled = false;
183
184                    // Reset the assets, which may have changed due to configuration changes
185                    // or further resource loading.
186                    attrs.mAssets = res.getAssets();
187
188                    final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
189                    if (attrs.mData.length >= fullLen) {
190                        return attrs;
191                    }
192
193                    attrs.mData = new int[fullLen];
194                    attrs.mIndices = new int[1 + len];
195                    return attrs;
196                }
197
198                return new TypedArray(res,
199                        new int[len*AssetManager.STYLE_NUM_ENTRIES],
200                        new int[1+len], len);
201(69)    }
202
203Essencially, the method creates an empty TypedAray with the pretended size.
204
205Going back to obtainStyledAttributes method from ResourcesImpl.java
206
207(1119)  final XmlBlock.Parser parser = (XmlBlock.Parser) set;
208
209This casts the received AttributeSet set into a XmlBlock object, which doesn't exist in the API and the source code docs say:
210"Wrapper around a compiled XML file."
211
212The next line, 1120, uses the AssetManager class, which is final.
213Since the rest of the obtainStyledAttributesCode doesn't do anything special, what's left is to see the AssetManager.applyStyle method. However, this is a native method, so we can't analyse.
214
215Here ends the TextView constructor code analysis. The only thing we can alter are the arguments it receives.