《Android秘籍.第一卷》
目录
《Android秘籍.第一卷》
《Activity篇》
Android系统架构?
Activity的生命周期?
在一个Activity中关闭另外一个Activity?
Activity中开启一个另一个Activity再返回的全部生命周期?
Activity A启动另一个Activity B会回调哪些方法?如果Activity B是完全透明呢?如果启动的是一个Dialog呢?
onStart()和onResume()/onPause()和onStop()的区别?
谈谈onSaveInstanceState()方法?何时会调用?
onSaveInstanceState()与onPause()的区别?
如何避免配置改变时Activity重建?
Activity横竖切换时候的生命周期?
优先级低的Activity在内存不足被回收后怎样做可以恢复到销毁前状态?
说下Activity的四种启动模式?
谈谈singleTop和singleTask的区别以及应用场景?
如何给Activity指定启动模式?
了解哪些Activity启动模式的标记位?
onNewIntent()调用时机?
如何启动其他应用的Activity?
Activity的启动过程?
《Fragment篇》
谈一谈Fragment的生命周期?
Activity和Fragment的异同?
Activity和Fragment的关系?
何时会考虑使用Fragment?
Fragment 横竖屏切换?
Fragment界面重叠问题如何解决?
《Service篇》
谈一谈Service的生命周期?
Service的两种启动方式?区别在哪?
一个Activty先start一个Service后,再bind时会回调什么方法?此时如何做才能回调Service的destory()方法?
Service如何和Activity进行通信?
常见系统Service?
是否能在Service进行耗时操作?如果非要可以怎么做?
AlarmManager能实现定时的原理?
前台服务是什么?和普通服务的不同?如何去开启一个前台服务?
是否了解ActivityManagerService,谈谈它发挥什么作用?
如何保证Service不被杀死?
《Broadcast Receiver篇》
广播的两种注册形式?区别在哪?
《ContentProvider篇》
ContentProvider了解多少?
ContentProvider的Uri(统一资源标识符)?
多个进程同时调用一个ContentProvider的query获取数据,ContentPrvoider是如何反应的呢?
Android设计ContentProvider的目的是什么呢?
运行在主线程的ContentProvider为什么不会影响主线程的UI操作?
《Activity篇》
Android系统架构?
- Android应用框架层
- Java系统框架层
- C++系统框架层
- Linux内核层
Activity的生命周期?
Activity一共有以下7个生命周期方法:
- onCreate():创建时调用(activity正在被创建,此时的UI操作不会更新UI)
- onStart():可见时调用(activity才可见,但是没有出现在前台,无法与用户交互)
- onResume():获取焦点时用(activity已经可见,并且出现在前台开始活动)
- onPause():失去焦点时调用(activity正在被停止,接下来马上调用onStop。特殊情况下快速回到该activity,onStop不会执行,会去执行onResume.一般在这可以做数据存储,停止动画,但是不能太耗时onPause执行完了,才回去执行新的activity的onResume)
- onStop():这个时候activity已经一丁点儿都看不到了
- onRestart():重启时调用(activity正在重新启动,从不可见状态到可见状态)
- onDestory():销毁时调用
在一个Activity中关闭另外一个Activity?
- 在一个Activity中关闭另外一个Activity 给Activity A中加上一个静态变量 instance = this,然后在Activity B中调用instance.finish()。
Activity中开启一个另一个Activity再返回的全部生命周期?
- A.onCreate()---->A.onStart()---->A.onResume()---->A.onPause()---->B.onCreate()---->B.onStart()---->B.onResume()---->A.onStop()---->B.onPause()---->A.onReStart()---->A.onStart()---->A.onResume()---->B.onStop()---->B.onDestory().
Activity A启动另一个Activity B会回调哪些方法?如果Activity B是完全透明呢?如果启动的是一个Dialog呢?
- A会回调onPause()>>onStop(),透明则不会调用onStop(),对话框则不会调用onPause()和onStop()
onStart()和onResume()/onPause()和onStop()的区别?
谈谈onSaveInstanceState()方法?何时会调用?
- 当Activity意外销毁时再重新创建时会调用此方法,比如横竖屏切换,会导致重新创建Activity,onSaveInstanceState()方法的调用在onStop()之前,用于保存当前Activity的状态,当Activity被重新创建后,会调用onRestoreInstanceState()来恢复Activity的状态,onRestoreInstanceState()的调用在onStart()之后。
- onSaveInstanceState在需要空出内存给当前Activity时执行。
- 当用户按下HOME键时。
- 长按HOME键,选择运行其他的程序时。
- 按下电源按键(关闭屏幕显示)时。
- 从activity A中启动一个新的activity时。
- 屏幕方向切换时,例如从竖屏切换到横屏时。
onSaveInstanceState()与onPause()的区别?
- 两者执行没有固定的先后顺序。
- onsavedinstance(Bundle savedinstancestate)方法的触发时机,其典型的情景是按home键或者切换activity,这样的activity可能被销毁的场合,但是按back键退出程序,则不会调用此方法,适合保存一些非持久性的数据(即程序运行期间需要储存的数据)。
- 而onpause(),不管是可能销毁还是退出程序,都必须调用,适合保存持久性的数据,但是android本身没有为此方法提供bundle参数,因此我们可以选用做一个静态变量或者是提供一个sharedpreference作为数据载体。
如何避免配置改变时Activity重建?
- 在清单文件(AndroidManifest.xml)下每个activity注册时写上android:configChanges=“XXX”比如横竖屏切换:android:configChanges=“orientation|screenSize”(记忆法:屏幕旋转的时候不只是方向改变大小也改变了)。
Activity横竖切换时候的生命周期?
Activity横竖切换:如果Activity设置了属性android:screenOrientation="portrait"生命周期不调用。
- 切横屏(生命周期一次)
- onSaveInstanceState()>onPause()>onStop()>onDestroy()>onCreate()>onStart()>onRestoreInstanceState()>onResume()>
- 切换竖屏(生命周期两次)
- onSaveInstanceState()>onPause()>onStop()>onDestroy()>onCreate()>onStart()>onRestoreInstanceState()>onResume()>
- onSaveInstanceState()>onPause()>onStop()>onDestroy()>onCreate()>onStart()>onRestoreInstanceState()>onResume()>
- 添加 Android:configChanges="orientation"横屏切换为竖屏
- onSaveInstanceState()>onPause()>onStop()>onDestroy()>onCreate()>onStart()>onRestoreInstanceState()>onResume()>
- 添加 Android:configChanges="orientation"竖屏切换为横屏多了onConfigChanged()
- onSaveInstanceState()>onPause()>onStop()>onDestroy()>onCreate()>onStart()>onRestoreInstanceState()>onResume()>
- onConfigurationChanged().
- 添加 android:configChanges="orientation|keyboardHidden"横竖屏切换相同。
- onConfigurationChanged()
- AndroidManifest.xml不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
- 设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
- 设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
- (注:当前Activity产生事件弹出Toast和AlertDialog的时候Activity的生命周期不会有改变,Activity运行时按下HOME键(跟被完全覆盖是一样的):onSaveInstanceState --> onPause --> onStop,onRestart -->onStart--->onResume。Activity未被完全覆盖只是失去焦点:onPause--->onResume)
优先级低的Activity在内存不足被回收后怎样做可以恢复到销毁前状态?
- 当app处于后台被系统回收时,app的进程被杀死了,Activity 也被回收了,而app的task和activity栈以及相应的intent和数据会被系统保存起来。当app被切回前台时,系统会恢复task和activity栈以及相应的intent和数据。
- 不要在Application类和全局单例类中存放数据,会导致app无法正确恢复状态。运行时的临时数据应存放在SharedPreference、临时文件或数据库中
- Activity之间传数据应该用系统提供的intent机制。
说下Activity的四种启动模式?
- standard(标准模式) :系统默认模式,每启动一个 Activity 就会重新创建一个新的实例。 这种模式下, Activity A 启动了 Activity B,那么 B 就会进入到 A 所在的任务栈中。
- singleTop(栈顶复用模式) :如果新 Activity 已经位于栈顶,那么此 Activity 不会再重新创建,同时它的 onNewIntent 方法会被回调。
- singleTask(栈内复用模式) :只要 Activity 在一个栈中存在,那么多次启动此 Activity 都不会重新创建实例。
- singleInstance(单实例模式, 加强的 singleTask 模式) :除了具有 singleTask 模式的所有特性外,还加强了一点,那就是具有此种模式的 Activity 只能单独的位于一个任务栈中。
谈谈singleTop和singleTask的区别以及应用场景?
- singleTop(栈顶复用模式):要求如果创建intent的时候栈顶已经有要创建的Activity的实例,则将intent发送给该实例,而不发送给新的实例。(注意是栈顶,不在栈顶照样创建新实例!)
- singleTask模式(栈内复用模式) :当intent到来,需要创建singleTask模式Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。
如何给Activity指定启动模式?
- 在AndroidManifest.xml中,通过标签的android:launchMode属性设置:android:launchMode="singleInstance"
- 在Intent中设置标志位韦Activity指定启动模式:Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)等同singleTask
了解哪些Activity启动模式的标记位?
- Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK):指定singleTask模式,等同singleTask效果。
- Intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP):指定singleTop模式,等同singleTop效果
- Intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP):具有这个标志的Activity启动时,在同一个任务栈中所以位于它上面的Activity都要出栈,一般会和singleTask模式一起出现
- Intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)具有这个标志的Activity不会出现在历史的Activity列表中,它等同于在AndroidManifest.xml中指定android:excludeFromRecents="true"
(注:标记位优先级比在AndroidManifest中指定优先级高)
onNewIntent()调用时机?
- 当进行singleTop和singleTask模式的时候,存在对应的Activity,即会调用该Activity的onNewIntent()。
如何启动其他应用的Activity?
- ComponentName,顾名思义,就是组件名称,通过调用Intent中的setComponent方法,我们可以打开另外一个应用中的Activity或者服务.
- 实例化一个ComponentName需要两个参数,第一个参数是要启动应用的包名称,这个包名称是指清单文件中列出的应用的包名称:第二个参数:参数是你要启动的Activity或者Service的全称(包名+类名);
- 如果你要的启动的其他应用的Activity不是该应用的入口Activity,那么在清单文件中,该Activity节点一定要加上Android:exported="true",表示允许其他应用打开,对于所有的Service,如果想从其他应用打开,也都要加上这个属性.对于除了入口Activity之外的其他组件,如果不加这个属性,都会抛出“java.lang.SecurityException: Permission Denial.....”异常
Activity的启动过程?
具体来讲,启动activity的方式有以下几种:
- 在应用程序中startActivity()或startActivityForResult()方法启动指定activity
- 在HOME(桌面)程序中单击应用图标,启动新的activity
- 按"BACK"键结束当前activity,自动启动上一个activity
- 长按“Home”键,显示出当前任务列表,从中选择一个启动。
这个问题说起来长篇大论了可以网上查找相关资料或者通过源码分析。这里只是简单描述下:
- 开始执行请求启动Activity
- ActivityManagerService接收启动Activity的请求
- 执行栈顶Activity的onPause方法
- 启动Activity所属的应用进程
- 执行启动Acitivity
- 栈顶Activity执行onStop方法
(简单点就是,Activity启动时是通过Binder向AMS(ActivityManagerService)发请求,通过PIC启动Activity的)
《Fragment篇》
谈一谈Fragment的生命周期?
Fragment一共有以下11个生命周期方法,除onRestart()拥有和Activity相同的6个生命周期方法。具体如下:
- onAttach():和宿主Activity建立关联时调用(onAttach()回调将在Fragment与其Activity关联之后调用。需要使用Activity的引用或者使用Activity作为其他操作的上下文)
- onCreate():创建时调用(fragmet还没有获得Activity的onCreate()已完成的通知,所以不能将依赖于Activity视图层次结构存在性的代码放入此回调方法中。我们应该尽量避免耗时操作。此时的bundle就可以获取到activity传来的参数)
- onCreateView():加载Fragment的布局时调用
- onActivityCreated():宿主Activity创建完毕时调用(在调用onActivityCreated()之前,Activity的视图层次结构已经准备好了,在这里可以做用户看到界面前最后的调整)
- onStart():可见时调用 (与Activity中对应的生命周期相同)
- onResume():获取焦点时用 onPause():(与Activity中对应的生命周期相同)
- 失去焦点时调用 onStop():(与Activity中对应的生命周期相同)
- 不可见时调用 onDestoryView():(视图层次结构与Fragment分离之后调用)
- 移除Fragment的布局时调用 onDestory():(不再使用Fragment时调用。Fragment仍然附加到Activity并任然可以找到,但是不能执行其他操作)
- 销毁时调用 onDetach():与宿主Activity解除关联时调用。(Fragment不再与Activity绑定,释放资源)
(注:Fragment不是Activity的扩展Fragment是直接从Object继承的,而Activity是Context的子类。)
下图很好的描述了 Fragment 与 Activity 生命周期的关系
Activity和Fragment的异同?
1、从最基础的开始说--->生命周期
Activity有7个生命周期:onCreate(); onStart(); onResume(); onPause(); onStop(); onDestroy(); onRestart();
Fragment有11个生命周期:onAttach(); onCreate(); onCreateView(); onActivityCreate(); onStart(); onResume(); onPause(); onStop(); onDestroyView(); onDestroy(); onDetach();
所以Fragment比较与Activity来说会更加灵活,因为生命周期多了,你可以控制的地方也就多了。
2、从灵活性上来说
Activity是四大组件之一,是每个页面的承载,一个就是一个,Fragment的显示要依赖于Activity,从Fragment的生命周期中就可以了解到。
Fragment是一个一个的小碎片
1)相比较与Activity来说更加灵活,可以在XML文件中直接进行写入,也可以在Activity中动态添加;
2)可以使用show()/hide()或者replace()随时对Fragment进行切换,并且切换的时候不会出现明显的效果,用户体验会好;Activity虽然也可以进行切换,但是Activity之间切换会有明显的翻页或者其他的效果,在小部分内容的切换上给用户的感觉不是很好
Activity和Fragment的关系?
Fragment的显示要依赖于Activity,从Fragment的生命周期中就可以了解到。
何时会考虑使用Fragment?
- 类似微信下方菜单栏,车载电话电话(蓝牙)以及手机和平板适配等。
Fragment 横竖屏切换?
- 启动
- onAttach()> onCreate() > onCreateView ()> onViewCreated() > onActivityCreated() > onStart() > onResume()
- 竖屏旋转到横屏(横屏旋转回竖屏也是执行同样的生命周期)
- onPause() > onStop() > onDestroyView() > onDestroy() > onDetach ()> onAttach ()> onCreate() > onCreateView() >
- onViewCreated ()> onActivityCreated() > onStart() > onResume()
- 退出
- onPause > onStop > onDestroyView > onDestroy > onDetach
Fragment界面重叠问题如何解决?
首先,Android管理Fragment有两种方式。
replace方式 ,如果使用这种方式,是可以避免重叠的问题,但是每次replace会把生命周期全部执行一遍,如果在这些生命周期函数 里拉取数据的话,就会不断重复的加载刷新数据,所以我们并不推荐使用这种方式。
add、hide、show的方式,虽然这种方式避免了可能重复加载刷新数据的问题,但是会出现重叠的问题。
原因当系统内存不足,Fragment 的宿主 Activity 回收的时候,Fragment 的实例并没有随之被回收。Activity 被系统回收时,会主动调用 onSaveInstance() 方法来保存视图层(View Hierarchy),所以当 Activity 通过导航再次被重建时,之前被实例化过的 Fragment 依然会出现在 Activity 中,此时的 FragmentTransaction 中的相当于又再次 add 了 fragment 进去的,hide()和show()方法对之前保存的fragment已经失效了,所以就出现了重叠。
解决方法:
方法一:简单暴力不保存之前Fragment state。即注释onSaveInstanceState()方法。
方法二:保存所有Fragment状态前把Fragment从FragmentManager中移除掉。
方法三:重写onAttachFragment,重新让新的Fragment指向了原本未被销毁的fragment,即onAttach方法对应的Fragment对象
(注:问题重现方法:手机打开 “设置” - “开发者选项” - 打开”不保留活动”(主要用于模拟Activity被及时回收) 然后把 app 切换到后台,再重新打开,通过点按不同的 tab 来切换 Fragment 。)
《Service篇》
谈一谈Service的生命周期?
Service的两种启动方式?区别在哪?
第一种:通过 startService() 来启动:
- 生命周期:oncreate——>onstartCommand——>onDestroy;多次通过该方法启动Service,oncreate函数只会被调用一次,onStartCommand函数会被多次调用,但只需要调用一次stopService就可以销毁该Service;
- 特点说明:通过该启动方式启动Service,一旦Service启动成功那么该Service就会和他所创建的Activity脱离关系,也就是说Service的不会随着Activity的销毁而销毁,并且在应用的任何Activiy中都可以对该Service进行操作
第二种:通过 bindService() 来启动:
- 生命周期:oncreate——>onBind——>unBind——>OnDestroy;多次bindService,oncreate和onBind方法都只会调用一次,而且只需要一次调用unBindService用于取消bind;
- 特点说明:它与startService正好相反,一个Activity通过bind的方式启动Service,那么该Service是依赖于该Activity存在的,也就是Activity的销毁也会导致bind所启动的Service的销毁(会经历unbind——>onDestroy的生命周期)
一个Activty先start一个Service后,再bind时会回调什么方法?此时如何做才能回调Service的destory()方法?
- 如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。
Service如何和Activity进行通信?
-
Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我们可以利用回调方法
-
Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好
常见系统Service?
- *******PowerManagerService –> PowerManager:********Android *的电源管理也是很重要的一部分。比如在待机的时候关掉不用的设备,待机时屏幕和键盘背光的关闭,用户操作的时候该打开多少设备等等。
- *********ActivityManagerService->ActivityManager*********:这个是整个Android framework框架中最为核心的一个服务,管理整个框架中任务、进程管理, Intent解析等的核心实现。虽然名为Activity的Manager Service,但它管辖的范围,不只是Activity,还有其他三大组件,和它们所在的进程。也就是说用户应用程序的生命管理,都是由他负责的。
- ********* TelephonyRegistry->TelephonyManager*********:电话注册、管理服务模块,可以获取电话的链接状态、信号强度等等。<可以删掉,但要看的大概明白>
- *********PackageManagerService -> PackageManager*********:包括对软件包的解包,验证,安装以及升级等等,对于我们现在不能安装.so文件的问题,应该先从这块着手分析原因。
- *******ContentService -> ContentResolver*******:内容服务,主要是数据库等提供解决方法的服务。
- **** *BatteryService*******:监控电池充电及状态的服务,当状态改变时,会广播Intent
- *******WindowManagerService -> WindowManager -> PhoneWindowManager*******:和ActivityManagerService高度粘合窗口管理,这里最核心的就是输入事件的分发和管理。
- **** ***AlarmManagerService -> AlarmManager:*******闹钟服务程序
- **** ***BluetoothService -> BluetoothDevice*******:蓝牙的后台管理和服务程序
- *******StatusBarService -> StatusBarManager*******:负责statusBar上图标的更新、动画等等的服务,服务不大。
- *******InputMethodManagerService -> InputMethodManager*******:输入法的管理服务程序,包括何时使能输入法,切换输入法等等。
- **** ***NetStatService*******:网络服务
- **** ***ConnectivityService -> ConnectivityManager*******:网络连接状态服务,可供其他应用查询,当网络状态变化时,也可广播改变。
- **** ***AccessibilityManagerService-> AccessibilityManager*******
- 这块可能要仔细看一下,主要是一些View获得点击、焦点、文字改变等事件的分发管理,对整个系统的调试、问题定位等,也需要最这个服务仔细过目一下。
- *******NotificationManagerService -> NotificationManager*******:负责管理和通知后台事件的发生等,这个和statusbar胶黏在一起,一般会在statusbar上添加响应图标。用户可以通过这知道系统后台发生了什么事情。
- *******MountService*******:磁盘加载服务程序,一般要和一个linux daemon程序如vold/mountd等合作起作用,主要负责监听并广播device的mount/unmount/bad removal等等事件。
- **** *DeviceStorageMonitorService*******:监控磁盘空间的服务,当磁盘空间不足10%的时候会给用户警告
- *******LocationManagerService -> LocationManager*******:要加入GPS服务等,这部分要细看,现在应用中的navigation没响应,可以从此处着手看一下
- *******WallpaperManagerService -> WallpaperManager:*******管理桌面背景的服务,深度定制化桌面系统,需要看懂并扩展<同时要兼容>这部分
- *******AudioService -> AudioManager:********AudioFlinger*的上层管理封装,主要是音量、音效、声道及铃声等的管理
- *******HeadsetObserver*******:耳机插拔事件的监控小循环
- *******BackupManagerService -> BackupManager*******:备份服务
- *******AppWidgetService -> AppWidgetManager:********Android可以让用户写的程序以widget*的方式放在桌面上,这就是这套管理和服务的接口
- *******StatusBarPolicy*******:管理哪个图标该在status bar上显示的策略。
- mediaServer服务进程:MediaServer服务基本上都是native的services,mediaServer进程也是在init.rc中启动的,它不是一个daemon进程,这点容易搞混。他也是和systemserver进程类似的系统服务进程,提供应用进程的RPC调用的真正服务代码所运行的位置。其服务都是和媒体录播放有关,主要有三个服务如下:
- *********AudioFlinger:*********声音的录播放服务,包括混音等
- *********MediaPlayerService:*********提供媒体播放服务,opencore是这块的核心模块,对java端的接口在mediaplayer.java
- *********CameraService:*********提供camera的录制、preview等功能的服务
- *********AudioPolicyService:*********主要功能有检查输入输出设备的连接状态及系统的音频策略的切换等。
是否能在Service进行耗时操作?如果非要可以怎么做?
- Service是运行在主线程中的,一般不能在Service进行耗时操作,如果非要,可以使用远程Service开启新进程。
AlarmManager能实现定时的原理?
- AlarmManager提供对系统警报服务的访问。这些允许您在将来的某个时间点运行应用程序。当警报响起时,系统会广播已注册的意图,如果目标应用程序尚未运行,则自动启动它。当设备处于休眠状态时,会保留已注册的警报(如果设备在此期间发生故障,可以选择将其唤醒),但如果设备被关闭并重新启动,则会清除该警报。警报管理器持有一个CPU唤醒锁,只要警报接收器的onReceive()方法正在执行。这保证了在你处理完广播后,手机才会休眠。一旦onReceive()返回,警报管理器将释放此唤醒锁。这意味着,在某些情况下,只要onReceive()方法完成,手机就会休眠。如果您的警报接收器调用Context.startService(),那么在启动所请求的服务之前,手机可能会休眠。为了防止这种情况发生,您的BroadcastReceiver和Service将需要实现一个单独的唤醒锁定策略,以确保在服务可用之前继续运行电话。
前台服务是什么?和普通服务的不同?如何去开启一个前台服务?
- 前台服务即对用户可见的服务,可以以通知的形式创建前台服务
是否了解ActivityManagerService,谈谈它发挥什么作用?
- ActivityManagerService(以后简称AMS)Android中最核心的服务 , 主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块类似,因此它在Android中非常重要
如何保证Service不被杀死?
- Service设置成START_STICKY(onStartCommand方法中),kill 后会被重启(5秒左右),重传Intent,保持与重启前一样
- 通过 startForeground将进程设置为前台进程,做前台服务,优先级和前台应用一个级别,除非在系统内存非常缺,否则此进程不会被 kill.具体实现方式为在service中创建一个notification,再调用void android.app.Service.startForeground(int id,Notificationnotification)方法运行在前台即可。
- 双进程Service:让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程可以立即重启进程
- AlarmManager不断启动service。该方式原理是通过定时警报来不断启动service,这样就算service被杀死,也能再启动。同时也可以监听网络切换、开锁屏等广播来启动service。
- 在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死
- 在已经root的设备下,修改相应的权限文件,将App伪装成系统级的应用(Android4.0系列的一个漏洞,已经确认可行)
- 联系厂商,加入白名单
- (注:退出程序后如何保证Service开启不关闭,Android中,service的开启,默认是绑定activity的,是activity级的。退出程序后,保持Service的运行,那么需要把service设置成为system级的,方法:在AndroidManifest.xml中注册service时,加上属性android:process="system",另外,还要在启动service时,加入FLAG_ACTIVITY_NEW_TASK标签。或者注册各种各样的 广播action ,例如 电量变化等等,拦截到这些事件后判断服务是否存在,不存在就重新启动)
《Broadcast Receiver篇》
广播的两种注册形式?区别在哪?
- 静态注册,也就是说在AndroidManifest文件中对BroadcastReceiver进行注册,通常还会加上action用来过滤。特点:常驻型广播,程序推出后,广播依然存在。
- 动态注册,调用Context中的registerReceiver对广播进行动态注册,使用unRegisterReceiver方法对广播进行取消注册的操作。特点:非常驻型,广播会跟随程序的生命周期的结束而结束。
《ContentProvider篇》
ContentProvider了解多少?
定义:四大组件之一,内容提供者。需要在AndroidManifest.xml文件中进行注册
作用:跨进程通信(IPC是Inter-Process Communication的缩写),即进程间进行数据交互和数据共享。
原理:Android中的Binder机制
优点:为存储和读取数据提供了统一的接口,安全,访问简单高效。
概述:ContentProvider可以理解为一个Android应用对外开放的接口,将存放在Android的数据库,以安全的方式进行封装,最终提供统一的数据存储和数据读取的接口供其他进程调用,最终实现跨进程时间共享。(Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。ContentProvider相当于一个搬运工,真正存储和操作数据得数据源的还是原理存储数据的方式。android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等))
ContentProvider的Uri(统一资源标识符)?
Uri固定格式的::////;(eg:content://com.bd.provider/Devide/1)
- :协议部分,表示ContentProvider使用的协议,这个是固定的content://。
- :ContentProvider的名称,即URI 的标识也是固定的,系统就是通过这个部分找到要操作的ContentProvide。
- :请求的数据类型,即资源部分(资源所在的路径),访问者可以访问不同的资源,这个是动态的。
- :指定请求的特定数据。没有指定则返回全部记录
多个进程同时调用一个ContentProvider的query获取数据,ContentPrvoider是如何反应的呢?
- 一个content provider可以接受来自另外一个进程的数据请求。尽管ContentResolver与ContentProvider类隐藏了实现细节,但是ContentProvider所提供的query(),insert(),delete(),update()都是在ContentProvider进程的线程池中被调用执行的,而不是进程的主线程中。这个线程池是有Binder创建和维护的,其实使用的就是每个应用进程中的Binder线程池。
Android设计ContentProvider的目的是什么呢?
-
隐藏数据的实现方式,对外提供统一的数据访问接口;
-
更好的数据访问权限管理。ContentProvider可以对开发的数据进行权限设置,不同的URI可以对应不同的权限,只有符合权限要求的组件才能访问到ContentProvider的具体操作。
-
ContentProvider封装了跨进程共享的逻辑,我们只需要Uri即可访问数据。由系统来管理ContentProvider的创建、生命周期及访问的线程分配,简化我们在应用间共享数据(进程间通信)的方式。我们只管通过ContentResolver访问ContentProvider所提示的数据接口,而不需要担心它所在进程是启动还是未启动。
运行在主线程的ContentProvider为什么不会影响主线程的UI操作?
- ContentProvider的onCreate()是运行在UI线程的,而query(),insert(),delete(),update()是运行在线程池中的工作线程的,所以调用这些方法并不会阻塞ContentProvider所在进程的主线程,但可能会阻塞调用者所在的进程的UI线程!
- 所以,调用ContentProvider的操作仍然要放在子线程中去做。虽然直接的CRUD的操作是在工作线程的,但系统会让你的调用线程等待这个异步的操作完成,你才可以继续线程之前的工作。