Android SDK dynamically loads APK (Fragment or Activity implementation) and androidapk

Source: Internet
Author: User

Android SDK dynamically loads APK (Fragment or Activity implementation) and androidapk

Respect originality: Http://blog.csdn.net/yuanzeyao/article/details/38565345

Recently, due to the project being too large, compilation and translation failed (Android seems to have a limit on the number of methods in an application), so I have been wondering whether to dynamically load the APK of some modules without installation, by searching for information and help from netizens on the Internet, we finally realized the dynamic loading of APK. There are many articles about the dynamic loading of APK on the Internet, however, I think this guy wrote well. I basically used this solution and added my own elements. This guy implemented it through Activity. I made some modifications and implemented dynamic loading through Fragment. I personally think it is easier to use Fragmnet, because Fragment does not need to be considered for its lifecycle.

Article: http://blog.csdn.net/singwhatiwanna/article/details/22597587
Http://blog.csdn.net/singwhatiwanna/article/details/23387079
You must read these two articles before reading this article, because I have borrowed the ideas of this article.


The first problem is that to run any program in java, a class must be added to the memory through the Class Loader. When we add the Activity to the memory through a class loader, in fact, this Activity is a common class and has no concept of lifecycle. In Android systems, the lifecycle of an Activity is controlled by ActivityManager, if we load the Activity dynamically, ActivityManager does not know the existence of the Activity, so we must handle the lifecycle of the Activity. As for the second problem, in Android, resources are obtained through Context, while the Dynamically Loaded APK does not have Context, so we cannot get resources as we used. The methods recommended in the previous two articles can solve the above two problems well, so the dynamic loading of APK is realized.
Let me first describe the idea of implementing dynamic loading in Daniel's blog:
Create a ProxyActivity by name. It is a proxy Activity. We call any Activity by calling ProxyActivity, I only need to input the path to dynamically load the apk and the class name to be dynamically loaded. For example, after an Activity is loaded, read all lifecycle functions of the Activity and functions such as onActivityResult through the reflection mechanism, and save them in a list. In onCreate of ProxyActivity, The onCreate of the Dynamically Loaded Activity is called through reflection, because ProxyActivity is a normal Activity and its lifecycle is normal, it is okay to call the dynamic loading Activity lifecycle function in the Life Cycle Function of ProxyActivity, therefore, the lifecycle of a Dynamically Loaded Activity also exists. At the same time, it is a proxy, so the proxy is a little thorough, simply transfer all the logic in the Dynamically Loaded Activity to ProxyActivity. This requires that the loaded Activity has a ProxyActivity reference, which allows all Dynamically Loaded activities to inherit a BaseActivity. This BaseActivity has a setProxy method used to set ProxyActivity. Therefore, not any APK can be dynamically loaded. Generally, only the self-compiled apk can be dynamically loaded. It is unrealistic to dynamically load other users' apk.
After reading the above ideas, is the logic of the dynamically loaded Activity moved to ProxyActivity?

The solution to the resource access problem is to create two functions in ProxyActivity that are reloaded.
Public abstract AssetManager getAssets ();
Public abstract Resources getResources ();
As to why we can solve the problem of resources, I recommend several articles for you to learn:
My other article: http://blog.csdn.net/yuanzeyao/article/details/12955459
An article on Android resource loading mechanism: http://blog.csdn.net/singwhatiwanna/article/details/24532419
 
Well, the above is the dynamic loading of apk through Activity. Let's take a look at how I use Fragment to achieve dynamic loading. If you are familiar with Fragment, you should know that, fragment is equivalent to a View with a lifecycle. its lifecycle is managed by the lifecycle of the Activity in which it is located, even if we add a Fragment to the memory through the class loader, it is no different from the Fragment we used previously. As long as we add this Fragment to ProxyActivity, ProxyActivity automatically manages the lifecycle of this Fragment. So we don't need to worry about the Fragment lifecycle. Let's take a look at the code implementation below:

1. BaseFragment. java

Public class BaseFragment extends Fragment implements IConstant {private static final String TAG = "BaseFragment"; protected String mDexPath; @ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); Bundle bundle = this. getArguments (); // the path for dynamically loading the apk: mDexPath = bundle. getString (DEX_PATH);} // start another Fragment protected void replaceFragmentByProxy (String name) {if (mDexPath = null) return; // PROXY_VIEW_ACTION is the action Intent intent = new Intent (PROXY_VIEW_ACTION) of ProxyActivity; // pass the apk path intent. putExtra (DEX_PATH, mDexPath); // whether to start Fragment or Fragment. Here, Fragment intent is started. putExtra (START_TYPE, TYPE_FRAGMENT); // specifies the intent Class Name of the fragment to be loaded. putExtra (CLASS_NAME, name); this. startActivity (intent );}}

All Fragment to be dynamically loaded must inherit this BaseFragment. Each time you start a Fragment, you only need to pass the apk path.
The following is a MyFragment I wrote, which is used to load network images using BitmapFun. Here we only load and display images without considering anything else. If you want to learn more about the usage of BitmapFun, please refer to my other article:
Http://blog.csdn.net/yuanzeyao/article/details/38355719

Public class MyFragment extends BaseFragment {private static final String TAG = "MyFragment"; private static final String IMAGE_CACHE_DIR = "thumbs"; private ImageFetcher mImageFetcher; private GridView mGridView; private Context context Context; private Button btn; @ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); ImageCacheParams cacheParams = new ImageCacheParams (getActivity (), IMAGE_CACHE_DIR); cacheParams. round (0.25f); // Set memory cache to 25% of app memory // The ImageFetcher takes care of loading images into our ImageView children asynchronously mImageFetcher = new ImageFetcher (getActivity (), 200); mImageFetcher. setLoadingImage (R. drawable. empty_photo); mImageFetcher. addImageCache (getActivity (). getsuppfrfragmentmanager (), cacheParams);} @ Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {// R can be directly used here. layout. fragment Resources mResources = this. getActivity (). getResources (); return inflater. inflate (mResources. getIdentifier ("fragment", "layout", "com. dl. client "), container, false) ;}@ Override public void onViewCreated (View view, Bundle savedInstanceState) {super. onViewCreated (view, savedInstanceState); mGridView = (GridView) view. findViewById (R. id. gridView); btn = (Button) view. findViewById (R. id. btn_fragment); btn. setOnClickListener (new View. onClickListener () {@ Override public void onClick (View arg0) {// dynamically load another Fragment replaceFragmentByProxy ("com. dl. client. tempFragment ") ;}}); context = this. getActivity (); mGridView. setAdapter (new BaseAdapter () {@ Override public View getView (int position, View contentView, ViewGroup arg2) {ImageView mImg; if (contentView = null) {contentView = LayoutInflater. from (context ). inflate (R. layout. item, null);} mImg = (ImageView) contentView. findViewById (R. id. img_11); // mImg. setImageResource (R. drawable. empty_photo); mImageFetcher. loadImage (Images. imageThumbUrls [position], mImg); return contentView ;}@ Override public long getItemId (int arg0) {return 0 ;}@ Override public Object getItem (int arg0) {return Images. imageThumbUrls [arg0];} @ Override public int getCount () {return Images. imageThumbUrls. length ;}});}}

Let's take a look at the effect of this application:


Note that the Dynamically Loaded apk cannot contain the same jar package as the host application. Otherwise, an error is returned...


Android wants to implement a click list and a piece of article (a fragment is called in an activity),

You need to control the layout of ListView and Fragment. Otherwise, there will indeed be overlaps. Fragment is a lightweight Activity that is introduced to facilitate the use of different la s in the same Activity, you don't need to use Fragment for this requirement. You need to modify the layout again if you want to use it.

The fragment of the new Android feature, in which how to jump to other unrelated activities through the button

GetActivity () can be used in fragment.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.