Android 开发基础常识
从上到下依次分为六层:
1
2
3
4
5
6
应用框架层
进程通信层
系统服务层
Android运行时层
硬件抽象层
Linux内核层
Activity如与Service通信?
可以通过bindService的方式,先在Activity里实现一个ServiceConnection接口,并将该接口传递给bindService()方法,在ServiceConnection接口的onServiceConnected()方法 里执行相关操作。
Service的生命周期与启动方法有什么区别?
startService():开启Service,调用者退出后Service仍然存在。 bindService():开启Service,调用者退出后Service也随即退出。
Service生命周期:
只是用startService()启动服务:onCreate() -> onStartCommand() -> onDestory 只是用bindService()绑定服务:onCreate() -> onBind() -> onUnBind() -> onDestory 同时使用startService()启动服务与bindService()绑定服务:onCreate() -> onStartCommnad() -> onBind() -> onUnBind() -> onDestory
广播分为哪几种,应用场景是什么?
普通广播:调用sendBroadcast()发送,最常用的广播。 有序广播:调用sendOrderedBroadcast(),发出去的广播会被广播接受者按照顺序接收,广播接收者按照Priority属性值从大-小排序,Priority属性相同者,动态注册的广播优先,广播接收者还可以 选择对广播进行截断和修改。
广播的两种注册方式有什么区别?
静态注册:常驻系统,不受组件生命周期影响,即便应用退出,广播还是可以被接收,耗电、占内存。 动态注册:非常驻,跟随组件的生命变化,组件结束,广播结束。在组件结束前,需要先移除广播,否则容易造成内存泄漏。
广播发送和接收的原理了解吗?
继承BroadcastReceiver,重写onReceive()方法。 通过Binder机制向ActivityManagerService注册广播。 通过Binder机制向ActivityMangerService发送广播。 ActivityManagerService查找符合相应条件的广播(Intent Filter/Permission)的BroadcastReceiver,将广播发送到BroadcastReceiver所在的消息队列中。 BroadcastReceiver所在消息队列拿到此广播后,回调它的on Receive()方法。
ContentProvider、ContentResolver与ContentObserver之间的关系是什么?
ContentProvider:管理数据,提供数据的增删改查操作,数据源可以是数据库、文件、XML、网络等,ContentProvider为这些数据的访问提供了统一的接口,可以用来做进程间数据共享。 Content Resolver:ContentResolver可以不同URI操作不同的ContentProvider中的数据,外部进程可以通过ContentResolver与ContentProvider进行交互。 ContentObserver:观察ContentProvider中的数据变化,并将变化通知给外界。
遇到过哪些关于Fragment的问题,如何处理的?
getActivity()空指针:这种情况一般发生在在异步任务里调用getActivity(),而Fragment已经onDetach(),此时就会有空指针,解决方案是在Fragment里使用一个全局变量mActivity,在onAttach()方法里赋值,这样可能会引起内存泄漏,但是异步任务没有停止的情况下本身就已经可能内存泄漏,相比直接crash,这种方式显得更妥当一些。 Fragment视图重叠:在类onCreate()的方法加载Fragment,并且没有判断saveInstanceState==null或if(findFragmentByTag(mFragmentTag) == null),导致重复加载了同一个Fragment导致重叠。(PS:replace情况下,如果没有加入回退栈,则不判断也不会造成重叠,但建议还是统一判断下)
1
2
3
4
5
6
7
8
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
// 在页面重启时,Fragment会被保存恢复,而此时再加载Fragment会重复加载,导致重叠 ;
if(saveInstanceState == null){
// 或者 if(findFragmentByTag(mFragmentTag) == null)
// 正常情况下去 加载根Fragment
}
}
Android里的Intent传递的数据有大小限制吗,如何解决?
Intent传递数据大小的限制大概在1M左右,超过这个限制就会静默崩溃。处理方式如下:
进程内:EventBus,文件缓存、磁盘缓存。 进程间:通过ContentProvider进行款进程数据共享和传递。
描述一下Android的事件分发机制?
Android事件分发机制的本质:事件从哪个对象发出,经过哪些对象,最终由哪个对象处理了该事件。此处对象指的是Activity、Window与View。
Android事件的分发顺序:Activity(Window) -> ViewGroup -> View
Android事件的分发主要由三个方法来完成,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 父View调用dispatchTouchEvent()开始分发事件
public boolean dispatchTouchEvent(MotionEvent event){
boolean consume = false;
// 父View决定是否拦截事件
if(onInterceptTouchEvent(event)){
// 父View调用onTouchEvent(event)消费事件,如果该方法返回true,表示
// 该View消费了该事件,后续该事件序列的事件(Down、Move、Up)将不会在传递
// 该其他View。
consume = onTouchEvent(event);
}else{
// 调用子View的dispatchTouchEvent(event)方法继续分发事件
consume = child.dispatchTouchEvent(event);
}
return consume;
}
描述一下View的绘制原理?
View的绘制流程主要分为三步:
onMeasure:测量视图的大小,从顶层父View到子View递归调用measure()方法,measure()调用onMeasure()方法,onMeasure()方法完成绘制工作。 onLayout:确定视图的位置,从顶层父View到子View递归调用layout()方法,父View将上一步measure()方法得到的子View的布局大小和布局参数,将子View放在合适的位置上。 onDraw:绘制最终的视图,首先ViewRoot创建一个Canvas对象,然后调用onDraw()方法进行绘制。onDraw()方法的绘制流程为:
1
2
3
4
5
6
① 绘制视图背景。
② 绘制画布的图层。
③ 绘制View内容。
④ 绘制子视图,如果有的话。
⑤ 还原图层。
⑥ 绘制滚动条。
requestLayout()、invalidate()与postInvalidate()有什么区别?
requestLayout():该方法会递归调用父窗口的requestLayout()方法,直到触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为true,会触发onMesaure()与onLayout()方法,不一定会触发onDraw()方法。
invalidate():该方法递归调用父View的invalidateChildInParent()方法,直到调用ViewRootImpl的invalidateChildInParent()方法,最终触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为false,不会触发onMesaure()与onLayout()方法,当时会触发onDraw()方法。
postInvalidate():该方法功能和invalidate()一样,只是它可以在非UI线程中调用。
一般说来需要重新布局就调用requestLayout()方法,需要重新绘制就调用invalidate()方法。
了解APK的打包流程吗,描述一下?
Android的包文件APK分为两个部分:代码和资源,所以打包方面也分为资源打包和代码打包两个方面,这篇文章就来分析资源和代码的编译打包原理。
APK整体的的打包流程:
通过AAPT工具进行资源文件(包括AndroidManifest.xml、布局文件、各种xml资源等)的打包,生成R.java文件。 通过AIDL工具处理AIDL文件,生成相应的Java文件。 通过Javac工具编译项目源码,生成Class文件。 通过DX工具将所有的Class文件转换成DEX文件,该过程主要完成Java字节码转换成Dalvik字节码,压缩常量池以及清除冗余信息等工作。 通过ApkBuilder工具将资源文件、DEX文件打包生成APK文件。 利用KeyStore对生成的APK文件进行签名。 如果是正式版的APK,还会利用ZipAlign工具进行对齐处理,对齐的过程就是将APK文件中所有的资源文件举例文件的起始距离都偏移4字节的整数倍,这样通过内存映射访问APK文件 的速度会更快。
(1)打包资源文件。 (2)处理aidl文件,生成相应java 文件。对于没有使用到aidl的android工程,可以跳过此步骤。 (3)编译工程源代码,生成相应class 文件。 这一步调用了javac编译工程src目录下所有的java源文件,生成的class文件位于工程的bin\classes目录下,上图假定编译工程源代码时程序是基于android SDK开发的,实际开发过程中,也有可能会使用android NDK来编译native代码,因此,如果可能的话,这一步还需要使用android NDK编译C/C++代码,当然,编译C/C++代码的步骤也可以提前到第一步或第二步。通过Java Compiler编译R.java、Java接口文件、Java源文件,生成.class文件。 (4)转换所有class文件,生成classes.dex文件。Android虚拟机的可执行文件为dex格式,所以需要此步骤。 (5)打包生成apk。打包后的res文件夹(除res/raw资源被原装不动地打包进APK之外)、打包后类文件(.dex文件)、libs文件(包括.so文件,当然很多工程都没有这样的文件,如果你不使用C/C++开发的话)、resources.arsc、assets、AndroidManifest.xml打包成apk文件。 (6)对apk文件进行签名。 (7)对签名后的apk文件进行对其处理。在 Android SDK 中包含一个名为 “zipalign” 的工具,它能够对打包后的 app 进行优化。 即对签名后的apk进行对齐处理。
当点击一个应用图标以后,都发生了什么,描述一下这个过程?
点击应用图标后会去启动应用的LauncherActivity,如果LancerActivity所在的进程没有创建,还会创建新进程,整体的流程就是一个Activity的启动流程。
其实 Launcher 本身就是一个应用程序,运行在自己的进程中,我们看到的桌面就是 Launcher 中的一个 Activity。
ActivityThread 是什么,它是一个线程吗,如何被启动的?
它不是一个线程,它是运行在 App 进程中的主线程中的一个方法中。当 App 进程创建时会执行 ActivityThread.main(),ActivityThread.main() 首先会创建 Looper 执行 Looper.prepareMainLooper();然后创建 ActivityThread 并调用 ActivityThread.attach() 方法告诉 ActivityManagerService 我们创建了一个应用 并将 ApplicationThread 传给 ActivityManagerService;最后调用 Looper.loop()。
ActivityClientRecord 与 ActivityRecord 是什么?
记录 Activity 相关信息,比如:Window,configuration,ActivityInfo 等。 ActivityClientRecord 是客户端的,ActivityRecord 是 ActivityManagerService 服务端的。
Context 是什么,ContextImpl,ContextWapper 是什么?
Context 定义了 App 进程的相关环境,Context 是一个接口,ContextImpl 是子类,ContextWapper 是具体实现。
应用资源是在 Application 初始化的时候,也就是创建 Application,ContextImpl 的时候,ContextImpl 就包含这个路径,主要就是对就是 ResourcesManager 这个单例的引用。
可以看出每次创建 Application 和 Acitvity 以及 Service 时就会有一个 ContextImpl 实例,ContentProvider 和BroadcastReceiver 的 Context 是其他地方传入的。
所以 Context 数量 = Application 数量 + Activity 数量 + Service 数量,单进程情况下 Application 数量就是 1。
Instrumentation 是什么?
管理着组件Application,Activity,Service等的创建,生命周期调用。
Application 是什么,什么时候创建的,每个应用程序有几个 Application?
Application 是在 ActivityThread.handleBindApplication() 中创建的,一个进程只会创建一个 Application,但是一个应用如果有多个进程就会创建多个 Application 对象。
点击 Launcher 启动 Activity 和应用内部启动 Activity 的区别?
点击 Launcher 时会创建一个新进程来开启 Activity,而应用内打开 Activity,如果 Activity 不指定新进程,将在原来进程打开,是否开启新进程实在 ActivityManagerService 进行控制的,上面分析得到,每次开启新进程时会保存进程信息,默认为 应用包名 + 应用UID,打开 Activity 时会检查请求方的信息来判断是否需要新开进程。Launcher 打开 Activity 默认 ACTIVITY_NEW_TASK,新开一个 Activity 栈来保存 Activity 的信息。
Activity 启动过程,onCreate(),onResume() 回调时机及具体作用?
Activity.onCreate() 完成了 App 进程,Application,Activity 的创建,调用 setContentView() 给 Activity 设置了 layout 布局。
Activity.onResume() 完成了 Activity 中 Window 与 WindowManager 的关联,并对所有子 View 进行渲染并显示。
注:这里单独提一下ActivityStackSupervisior,这是高版本才有的类,它用来管理多个ActivityStack,早期的版本只有一个ActivityStack对应着手机屏幕,后来高版本支持多屏以后,就有了多个ActivityStack,于是就引入了ActivityStackSupervisior用来管理多个ActivityStack。
整个流程主要涉及四个进程:
调用者进程,如果是在桌面启动应用就是Launcher应用进程。 ActivityManagerService等所在的System Server进程,该进程主要运行着系统服务组件。 Zygote进程,该进程主要用来fork新进程。 新启动的应用进程,该进程就是用来承载应用运行的进程了,它也是应用的主线程(新创建的进程就是主线程),处理组件生命周期、界面绘制等相关事情。
有了以上的理解,整个流程可以概括如下:
点击桌面应用图标,Launcher进程将启动Activity(MainActivity)的请求以Binder的方式发送给了AMS。 AMS接收到启动请求后,交付ActivityStarter处理Intent和Flag等信息,然后再交给ActivityStackSupervisior/ActivityStack 处理Activity进栈相关流程。同时以Socket方式请求Zygote进程fork新进程。 Zygote接收到新进程创建请求后fork出新进程。 在新进程里创建ActivityThread对象,新创建的进程就是应用的主线程,在主线程里开启Looper消息循环,开始处理创建Activity。 ActivityThread利用ClassLoader去加载Activity、创建Activity实例,并回调Activity的onCreate()方法。这样便完成了Activity的启动。
BroadcastReceiver与LocalBroadcastReceiver有什么区别?
BroadcastReceiver 是跨应用广播,利用Binder机制实现。 LocalBroadcastReceiver 是应用内广播,利用Handler实现,利用了IntentFilter的match功能,提供消息的发布与接收功能,实现应用内通信,效率比较高。
Android Handler机制是做什么的,原理了解吗?
主要涉及的角色如下所示:
Message:消息,分为硬件产生的消息(例如:按钮、触摸)和软件产生的消息。 MessageQueue:消息队列,主要用来向消息池添加消息和取走消息。 Looper:消息循环器,主要用来把消息分发给相应的处理者。 Handler:消息处理器,主要向消息队列发送各种消息以及处理各种消息。
整个消息的循环流程还是比较清晰的,具体说来:
Handler通过sendMessage()发送消息Message到消息队列MessageQueue。 Looper通过loop()不断提取触发条件的Message,并将Message交给对应的target handler来处理。 target handler调用自身的handleMessage()方法来处理Message。
事实上,在整个消息循环的流程中,并不只有Java层参与,很多重要的工作都是在C++层来完成的。我们来看下这些类的调用关系。
Android Binder机制是做什么的,为什么选用Binder,原理了解吗?
Android Binder是用来做进程通信的,Android的各个应用以及系统服务都运行在独立的进程中,它们的通信都依赖于Binder。
为什么选用Binder,在讨论这个问题之前,我们知道Android也是基于Linux内核,Linux现有的进程通信手段有以下几种:
管道:在创建时分配一个page大小的内存,缓存区大小比较有限; 消息队列:信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信; 共享内存:无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快;但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决; 套接字:作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信; 信号量:常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。6. 信号: 不适用于信息交换,更适用于进程中断控制,比如非法内存访问,杀死某个进程等;
既然有现有的IPC方式,为什么重新设计一套Binder机制呢。主要是出于以上三个方面的考量:
高性能:从数据拷贝次数来看Binder只需要进行一次内存拷贝,而管道、消息队列、Socket都需要两次,共享内存不需要拷贝,Binder的性能仅次于共享内存。 稳定性:上面说到共享内存的性能优于Binder,那为什么不适用共享内存呢,因为共享内存需要处理并发同步问题,控制负责,容易出现死锁和资源竞争,稳定性较差。而Binder基于C/S架构,客户端与服务端彼此独立,稳定性较好。 安全性:我们知道Android为每个应用分配了UID,用来作为鉴别进程的重要标志,Android内部也依赖这个UID进行权限管理,包括6.0以前的固定权限和6.0以后的动态权限,传荣IPC只能由用户在数据包里填入UID/PID,这个标记完全 是在用户空间控制的,没有放在内核空间,因此有被恶意篡改的可能,因此Binder的安全性更高。
Binde机制简单理解:
在Android系统的Binder机制中,是有Client,Service,ServiceManager,Binder驱动程序组成的,其中Client,service,Service Manager运行在用户空间,Binder驱动程序是运行在内核空间的。而Binder就是把这4种组件粘合在一块的粘合剂,
请解释下Android程序运行时权限与文件系统权限的区别。
答:运行时权限Dalvik( android授权)
文件系统 linux 内核授权
常用五种布局方式,分别是:
FrameLayout(框架布局), LinearLayout (线性布局), AbsoluteLayout(绝对布局), RelativeLayout(相对布局), TableLayout(表格布局)
1. Tcp和http 的区别
Tcp是在网络层,http是在服务层.Http借助Httpclient和urlconnenticon是短连接 ,请求一次后就断开了需要 重新请求才能连接 Tcp借助是socket,长连接需要三次握手,第四次握手才能取消连接
2 .存储数据有哪些方式
文件存储, sharedpreference存储, sqllite存储 , contentprivider存储 , 网络存储
5. 两个Activity之间怎么传递数据?
基本数据类型可以通过.Intent 传递数据 Bundle bundle = new Bundle(); bundle.putShort(key, value); intent.putExtras(bundle); 获取到激活他的 getIntent(); Intent intent = getIntent(); Bundle bundle = intent.getExtras(); Bundle 类似map的集合 intent.getStringExtra(“key”,”value”);
6. Activity怎么和service绑定,怎么在activity中启动自己对应的service?
startService() 方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。 stopService停止 bindService () 把service 与调用者绑定 ,如果调用者被销毁, service会销毁 //unbindService(conn);//解除绑定 onCreate, onStart, onDestroy,
7 . 什么时候使用service
1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作. 后台播放音乐, 录音通话记录 2.Broadcast receiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作.
8. Intent传递数据时,可以传递哪些类型数据?
1.一般的基本数据类型 Intent .putextra() intent.getStringextra(); 2. 数据的uri, intent.setData() intent.getData();
9.请描述一下Broadcast Receiver。
有很多广播接收者 ,系统已经实现了,监听一些事件:如接收到短信 ,打出去电话 广播分两种 有序广播 可被拦截,可终止,可以修改数据 无序广播 是不可以被拦截掉的
10. 请介绍下ContentProvider是如何实现数据共享的。
android 系统下不同程序 数据默认是不能共享访问 把自己的数据通过uri的形式共享出去(查看短信,查看通讯录联系人) 1.看urlmarcher. 2. 根据匹配码 查看增删改查的具体实现
11. 为什么要用ContentProvider?它和sql的实现上有什么差别?
屏蔽数据存储的细节,对用户透明,用户只需要关心操作数据的uri就可以了,对应的参数 .
15.activity的生命周期。
activity主要生命周期的方法说明: onCreate(Bundle savedInstanceState):创建activity时调用。设置在该方法中,还以Bundle的形式提供对以前储存的任何状态的访问! onStart():activity变为在屏幕上对用户可见时调用。 onResume():activity开始与用户交互时调用(无论是启动还是重新启动一个活动,该方法总是被调用的)。 onPause():activity被暂停或收回cpu和其他资源时调用,该方法用于保存活动状态的,也是保护现场,压栈吧! onStop():activity被停止并转为不可见阶段及后续的生命周期事件时调用。 onRestart():重新启动activity时调用。该活动仍在栈中,而不是启动新的活动。 onDestroy():activity被完全从系统内存中移除时调用,该方法被
16 .在Android中,怎么节省内存的使用,怎么主动回收内存?
尽量多使用内部类 提高程序效率 回收已经使用的资源, 合理的使用缓存 合理设置变量的作用范围 application 对象
17. dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念
Dvm的进程是dalivk虚拟机进程,每个android程序都运行在自己的进程里面, 每个android程序系统都会给他分配一个单独的liunx uid(user id), 每个dvm都是linux里面的一个进程.所以说这两个进程是一个进程.
19. 什么是ANR 如何避免它?
主线程被阻塞的时候,会出现5秒超时的异常 在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称 作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次 都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样,系统不会显示ANR给用户。 Activity 5秒 broadcast10秒 耗时的操作 worker thread里面完成, handler message…AsynsTask , intentservice.等…
22,udp连接和TCP的不同之处
tcp/滑动窗口协议. 拥塞控制. 可靠的连接 ,三次握手 udp 不关心数据是否达到,是否阻塞,不可靠的连接 画面优先. tcp 流畅优先 udp
23.handler机制的原理
是一个消息的处理者, 是满足线程间的通讯,和传递一些信息 Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。 1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。 2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里; 或者接收Looper从Message Queue取出)所送来的消息。 3) Message Queue(消息队列):用来存放线程放入的消息。 4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
24.AsycTask与一般线程异步之间的差别
1)是因为AsyncTask使用了线程池技术,而且其中的方法很容易实现调用 2)是因为AsyncTask可以调用相关的方法,在开启子线程前和后,进行界面的更新 3)是因为一旦任务多了,不用每次都new新的线程,可以直接使用
26. 图片的优化
异步加载图片 图片的压缩处理bitMapFactory.options 设置内存的大小 缓存在内存,缓存在SD卡, 取的时候先从内存中取 ,在去SD卡取 ,没有的话,去网上取
27.屏幕的适配
文字使用SP ,控件使用dp ,weight 多布局, 里面加不同的dimens.xml 图片有要求的话,采用多图片处理
28.Activity的启动模式
1. standard 默认标准的启动模式, 每次startActivity都是创建一个新的activity的实例。 适用于绝大大数情况 2. singleTop 单一顶部,如果要开启的activity在任务栈的顶部已经存在,就不会创建新的实例, 而是调用 onNewIntent() 方法。 应用场景: 浏览器书签。 避免栈顶的activity被重复的创建,解决用户体验问题。 3. singletask 单一任务栈 , activity只会在任务栈里面存在一个实例。如果要激活的activity,在 任务栈里面已经存在,就不会创建新的activity,而是复用这个已经存在的activity, 调用 onNewIntent() 方法,并且清空当前activity任务栈上面所有的activity 应用场景:浏览器activity, 整个任务栈只有一个实例,节约内存和cpu的目的 注意: activity还是运行在当前应用程序的任务栈里面的。不会创建新的任务栈。
singleInstance 单态 单例模式 单一实例,整个手机操作系统里面只有一个实例存在。不同的应用去打开这个activity 共享 公用的同一个activity。 他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。 应用场景:呼叫来电界面 InCallScreen
29.注册广播哪几种方法
2种 , 1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。registerReceiver 2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。一种是在AndroidManifest.xml中配置广播
30.横竖屏切换时候activity的生命周期?
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期, 切横屏时会执行一次,切竖屏时会执行两次 2、设置Activity的android:configChanges=”orientation”时, 切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次 3、设置Activity的android:configChanges=”orientation|keyboardHidden”时, 切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
33、 你后台的Activity被系统回收怎么办:
onSaveInstanceState
34.Framework工作方式及原理,Activity是如何生成一个view的,机制是什么。
反射 , 配置文件 每个activity里面都有window.callback和keyevent.callback,一些回调的接口或者函数吧. 框架把activity创建出来就会调用里面的这些回调方法,会调用 activity生命周期相关的方法. setContentView(); 普通的情况: Activity创建一个view是通过 ondraw 画出来的, 画这个view之前呢,还会调用onmeasure方法来计算显示的大小.
35.请解释下Android程序运行时权限与文件系统权限的区别。
运行时权限Dalvik( android授权) 文件系统 linux 内核授权
36. IntentService有何优点?
答:IntentService 的好处 * Acitivity的进程,当处理Intent的时候,会产生一个对应的Service * Android的进程处理器现在会尽可能的不kill掉你 * 非常容易使用
38.引入任务栈目的 :
为了记录用户开启了那些activity, 记录这些activity开启的先后顺序, 帮助维护好的用户体验。
40. 简单描述下Android 数字签名。
在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系 Android系统要求每一个安装进系统的应用程序都是经过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。Android将数字证书用来标识应用程序的作者和在应用程序之间建立信任关系,不是用来决定最终用户可以安装哪些应用程序。 这个数字证书并不需要权威的数字证书签名机构认证(CA),它只是用来让应用程序包自我认证的。 同一个开发者的多个程序尽可能使用同一个数字证书,这可以带来以下好处。 (1)有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同一个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不同的程序,并产生冲突,会要求新程序更改包名。 (2)有利于程序的模块化设计和开发。Android系统允许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序。所以开发者可以将自己的程序分模块开发,而用户只需要在需要的时候下载适当的模块。 在签名时,需要考虑数字证书的有效期: (1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的程序将不能正常升级。 (2)如果多个程序使用同一个数字证书,则该数字证书的有效期要包含所有程序的预计生命周期。 (3)Android Market强制要求所有应用程序数字证书的有效期要持续到2033年10月22日以后。 Android数字证书包含以下几个要点: (1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序 (2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证 (3)如果要正式发布一个Android,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。 (4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。
Android 开发基础常识 https://blog.51cto.com/u_12480926/5694577