生活随笔
收集整理的這篇文章主要介紹了
android settings源代码分析(2)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? ? ? ?通過前一篇文章 ?Android?settings源代碼分析(1)? 分析,大概知道了Settings主頁面是如何顯示,今天主要分析“應用”這一塊google是如何實現的。
?
應用對應的fragment為:
[html]?view plaincopy
<span?style="font-size:14px;">??? ????<header?? ????????android:fragment="com.android.settings.applications.ManageApplications"?? ????????android:icon="@drawable/ic_settings_applications"?? ????????android:title="@string/applications_settings"?? ????????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 plaincopy
View?rootView?=?mInflater.inflate(R.layout.manage_applications_content,?? ???????????????container,?false);??
這里會使用manage_applications_content.xml,我們查看xml的內容:
[html]?view plaincopy
<?xml?version="1.0"?encoding="utf-8"?>?? <!--?? /*?? **?? **?Copyright?2012,?The?Android?Open?Source?Project?? **?? **?Licensed?under?the?Apache?License,?Version?2.0?(the?"License");?? **?you?may?not?use?this?file?except?in?compliance?with?the?License.?? **?You?may?obtain?a?copy?of?the?License?at?? **?? **?????http://www.apache.org/licenses/LICENSE-2.0?? **?? **?Unless?required?by?applicable?law?or?agreed?to?in?writing,?software?? **?distributed?under?the?License?is?distributed?on?an?"AS?IS"?BASIS,?? **?WITHOUT?WARRANTIES?OR?CONDITIONS?OF?ANY?KIND,?either?express?or?implied.?? **?See?the?License?for?the?specific?language?governing?permissions?and?? **?limitations?under?the?License.?? */?? -->?? ?? <LinearLayout?? ????xmlns:android="http://schemas.android.com/apk/res/android"?? ????android:layout_width="match_parent"?? ????android:layout_height="match_parent"?? ????android:orientation="vertical">?? ?? ????<android.support.v4.view.ViewPager?? ????????????android:id="@+id/pager"?? ????????????android:layout_width="match_parent"?? ????????????android:layout_height="match_parent"?? ????????????android:layout_weight="1">?? ????????<android.support.v4.view.PagerTabStrip?? ????????????????android:id="@+id/tabs"?? ????????????????android:layout_width="match_parent"?? ????????????????android:layout_height="wrap_content"?? ????????????????android:layout_gravity="top"?? ????????????????android:textAppearance="@style/TextAppearance.PagerTabs"?? ????????????????android:padding="0dp">?? ????????</android.support.v4.view.PagerTabStrip>?? ????</android.support.v4.view.ViewPager>?? ?? </LinearLayout>??
application fragment的布局本質就是一個ViewPager,因此可以支持左右滑動,每一頁對應一個tab的顯示。
?
[java]?view plaincopy
MyPagerAdapter?adapter?=?new?MyPagerAdapter();?? ???????mViewPager.setAdapter(adapter);?? ???????mViewPager.setOnPageChangeListener(adapter);??
這里會設置一個adapter,用來填充ViewPager里的內容。
?
[java]?view plaincopy
class?MyPagerAdapter?extends?PagerAdapter?? ???????????implements?ViewPager.OnPageChangeListener?{?? ???????int?mCurPos?=?0;?? ?? ???????@Override?? ???????public?int?getCount()?{?? ???????????return?mNumTabs;?? ???????}?? ????????? ???????@Override?? ???????public?Object?instantiateItem(ViewGroup?container,?int?position)?{?? ???????????TabInfo?tab?=?mTabs.get(position);?? ???????????View?root?=?tab.build(mInflater,?mContentContainer,?mRootView);?? ???????????container.addView(root);?? ???????????root.setTag(R.id.name,?tab);?? ???????????return?root;?? ???????}?? ?? ???????@Override?? ???????public?void?destroyItem(ViewGroup?container,?int?position,?Object?object)?{?? ???????????container.removeView((View)object);?? ???????}?? ?? ???????@Override?? ???????public?boolean?isViewFromObject(View?view,?Object?object)?{?? ???????????return?view?==?object;?? ???????}?? ?? ???????@Override?? ???????public?int?getItemPosition(Object?object)?{?? ???????????return?super.getItemPosition(object);?? ????????????? ???????}?? ?? ???????@Override?? ???????public?CharSequence?getPageTitle(int?position)?{?? ???????????return?mTabs.get(position).mLabel;?? ???????}?? ?? ???????@Override?? ???????public?void?onPageScrolled(int?position,?float?positionOffset,?int?positionOffsetPixels)?{?? ???????}?? ?? ???????@Override?? ???????public?void?onPageSelected(int?position)?{?? ???????????mCurPos?=?position;?? ???????}?? ?? ???????@Override?? ???????public?void?onPageScrollStateChanged(int?state)?{?? ???????????if?(state?==?ViewPager.SCROLL_STATE_IDLE)?{?? ???????????????updateCurrentTab(mCurPos);?? ???????????}?? ???????}?? ???}??
此adapter中instantiateItem函數會初始化每一個子項,即每一頁:
[java]?view plaincopy
TabInfo?tab?=?mTabs.get(position);?? View?root?=?tab.build(mInflater,?mContentContainer,?mRootView);??
因此需要查看TabInfo中的build函數。
[java]?view plaincopy
public?View?build(LayoutInflater?inflater,?ViewGroup?contentParent,?View?contentChild)?{?? ????????????if?(mRootView?!=?null)?{?? ????????????????return?mRootView;?? ????????????}?? ?? ????????????mInflater?=?inflater;?? ????????????mRootView?=?inflater.inflate(mListType?==?LIST_TYPE_RUNNING?? ??????????????????????R.layout.manage_applications_running?? ????????????????????:?R.layout.manage_applications_apps,?null);?? ????????????mLoadingContainer?=?mRootView.findViewById(R.id.loading_container);?? ????????????mLoadingContainer.setVisibility(View.VISIBLE);?? ????????????mListContainer?=?mRootView.findViewById(R.id.list_container);?? ????????????if?(mListContainer?!=?null)?{?? ?????????????????? ????????????????View?emptyView?=?mListContainer.findViewById(com.android.internal.R.id.empty);?? ????????????????ListView?lv?=?(ListView)?mListContainer.findViewById(android.R.id.list);?? ????????????????if?(emptyView?!=?null)?{?? ????????????????????lv.setEmptyView(emptyView);?? ????????????????}?? ????????????????lv.setOnItemClickListener(this);?? ????????????????lv.setSaveEnabled(true);?? ????????????????lv.setItemsCanFocus(true);?? ????????????????lv.setTextFilterEnabled(true);?? ????????????????mListView?=?lv;?? ????????????????mApplications?=?new?ApplicationsAdapter(mApplicationsState,?this,?mFilter);?? ????????????????mListView.setAdapter(mApplications);?? ????????????????mListView.setRecyclerListener(mApplications);?? ????????????????mColorBar?=?(LinearColorBar)mListContainer.findViewById(R.id.storage_color_bar);?? ????????????????mStorageChartLabel?=?(TextView)mListContainer.findViewById(R.id.storageChartLabel);?? ????????????????mUsedStorageText?=?(TextView)mListContainer.findViewById(R.id.usedStorageText);?? ????????????????mFreeStorageText?=?(TextView)mListContainer.findViewById(R.id.freeStorageText);?? ????????????????Utils.prepareCustomPreferencesList(contentParent,?contentChild,?mListView,?false);?? ????????????????if?(mFilter?==?FILTER_APPS_SDCARD)?{?? ????????????????????mStorageChartLabel.setText(mOwner.getActivity().getText(?? ????????????????????????????R.string.sd_card_storage));?? ????????????????}?else?{?? ????????????????????mStorageChartLabel.setText(mOwner.getActivity().getText(?? ????????????????????????????R.string.internal_storage));?? ????????????????}?? ????????????????applyCurrentStorage();?? ????????????}?? ????????????mRunningProcessesView?=?(RunningProcessesView)mRootView.findViewById(?? ????????????????????R.id.running_processes);?? ????????????if?(mRunningProcessesView?!=?null)?{?? ????????????????mRunningProcessesView.doCreate(mSavedInstanceState);?? ????????????}?? ?? ????????????return?mRootView;?? ????????}??
此函數中用來顯示tab中listview和tab下對應的storage顯示信息。
?
對于tab中listView的填充:
[java]?view plaincopy
public?View?getView(int?position,?View?convertView,?ViewGroup?parent)?{?? ?????????????? ?????????????? ????????????AppViewHolder?holder?=?AppViewHolder.createOrRecycle(mTab.mInflater,?convertView);?? ????????????convertView?=?holder.rootView;?? ?? ?????????????? ????????????ApplicationsState.AppEntry?entry?=?mEntries.get(position);?? ????????????synchronized?(entry)?{?? ????????????????holder.entry?=?entry;?? ????????????????if?(entry.label?!=?null)?{?? ????????????????????holder.appName.setText(entry.label);?? ????????????????}?? ????????????????mState.ensureIcon(entry);?? ????????????????if?(entry.icon?!=?null)?{?? ????????????????????holder.appIcon.setImageDrawable(entry.icon);?? ????????????????}?? ????????????????holder.updateSizeText(mTab.mInvalidSizeStr,?mWhichSize);?? ????????????????if?((entry.info.flags&ApplicationInfo.FLAG_INSTALLED)?==?0)?{?? ????????????????????holder.disabled.setVisibility(View.VISIBLE);?? ????????????????????holder.disabled.setText(R.string.not_installed);?? ????????????????}?else?if?(!entry.info.enabled)?{?? ????????????????????holder.disabled.setVisibility(View.VISIBLE);?? ????????????????????holder.disabled.setText(R.string.disabled);?? ????????????????}?else?{?? ????????????????????holder.disabled.setVisibility(View.GONE);?? ????????????????}?? ????????????????if?(mFilterMode?==?FILTER_APPS_SDCARD)?{?? ????????????????????holder.checkBox.setVisibility(View.VISIBLE);?? ????????????????????holder.checkBox.setChecked((entry.info.flags?? ????????????????????????????&?ApplicationInfo.FLAG_EXTERNAL_STORAGE)?!=?0);?? ????????????????}?else?{?? ????????????????????holder.checkBox.setVisibility(View.GONE);?? ????????????????}?? ????????????}?? ????????????mActive.remove(convertView);?? ????????????mActive.add(convertView);?? ????????????return?convertView;?? ????????}??
?
對于storage的獲取,需要使用到IMediaContainerService,綁定此service的地方:
[java]?view plaincopy
getActivity().bindService(containerIntent,?mContainerConnection,?Context.BIND_AUTO_CREATE);??
連接此service,每一個tab都會得到此service實例,通過此實例獲取storage相關信息
[java]?view plaincopy
private?volatile?IMediaContainerService?mContainerService;?? ?? ???private?final?ServiceConnection?mContainerConnection?=?new?ServiceConnection()?{?? ???????@Override?? ???????public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{?? ???????????mContainerService?=?IMediaContainerService.Stub.asInterface(service);?? ???????????for?(int?i=0;?i<mTabs.size();?i++)?{?? ???????????????mTabs.get(i).setContainerService(mContainerService);?? ???????????}?? ???????}?? ?? ???????@Override?? ???????public?void?onServiceDisconnected(ComponentName?name)?{?? ???????????mContainerService?=?null;?? ???????}?? ???};??
獲取storage信息代碼如下:
獲取SD卡:
[java]?view plaincopy
if?(mFilter?==?FILTER_APPS_SDCARD)?{?? ????????????????if?(mContainerService?!=?null)?{?? ????????????????????try?{?? ????????????????????????final?long[]?stats?=?mContainerService.getFileSystemStats(?? ????????????????????????????????Environment.getExternalStorageDirectory().getPath());?? ????????????????????????mTotalStorage?=?stats[0];?? ????????????????????????mFreeStorage?=?stats[1];?? ????????????????????}?catch?(RemoteException?e)?{?? ????????????????????????Log.w(TAG,?"Problem?in?container?service",?e);?? ????????????????????}?? ????????????????}?? ?? ????????????????if?(mApplications?!=?null)?{?? ????????????????????final?int?N?=?mApplications.getCount();?? ????????????????????for?(int?i=0;?i<N;?i++)?{?? ????????????????????????ApplicationsState.AppEntry?ae?=?mApplications.getAppEntry(i);?? ????????????????????????mAppStorage?+=?ae.externalCodeSize?+?ae.externalDataSize?? ????????????????????????????????+?ae.externalCacheSize;?? ????????????????????}?? ????????????????}??
獲取本地存儲空間信息:
[java]?view plaincopy
if?(mContainerService?!=?null)?{?? ???????????????????try?{?? ???????????????????????final?long[]?stats?=?mContainerService.getFileSystemStats(?? ???????????????????????????????Environment.getDataDirectory().getPath());?? ???????????????????????mTotalStorage?=?stats[0];?? ???????????????????????mFreeStorage?=?stats[1];?? ???????????????????}?catch?(RemoteException?e)?{?? ???????????????????????Log.w(TAG,?"Problem?in?container?service",?e);?? ???????????????????}?? ???????????????}??
最后顯示到UI上去:
[java]?view plaincopy
void?applyCurrentStorage()?{?? ?????? ????if?(mRootView?==?null)?{?? ????????return;?? ????}?? ????if?(mTotalStorage?>?0)?{?? ????????BidiFormatter?bidiFormatter?=?BidiFormatter.getInstance();?? ????????mColorBar.setRatios((mTotalStorage-mFreeStorage-mAppStorage)/(float)mTotalStorage,?? ????????????????mAppStorage/(float)mTotalStorage,?mFreeStorage/(float)mTotalStorage);?? ????????long?usedStorage?=?mTotalStorage?-?mFreeStorage;?? ????????if?(mLastUsedStorage?!=?usedStorage)?{?? ????????????mLastUsedStorage?=?usedStorage;?? ????????????String?sizeStr?=?bidiFormatter.unicodeWrap(?? ????????????????????Formatter.formatShortFileSize(mOwner.getActivity(),?usedStorage));?? ????????????mUsedStorageText.setText(mOwner.getActivity().getResources().getString(?? ????????????????????R.string.service_foreground_processes,?sizeStr));?? ????????}?? ????????if?(mLastFreeStorage?!=?mFreeStorage)?{?? ????????????mLastFreeStorage?=?mFreeStorage;?? ????????????String?sizeStr?=?bidiFormatter.unicodeWrap(?? ????????????????????Formatter.formatShortFileSize(mOwner.getActivity(),?mFreeStorage));?? ????????????mFreeStorageText.setText(mOwner.getActivity().getResources().getString(?? ????????????????????R.string.service_background_processes,?sizeStr));?? ????????}?? ????}?else?{?? ????????mColorBar.setRatios(0,?0,?0);?? ????????if?(mLastUsedStorage?!=?-1)?{?? ????????????mLastUsedStorage?=?-1;?? ????????????mUsedStorageText.setText("");?? ????????}?? ????????if?(mLastFreeStorage?!=?-1)?{?? ????????????mLastFreeStorage?=?-1;?? ????????????mFreeStorageText.setText("");?? ????????}?? ????}?? }??
當點擊listView子項時,會跳轉到詳細列表頁面:
[java]?view plaincopy
public?void?onItemClick(TabInfo?tab,?AdapterView<?>?parent,?View?view,?int?position,?? ??????????long?id)?{?? ??????if?(tab.mApplications?!=?null?&&?tab.mApplications.getCount()?>?position)?{?? ??????????ApplicationsState.AppEntry?entry?=?tab.mApplications.getAppEntry(position);?? ??????????mCurrentPkgName?=?entry.info.packageName;?? ??????????startApplicationDetailsActivity();?? ??????}?? ??}??
[java]?view plaincopy
?? ??private?void?startApplicationDetailsActivity()?{?? ???????? ??????Bundle?args?=?new?Bundle();?? ??????args.putString(InstalledAppDetails.ARG_PACKAGE_NAME,?mCurrentPkgName);?? ?? ??????PreferenceActivity?pa?=?(PreferenceActivity)getActivity();?? ??????pa.startPreferencePanel(InstalledAppDetails.class.getName(),?args,?? ??????????????R.string.application_info_label,?null,?this,?INSTALLED_APP_DETAILS);?? ??}??
查看詳細列表對應的類:
[java]?view plaincopy
public?class?InstalledAppDetails?extends?Fragment?? ????????implements?View.OnClickListener,?CompoundButton.OnCheckedChangeListener,?? ????????ApplicationsState.Callbacks??
即也是一個fragment。
?
詳細列表界面相關button操作代碼如下:
[java]?view plaincopy
public?void?onClick(View?v)?{?? ???????String?packageName?=?mAppEntry.info.packageName;?? ???????if(v?==?mUninstallButton)?{?? ???????????if?(mUpdatedSysApp)?{?? ???????????????showDialogInner(DLG_FACTORY_RESET,?0);?? ???????????}?else?{?? ???????????????if?((mAppEntry.info.flags?&?ApplicationInfo.FLAG_SYSTEM)?!=?0)?{?? ???????????????????if?(mAppEntry.info.enabled)?{?? ???????????????????????showDialogInner(DLG_DISABLE,?0);?? ???????????????????}?else?{?? ???????????????????????new?DisableChanger(this,?mAppEntry.info,?? ???????????????????????????????PackageManager.COMPONENT_ENABLED_STATE_DEFAULT)?? ???????????????????????.execute((Object)null);?? ???????????????????}?? ???????????????}?else?if?((mAppEntry.info.flags?&?ApplicationInfo.FLAG_INSTALLED)?==?0)?{?? ???????????????????uninstallPkg(packageName,?true,?false);?? ???????????????}?else?{?? ???????????????????uninstallPkg(packageName,?false,?false);?? ???????????????}?? ???????????}?? ???????}?else?if(v?==?mSpecialDisableButton)?{?? ???????????showDialogInner(DLG_SPECIAL_DISABLE,?0);?? ???????}?else?if(v?==?mActivitiesButton)?{?? ???????????mPm.clearPackagePreferredActivities(packageName);?? ???????????try?{?? ???????????????mUsbManager.clearDefaults(packageName,?UserHandle.myUserId());?? ???????????}?catch?(RemoteException?e)?{?? ???????????????Log.e(TAG,?"mUsbManager.clearDefaults",?e);?? ???????????}?? ???????????mAppWidgetManager.setBindAppWidgetPermission(packageName,?false);?? ???????????TextView?autoLaunchTitleView?=?? ???????????????????(TextView)?mRootView.findViewById(R.id.auto_launch_title);?? ???????????TextView?autoLaunchView?=?(TextView)?mRootView.findViewById(R.id.auto_launch);?? ???????????resetLaunchDefaultsUi(autoLaunchTitleView,?autoLaunchView);?? ???????}?else?if(v?==?mClearDataButton)?{?? ???????????if?(mAppEntry.info.manageSpaceActivityName?!=?null)?{?? ???????????????if?(!Utils.isMonkeyRunning())?{?? ???????????????????Intent?intent?=?new?Intent(Intent.ACTION_DEFAULT);?? ???????????????????intent.setClassName(mAppEntry.info.packageName,?? ???????????????????????????mAppEntry.info.manageSpaceActivityName);?? ???????????????????startActivityForResult(intent,?REQUEST_MANAGE_SPACE);?? ???????????????}?? ???????????}?else?{?? ???????????????showDialogInner(DLG_CLEAR_DATA,?0);?? ???????????}?? ???????}?else?if?(v?==?mClearCacheButton)?{?? ????????????? ???????????if?(mClearCacheObserver?==?null)?{?? ???????????????mClearCacheObserver?=?new?ClearCacheObserver();?? ???????????}?? ???????????mPm.deleteApplicationCacheFiles(packageName,?mClearCacheObserver);?? ???????}?else?if?(v?==?mForceStopButton)?{?? ???????????showDialogInner(DLG_FORCE_STOP,?0);?? ????????????? ???????}?else?if?(v?==?mMoveAppButton)?{?? ???????????if?(mPackageMoveObserver?==?null)?{?? ???????????????mPackageMoveObserver?=?new?PackageMoveObserver();?? ???????????}?? ???????????int?moveFlags?=?(mAppEntry.info.flags?&?ApplicationInfo.FLAG_EXTERNAL_STORAGE)?!=?0???? ???????????????????PackageManager.MOVE_INTERNAL?:?PackageManager.MOVE_EXTERNAL_MEDIA;?? ???????????mMoveInProgress?=?true;?? ???????????refreshButtons();?? ???????????mPm.movePackage(mAppEntry.info.packageName,?mPackageMoveObserver,?moveFlags);?? ???????}?? ???}??
?原文地址:?http://blog.csdn.net/zhudaozhuan/article/details/40619371
總結
以上是生活随笔為你收集整理的android settings源代码分析(2)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。