android settings源代码分析(2)

来源:互联网 发布:golang.org上不去 编辑:程序博客网 时间:2024/04/30 08:50

       通过前一篇文章  Android settings源代码分析(1)  分析,大概知道了Settings主页面是如何显示,今天主要分析“应用”这一块google是如何实现的。

 

应用对应的fragment为:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <span style="font-size:14px;"> <!-- Application Settings -->  
  2.     <header  
  3.         android:fragment="com.android.settings.applications.ManageApplications"  
  4.         android:icon="@drawable/ic_settings_applications"  
  5.         android:title="@string/applications_settings"  
  6.         android:id="@+id/application_settings" /></span>  

因此需要查看ManageApplications如何实现。

ManageApplications所在路径为:

kikat_4.4_CTS\packages\apps\Settings\src\com\android\settings\applications

 

从Application UI可以看出,fragment主要是一个tab,以及每一个tab下都会显示和存储相关的信息,比如RAM,SDCARD和内部存储空间的大小。接下来分析tab如何实现以及这些存储信息如何获取。

 

查看ManageApplications的onCreateView函数,可以看到:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. View rootView = mInflater.inflate(R.layout.manage_applications_content,  
  2.                container, false);  

这里会使用manage_applications_content.xml,我们查看xml的内容:

[html] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!--  
  3. /*  
  4. **  
  5. ** Copyright 2012, The Android Open Source Project  
  6. **  
  7. ** Licensed under the Apache License, Version 2.0 (the "License");  
  8. ** you may not use this file except in compliance with the License.  
  9. ** You may obtain a copy of the License at  
  10. **  
  11. **     http://www.apache.org/licenses/LICENSE-2.0  
  12. **  
  13. ** Unless required by applicable law or agreed to in writing, software  
  14. ** distributed under the License is distributed on an "AS IS" BASIS,  
  15. ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  16. ** See the License for the specific language governing permissions and  
  17. ** limitations under the License.  
  18. */  
  19. -->  
  20.   
  21. <LinearLayout  
  22.     xmlns:android="http://schemas.android.com/apk/res/android"  
  23.     android:layout_width="match_parent"  
  24.     android:layout_height="match_parent"  
  25.     android:orientation="vertical">  
  26.   
  27.     <android.support.v4.view.ViewPager  
  28.             android:id="@+id/pager"  
  29.             android:layout_width="match_parent"  
  30.             android:layout_height="match_parent"  
  31.             android:layout_weight="1">  
  32.         <android.support.v4.view.PagerTabStrip  
  33.                 android:id="@+id/tabs"  
  34.                 android:layout_width="match_parent"  
  35.                 android:layout_height="wrap_content"  
  36.                 android:layout_gravity="top"  
  37.                 android:textAppearance="@style/TextAppearance.PagerTabs"  
  38.                 android:padding="0dp">  
  39.         </android.support.v4.view.PagerTabStrip>  
  40.     </android.support.v4.view.ViewPager>  
  41.   
  42. </LinearLayout>  

application fragment的布局本质就是一个ViewPager,因此可以支持左右滑动,每一页对应一个tab的显示。

 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. MyPagerAdapter adapter = new MyPagerAdapter();  
  2.        mViewPager.setAdapter(adapter);  
  3.        mViewPager.setOnPageChangeListener(adapter);  

这里会设置一个adapter,用来填充ViewPager里的内容。

 

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class MyPagerAdapter extends PagerAdapter  
  2.            implements ViewPager.OnPageChangeListener {  
  3.        int mCurPos = 0;  
  4.   
  5.        @Override  
  6.        public int getCount() {  
  7.            return mNumTabs;  
  8.        }  
  9.          
  10.        @Override  
  11.        public Object instantiateItem(ViewGroup container, int position) {  
  12.            TabInfo tab = mTabs.get(position);  
  13.            View root = tab.build(mInflater, mContentContainer, mRootView);  
  14.            container.addView(root);  
  15.            root.setTag(R.id.name, tab);  
  16.            return root;  
  17.        }  
  18.   
  19.        @Override  
  20.        public void destroyItem(ViewGroup container, int position, Object object) {  
  21.            container.removeView((View)object);  
  22.        }  
  23.   
  24.        @Override  
  25.        public boolean isViewFromObject(View view, Object object) {  
  26.            return view == object;  
  27.        }  
  28.   
  29.        @Override  
  30.        public int getItemPosition(Object object) {  
  31.            return super.getItemPosition(object);  
  32.            //return ((TabInfo)((View)object).getTag(R.id.name)).mListType;  
  33.        }  
  34.   
  35.        @Override  
  36.        public CharSequence getPageTitle(int position) {  
  37.            return mTabs.get(position).mLabel;  
  38.        }  
  39.   
  40.        @Override  
  41.        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {  
  42.        }  
  43.   
  44.        @Override  
  45.        public void onPageSelected(int position) {  
  46.            mCurPos = position;  
  47.        }  
  48.   
  49.        @Override  
  50.        public void onPageScrollStateChanged(int state) {  
  51.            if (state == ViewPager.SCROLL_STATE_IDLE) {  
  52.                updateCurrentTab(mCurPos);  
  53.            }  
  54.        }  
  55.    }  

此adapter中instantiateItem函数会初始化每一个子项,即每一页:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. TabInfo tab = mTabs.get(position);  
  2. View root = tab.build(mInflater, mContentContainer, mRootView);  

因此需要查看TabInfo中的build函数。

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public View build(LayoutInflater inflater, ViewGroup contentParent, View contentChild) {  
  2.             if (mRootView != null) {  
  3.                 return mRootView;  
  4.             }  
  5.   
  6.             mInflater = inflater;  
  7.             mRootView = inflater.inflate(mListType == LIST_TYPE_RUNNING  
  8.                     ? R.layout.manage_applications_running  
  9.                     : R.layout.manage_applications_apps, null);  
  10.             mLoadingContainer = mRootView.findViewById(R.id.loading_container);  
  11.             mLoadingContainer.setVisibility(View.VISIBLE);  
  12.             mListContainer = mRootView.findViewById(R.id.list_container);  
  13.             if (mListContainer != null) {  
  14.                 // Create adapter and list view here  
  15.                 View emptyView = mListContainer.findViewById(com.android.internal.R.id.empty);  
  16.                 ListView lv = (ListView) mListContainer.findViewById(android.R.id.list);  
  17.                 if (emptyView != null) {  
  18.                     lv.setEmptyView(emptyView);  
  19.                 }  
  20.                 lv.setOnItemClickListener(this);  
  21.                 lv.setSaveEnabled(true);  
  22.                 lv.setItemsCanFocus(true);  
  23.                 lv.setTextFilterEnabled(true);  
  24.                 mListView = lv;  
  25.                 mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter);  
  26.                 mListView.setAdapter(mApplications);  
  27.                 mListView.setRecyclerListener(mApplications);  
  28.                 mColorBar = (LinearColorBar)mListContainer.findViewById(R.id.storage_color_bar);  
  29.                 mStorageChartLabel = (TextView)mListContainer.findViewById(R.id.storageChartLabel);  
  30.                 mUsedStorageText = (TextView)mListContainer.findViewById(R.id.usedStorageText);  
  31.                 mFreeStorageText = (TextView)mListContainer.findViewById(R.id.freeStorageText);  
  32.                 Utils.prepareCustomPreferencesList(contentParent, contentChild, mListView, false);  
  33.                 if (mFilter == FILTER_APPS_SDCARD) {  
  34.                     mStorageChartLabel.setText(mOwner.getActivity().getText(  
  35.                             R.string.sd_card_storage));  
  36.                 } else {  
  37.                     mStorageChartLabel.setText(mOwner.getActivity().getText(  
  38.                             R.string.internal_storage));  
  39.                 }  
  40.                 applyCurrentStorage();  
  41.             }  
  42.             mRunningProcessesView = (RunningProcessesView)mRootView.findViewById(  
  43.                     R.id.running_processes);  
  44.             if (mRunningProcessesView != null) {  
  45.                 mRunningProcessesView.doCreate(mSavedInstanceState);  
  46.             }  
  47.   
  48.             return mRootView;  
  49.         }  

此函数中用来显示tab中listview和tab下对应的storage显示信息。

 

对于tab中listView的填充:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public View getView(int position, View convertView, ViewGroup parent) {  
  2.             // A ViewHolder keeps references to children views to avoid unnecessary calls  
  3.             // to findViewById() on each row.  
  4.             AppViewHolder holder = AppViewHolder.createOrRecycle(mTab.mInflater, convertView);  
  5.             convertView = holder.rootView;  
  6.   
  7.             // Bind the data efficiently with the holder  
  8.             ApplicationsState.AppEntry entry = mEntries.get(position);  
  9.             synchronized (entry) {  
  10.                 holder.entry = entry;  
  11.                 if (entry.label != null) {  
  12.                     holder.appName.setText(entry.label);  
  13.                 }  
  14.                 mState.ensureIcon(entry);  
  15.                 if (entry.icon != null) {  
  16.                     holder.appIcon.setImageDrawable(entry.icon);  
  17.                 }  
  18.                 holder.updateSizeText(mTab.mInvalidSizeStr, mWhichSize);  
  19.                 if ((entry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {  
  20.                     holder.disabled.setVisibility(View.VISIBLE);  
  21.                     holder.disabled.setText(R.string.not_installed);  
  22.                 } else if (!entry.info.enabled) {  
  23.                     holder.disabled.setVisibility(View.VISIBLE);  
  24.                     holder.disabled.setText(R.string.disabled);  
  25.                 } else {  
  26.                     holder.disabled.setVisibility(View.GONE);  
  27.                 }  
  28.                 if (mFilterMode == FILTER_APPS_SDCARD) {  
  29.                     holder.checkBox.setVisibility(View.VISIBLE);  
  30.                     holder.checkBox.setChecked((entry.info.flags  
  31.                             & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);  
  32.                 } else {  
  33.                     holder.checkBox.setVisibility(View.GONE);  
  34.                 }  
  35.             }  
  36.             mActive.remove(convertView);  
  37.             mActive.add(convertView);  
  38.             return convertView;  
  39.         }  

 

对于storage的获取,需要使用到IMediaContainerService,绑定此service的地方:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. getActivity().bindService(containerIntent, mContainerConnection, Context.BIND_AUTO_CREATE);  


连接此service,每一个tab都会得到此service实例,通过此实例获取storage相关信息

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. private volatile IMediaContainerService mContainerService;  
  2.   
  3.    private final ServiceConnection mContainerConnection = new ServiceConnection() {  
  4.        @Override  
  5.        public void onServiceConnected(ComponentName name, IBinder service) {  
  6.            mContainerService = IMediaContainerService.Stub.asInterface(service);  
  7.            for (int i=0; i<mTabs.size(); i++) {  
  8.                mTabs.get(i).setContainerService(mContainerService);  
  9.            }  
  10.        }  
  11.   
  12.        @Override  
  13.        public void onServiceDisconnected(ComponentName name) {  
  14.            mContainerService = null;  
  15.        }  
  16.    };  


获取storage信息代码如下:

获取SD卡:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (mFilter == FILTER_APPS_SDCARD) {  
  2.                 if (mContainerService != null) {  
  3.                     try {  
  4.                         final long[] stats = mContainerService.getFileSystemStats(  
  5.                                 Environment.getExternalStorageDirectory().getPath());  
  6.                         mTotalStorage = stats[0];  
  7.                         mFreeStorage = stats[1];  
  8.                     } catch (RemoteException e) {  
  9.                         Log.w(TAG, "Problem in container service", e);  
  10.                     }  
  11.                 }  
  12.   
  13.                 if (mApplications != null) {  
  14.                     final int N = mApplications.getCount();  
  15.                     for (int i=0; i<N; i++) {  
  16.                         ApplicationsState.AppEntry ae = mApplications.getAppEntry(i);  
  17.                         mAppStorage += ae.externalCodeSize + ae.externalDataSize  
  18.                                 + ae.externalCacheSize;  
  19.                     }  
  20.                 }  


获取本地存储空间信息:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. if (mContainerService != null) {  
  2.                    try {  
  3.                        final long[] stats = mContainerService.getFileSystemStats(  
  4.                                Environment.getDataDirectory().getPath());  
  5.                        mTotalStorage = stats[0];  
  6.                        mFreeStorage = stats[1];  
  7.                    } catch (RemoteException e) {  
  8.                        Log.w(TAG, "Problem in container service", e);  
  9.                    }  
  10.                }  

最后显示到UI上去:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void applyCurrentStorage() {  
  2.     // If view hierarchy is not yet created, no views to update.  
  3.     if (mRootView == null) {  
  4.         return;  
  5.     }  
  6.     if (mTotalStorage > 0) {  
  7.         BidiFormatter bidiFormatter = BidiFormatter.getInstance();  
  8.         mColorBar.setRatios((mTotalStorage-mFreeStorage-mAppStorage)/(float)mTotalStorage,  
  9.                 mAppStorage/(float)mTotalStorage, mFreeStorage/(float)mTotalStorage);  
  10.         long usedStorage = mTotalStorage - mFreeStorage;  
  11.         if (mLastUsedStorage != usedStorage) {  
  12.             mLastUsedStorage = usedStorage;  
  13.             String sizeStr = bidiFormatter.unicodeWrap(  
  14.                     Formatter.formatShortFileSize(mOwner.getActivity(), usedStorage));  
  15.             mUsedStorageText.setText(mOwner.getActivity().getResources().getString(  
  16.                     R.string.service_foreground_processes, sizeStr));  
  17.         }  
  18.         if (mLastFreeStorage != mFreeStorage) {  
  19.             mLastFreeStorage = mFreeStorage;  
  20.             String sizeStr = bidiFormatter.unicodeWrap(  
  21.                     Formatter.formatShortFileSize(mOwner.getActivity(), mFreeStorage));  
  22.             mFreeStorageText.setText(mOwner.getActivity().getResources().getString(  
  23.                     R.string.service_background_processes, sizeStr));  
  24.         }  
  25.     } else {  
  26.         mColorBar.setRatios(000);  
  27.         if (mLastUsedStorage != -1) {  
  28.             mLastUsedStorage = -1;  
  29.             mUsedStorageText.setText("");  
  30.         }  
  31.         if (mLastFreeStorage != -1) {  
  32.             mLastFreeStorage = -1;  
  33.             mFreeStorageText.setText("");  
  34.         }  
  35.     }  
  36. }  


当点击listView子项时,会跳转到详细列表页面:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public void onItemClick(TabInfo tab, AdapterView<?> parent, View view, int position,  
  2.           long id) {  
  3.       if (tab.mApplications != null && tab.mApplications.getCount() > position) {  
  4.           ApplicationsState.AppEntry entry = tab.mApplications.getAppEntry(position);  
  5.           mCurrentPkgName = entry.info.packageName;  
  6.           startApplicationDetailsActivity();  
  7.       }  
  8.   }  
[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. // utility method used to start sub activity  
  2.   private void startApplicationDetailsActivity() {  
  3.       // start new fragment to display extended information  
  4.       Bundle args = new Bundle();  
  5.       args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mCurrentPkgName);  
  6.   
  7.       PreferenceActivity pa = (PreferenceActivity)getActivity();  
  8.       pa.startPreferencePanel(InstalledAppDetails.class.getName(), args,  
  9.               R.string.application_info_label, nullthis, INSTALLED_APP_DETAILS);  
  10.   }  

查看详细列表对应的类:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public class InstalledAppDetails extends Fragment  
  2.         implements View.OnClickListener, CompoundButton.OnCheckedChangeListener,  
  3.         ApplicationsState.Callbacks  

即也是一个fragment。

 

详细列表界面相关button操作代码如下:

[java] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. public void onClick(View v) {  
  2.        String packageName = mAppEntry.info.packageName;  
  3.        if(v == mUninstallButton) {  
  4.            if (mUpdatedSysApp) {  
  5.                showDialogInner(DLG_FACTORY_RESET, 0);  
  6.            } else {  
  7.                if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {  
  8.                    if (mAppEntry.info.enabled) {  
  9.                        showDialogInner(DLG_DISABLE, 0);  
  10.                    } else {  
  11.                        new DisableChanger(this, mAppEntry.info,  
  12.                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)  
  13.                        .execute((Object)null);  
  14.                    }  
  15.                } else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {  
  16.                    uninstallPkg(packageName, truefalse);  
  17.                } else {  
  18.                    uninstallPkg(packageName, falsefalse);  
  19.                }  
  20.            }  
  21.        } else if(v == mSpecialDisableButton) {  
  22.            showDialogInner(DLG_SPECIAL_DISABLE, 0);  
  23.        } else if(v == mActivitiesButton) {  
  24.            mPm.clearPackagePreferredActivities(packageName);  
  25.            try {  
  26.                mUsbManager.clearDefaults(packageName, UserHandle.myUserId());  
  27.            } catch (RemoteException e) {  
  28.                Log.e(TAG, "mUsbManager.clearDefaults", e);  
  29.            }  
  30.            mAppWidgetManager.setBindAppWidgetPermission(packageName, false);  
  31.            TextView autoLaunchTitleView =  
  32.                    (TextView) mRootView.findViewById(R.id.auto_launch_title);  
  33.            TextView autoLaunchView = (TextView) mRootView.findViewById(R.id.auto_launch);  
  34.            resetLaunchDefaultsUi(autoLaunchTitleView, autoLaunchView);  
  35.        } else if(v == mClearDataButton) {  
  36.            if (mAppEntry.info.manageSpaceActivityName != null) {  
  37.                if (!Utils.isMonkeyRunning()) {  
  38.                    Intent intent = new Intent(Intent.ACTION_DEFAULT);  
  39.                    intent.setClassName(mAppEntry.info.packageName,  
  40.                            mAppEntry.info.manageSpaceActivityName);  
  41.                    startActivityForResult(intent, REQUEST_MANAGE_SPACE);  
  42.                }  
  43.            } else {  
  44.                showDialogInner(DLG_CLEAR_DATA, 0);  
  45.            }  
  46.        } else if (v == mClearCacheButton) {  
  47.            // Lazy initialization of observer  
  48.            if (mClearCacheObserver == null) {  
  49.                mClearCacheObserver = new ClearCacheObserver();  
  50.            }  
  51.            mPm.deleteApplicationCacheFiles(packageName, mClearCacheObserver);  
  52.        } else if (v == mForceStopButton) {  
  53.            showDialogInner(DLG_FORCE_STOP, 0);  
  54.            //forceStopPackage(mAppInfo.packageName);  
  55.        } else if (v == mMoveAppButton) {  
  56.            if (mPackageMoveObserver == null) {  
  57.                mPackageMoveObserver = new PackageMoveObserver();  
  58.            }  
  59.            int moveFlags = (mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?  
  60.                    PackageManager.MOVE_INTERNAL : PackageManager.MOVE_EXTERNAL_MEDIA;  
  61.            mMoveInProgress = true;  
  62.            refreshButtons();  
  63.            mPm.movePackage(mAppEntry.info.packageName, mPackageMoveObserver, moveFlags);  
  64.        }  
  65.    }  


 原文地址: http://blog.csdn.net/zhudaozhuan/article/details/40619371

0 0
原创粉丝点击