Body
I. Objectives
Note that the called APK has been installed in the Android system.
Previous Article: Android app development enhancement series (4) -- Android dynamic loading (on) -- loading classes in APK Not Installed
Call another installed APK string, color value, image, layout file resource, and Activity from the current APK.
II. Implementation
2.1 called projects
Basically, the previous project is followed, and the called strings and images are added. Therefore, the project will not be pasted here, and a download link will be provided later.
2.2 call the project code
Public class TestAActivity extends Activity {
/** TestB package name */
Private static final String PACKAGE_TEST_ B = "com. nmbb. B ";
@ Override
Public void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. main );
Try {
Final Context ctxTestB = getTestBContext ();
Resources res = ctxTestB. getResources ();
// Obtain the string
String hello = res. getString (getId (res, "string", "hello "));
(TextView) findViewById (R. id. testb_string). setText (hello );
// Obtain the image Drawable
Drawable drawable = res
. GetDrawable (getId (res, "drawable", "testb "));
(ImageView) findViewById (R. id. testb_drawable ))
. SetImageDrawable (drawable );
// Obtain the color value
Int color = res. getColor (getId (res, "color", "white "));
(TextView) findViewById (R. id. testb_color ))
. SetBackgroundColor (color );
// Obtain the layout File
View view = getView (ctxTestB, getId (res, "layout", "main "));
LinearLayout layout = (LinearLayout) findViewById (R. id. testb_layout );
Layout. addView (view );
// Start TestB Activity
FindViewById (R. id. testb_activity). setOnClickListener (
New OnClickListener (){
@ Override
Public void onClick (View v ){
Try {
@ SuppressWarnings ("rawtypes ")
Class cls = ctxTestB. getClassLoader ()
. LoadClass ("com. nmbb. TestBActivity ");
StartActivity (new Intent (ctxTestB, cls ));
} Catch (ClassNotFoundException e ){
E. printStackTrace ();
}
}
});
} Catch (NameNotFoundException e ){
E. printStackTrace ();
}
}
/**
* Obtain the resource ID.
*
* @ Param testb
* @ Param resName
* @ Param resType
* Layout, drawable, string
* @ Return
*/
Private int getId (Resources testb, String resType, String resName ){
Return testb. getIdentifier (resName, resType, PACKAGE_TEST_ B );
}
/**
* Retrieving views
*
* @ Param ctx
* @ Param id
* @ Return
*/
Public View getView (Context ctx, int id ){
Return (LayoutInflater) ctx
. GetSystemService (Context. LAYOUT_INFLATER_SERVICE). inflate (id,
Null );
}
/**
* Obtain the Context of TestB.
*
* @ Return
* @ Throws NameNotFoundException
*/
Private Context getTestBContext () throws NameNotFoundException {
Return createPackageContext (PACKAGE_TEST_ B,
Context. CONTEXT_IGNORE_SECURITY | Context. CONTEXT_INCLUDE_CODE );
}
Code Description:
Basic principle: Get the Context of the called application through package, and get the corresponding resources and classes through Context.
Note:
A ). many articles on the Internet use the R. id to call the resources of the called Project. This is incorrect. Even if no error is reported, it is coincidentally because R is automatically generated and the IDs of the two applications cannot be matched, therefore, you need to search by getIdentifier.
B). Context. CONTEXT_INCLUDE_CODE generally does not need to be added. If layout contains a custom control, it must be added. Note that this custom control cannot be obtained by force conversion in the current project because it is in two ClassLoader and cannot be converted.
C). You do not need to upload userid to obtain these resources.
Iii. Summary
Compared with the previous article, it is more convenient to obtain resources, but there are also some restrictions:
3.1 The called apk must have been installed to reduce the user experience.
3.2 style cannot be set dynamically, even if it can be obtained.
3.3 According to the current research results, if a custom control is used for the called Project, it will be subject to a large limit and cannot be forcibly converted for use (as mentioned earlier ).
3.4 because a project is mixed with two contexts, it is easy to cause confusion and resource retrieval is also troublesome. Here we will share with you the method of hiding two apk IDs in batches. You can obtain the R classes of the two apk through reflection, get each id and value at a time, and match each id and value by name one by one, in this way, you do not need to manually input strings.
@ SuppressWarnings ("rawtypes ")
Private static HashMap <String, Integer> getR (Class cls) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
HashMap <String, Integer> result = new HashMap <String, Integer> ();
For (Class r: cls. getClasses ()){
If (! R. getName (). endsWith ("styleable ")){
Object owner = r. newInstance ();
For (Field field: r. getFields ()){
Result. put (field. getName (), field. getInt (owner ));
}
}
}
Return result;
}
4. Download
Test2012-4-19.zip: http://www.bkjia.com/uploadfile/2012/0429/20120429100345551.zip
End
If it is a large area of skin replacement, it is still complicated, and this method is not very convenient, which is why there are very few skin replacements on the market, there is also a very simple skin replacement. Another solution that I have come up with over the past few days has not been put into practice yet. I will share it with you if it works. Thank you for your discussion :)
From farmer's uncle