当前位置: 首页 > news >正文

做一个英文网站多少钱佛山新网站制作代理商

做一个英文网站多少钱,佛山新网站制作代理商,新手做导航网站,网站自定义链接怎么做SystemUI的实现 以StatusBar为例#xff0c;来分析下Android系统具体是如何实现它们的。 相关代码分为两部分#xff0c;即#xff1a; Service部分 代码路径#xff1a;frameworks/base/services/java/com/android/server。 应用部分 代码路径#xff1a;frameworks…SystemUI的实现 以StatusBar为例来分析下Android系统具体是如何实现它们的。 相关代码分为两部分即 Service部分 代码路径frameworks/base/services/java/com/android/server。 应用部分 代码路径frameworks/base/packages/SystemUI。 下面来看看SystemUI的“目录” … applicationandroid:persistenttrueandroid:allowClearUserDatafalse android:allowBackupfalseandroid:hardwareAcceleratedtrueandroid:labelstring/app_ label android:icon*android:drawable/platlogoandroid:supportsRtltrue service android:nameSystemUIServiceandroid:exportedtrue//*SystemUIService是我们分析的重点状态栏等系统UI实现都是在这里完成的*/service android:name.screenshot.TakeScreenshotServiceandroid:process:screenshot android:exportedfalse //*由此可知SystemUI提供了截屏操作。有兴趣的读者可以自己研究下是如何实现的*/receiver android:name.BootReceiverandroidprv:primaryUserOnlytrue /*开机自启动不过这里启动的是LoadAverageService而不是SystemUIService*/intent-filteraction android:nameandroid.intent.action.BOOT_COMPLETED //intent-filter /receiver …通过AndroidManfiest我们知道SystemUIService是整个系统UI的“载体”所以接下来将根据这一线索来把整个代码流程“串”起来。和其他很多系统服务一样SystemUIService也是在SystemServer中启动的。具体而言SystemServer会在适当的时机通知ActivityManagerService“系统已经就绪systemReady可以进一步运行第三方模块了”——这其中就包括将由startServiceAsUser启动的SystemUIService。 SystemUIService继承了标准的Service组件因而必须重载onCreate接口 /*frameworks/base/packages/systemui/src/com/android/systemui/SystemUIService.java*/public void onCreate() {… IWindowManager wm WindowManagerGlobal.getWindowManagerService();//获取WMS服务try {SERVICES[0] wm.hasSystemNavBar()? R.string.config_systemBarComponent: R.string.config_statusBarComponent;//是StatusBar还是SystemBar?} catch (RemoteException e) {Slog.w(TAG, Failing checking whether status bar can hide, e);}final int N SERVICES.length;mServices new SystemUI[N];for (int i0; iN; i) {Class cl chooseClass(SERVICES[i]);Slog.d(TAG, loading: cl);try {mServices[i] (SystemUI)cl.newInstance();} …mServices[i].mContext this;Slog.d(TAG, running: mServices[i]);mServices[i].start();//mServices中的每个元素都继承自SystemUI}}SERVICES是一个object数组它的初始值如下所示 final Object[] SERVICES new Object[] {0, // system bar or status bar, filled in below.com.android.systemui.power.PowerUI.class,com.android.systemui.media.RingtonePlayer.class,com.android.systemui.settings.SettingsUI.class,};其中SERVICES[0]在初始化时没有赋值。它将根据hasSystemNavBar的执行结果来决定是用systemBar还是statusBar。上面这段代码首先取出SERVICES数组中的class名然后分别实例化它们最后调用start接口统一启动。因此每一个系统ui元素包括statusBarPowerUI等都必须继承自SystemUI这个抽象类并重载其中的start方法。 函数hasSystemNavBar做了哪些判断来对statusBar和systemBar进行取舍呢WindowManager的真正实现体是WindowManagerService。 /*frameworks/base/services/java/com/android/server/wm/WindowManagerService.java*/public boolean hasSystemNavBar() {return mPolicy.hasSystemNavBar();}**Policy是Android中定义UI行为的一个“规范”。**比如有没有Navigation BarWindowLayer如何排布等。以PhoneWindowManager为例它判断当前系统是否需要导航条。 我们假设设备的分辨率是800*480屏幕密度为ldpi /*frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java*/int shortSizeDp shortSize*DisplayMetrics.DENSITY_DEFAULT/ density;/*在这个场景中shortSize480DENSITY_DEFAULT160density 120, 所以最终shortSizeDp 640*/if (shortSizeDp 600) {//在这个场景中不成立mHasSystemNavBar false;mNavigationBarCanMove true;} else if (shortSizeDp 720) {/*本场景属于这一分支*/mHasSystemNavBar false;mNavigationBarCanMove false;} if (!mHasSystemNavBar) {//进一步判断是否有Navigation Bar…} else {mHasNavigationBar false;}所以在这个场景中经过上面的判决后mHasSystemNavBar为false。换句话说对于分辨率800*480且密度为ldpi的屏幕它的SERVICES[0]对应的class类名是R.string.config_statusBar Component即“com.android.systemui.statusbar.phone.PhoneStatusBar”。下面以PhoneStatusBar为例来看看它的创建过程及具体样式 /*frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/ PhoneStatusBar.java*/public void start() {mDisplay ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();/*mDisplay记录了当前默认显示屏的大小密度等等信息*/…super.start();// 关键语句下面我们会重点介绍addNavigationBar();/*不是所有Phone都需要Navigation Bar。比如设备本身已经配备了物理按键这种情况下如果一直在屏幕上显示导航条反而是一种累赘*/…}PhoneStatusBar的“父类”是BaseStatusBar很多框架性的操作都是在这里面完成的但UI界面的具体描述还是会通过回调PhoneStatusBar中的方法来确定 /*frameworks/base/packages/systemui/src/com/android/systemui/statusbar/BaseStatusBar.java*/public void start() {…mBarService IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));// Connect in to the status bar manager serviceStatusBarIconList iconList new StatusBarIconList();//状态栏图标列表ArrayListIBinder notificationKeys new ArrayListIBinder();ArrayListStatusBarNotification notifications new ArrayListStatusBarNoti fication();mCommandQueue new CommandQueue(this, iconList);int[] switches new int[7];ArrayListIBinder binders new ArrayListIBinder();try {mBarService.registerStatusBar(mCommandQueue,iconList,notificationKeys,notifications,switches, binders); /*经过一系列对象的创建与初始化后开始向StatusBarService进行注册。这里涉及跨进程操作因而传递的参数都是继承自Parcelable的*/} catch (RemoteException ex) {// If the system process isnt there were doomed anyway.}createAndAddWindows(); /*这是真正将Status Bar显示出来的地方*/…}好不容易快到“水落石出”的时候了但是上面这段代码却又杀出一个“程咬金”——StatusBarService。 既然SystemUI这个应用程序中已经有StatusBar了为什么又需要StatusBarService? 先来看看StatusBarService是在哪里启动的。 /*frameworks/base/services/java/com/android/server/SystemServer.java*/try {Slog.i(TAG, Status Bar);statusBar new StatusBarManagerService(context, wm); /*确实在这里。而且具体的实现类叫做StatusBarManagerService*/ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);} catch (Throwable e) {reportWtf(starting StatusBarManagerService, e);}现在可以进一步分析StatusBarManagerService的实现了。针对上面BaseStatusBar中调用的注册操作 public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,ListIBindernotificationKeys,ListStatusBarNotification notifications,int switches[], ListIBinder binders) {enforceStatusBarService();mBar bar;synchronized (mIcons) {iconList.copyFrom(mIcons); /*复制Icon列表注意方向是从StatusBarManager- BaseStatusBar*/}synchronized (mNotifications) {for (Map.EntryIBinder,StatusBarNotification e: mNotifications.entrySet()) {notificationKeys.add(e.getKey());notifications.add(e.getValue());/*和Icon列表类似方向也是从StatusBarManager到BaseStatusBar*/}}…}由上面这段代码可以看出registerStatusBar有两个作用 其一为新启动的SystemUI应用中的StatusBar赋予当前系统的真实值比如有多少需要显示的图标。其二通过成员变量mBar记录下IStatusBar对象——它在SystemUI中对应的是CommandQueue。 我们再回到BaseStatusBar。向StatusBarManagerService注册完成后它会执行如下语句。 createAndAddWindows();BaseStatusBar中的这个方法是抽象的因而其子类PhoneStatusBar必须要重载它 /*frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/Ph- oneStatusBar.java*/public void createAndAddWindows() {addStatusBarWindow();}private void addStatusBarWindow() {final int height getStatusBarHeight();/*首先获取StatusBar的高度。默认的高度值是通过com.android.internal.R.dimen.status_bar_height来指定的因而开发人员如果需要更改StatusBar高度的话可以考虑修改这个值*/ final WindowManager.LayoutParams lp new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, /*宽度是MATCH_PARENT*/height, //高度值是可定制的WindowManager.LayoutParams.TYPE_STATUS_BAR, /*指定窗口类型*/WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,/*设置flag, 下面还会加上硬件加速属性*/PixelFormat.TRANSLUCENT/*半透明的*/);lp.flags |windowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;lp.gravity getStatusBarGravity();/*设置Gravity属性默认值为Gravity.TOP |Gravity.FILL_HORIZONTAL,所以StatusBar是在屏幕上方*/lp.setTitle(StatusBar); //标题lp.packageName mContext.getPackageName();makeStatusBarView(); //下面会详细介绍mWindowManager.addView(mStatusBarWindow, lp); /*将一切就绪的mStatusBarWindow加入WindowManager中。请参见本书显示系统章节的讲解*/}从makeStatusBarView这个函数名可以推断出StatusBarView会被创建并且初始化。先来了解下两个重要的变量。 mStatusBarWindow 这是一个StatusBarWindowView类对象同时我们通过addView传给WindowManager的也是这个变量——说明它很可能包含了StatusBarView。 mStatusBarView 这就是makeStatusBarView需要操作的对象。 /*frameworks/base/packages/systemui/src/com/android/systemui/statusbar/phone/Ph-one StatusBar.java*/protected PhoneStatusBarView makeStatusBarView() {…mStatusBarWindow (StatusBarWindowView) View.inflate(context, R.layout.super_ status_bar, null);mStatusBarWindow.mService this; //mService其实指的是PhoneStatusBarmStatusBarWindow.setOnTouchListener(new View.OnTouchListener() {//设置触摸事件Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() MotionEvent.ACTION_DOWN) {//支持下拉手势if (mExpandedVisible) {animateCollapsePanels ();//通知栏的“下拉展开”需要动画效果不然会很突兀}}return mStatusBarWindow.onTouchEvent(event);}});mStatusBarView (PhoneStatusBarView)mStatusBarWindow.findViewById(R.id.status_ bar);mStatusBarView.setBar(this); /*状态栏出场了*/…mNotificationPanel (NotificationPanelView) mStatusBarWindow.findViewById(R.id. notification_panel);mNotificationPanel.setStatusBar(this); /*通知栏也很关键只不过它只有在下拉后才会出现*//*从下面开始将利用mStatusBarView为PhoneStatusBar中的众多内部变量赋值*/…try {boolean showNav mWindowManagerService.hasNavigationBar();/*决定是否需要导航条*/if (showNav) {mNavigationBarView (NavigationBarView) View.inflate(context, R.layout. navigation_ bar, null);/*Navigation Bar对应的layout。有兴趣的读者可以自己看一下*/…}} catch (RemoteException ex) {/*Android中的不少代码在捕捉异常时很常见的一种处理就是“听天由命”…*/}/*接下来通过findViewById从mStatusBarView中获取StatusIcons、NotificationIcons、ClearButton等一系列按键。我们将会在StatusBar布局文件中做统一分析。这里暂时略过*/… /*最后动态注册需要接收的广播比如系统设置改变屏幕关闭等*/IntentFilter filter new IntentFilter();filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);…context.registerReceiver(mBroadcastReceiver, filter);…return mStatusBarView;//注意最终返回值是mStatusBarWindow的子View}变量mStatuBarWindow来源于super_status_bar布局。它本质上还是一个FrameLayout包含的元素也很简单就是status_bar和status_bar_expanded两个布局前者对应的是状态栏mStatusBarView后者其实就是通知栏mNotificationPanel。为status_bar中的众多元素按键、背景等进行初始化。 最终的返回值是mStatusBarView。然后利用WindowManager的addView接口将mStatus- BarWindow注意不是mStatusBarView添加进窗口系统中。接下来的主动权就转交给WindowManager。 这样我们就把StatusBarNotification和NavigationBar的调用流程“串”起来了。 Android壁纸资源——WallpaperService 除了前面讲解的状态栏、通知栏外壁纸也属于SystemUI管理的一个重点。在Android系统中用户可以从设备内部或者外存储器比如SD卡中中选取图片资源作为壁纸。另外系统还支持动态壁纸的显示。 壁纸管理系统主要包括以下几个方面。 WallpaperManagerServiceWPMS 它是壁纸机制的“大总管”静态、动态壁纸都是在这里统一调度的。 WallpaperServiceWPS WPS继承了标准的Service组件因而它一定会实现onCreate、onDestroy、onBind等一系列方法。此外它还包含了一个重要的嵌套类engine我们在后面会做详细讲解。WPS是静态、动态壁纸的基类代表了作为“壁纸”所应该具有的一切属性。 ImageWallpaperIWP 从名称可以看出它是静态壁纸的实现类而且一定是继承自上面的WPS。 WallPaperManagerService WPMS既然是基于AIDL实现的我们来看看它的接口描述 /*frameworks/base/core/java/android/app/IWallpaperManager.aidl*/ interface IWallpaperManager {ParcelFileDescriptor setWallpaper(String name); /*设置壁纸*/void setWallpaperComponent(in ComponentName name); /*设置动态壁纸*/ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,out Bundle outParams);WallpaperInfo getWallpaperInfo();… }从上面的接口定义可以看出WPMS的工作并不复杂——它提供了全局的壁纸注册、取消和查询功能并在接收到事件时进行合理分配。 和其他系统服务一样WPMS是在SystemServer.java中启动并注册进ServiceManager中的如下所示 /*frameworks/base/services/java/com/android/server/SystemServer.java*/try {Slog.i(TAG, Wallpaper Service);if (!headless) {wallpaper new WallpaperManagerService(context);ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);}} catch (Throwable e) {reportWtf(starting Wallpaper Service, e);}接下来的一个问题是既然系统同时支持静态壁纸和动态壁纸而且每种类型中还包含了N个实例比如原生态系统就自带多个动态壁纸供用户选择那么系统在显示时是如何选择的呢我们很自然地会想到在WPMS启动时它应该会去读取某个“配置文件”这个文件记录了用户最近一次的选择 public WallpaperManagerService(Context context) {…loadSettingsLocked(UserHandle.USER_OWNER);//加载配置}当WPMS构造时它调用了loadSettingsLocked private void loadSettingsLocked(int userId) {//这里传进来的userId0…try {stream new FileInputStream(file);XmlPullParser parser Xml.newPullParser();parser.setInput(stream, null);int type;do {type parser.next();if (type XmlPullParser.START_TAG) {String tag parser.getName();if (wp.equals(tag)) {…wallpaper.name parser.getAttributeValue(null, name);String comp parser.getAttributeValue(null, component);…}}} while (type ! XmlPullParser.END_DOCUMENT);success true;} … }上面这段代码会按照写入时的格式将wallpaper的配置信息读出来并保存在WallpaperData结构中——专门用于描述壁纸信息的通用数据结构。不过这时壁纸还没有真正显示出来而是要等到系统进入Ready状态此时系统会回调SystemReady接口后才会通知具体的壁纸程序进行绘制 public void systemReady() {WallpaperData wallpaper mWallpaperMap.get(UserHandle.USER_OWNER);switchWallpaper(wallpaper, null);…}接着进入Wallpaper的具体处理中 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {synchronized (mLock) {…try {ComponentName cname wallpaper.wallpaperComponent ! null ?wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;if (bindWallpaperComponentLocked(cname, true, false, wallpaper,reply)) {return;}} …}系统开机后wallpaper.wallpaperComponent为空除非上一次用户选择了其他方式而wallpaper.nextWallpaperComponent则在loadSettingsLocked中被设置为wallpaper.imageWallpaper Component即我们前面提到的ImageWallpaper这个Service。所以当调用bindWallpaperComponentLocked时传入的cname就代表了ImageWallpaper。从bindWallpaperComponentLocked的函数名称可以看出它将会以bindService的方式来启动目标壁纸Service所以后期如果确认已经不再使用这个Service还要主动执行unbind然后这个壁纸服务就会自动销毁。 WPMS启动后就可以接收客户端的请求了因为它属于实名的BinderServer意味着所有人都可以自由地使用它所提供的服务。比如我们既可以在系统自带的Launcher应用程序中选择壁纸也完全可以自己编写一个更改壁纸的应用程序。 下面我们以设置壁纸这一场景为例来分析WPMS的内部实现 /*frameworks/base/services/java/com/android/server/WallpaperManagerService.java*/public ParcelFileDescriptor setWallpaper(String name) {checkPermission(android.Manifest.permission.SET_WALLPAPER);synchronized (mLock) {int userId UserHandle.getCallingUserId();WallpaperData wallpaper mWallpaperMap.get(userId);…final long ident Binder.clearCallingIdentity();try {ParcelFileDescriptor pfd updateWallpaperBitmapLocked(name, wallpaper);…return pfd;} finally {Binder.restoreCallingIdentity(ident);}}}首先系统会做下权限检查所以提供壁纸设置功能的应用程序一定要在AndroidManifest.xml中显式写上如下权限声明 uses-permission android:nameandroid.permission.SET_WALLPAPER /变量wallpaper是从mWallpaperMap取出来的代表UserId为0时的壁纸——如果不为空就进入以下函数 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {if (name null) name ;try {File dir getWallpaperDir(wallpaper.userId);//wallpaper的路径if (!dir.exists()) {//指定的路径不存在需要创建dir.mkdir();FileUtils.setPermissions(dir.getPath(),FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, -1, -1);}File file new File(dir, WALLPAPER);ParcelFileDescriptorParcelFileDescriptor.open(file,MODE_CREATE|MODE_READ_WRITE);if (!SELinux.restorecon(file)) {return null;}wallpaper.name name;return fd;} catch (FileNotFoundException e) {Slog.w(TAG, Error setting wallpaper, e);}return null;} 上面getWallpaperDir将得到一个WALLPAPER_BASE_DIR“/”userId的路径其中WALLPAPER_BASE_DIR默认值是/data/system/users。 ImageWallpaper 前面讲过当WPMS开机启动时默认情况下会选择ImageWallpaper这个壁纸实现并且以bindService的方式来启动它。在bindService中WPMS同时传入名为newConn的Binder对象WallpaperConnection来使ImageWallpaper其他WallpaperService也是一样的可以访问到WPMS。而ImageWallpaper则响应onBind返回一个IWallpaperServiceWrapper的Binder对象如图所示。 我们来看看当绑定成功后WPMS中的操作 public void onServiceConnected(ComponentName name, IBinder service) {synchronized (mLock) {if (mWallpaper.connection this) {…attachServiceLocked(this, mWallpaper);…saveSettingsLocked(mWallpaper);}}}WPMS除了要保存当前所选的壁纸外还要调用attachServiceLocked间接调用Iwallpaper ServiceWrapper.attach来执行实际的工作。 WPS这边的attach函数将生成一个IWallpaperEngineWrapper对象并给它发送一个DO_ATTACH这个消息最终由IWallpaperEngineWrapper. executeMessage来处理 public void executeMessage(Message message) {switch (message.what) {case DO_ATTACH: {try {mConnection.attachEngine(this);} catch (RemoteException e) {Log.w(TAG, Wallpaper host disappeared, e);return;}Engine engine onCreateEngine();mEngine engine;mActiveEngines.add(engine);engine.attach(this);return;}上述代码段通过onCreateEngine生成了一个壁纸引擎——这也是各壁纸应用间最核心的差异。所以系统要求每一个WallpaperService实例必须要重载onCreateEngine来实现自己的engine。在ImageWallpaper中它将产生一个DrawableEngine——这个engine随后会被加入mActiveEngines的全局list中然后调用它提供的attach接口。如下所示 /*frameworks/base/core/java/android/service/wallpaper/WallpaperService.java*/public class Engine {…void attach(IWallpaperEngineWrapper wrapper) {…mSession WindowManagerGlobal.getWindowSession();mWindow.setSession(mSession);…IntentFilter filter new IntentFilter();filter.addAction(Intent.ACTION_SCREEN_ON);filter.addAction(Intent.ACTION_SCREEN_OFF);registerReceiver(mReceiver, filter); …updateSurface(false, false, false);//更新Surface }…Engine内部首先需要进行各重要变量的初始化然后注册监听屏幕的开/关事件最后调用updateSurface。
http://www.pierceye.com/news/20813/

相关文章:

  • 手机网站js触屏滑动图片特效广州cms建站系统
  • 做网站对电脑要求高吗国外域名的网站
  • 做3d模型的叫什么牛的网站上海地产网站建设
  • html5国内网站建设网页设计与制作思政微课
  • 萧山区建设工程质量监督站网站峡山网站建设
  • 建设网站的目的饮食类Wordpress主页面增加
  • 宛城区微网站开发智慧团建登录平台入口
  • 个人做收费网站discuz wordpress 整合
  • phpcms手机网站少儿编程培训机构哪里好
  • 黔西网站建设wordpress打印插件
  • wordpress企业网站制作建盏厂家
  • 做寻亲网站的理由万网创始人为什么封停慧聪网
  • 城市建设网站hhvm wordpress 空白
  • 宁波模板建站哪家好二维码生成器工具
  • 个旧市哪里有做网站WordPress打开 速度
  • 网站手机自动跳转网站导航用什么字体
  • 杨浦企业网站建设百度手机端排名如何优化
  • 徐州建设工程材料检测预约网站广西灵山县住房和城乡建设局网站
  • 多个域名绑定同一个网站蓝色大气企业主题wordpress
  • 网站有哪些类型如何在国内做网站
  • 网站的推广方式组合成都市 网站建设
  • 东莞建网站服务慈溪哪点有学做网站的
  • 邳州哪家做百度推广网站百度收录提交入口
  • 费县建设局网站创建外卖平台
  • 提交网站的入口地址西安网站建设盈科
  • 厦门建站价格网站建设网络推广
  • 绍兴专业做网站途牛网站建设的基本特点
  • 网站板块建设的重要性短视频获客
  • 成立网站建设公司要求网站建设做网站费用
  • 飞创网站建设做网站还是订阅号