Android Galler2源码分析
Android逆向分析案例——某地图的定位请求分析
Android逆向分析案例——某地图的定位请求分析微信里面有个“附近的人”,相信大家都知道,大概的原理就是调用腾讯地图的sdk进行定位,然后把个人的定位信息发到微信服务器上进行处理,再把一定范围内的人的信息返回并用列表的形式显示出来。
因为刚踏入逆向分析这行,所以抱着学习的态度,研究一下大公司的东西,涨一下知识,嗯,本次的案例就是分析腾讯地图中定位请求数据的加解密,以及搭建简易的APK模拟实现定位请求。
为了分析这一案例,是要掌握一定的分析工具的,其中包括APKTOOL,Sublime-Text,Xposed框架,Wireshark等。
嗯,作为分析笔记,我就不细说了,只是将分析的步骤一步步地列举出来。
首先,下载微信APK,利用APKTOOL在DOS下敲命令生成smali文件夹,这个过程我就不说了,前面博客已介绍过APKTOOL的使用方法。
对于初学者来说,他们喜欢看到直接明了的源代码,所以他们会喜欢用dex2jar去反编译,并利用jd-gui去查看代码,包括我当初也是如此,但现在我为什么不用dex2jar和jd-gui 去分析呢?再往下看看然后用smali文件查看工具Sublime-Text 3打开其刚刚生成的smali文件夹,如下图:嗯,反编译出来的文件数量令人感到窒息的,是不是有点感到逆向分析的痛苦了?要在如此多的smali文件里找到对应的类,并定位到关键的代码,这是需要一定的技巧的,不然你就只能码海捞针了。
顺便一提,这货混淆得太好了,里面的可读性非常差,而且通过smali可以看到代码是有一定的复杂性的,特别多goto 语句,所以如果用jd-gui浏览代码的话,是很不准确的,而且有一些内部类jd-gui是不会显示出来的等等。
总而言之,smali的表达基本是正确的,但jd-gui转变过程并没有那么智能,所以jd-gui所表达的信息很大程度是错的,只能辅助用,不能依赖。
既然我们要找的是地图地位请求,那么肯定涉及到网络,那么又怎么能少了抓包过程呢?好,进入微信,打开wireshark,在点击“附近的人”按钮同时观察wireshark抓到的包,主要是Http协议的包。
Android+2.2+开发环境配置详解
Android 2.2 开发环境配置详解Google在旧金山Moscone会展中心举办Google I/O 2010大会第二天(美国时间5月20日上午)的会议之上如约正式发布了代号为“Froyo(冻酸奶)”的最新版Android 2.2操作系统。
而紧接着网络中也开始提供SDK(开发者套件)安装包的下载,虽然仅凭SDK 包尚无法让我们体验到诸如Flash10.1等应用,但据官方介绍,新版系统带来性能的大幅度提升,除了支持Flash 10.1,另外还在系统界面、功能等方面进行了许多细节性优化.Android 2.2是非常值得期待,下面是根据个人实践经验配置Android SDK2.2+Eclipse 的开放环境编写的详细步骤。
根据这些步骤,就是门外汉也可有完成。
系统环境的要求可以参考/sdk/requirements.html 一,下载所软件包(1)JDK要求JDK1.5+,建议JDK6.X下载网址/javase/downloads/index.jsp下载后,一步一步安装!设置系统变量JAVA_HOME为你安装目录,在系统变量path的后面加入;%JAVA_HOME%\bin;图1.1 JAVA_HOME设置图1.2 Path系统变量配置本文实践选择JDK1.6.0_19(2)IDEEclipse 3.4 (Ganymede) or 3.5 (Galileo)下载网址/downloads 建议下载下面其中的一个版本Eclipse IDE for Java EE DevelopersEclipse IDE for Java DevelopersEclipse for RCP/Plug-in DevelopersEclipse Classic下载完成后,解压即可!本文选择当前最新的eclipse-reporting-galileo-SR2-win32 (Base On Eclipse 3.5 SR2)(3)Android SDK准确来说下载的不是SDK而是SDK下载安装器,因为下载下来的并没SDK,而需要连接到官方网址下载所需的SDK。
AndroidGallery2源代码分析
AndroidGallery2源代码分析打开图库中图⽚为什么从模糊变清晰1. 有⼀点要明⽩,图⽚要进⾏显⽰,⾸先要先将图⽚进⾏decode,然后才⼲显⽰2. 图⽚decode须要时间,越⼤的图⽚,细节越多的图⽚,那么它decode时间就越长3. 最笨的做法就是,等图⽚decode完了,我们再显⽰,在decode完之前就看到⿊⾊的背景。
但这种做法不太友好,尤其是⼤的图⽚的时候,等待的时间就越长为了给客户更好的⽤户体验,我们会先decode⼀张图⽚的thumbnail即缩略图, 当我们点击⼀张图⽚进来之后,我们⾸先看到的是这个图⽚的thumbnail,这样⽤户就知道图⽚有被显⽰可是,因为thumbnail的分辨率有限,贴到屏幕上之后就会⽐較模糊。
这就是为什么⼀開始看到模糊的原因4. 这个时候,还是逃不掉decode整张图⽚的步骤,我们全然能够等整张图⽚decode完成之后再更新到屏幕。
但我们觉得这样的⽅式也不是太好,为什么不是decode出⼀部分就显⽰⼀部分呢?所以终于的⽅法是:我们将整个图⽚分成⼩块(tile),high resolution的图⽚,tile的size是510,普通图⽚的tile size是254,然后我们依照从上到下,从左到右的顺序依次decodetile,所以你看到图⽚⼀⼩块⼀⼩块的显⽰,图⽚逐步变清晰的过程所以,眼下此⽅案已经做到了最优化,只是因为本⾝decode须要时间,我们不能做到⼀下显⽰清晰图⽚,或者缩短图⽚变清晰的时间。
void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx,int awPx, int ahPx) {Configuration configuration = resources.getConfiguration();isLandscape = (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE);isTablet = resources.getBoolean(R.bool.is_tablet);isLargeTablet = resources.getBoolean(R.bool.is_large_tablet);if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {isLayoutRtl = (configuration.getLayoutDirection() == YOUT_DIRECTION_RTL);} else {isLayoutRtl = false;}widthPx = wPx;heightPx = hPx;availableWidthPx = awPx;availableHeightPx = ahPx;updateAvailableDimensions(context);}图⽚双击变⼤算法图⽚双击放⼤倍数和图⽚⼤⼩、显⽰图⽚的view⼤⼩,及图⽚当前的scale⼤⼩均有关系。
Gallery 3D 源码分析汇总
Gallery 3D 分析文章分类:移动开发Gallery 3D 分析yer 是个抽象类。
有5个变量,分别是mX;mY(位置坐标);mWidth;mHeight(宽与高);mHidden (是否隐藏); 一个抽象方法,非抽象子类都有实现。
Java代码其他的可以在子类中重写有好几个类都继承了Layer抽象类:BackgroundLayerCanvasLayerGridLayerHudLayerLoadingLayerRootLayer其中用到的RenderView类Java代码里面有个静态final 类Lists里面定义了updateList,opaqueList,blendedList,hitTestList,systemList等以Layer为对象内容的ArrayList;以及一个清空所有ArrayList的方法Clear().Gallery 3D 代码分析之概览文章分类:移动开发Gallery 3D UI 非常炫,如下图所示:需要明确的几个问题伪2D 还是3D:gallery3d 基于android SDK OpenGL ES 接口开发,使用了Java API,没有使用NDK。
图片如何显示:在OpenGL ES 中,要显示图片,需要定义一个四边形,然后把图片当作texture 贴到四边形上。
布局及特效如何实现:这是gallery3d 的精华所在,需认真分析。
大数据量图片/cache 如何实现和管理:gallery3d 有缓冲区的设计,非常不错,需要认真分析。
动画引擎:简单的讲,动画引擎对外可表现为一个接口:Java代码即,给定初始值(initVal),动画引擎根据逝去的时间(timeElapsed)和动画总时间(duration)计算下一帧对应的值(currentVal),这个值可能是位置坐标,也可能是一个矩阵matrix,或者是其它的属性。
显示一帧就调用该函数更新actor的属性,各个帧连起来显示就成了动画。
使用Android自带Gallery组件实现CoverFlow,源码+解析(An-Beer工作室)
使用Android自带Gallery组件实现CoverFlow,源码+解析android, gallery, coverflow, 源码, 解析本帖最后由 kearnel 于 2010-10-24 11:46 编辑首先声明,源代码转载自国外Neil Davies,使用Apache2.0开源协议,请使用源代码的人自觉遵守协议内容。
本文为Kearnel原创,转载请注明出处。
以下是正文:使用过Android自带的gallery组件的人都知道,gallery实现的效果就是拖动浏览一组图片,相比iphone里也是用于拖动浏览图片的coverflow,显然逊色不少。
实际上,可以通过扩展gallery,通过伪3D变换可以基本实现coverflow的效果。
本文通过源代码解析这一功能的实现。
具体代码作用可参照注释。
最终实现效果如下:要使用gallery,我们必须首先给其指定一个adapter。
在这里,我们实现了一个自定义的ImageAdapter,为图片制作倒影效果。
传入参数为context和程序内drawable中的图片ID数组。
之后调用其中的createReflectedImages()方法分别创造每一个图像的倒影效果,生成对应的ImageView数组,最后在getView()中返回。
1./*2.* Copyright (C) 2010 Neil Davies3.*4.* Licensed under the Apache License, Version 2.0 (the "License");5.* you may not use this file except in compliance with the License.6.* You may obtain a copy of the License at7.*8.* /licenses/LICENSE-2.09.*10.* Unless required by applicable law or agreed to in writing, software11.* distributed under the License is distributed on an "AS IS" BASIS,12.* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13.* See the License for the specific language governing permissions and14.* limitations under the License.15.*16.* This code is base on the Android Gallery widget and was Created17.* by Neil Davies neild001 'at' gmail dot com to be a Coverflow widget18.*19.* @author Neil Davies20.*/21.public class ImageAdapter extends BaseAdapter {22.int mGalleryItemBackground;23.private Context mContext;24.25.private Integer[] mImageIds ;26.27.private ImageView[] mImages;28.29.public ImageAdapter(Context c, int[] ImageIds) {30.mContext = c;31.mImageIds = ImageIds;32.mImages = new ImageView[mImageIds.length];33.}34.35.public boolean createReflectedImages() {36.// The gap we want between the reflection and the original image37.final int reflectionGap = 4;38.39.int index = 0;40.for (int imageId : mImageIds) {41.Bitmap originalImage = BitmapFactory.decodeResource(42.mContext.getResources(), imageId);43.int width = originalImage.getWidth();44.int height = originalImage.getHeight();45.46.// This will not scale but will flip on the Y axis47.Matrix matrix = new Matrix();48.matrix.preScale(1, -1);49.50.// Create a Bitmap with the flip matrix applied to it.51.// We only want the bottom half of the image52.Bitmap reflectionImage = Bitmap.createBitmap(originalImage, 0,53.height / 2, width, height / 2, matrix, false);54.55.// Create a new bitmap with same width but taller to fit56.// reflection57.Bitmap bitmapWithReflection = Bitmap.createBitmap(width,58.(height + height / 2), Config.ARGB_8888);59.60.// Create a new Canvas with the bitmap that's big enough for61.// the image plus gap plus reflection62.Canvas canvas = new Canvas(bitmapWithReflection);63.// Draw in the original image64.canvas.drawBitmap(originalImage, 0, 0, null);65.// Draw in the gap66.Paint deafaultPaint = new Paint();67.canvas.drawRect(0, height, width, height + reflectionGap,68.deafaultPaint);69.// Draw in the reflection70.canvas.drawBitmap(reflectionImage, 0, height + reflectionGap,71.null);72.73.// Create a shader that is a linear gradient that covers the74.// reflection75.Paint paint = new Paint();76.LinearGradient shader = new LinearGradient(0,77.originalImage.getHeight(), 0,78.bitmapWithReflection.getHeight() + reflectionGap,79.0x70ffffff, 0x00ffffff, TileMode.CLAMP);80.// Set the paint to use this shader (linear gradient)81.paint.setShader(shader);82.// Set the Transfer mode to be porter duff and destination in83.paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));84.// Draw a rectangle using the paint with our linear gradient85.canvas.drawRect(0, height, width,86.bitmapWithReflection.getHeight() + reflectionGap, paint);87.88.ImageView imageView = new ImageView(mContext);89.imageView.setImageBitmap(bitmapWithReflection);90.imageView91..setLayoutParams(new youtParams(160, 240));92.// imageView.setScaleType(ScaleType.MATRIX);93.mImages[index++] = imageView;94.95.}96.return true;97.}98.99.public int getCount() {100.return mImageIds.length;101.}102.103.public Object getItem(int position) {104.return position;105.}106.107.public long getItemId(int position) {108.return position;109.}110.111.public View getView(int position, View convertView, ViewGroup parent) {112.113.// Use this code if you want to load from resources114./*115.* ImageView i = new ImageView(mContext);116.* i.setImageResource(mImageIds[position]); i.setLayoutParams(new117.* youtParams(350,350));118.* i.setScaleType(ImageView.ScaleType.CENTER_INSIDE);119.*120.* //Make sure we set anti-aliasing otherwise we get jaggies121.* BitmapDrawable drawable = (BitmapDrawable) i.getDrawable();122.* drawable.setAntiAlias(true); return i;123.*/124.125.return mImages[position];126.}127.128./**129.* Returns the size (0.0f to 1.0f) of the views depending on the130.* 'offset' to the center.131.*/132.public float getScale(boolean focused, int offset) {133./* Formula: 1 / (2 ^ offset) */134.return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));135.}136.137.}138.}复制代码仅仅实现了图片的倒影效果还不够,因为在coverflow中图片切换是有旋转和缩放效果的,而自带的gallery中并没有实现。
Android7.0Gallery图库源码分析2-分析启动流程
Android7.0Gallery图库源码分析2-分析启动流程前⾯⼀讲解了Gallery启动Activity以及界⾯如何绘制,现在开始讲解启动流程的代码逻辑。
GalleryActivity的onCreate⽅法中调⽤initializeByIntent()⽅法,顾名思义这个⽅法就是根据Intent事件来初始化的。
1private void initializeByIntent() {2 Intent intent = getIntent();3 String action = intent.getAction();45if (Intent.ACTION_GET_CONTENT.equalsIgnoreCase(action)) {6 startGetContent(intent);7 } else if (Intent.ACTION_PICK.equalsIgnoreCase(action)) {8 ......9 } else if (Intent.ACTION_VIEW.equalsIgnoreCase(action)10 || ACTION_REVIEW.equalsIgnoreCase(action)){11 startViewAction(intent);12 } else {13//我们从桌⾯启动应⽤时Intent的Action是android.intent.action.MAIN,所以会⾛到这⼀步14 startDefaultPage();15 }16 }我们看⼀下这个⽅法,它是通过Bundle来传输数据1public void startDefaultPage() {2 ......3 Bundle data = new Bundle();4 data.putString(AlbumSetPage.KEY_MEDIA_PATH,5 getDataManager().getTopSetPath(DataManager.INCLUDE_ALL));6 getStateManager().startState(AlbumSetPage.class, data);7 ......8 }上⾯这个⽅法涉及的东西很多,AlbumSetPage继承⾃ActivityState,显⽰所有相册缩略图的页⾯,也就是进⼊Gallery显⽰的第⼀个界⾯。
android onimageavailable中的逻辑
android onimageavailable中的逻辑`onImageAvailable()`是Android Camera2 API中的一个回调方法,用于在图像可用时进行处理。
其逻辑通常如下:1. 在Camera2 API中,你需要创建一个`ImageReader`对象来接收相机捕捉到的图像。
在`onImageAvailable()`方法中,你将处理这个可用的图像。
2. 首先,你需要从回调方法的参数中获取`ImageReader`对象,以便访问可用的图像。
通常是通过`ImageReader`的`acquireNextImage()`方法获取最新的图像。
如下所示:```java@Overridepublic void onImageAvailable(ImageReader reader) {Image image = reader.acquireNextImage();// 处理图像...}```3. 一旦你获得了图像,你可以使用`Image`对象来获取图像的相关信息,如宽度、高度、像素数据等。
4. 对于每个图像,你可以根据需要进行各种处理,例如保存到设备存储、显示在用户界面、进行图像处理等。
你可以使用`Image`对象的方法来获取和操作图像的像素数据。
5. 在处理完图像后,你应该释放`Image`对象以避免内存泄漏。
使用`Image`对象的`close()`方法来释放资源。
例如:```java@Overridepublic void onImageAvailable(ImageReader reader) {Image image = reader.acquireNextImage();// 处理图像...// 释放图像资源image.close();}```注意:在处理图像时,请确保在一个合适的线程上进行,以避免阻塞主线程。
以上是`onImageAvailable()`方法的基本逻辑,你可以根据自己的需求在该方法中进行图像处理和后续操作。
androidcamera系统架构源码分析(5)
androidcamera系统架构源码分析(5)写到第五篇,我们已经把大致的流程已经贯穿完了,还有很多东西没有讲,日后慢慢再说。
不过现在有一个重要的问题,就是整个流利里各种buf,provider,bufmgr,queue类等之间的关系,说白了就是buf类和buf辅助类之前的关系。
理清这些类的关系和这些类的作用,再从Buf流理解一下整个框架,CamAdapter和CamClient是怎么通过Buf联系,会对日后的分析有一个很大的帮助。
也相当于对本文的一个总结。
本来为了避免贴太多代码,想直接写中文总结的,后来发现贴代码虽然看得更辛苦一点,但细节更清晰,还是贴代码吧DisplayClient::onThreadLoop(Command const& rCmd){ // (0) lock Processor. //pImgBufQueue的实现在ImgBufQueue.cpp里spIImgBufQueue> pImgBufQueue; pImgBufQueue = mpImgBufQueue; /** (1) Prepare all TODO buffers. pImgBufQueue里有两个Buf队列mTodoImgBufQue 和mDoneImgBufQue 下面的函数用StreamImgBuf生成好ImgBufQueNode,把buf的标志位设为eSTATUS_TODO 后调用ImgBufQueue的enqueProcessor()把所有的Buf都放入到mTodoImgBufQue做接收数据的准备**/ prepareAllTodoBuffers(pImgBufQueue); // (2) Start 只是通知队列,不做任何队列的数据处理pImgBufQueue->startProcessor(); // (3) Do until disabled. while ( 1 ) { /**(.1) 在此处会ImgBufQueue的dequeProcessor()等待通知,并接收数据收到通知后,接收的是mDoneImgBufQue,一个ImgBufQueNode队列接收到队列后把整个mDoneImgBufQue传入handleReturnBuffers()中被处理handleReturnBuffers()首先会获得单个ImgBufQueNode中的IImgBuf,即最原始的Mem 接下来就是操作mem。
Android HAL分析报告
Android HAL分析报告1 HAL简介Android 的HAL(Hardware Abstract Layer硬件抽象层)是Google因应厂商「希望不公开源码」的要求下,所推出的新观念,其架构如下图。
虽然HAL 现在的「抽象程度」还不足,现阶段实作还不是全面符合HAL的架构规划,不过也确实给了我们很好的思考空间。
图1:Android HAL 架构规划这是Patrick Brady (Google) 在2008 Google I/O 所发表的演讲「Anatomy & Physiology of an Android」中,所提出的Android HAL 架构图。
从这张架构图我们知道,HAL 的目的是为了把Android framework 与Linux kernel 完整「隔开」。
让Android 不至过度依赖Linux kernel,有点像是「kernel independent」的意思,让Android framework 的开发能在不考虑驱动程序的前提下进行发展。
在Android 原始码里,HAL 主要的实作储存于以下目录:1. libhardware_legacy/ - 过去的实作、采取链接库模块的观念进行2. libhardware/ - 新版的实作、调整为HAL stub 的观念3. ril/ - Radio Interface Layer在HAL 的架构实作成熟前(即图1的规划),我们先就目前HAL 现况做一个简单的分析。
另外,目前Android 的HAL实作,仍旧散布在不同的地方,例如Camera、WiFi 等,因此上述的目录并不包含所有的HAL 程序代码。
图2:Android HAL / libhardware_legacy 过去的libhardware_legacy 作法,是比较传统的「module」方式,也就是将*.so 档案当做「shared library」来使用,在runtime(JNI 部份)以direct function call 使用HAL module。
Android12系统源码分析:NativeTombstoneManager
Android12系统源码分析:NativeTombstoneManagerAndroid12系统源码分析:NativeTombstoneManager概述android12新增的system_server进程(LocalService)本地服务,⽤于管理native tombstones。
该服务在开机Systemerver初始化流程启动,添加到LocalService,然后启动⼀个ServiceThread线程⽤于(mHandler.post)处理本服务的业务。
NativeTombstoneManager的功能主要是:监听/data/tombstones ⽬录⽂件变动,解析为TombstoneFile 对象保存,通知dropbox特定tombstones ⽂件删除特定tombstones ⽂件检索值得关注的是AMS对该服务的使⽤,也是Android11新增API:getHistoricalProcessExitReasons()软件架构如图:BootReceiver SystemServer 开机启动仅添加本地服务LocalServices.addService NativeTombstoneManager.class SystemService AppExitInfoTracker Nativ eTombs toneManager tombs toneServ ic e void clearHistoryProcessExitInfo()ActivityManagerService Nativ eTombs toneManager tombs toneServ ic e public getHistoricalProcessExitReasons()暴露接⼝给appNativeTombstoneManagerServiceNativ eTombs toneManager mManagerpublic v oid onStart()public v oid onBootPhas e()TombstoneFile by:qiuchengParcelFileDescriptorRetrieverNativeTombstoneManagerpriv ate v oid handleTombs tone()priv ate v oid handleProtoTombs tone()public v oid c ollec tTombs tones ()服务核⼼实现TombstoneWatcher 监听⽬录:/data/tombstones FileObserver 图:NativeTombstoneManager类图启动流程SystemServer SystemServer SystemServiceManager SystemServiceManager NativeTombstoneManagerService NativeTombstoneManagerService NativeTombstoneManager NativeTombstoneManager LocalServicesLocalServices 1startCoreServices23by:qiucheng4NativeTombstoneManager567addService(NativeTombstoneManager.class8startOtherServices9startBootPhasePHASE_ACTIVITY_MANAGER_READY10onBootPhase111213registerForPackageRemoval14handleTombstone图:NativeTombstoneManager服务启动时序图服务⽐较简单,和其他SystemServer启动的服务⼀样,frameworks/base/services/core/java/com/android/server/os/NativeTombstoneManagerService.java public class NativeTombstoneManagerService extends SystemService {private NativeTombstoneManager mManager;@Overridepublic void onStart() {mManager = new NativeTombstoneManager(getContext());//仅添加本地服务,没有binder服务LocalServices.addService(NativeTombstoneManager.class, mManager);}@Overridepublic void onBootPhase(int phase) {if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {mManager.onSystemReady();}}}本服务也是SystemService⼯具类的⼦类,通过重写onStart、onBootPhase获得代码流程在onStart中初始化真正的服务实现NativeTombstoneManager,实例化后添加到LocalServicesframeworks/base/services/core/java/com/android/server/os/NativeTombstoneManager.javapublic final class NativeTombstoneManager {NativeTombstoneManager(Context context) {//启动handler线程,⽤于后续处理本服务的业务final ServiceThread thread = new ServiceThread(TAG + ":tombstoneWatcher",THREAD_PRIORITY_BACKGROUND, true /* allowIo */);thread.start();mHandler = thread.getThreadHandler();//启动⽂件监听/data/tombstonesmWatcher = new TombstoneWatcher();mWatcher.startWatching();}void onSystemReady() {registerForUserRemoval();registerForPackageRemoval();// 开机阶段先扫描⼀次/data/tombstones⽬录mHandler.post(() -> {final File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();for (int i = 0; tombstoneFiles != null && i < tombstoneFiles.length; i++) {if (tombstoneFiles[i].isFile()) {handleTombstone(tombstoneFiles[i]);开机流程有三个动作启动handler线程,⽤于后续处理本服务的业务TombstoneWatcher启动⽂件监听/data/tombstones开机阶段先扫描⼀次/data/tombstones⽬录看⼀下handleTombstoneframeworks/base/services/core/java/com/android/server/os/NativeTombstoneManager.javaprivate void handleTombstone(File path) {final String filename = path.getName();if (!filename.startsWith("tombstone_")) {return;}if (filename.endsWith(".pb")) {handleProtoTombstone(path);BootReceiver.addTombstoneToDropBox(mContext, path, true);} else {BootReceiver.addTombstoneToDropBox(mContext, path, false);如果是以pb结尾的原型⽂件,则handleProtoTombstone⽅法中为该⽂件⽣成TombstoneFile对象,并添加到数据结构private final SparseArray<TombstoneFile> mTombstones;并且,每个新⽣成的tombstone⽂件都会同步给dropbox新⽂件的监听frameworks/base/services/core/java/com/android/server/os/NativeTombstoneManager.javaclass TombstoneWatcher extends FileObserver {TombstoneWatcher() {super(TOMBSTONE_DIR, FileObserver.CREATE | FileObserver.MOVED_TO);}@Overridepublic void onEvent(int event, @Nullable String path) {mHandler.post(() -> {handleTombstone(new File(TOMBSTONE_DIR, path));});内部类TombstoneWatcher,当⽬录/data/tombstones有⽂件⽣成时,回调到onEvent,然后通过handleTombstone⽅法做处理AciivtyManager#getHistoricalProcessExitReasonsActivityManager ActivityManager ActivityManagerServiceActivityManagerServiceLocalServicesLocalServicesNativeTombstoneManagerNativeTombstoneManagergetHistoricalProcessExitReasonsenforceNotIsolatedCallerenforceDumpPermissionForPackageby:qiuchenggetServicecollectTombstonesnew ParceledListSlice<ApplicationExitInfo>(results)图:getHistoricalProcessExitReasons⽅法时序图需要注意返回的数据结构的处理ApplicationExitInfo。
Ubuntu下编译Android源码并运行Emulator 2
Ubuntu下编译Android源码并运行Emulator 2//apt-get autoremove sun-java5-jdk//apt-get install nautilus-open-terminalandroid源码的编译安装虚拟机时建议设置空间为16G左右,否则后面编译源代码可能会导致空间不够编译环境:Ubuntu8.101、安装一些环境sudo apt-get install build-essential //sudo apt-get install makesudo apt-get install gccsudo apt-get install g++ //sudo apt-get install libc6-devsudo apt-get install patch //sudo apt-get install texinfo //sudo apt-get install libncurses-dev //sudo apt-get install git-core gnupg //sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl sudo apt-get install ncurses-devsudo apt-get install zlib1g-devsudo apt-get install valgrindsudo apt-get install python2.5安装java环境sudo apt-get install sun-java5-jdk不要用sun-java6-jdk,否则会有问题2、设置环境变量vim ~/.bashrc在.bashrc中新增或整合PA TH变量,如下#java 程序开发/运行的一些环境变量在home/你的用户名/.bashrc中加入下面一些,有些是后面运行编译后的模拟器而用的export JA VA_HOME=usr/lib/jvm/java-1.5.0-sunexport JRE_HOME=usr/lib/jvm/java-1.5.0-sun/jreexport PA TH=$PATH JA V A_HOME/binexport PA TH=$PATH:~/mydroid/out/host/linux-x86/binexport ANDROID_PRODUCT_OUT=~/mydroid/out/target/product/genericexport CLASSPATH=.{JA V A_HOME}/lib JRE_HOME/lib CLASSPATHexport JA VA_PATH=${JA V A_HOME}/bin{JRE_HOME}/binHOME_BIN=~/bin/export PA TH=${PATH}{JA V A_PA TH}{JRE_PATH}{HOME_BIN};3、安装repo(用来更新android源码)创建~/bin目录,用来存放repo程序,如下:$ cd ~$ mkdir bin注意:下载后的.repo也许并不在这个文件夹中,请返回上一级目录找到后拷贝至此下载repo脚本并使其可执行:$ curl /repo >~/bin/repo$ chmod a+x ~/bin/repo4、下载android源码并更新之$ mkdir mydroid$ cd mydroid方式一建议不要用repo来下载(android源码超过1G,非常慢),直接在网上下载http: ///bbs/pub/cupcake.tar.gz。
enhancedscroller源码解读
第一部分:介绍1. 什么是enhancedscroller?enhancedscroller是一个用于构建iOS和Android应用程序的开源软件项目,它提供了一种高性能和灵活的滚动视图组件。
这个库旨在解决滚动视图在移动端应用开发中的性能和灵活性问题,为开发者提供一种更加高效和便捷的滚动视图解决方案。
2. 为什么要解读enhancedscroller的源码?作为开发者,在学习和使用一个开源库时,了解其源码是非常重要的。
通过阅读enhancedscroller的源码,开发者可以更加深入地理解这个库的实现原理和设计思想,为自己在实际项目中的应用提供更多的灵活性和优化方案。
解读enhancedscroller的源码对于希望深入理解移动端应用开发和滚动视图实现的开发者来说是非常有益的。
第二部分:准备工作1. 下载源码在进行源码解读之前,首先需要从enhancedscroller的官方仓库中下载源代码。
可以在GitHub上搜索enhancedscroller,然后找到其官方仓库并选择下载源代码的方式进行下载。
一般来说,enhancedscroller的源码会以ZIP压缩包的形式提供,下载后解压即可。
2. 安装开发环境为了更好地阅读和理解源码,建议在自己的开发环境中安装相关的开发工具和依赖库。
如果是iOS开发者,可以在Xcode中打开enhancedscroller的工程文件;如果是Android开发者,可以使用Android Studio进行相关的配置和导入。
第三部分:源码解读1. 整体结构在阅读源码之前,可以先了解一下enhancedscroller的整体结构。
通常一个开源库的源码结构会包括各种配置文件、源代码文件、测试文件等,通过对整体结构的了解,可以更快地找到自己感兴趣的部分进行深入学习。
2. 关键模块在源码解读的过程中,可以重点关注一些关键模块,比如滚动视图的布局计算、重用机制的实现、滚动事件的处理等。
android6.0源码分析之cameraapi2.0下的初始化流程分析
android6.0源码分析之cameraapi2.0下的初始化流程分析在文章android源码分析之Camera API2.0简介中,对Camera API2.0的框架以及代码做了简单介绍,本文将基于android6.0源码,分析Camera API2.0下的Camera2内置应用中,对Camera的初始化的流程分析,主要涉及Camera HAL3.0,Java 层的IPC Binder,Native层的CameraService 的C/S服务架构等关键点。
Camera2相关分析文章目录:android6.0源码分析之Camera API2.0简介android6.0源码分析之Camera2 HAL分析android6.0源码分析之Camera API2.0下的初始化流程分析android6.0源码分析之Camera API2.0下的Preview(预览)流程分析android6.0源码分析之Camera API2.0下的Capture流程分析android6.0源码分析之Camera API2.0下的video流程分析Camera API2.0的应用1、Camera2初始化的应用层流程分析Camera2的初始化流程与Camera1.0有所区别,本文将就Camera2的内置应用来分析Camera2.0的初始化过程。
Camera2.0首先启动的是CameraActivity,而它继承自QuickActivity,在代码中你会发现没有重写OnCreate等生命周期方法,因为此处采用的是模板方法的设计模式,在QuickActivity中的onCreate方法调用的是onCreateTasks等方法,所以要看onCreate方法就只须看onCreateTasks方法即可://CameraActivity.java@Overridepublic void onCreateTasks(Bundle state) { Profile profile =mProfiler.create('CameraActivity.onCreateTasks') .start(); ... mOnCreateTime = System.currentTimeMillis(); mAppContext = getApplicationContext(); mMainHandler = new MainHandler(this, getMainLooper()); …try { //初始化OneCameraOpener对象①mOneCameraOpener = OneCameraModule.provideOneCameraOpener( mFeatureConfi g, mAppContext,mActiveCameraDeviceTracker, ResolutionUtil.getDisplayMetrics(this)); mOneCameraManager = OneCameraModule.provideOneCameraManager(); } catch (OneCameraException e) {...} …//建立模块信息②ModulesInfo.setupModules(mAppContext, mModuleManager, mFeatureConfig); …//进行初始化③mCurrentModule.init(this, isSecureCamera(), isCaptureIntent()); …}123456789101112131415161718192021 22232425如代码所示,重要的有以上三点,先看第一点://OneCameraModule.javapublic static OneCameraOpener provideOneCameraOpener(OneCameraFeatureConfig featureConfig, Context context, ActiveCameraDeviceTrackeractiveCameraDeviceTracker,DisplayMetrics displayMetrics) throws OneCameraException { //创建OneCameraOpener对象Optional manager =Camera2OneCameraOpenerImpl.create( featureConfig, context, activeCameraDeviceTracker, displayMetrics); if(!manager.isPresent()) { manager = LegacyOneCameraOpenerImpl.create(); } ... return manager.get();}1234567891011121314它调用Camera2OneCameraOpenerImpl的create方法来获得一个OneCameraOpener对象,以供CameraActivity之后的操作使用,继续看create方法://Camera2OneCameraOpenerImpl.javapublic static Optional create(OneCameraFeatureConfig featureConfig, Context context, ActiveCameraDeviceTracker activeCameraDeviceTracker, DisplayMetrics displayMetrics) { ... CameraManager cameraManager; try { cameraManager =AndroidServices.instance().provideCameraManager(); } catch (IllegalStateException ex) {...} //新建一个Camera2OneCameraOpenerImpl对象OneCameraOpener oneCameraOpener = newCamera2OneCameraOpenerImpl( featureConfig, context, cameraManager, activeCameraDeviceTracker, displayMetrics);returnOptional.of(oneCameraOpener);}12345678910111213141516很明显,它首先获取一个cameraManger对象,然后根据这个cameraManager对象来新创建了一个Camera2OneCameraOpenerImpl对象,所以第一步主要是为了获取一个OneCameraOpener对象,它的实现为Camera2OneCameraOpenerImpl类。
AndroidAdapterView源码分析以及其相关回收机制的分析
AndroidAdapterView源码分析以及其相关回收机制的分析前言忽然,发现,网上的公开资料都是教你怎么继承一个baseadapter,然后重写那几个方法,再调用相关view的setAdpater()方法,接着,你的item 就显示在手机屏幕上了。
很少有人关注android adpater模式机制的实现原理,比较深入的也不过是说说adapter getview()中的回收情况。
今天把相关的源码看了一遍,把自己的理解记录下来。
AdpaterView 概览AdpaterViewapi手册的说明:An AdapterView is aview whose children are determined by anAdapter.实际上android里面ListView, GridView, Spinner , Gallery等view都是基于设计模式上的设配器模式实现的,只要熟悉设配器模式的相关知识,就知道如何从源码里面找到相关的实现线索。
认识AdapterView源码链接https:///android/platform_frameworks_base/blob/m aster/core/java/android/widget/AdapterView.java要理解listview等的实现,其父类是不得不看。
源码有1200多行。
阅读完AdapterView,能搞明白以下问题1.响应数据的更改。
(793 - 842)2.知道点击view的时候,获得对应的位置.(593 - 615)响应数据的更改这里假设你已经打开了AdpaterView 的 793 到 842 行。
在我刚开始用adapterview 的时候,最让我费劲的就是,为什么我调用adpater 的 notifyDataSetChanged() 就能更新view 的状态了呢,然后跟调用notifyDataSetInvalidated() 两者之间又有什么区别呢?以前,找了一下资料,没找到很详细的说明,现在从源码里面找答案的话,就很清晰了。
Ubuntu下编译Android源码并运行Emulator2
Ubuntu下编译Android源码并运行Emulator2Ubuntu下编译Android源码并运行Emulator2在Ubuntu上编译和运行Android源码并运行Emulator需要一些准备工作和步骤,下面是详细的步骤说明。
准备工作:1.安装必要的依赖项:- Java Development Kit (JDK): 通过运行`sudo apt-get install openjdk-8-jdk`命令安装Java开发工具包。
- Git: 运行`sudo apt-get install git`命令安装Git。
- 必要的库和工具: 运行`sudo apt-get install libx11-dev libxext-dev libxi-dev libxrender-dev libxtst-dev libxt-dev libcups2-dev libncurses5-dev libgnome2-0 libgnomeui-0 libgtk2.0-0 libatk1.0-0 libbonoboui2-0 libcairo2 libfontconfig1-devlibxslt-dev libxml2-dev libcurl4-openssl-dev libusb-1.0-0-dev libgtk2.0-bin libdbus-1-dev libdbus-glib-1-dev libgconf2-dev libnss3-dev automake libtool pkg-config`命令安装必要的库和工具。
2. 安装Repo及相关工具:编译源码:1. 初始化环境:运行`. build/envsetup.sh`命令初始化环境。
2. 选择目标设备:运行`lunch`命令选择目标设备,例如选择"2.修改设备名-eng"即选择修改设备名为eng类型的目标设备。
3. 编译源码:运行`make -j4`命令开始编译源码,-j4参数可以指定并行编译的线程数,可以根据系统配置适当调整。
Android2.2源码编译步骤详解
Android2.2源码编译步骤详解Ubuntu10.4 + Android2.2 + JDK1.51、编译环境Android2.2 + Ubuntu10.04 + JDK1.5安装必要的软件环境sudo apt-get install git-coresudo apt-get install gnupgsudo apt-get install flexsudo apt-get install bisonsudo apt-get install gperfsudo apt-get install libsdl-devsudo apt-get install libesd0-devsudo apt-get install libwxgtk2.6-devsudo apt-get install build-essentialsudo apt-get install zipsudo apt-get install curlsudo apt-get install libncurses5-devsudo apt-get install zlib1g-dev以上就是官方推荐的软件包,可能需要的软件包还有以下几个sudo apt-get install makesudo apt-get install gccsudo apt-get install g++sudo apt-get install libc6-devsudo apt-get install patchsudo apt-get install texinfosudo apt-get install valgrindsudo apt-get install pythonJDK1.5安装官方声明:32位操作系统下JDK必须要用1.5的,是因为在编译Android api docs时需要1.5的。
用JDK1.6必须用64位系统,当然也有解决办法,网上教程很多此处就不再一一声明。
Android reboot分析
Androidreboot分析1./system/core/android_reboot.c[cpp]view plaincopyprint?1.int android_reboot(int cmd, int flags, char *arg)该函数作为通用API, 可以分别用在如下地方:2.adbshellmodereboot3.fastbootdownloadingmodereboot4.recoverymodereboot5.Chargingmodereboot2./kernel/include/linux/reboot.ho定义了__reboot() 系统调用的magicvalueo定义了__reboot系统调用的commando需要关注一下某些函数是体系结构无关的,某些是有体系结构依赖的[cpp]view plaincopyprint?1./*2.* Architecture-specific implementations of sys_reboot commands.3.*/4.5.extern void machine_restart(char *cmd);6.extern void machine_halt(void);7.extern void machine_power_off(void);8.9.extern void machine_shutdown(void);10.struct pt_regs;11.extern void machine_crash_shutdown(struct pt_ regs *);12.13./*14.* Architecture independent implemenations of sys_reboot commands.15.*/16.17.extern void kernel_restart_prepare(char *cmd);18.extern void kernel_restart(char *cmd);19.extern void kernel_halt(void);20.extern void kernel_power_off(void);21.22.extern int C_A_D; /* for sysctl */23.void ctrl_alt_del(void);24.25.#define POWEROFF_CMD_PATH_LEN 25626.extern char poweroff_cmd[POWEROFF_CMD_P ATH_LEN];27.28.extern int orderly_poweroff(bool force);29.30./*31.* Emergency restart, callable from an interrupt handler.32.*/33.34.extern void emergency_restart(void);35.#include <asm/emergency-restart.h>o展开<asm/emergency-restart.h> 后如下[cpp]view plaincopyprint?static inline void machine_emergency_restart(void){<span style="color:#33cc0;">machine_restart</span>(N ULL);}3./kernel/kernel/sys.creboot() systemcall4.5.reboot() 系统调用需要:oOnlyrootmaycallitwithobviousreasonsorootneedstosetupsomemagicnumbersinregisters以避免错误o这里可以添加ctrl-alt-del-key响应oreboot() 不做sync() 动作,需要自己显式调用sync()[cpp]view plaincopyprint?1.SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, u nsigned int, cmd,2.void __user *, arg)3.{4.char buffer[256];5.int ret = 0;6.7./* We only trust the superuser with rebooting the sys tem. */8.if (!capable(CAP_SYS_BOOT))9.return -EPERM;10.11./* For safety, we require "magic" arguments. */12.if (magic1 != LINUX_REBOOT_MAGIC1 ||13.(magic2 != LINUX_REBOOT_MAGIC2 &&14.magic2 != LINUX_REBOOT_MAGIC2A &&15.magic2 != LINUX_REBOOT_MAGIC2B &&16.magic2 != LINUX_REBOOT_MAGIC2C))17.return -EINVAL;18.19./* Instead of trying to make the power_off code look like20.* halt when pm_power_off is not set do it the easy w ay.21.*/22.if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)23.cmd = LINUX_REBOOT_CMD_HALT;24.25.mutex_lock(&reboot_mutex);26.switch (cmd) {27.case LINUX_REBOOT_CMD_RESTART:28.kernel_restart(NULL);29.break;30.31.case LINUX_REBOOT_CMD_CAD_ON:32.C_A_D = 1;33.break;34.35.case LINUX_REBOOT_CMD_CAD_OFF:36.C_A_D = 0;37.break;38.39.case LINUX_REBOOT_CMD_HALT:40.kernel_halt();41.do_exit(0);42.panic("cannot halt");43.44.case LINUX_REBOOT_CMD_POWER_OFF:45.kernel_power_off();46.do_exit(0);47.break;48.49.case LINUX_REBOOT_CMD_RESTART2:50.if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {51.ret = -EFAULT;52.break;53.}54.buffer[sizeof(buffer) - 1] = '\0';55.56.kernel_restart(buffer);57.break;59.#ifdef CONFIG_KEXEC60.case LINUX_REBOOT_CMD_KEXEC:61.ret = kernel_kexec();62.break;63.#endif64.65.#ifdef CONFIG_HIBERNATION66.case LINUX_REBOOT_CMD_SW_SUSPEND:67.ret = hibernate();68.break;69.#endif70.71.default:72.ret = -EINVAL;73.break;74.}75.mutex_unlock(&reboot_mutex);76.return ret;77.}2.体系结构无关的API将会调用平台体系结构相关的API3.[cpp]view plaincopyprint?1./**2.* kernel_restart - reboot the system3.* @cmd: pointer to buffer containing command to e xecute for restart4.* or %NULL6.* Shutdown everything and perform a clean reboot.7.* This is not safe to call in interrupt context.8.*/9.void kernel_restart(char *cmd)10.{11.kernel_restart_prepare(cmd);12.if (!cmd)13.printk(KERN_EMERG "Restarting system.\n");14.else15.printk(KERN_EMERG "Restarting system with comma nd '%s'.\n", cmd);16.kmsg_dump(KMSG_DUMP_RESTART);17.machine_restart(cmd);18.}4.对于armplatform, 下一步是/kernel/arch/arm/kernel/process.c[cpp]view plaincopyprint?1.void machine_restart(char *cmd)2.{3.machine_shutdown();4.arm_pm_restart(reboot_mode, cmd);5.}5.同文件里面进行了函数指针转换[cpp]view plaincopyprint?1.void (*arm_pm_restart)(char str, const char *cmd) = a rm_machine_restart;2.EXPORT_SYMBOL_GPL(arm_pm_restart);6.arm_machine_restart() 如下[cpp]view plaincopyprint?1.void arm_machine_restart(char mode, const char *cmd)2.{3./* Flush the console to make sure all the relevant me ssages make it4.* out to the console drivers */5.arm_machine_flush_console();6.7./* Disable interrupts first */8.local_irq_disable();9.local_fiq_disable();10.11./*12.* Tell the mm system that we are going to reboot -13.* we may need it to insert some 1:1 mappings so tha t14.* soft boot works.15.*/16.setup_mm_for_reboot(mode, NULL);17.18./* Clean and invalidate caches */19.flush_cache_all();20.21./* Turn off caching */22.cpu_proc_fin();23.24./* Push out any further dirty data, and ensure cache is empty */25.flush_cache_all();26.27./*28.* Now call the architecture specific reboot code.29.*/30.arch_reset(mode, cmd);31.32./*33.* Whoops - the architecture was unable to reboot.34.* Tell the user!35.*/36.mdelay(1000);37.printk("Reboot failed -- System halted\n");38.while (1);39.}7.然后是/kernel/arch/arm/plat-xxxx/include/mach/system.h8.对于Qualcomm是[cpp]view plaincopyprint?1.#include <mach/hardware.h>2.3.void arch_idle(void);4.5.static inline void arch_reset(char mode, const char *c md)6.{7.for (;;) ; /* depends on IPC w/ other core */8.}9.10./* low level hardware reset hook -- for example, hitting the11.* PSHOLD line on the PMIC to hard reset the system12.*/13.extern void (*msm_hw_reset_hook)(void);对于SamsungS3C2410是[cpp]view plaincopyprint?1.extern void (*s3c24xx_reset_hook)(void);2.3.static void4.arch_reset(char mode, const char *cmd)5.{6.if (mode == 's') {7.cpu_reset(0);8.}9.10.if (s3c24xx_reset_hook)11.s3c24xx_reset_hook();12.13.arch_wdt_reset();14.15./* we'll take a jump through zero as a poor second */16.cpu_reset(0);17.}典型的示例如下:[cpp]view plaincopyprint?1.static inline void arch_idle(void)2.{3.cpu_do_idle();4.}5.6.static inline void arch_reset(char mode, const char *c md)7.{8.cpu_reset(0);9.}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图库Gallery2Gallery2主要功能是实现本地存储器、MTP存储器和网络存储器中媒体(图像和视频)的浏览、显示和更多操作(删除、分享、选择和缩放等)。
下面用一张简单的用例图描述了Gallery2的功能和职责。
Gallery 主要是4个页面的跳转:AlbumSetPage.Java(相册缩略图);AlbumPage.java(单个相册照片缩略图);PhotoPage.java(单张照片);SlideShowPage.java(幻灯片界面);跳转过程:AlbumSetPage.Java→AlbumPage.java→PhotoPage.javaSlideShowPage.java是单独的。
这些界面类父类为ActivityState.java;这些界面的切换由StateManager.java负责。
1 界面跳转过程:在Galley2模块,我们先从程序的入口看起,在androidManifest.xml中注册Application标签(Android 系统会为每个程序运行时创建一个Application的类对象且仅创建一个,他的生命周期等于这个程序的生命周期,它是全局的单实例的,一般做一些全局的初始化操作),应用创建时就会被初始化,维护应用内部全局数据,主要看几个函数:initializeAsyncTask(), GalleryUtils.initialize(this),GalleryUtil是Gallery的工具类,获得了屏幕参数,WindowManager,Resource等Gallery 从launcher进入Gallery,进入GalleryActivity.ava@Overrideprotected void onCreate(Bundle savedInstanceState) {…...setContentView(yout.main);if (savedInstanceState != null) {getStateManager().restoreFromState(savedInstanceState);} else {initializeByIntent();}}private void initializeByIntent() {Intent intent = getIntent();String action = intent.getAction();if (Intent.ACTION_GET_CONTENT.equalsIgnoreCase(action)){ startGetContent(intent);} else if(Intent.ACTION_PICK.equalsIgnoreCase(action)) { // We do NOT really support the PICKintent. Handle it as// the GET_CONTENT. However, we needto translate the type// in the intent here.Log.w(TAG, "action PICK is notsupported");String type =Utils.ensureNotNull(intent.getType());if(type.startsWith("vnd.android.cursor.dir/")) {if(type.endsWith("/image")) intent.setType("image/*");if(type.endsWith("/video")) intent.setType("video/*");}startGetContent(intent);} else if(Intent.ACTION_VIEW.equalsIgnoreCase(action)||ACTION_REVIEW.equalsIgnoreCase(action)){startViewAction(intent);} else {startDefaultPage();}}从这个函数看,如果从相册应用图标进入,会走startDefaultPage流程,如果外部打开图片,会走startGetContent流程。
public void startDefaultPage() {PicasaSource.showSignInReminder(this);Bundle data = new Bundle();data.putString(AlbumSetPage.KEY_MEDIA_PATH,getDataManager().getTopSetPath(DataManager.INCLUDE_ALL));getStateManager().startState(AlbumSetPage.class,data);mVersionCheckDialog =PicasaSource.getVersionCheckDialog(this);if (mVersionCheckDialog != null) {mVersionCheckDialog.setOnCancelListener(this);}}这样我们看到的是AlbumSetPage.Java这个界面了。
我们从起始页面开始,点击某个相册:一个相册是一个SlotView对象,这里不详细说明SlotView,相关介绍请访问:/discovery_by_joseph/article/details/17500425在onCreate()中初始化了SlotView。
并且对SlotView进行了监听:mSlotView.setListener(new SlotView.SimpleListener() {@Overridepublic void onDown(int index) {AlbumSetPage.this.onDown(index);}@Overridepublic void onUp(boolean followedByLongPress) {AlbumSetPage.this.onUp(followedByLongPress);}@Overridepublic void onSingleTapUp(int slotIndex) {AlbumSetPage.this.onSingleTapUp(slotIndex);}@Overridepublic void onLongTap(int slotIndex) {AlbumSetPage.this.onLongTap(slotIndex);}});接下来我们看红色部分:public void onSingleTapUp(int slotIndex) {if (!mIsActive) return;if (mSelectionManager.inSelectionMode()) {MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);if (targetSet == null) return; // Content is dirty, we shall reload soon mSelectionManager.toggle(targetSet.getPath());mSlotView.invalidate();} else {// Show pressed-up animation for the single-tap.mAlbumSetView.setPressedIndex(slotIndex);mAlbumSetView.setPressedUp();mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0), FadeTexture.DURATION);}}这里发了消息:消息处理是在onCreate中创建的:mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {@Overridepublic void handleMessage(Message message) {switch (message.what) {case MSG_PICK_ALBUM: {try {pickAlbum(message.arg1);} catch (Exception e) {Log.d(TAG, "exception when pickAlbum");}}default: throw new AssertionError(message.what);}}};}private void pickAlbum(int slotIndex) {if (!mIsActive) return;......mActivity.getStateManager().startStateForResult(AlbumPage.class, REQUEST_DO_ANIMATION, data);}@Overrideprotected void onStateResult(int requestCode, int resultCode, Intent data) {if (data != null && data.getBooleanExtra(AlbumPage.KEY_EMPTY_ALBUM, false)) {showEmptyAlbumToast(Toast.LENGTH_SHORT);}switch (requestCode) {case REQUEST_DO_ANIMATION: {mSlotView.startRisingAnimation();}}}接收到动作消息,启动相册页面AlbumPage。
后续的进入到单张页面:PhotoPage.java 也是同样的过程,但是我们在代码里看到的是下面:private void pickPhoto(int slotIndex, boolean startInFilmstrip) {if (!mIsActive) return;......if (startInFilmstrip) {mActivity.getStateManager().switchState(this, FilmstripPage.class, data);} else {mActivity.getStateManager().startStateForResult(SinglePhotoPage.class, REQUEST_PHOTO, data);}}这里我们看到跳转的是SinglePhotoPage 不是PhotoPage。