Service是Android的四大组件之一。和Activity,BroadcastReceiver相比,Service定位于业务层逻辑处理,而Activity定位于前端UI层逻辑处理,BroadcastReceiver定位于通知逻辑的处理。

一篇就够了系列之Activity全解析- https://blog.csdn.net/fine1938768839/article/details/74231639
一篇就够了系列之ContentProvider全解析- https://blog.csdn.net/fine1938768839/article/details/74942373
一篇就够了系列之BroadcastReceiver全解析- https://blog.csdn.net/fine1938768839/article/details/74909406
一篇就够了系列之Service全解析- https://blog.csdn.net/fine1938768839/article/details/74466043

-- Activity 劫持
Android Activity 劫持,模拟 Activity 劫持- https://github.com/abigbread/Hijack

Android P 调用隐藏API限制原理- https://mp.weixin.qq.com/s/sktB0x5yBexkn4ORQ1YofA
突破Android P(Preview 1)对调用隐藏API限制的方法- https://mp.weixin.qq.com/s/4k3DBlxlSO2xNNKqjqUdaQ
use hideapi on anroid P- https://github.com/Guolei1130/android_p_no_sdkapi_support

> Context相关问题
  Context是Android中一个非常重要的概念,用于访问全局信息,几乎所有的基础组件都继承自 Context。当前对象在程序中所处的一个环境,一个与系统交互的过程。APP中的Context可以这样认为,它是当前APP运行的一个系统环境、沙箱。
  Activity和Service以及Application的Context是不一样的,Activity继承自ContextThemeWraper.其他的继承自ContextWrapper.
  每一个Activity和Service以及Application的Context都是一个新的ContextImpl对象. getApplication()用来获取Application实例的,但是这个方法只有在Activity和Service中才能调用的到。那么也许在绝大多数情况下我们都是在Activity或者Service中使用Application的,但是如果在一些其它的场景,比如BroadcastReceiver中也想获得Application的实例,这时就可以借助getApplicationContext()方法.getApplicationContext()比getApplication()方法的作用域会更广一些,任何一个Context的实例,只要调用getApplicationContext()方法都可以拿到我们的Application对象。 
   App Context的数量等于Activity的个数 + Service的个数 + 1,这个1为Application。那Broadcast Receiver,Content Provider呢?Broadcast Receiver,Content Provider并不是Context的子类,他们所持有的Context都是其他地方传过去的,所以并不计入Context总数。

-- 使用Socket进行通信,不能在主线程中访问网络
  因为这会导致我们的程序无法在Android4.0及以上的设备上运行,会抛出异常:android.os.NetworkOnMainThreadException。而且进行网络操作很可能是耗时的。

-- Android Mashup设计的理解
  android中的Mashup,是将应用切分成不同类别的组件,通过统一的定位模型和接口标准将它们整合在一起,来共同完成某项任务。而在Android的Mashup模式下,每个组件的功能都可以被充分地复用。来自不同应用的组件可以有机地结合在一起,共同完成任务。开发者无须耗费精力去重新开发一些附属功能,而是可以全身心地投入到核心功能的开发中。这样不但提高了应用开发的效率,也增强了用户体验。
  Android的组件管理服务,就是通过配置文件中的信息去了解每个组件(Activity Service等)的特征。
  在Mashup的概念下构造Android应用,有三个基本要素:组件(Component)、连接和配置。
-- 把源代码看作是一份工程文档——设计。

1. class Application extends ContextWrapper implements ComponentCallbacks2{}
 class ContextWrapper extends Context {}

2. class Activity extends ContextThemeWrapper implements Factory2, Callback,
android.view.KeyEvent.Callback, OnCreateContextMenuListener, ComponentCallbacks2 {}
 class ContextThemeWrapper extends ContextWrapper
 class ContextWrapper extends Context {}

3. abstract class Service extends ContextWrapper implements ComponentCallbacks2 {}
 class ContextWrapper extends Context {}
4. abstract class BroadcastReceiver {}

5.abstract class ContentProvider implements ComponentCallbacks2 {}
  interface ComponentCallbacks2 extends ComponentCallbacks {}
  interface ComponentCallbacks {}

 总context对象 = activity(app总共创建的activity数量)+service(app总共创建service数量)+1(application只有一个);原因:activity和service ,application都是继承context的。

> Android四大组件
  Android四大组件的生命周期,Activity、Service、ContentProvider、BroaderReceiver的生命周期?对象的生命周期与四大组件的生命周期要一致,才不会有内存泄露。 Android的几大组件的创建方式是依赖注入的方式,因此不能被混淆。
  ContentProvider通过工具ContentResolver激活,使用者自行管理cursor的生命周期,当要提供一系列数据供其他app或者进程使用的时候,就必须得考虑自己的生命周期。ContentProvider的生命周期-- http://stackoverflow.com/questions/24047248/contentprovider-destruction-lifecycle 。
  BroadCast Receiver的生命周期:动态广播,实时注册和注销;静态广播一直存在,直到App进程被终止。

 AndroidMantifest.xml中的activity、service、receiver和provider均支持android:process属性,设置该属性可以使每个组件均在各自的进程中运行,或者使一些组件共享一个进程;

-- 在Intent中传递Bundle数据
  四大组件中的三大组件(Activity、Service、Receiver)都是支持在Intent中传递Bundle数据的。由于Bundle实现了Parcelable接口,所以它可以方便的在不同的进程间传输。我们可以在Bundle中附加我们需要传输给远程进程的信息并通过Intent发送出去。

-- Android中Activity、Service、Fragment之间的相互通信比较麻烦,主要有以下几种方式:
(1)使用广播,发送者发出广播,接收者接收广播后进行处理;
(2)使用Handler和Message,如下载线程完成下载任务后,给UI发送Message,UI收到Message后更新界面。
(3)简单有效的方法事件总线。

-- ANR 
1.Activity输入事件(按键和触摸事件)5s内没被处理: Input event dispatching timed out
2.BroadcastReceiver的事件(onRecieve方法)在规定时间内没处理完(前台广播为10s,后台广播为60s)
3.service 前台20s后台200s未完成启动 Timeout executing service
4.ContentProvider的publish在10s内没进行完:timeout publishing content providers

1.Activity 屏幕或按键点击后5秒内无响应 ActivityManagerService.java
// How long we wait until we timeout on key dispatching.
static final int KEY_DISPATCHING_TIMEOUT = 5*1000;

2.前台广播10秒内没处理完,后台广播可以60秒没处理完 ActivityManagerService.java
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_FG_TIMEOUT = 10*1000;
static final int BROADCAST_BG_TIMEOUT = 60*1000;

3.Service的超时定义在ActiveServices.java里
意思是处于前台进程里的服务20秒没处理完超时,处于后台进程里的服务200秒没响应。
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;
// How long we wait for a service to finish executing.
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

-- 在应用程序中,启动四大组件,开发者通过:
1.startActivity(Intent intent) 来启动Activity
2.startService(Intent service) 来启动Service
3.sendBroadcast(Intent intent) 来发送广播
4.ContentResolver 中的接口来使用ContentProvider
这其中,startActivity,startService和sendBroadcast还有一些重载方法。

  1.在Activity启动的最后,会将前一个Activity pause,将新启动的Activity resume以便被用户看到。在这个时候,如果发现新启动的Activity进程还没有启动,则会通过startSpecificActivityLocked将其启动。整个调用流程如下:
ActivityManagerService.activityPaused =>ActivityStack.activityPausedLocked =>ActivityStack.completePauseLocked =>ActivityStackSupervisor.ensureActivitiesVisibleLocked =>ActivityStack.makeVisibleAndRestartIfNeeded =>ActivityStackSupervisor.startSpecificActivityLocked =>ActivityManagerService.startProcessLocked
  2.启动Service的调用流程如下:
ActivityManagerService.startService =>ActiveServices.startServiceLocked =>ActiveServices.startServiceInnerLocked =>ActiveServices.bringUpServiceLocked =>ActivityManagerService.startProcessLocked。
ActiveServices.bringUpServiceLocked会判断如果Service所在进程还没有启动,则通过ActivityManagerService.startProcessLocked将其启动。
  3.开发者通过ContentResolver中的insert, delete, update, query这些API来使用ContentProvider。在ContentResolver的实现中,无论使用这里的哪个接口,ContentResolver都会先通过acquireProvider 这个方法来获取到一个类型为IContentProvider的远程接口。这个远程接口对接了ContentProvider的实现提供方。
  4.开发者通过Context.sendBroadcast接口来发送广播。ActivityManagerService.broadcastIntent 方法了对应广播发送的处理。
在ActivityManagerService内部,是通过队列的形式来管理广播的:
 BroadcastQueue 描述了一个广播队列;BroadcastRecord 描述了一个广播事件;
在ActivityManagerService中,如果收到了一个发送广播的请求,会先创建一个BroadcastRecord接着将其放入BroadcastQueue中。然后通知队列自己去处理这个广播。然后ActivityManagerService自己就可以继续处理其他请求了。广播队列本身是在另外一个线程处理广播的发送的,这样保证的ActivityManagerService主线程的负载不会太重。

-- Android四大组件是如何协同工作?
  主要还是看应用场景,但是也是各自都是相互有些许联系的,Activity负责界面,展示数据,数据的来源可以通过资源获取;Contentprovider也可以获取其他应用的信息,不需要用户看到的操作可以用Service来处理,而且Android系统在执行某种特定的操作的时候回发出一个广播出来,我们可以用BroadCastReceiver去接收,他们之间的信息联动靠的是Intent这个信使,是一样四大组件的运行即是独立也有紧密的联系。

-- Android源代码,阅读优秀代码
  想要看懂Android的源代码其实还是有些费劲的,因为应用层用的是JAVA,而底层还是用C,你还要懂脚本,还要动软硬交互,而且源代码很多,实在是多,你要慢慢看,慢慢看,但是我们其实只要知道哪些在什么结构就行,什么地方有问题我们可以找到并且说出个所以然来。
  大多数的伟大作家也是如饥似渴的读者,这是一个普遍事实。 在你能写出任何拿得出手的东西之前,你需要品读其他伟大作家,吸收不同的风格,看看前辈已尝试过的东西,从中吸取精华。 你的知识会慢慢增长,你自己的作品最终会透露出些许成熟,你也会找到一种“感觉”。

阅读优秀代码是提高开发人员修为的一种捷径- http://blog.jobbole.com/471/
Eric Lippert:阅读代码真的很难- http://blog.jobbole.com/438/

-- Activity
 public class Activity extends ContextThemeWrapper implements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2 {  }

 activity几大生命周期等及activity绘制:
    每个activity都有一个window对象,在Android中,window对象通常由一个phonewindow去实现的,phonewindow将一个DecorView设置为整个窗口的根View,DecorView作为窗口界面的顶层视图,封装了一些通用的方法。可以说,DecorView将要显示的内容都给了phonewindow,这里面所有的View监听,都是通过WinsowManagerService来接收的,通过相应的回调来OnClicListener,在显示上,他将屏幕分成了两部分,一个title 一个content,看到这里,大家应该能看到一个熟悉的界面ContentView,它是一个ID为content分framelayout,activity_main.xml就是设置在这个framelayout里面。

-- service
public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {  }
/**
 * @hide
*/
public final void attach(Context context,ActivityThread thread, String className, IBinder token,
            Application application, Object activityManager) {   }

service处理一些逻辑后,发送广播,然后关闭自己(stopSelf)?AIDL与service的双向通信,Local Service与Remote Service?
startService(intent)与 stopService(intent)。
 Service stopSelf(int startId)与stopSelf()的区别- http://blog.csdn.net/mingli198611/article/details/8782772
 stopSelf() is used to always stop the current service.
 stopSelf(int startId) is also used to stop the current service, but only if startId was the ID specified the last time the service was started.
 stopService(Intent service) is used to stop services, but from outside the service to be stopped.

-- IntentService与Service
 IntentService具有以下特点:
 1. IntentService自带一个工作线程,当我们的Service需要做一些可能会阻塞主线程的工作的时候可以考虑使用IntentService。
 2. 我们需要将要做的实际工作放入到IntentService的onHandleIntent回到方法中,当我们通过startService(intent)启动了IntentService之后,最终Android Framework会回调其onHandleIntent方法,并将intent传入该方法,这样我们就可以根据intent去做实际工作,并且onHandleIntent运行在IntentService所持有的工作线程中,而非主线程。
 3. 当我们通过startService多次启动了IntentService,这会产生多个job,由于IntentService只持有一个工作线程,所以每次onHandleIntent只能处理一个job。面多多个job,IntentService会如何处理?处理方式是one-by-one,也就是一个一个按照先后顺序处理,先将intent1传入onHandleIntent,让其完成job1,然后将intent2传入onHandleIntent,让其完成job2…这样直至所有job完成,所以我们IntentService不能并行的执行多个job,只能一个一个的按照先后顺序完成,当所有job完成的时候IntentService就销毁了,会执行onDestroy回调方法。

public MusicService extends IntentService{
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
        String action = intent.getExtras().getString("paramType");
        if (action.equals("musicScan")) {//扫描音乐
            LogUtil.e("ScanSDIIntentService", "onHandleIntent,扫描音乐");
            int currentPage = intent.getExtras().getInt("currentPage", 0);
            int numOfOnePage = intent.getExtras().getInt("numOfOnePage", 0);
            List list = ScanMusicSDUtils.musicInfos(getApplicationContext(), currentPage, numOfOnePage);
            String json = GsonUtils.list2Json(list);
            LogUtil.v("onHandleIntent", "json=" + json);
      //musicIntent要新建,不能复用intent
            Intent musicIntent = new Intent();
            musicIntent.putExtra("musicListJson", json);
            musicIntent.setAction("com.desaco.desacoplayer.music");
            sendBroadcast(musicIntent);
            LogUtil.e("ScanSDIIntentService", "扫描音乐完成,发送广播");
        } else if (action.equals("videoScan")) {//扫描视频
            //TODO
            intent.setAction("com.desaco.desacoplayer.video");
        }
    }
}

-- BroadcastReceiver ,局部广播和全局广播
public abstract class BroadcastReceiver {  }
-- 本地广播
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);//获取实例
localBroadcastManager.sendBroadcast(intent);/发送本地广播
  本地广播有它的优势:
1.可以明确的知道正在发送的广播不会离开我们的程序,因此不用担心机密数据泄露问题
2.其他程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐患
3.发送本地广播要比全局广播更加高效
-- 广播注册了两次会出现什么问题  Android?
广播注册The complementary method pairs are:
1.onCreate注册 - onDestroy反注册
2.onResume注册 - onPause反注册
3.onStart注册  - onStop反注册

-- ContentProvider
public abstract class ContentProvider implements ComponentCallbacks2 {   }
ContentProvider自SDK17以后,默认是私有的,但对低版本的API是公开的。
Android:关于ContentProvider的知识都在这里了!- http://blog.csdn.net/carson_ho/article/details/76101093

-- AssetManager
public final class AssetManager {
native final String getResourceName(int resid);   
private native final int openAsset(String fileName, int accessMode);

更多相关文章

  1. AndroidStudio中的图片资源存放位置以及drawable文件夹的创建方
  2. android,ExpandableList,将被选中的group置于顶端
  3. Android(安卓)挂断电话流程
  4. android中画廊视图Gallery和ImageSwitcher组件的使用
  5. 深入源码分析Handler的消息处理机制
  6. Android中的自定义注解
  7. 查看Linux & Android中内存占用方法
  8. android 监控应用进程
  9. [万能方法] Android(安卓)Studio 调试出现 waiting for debugger

随机推荐

  1. [php]0-1背包动态规划
  2. php.ini与php-fpm.conf配置文件的区别
  3. PHP根据数组的值分组
  4. PHP扩展的URL Library快速入门
  5. Json调用JSON.parse:意外结束数据
  6. PHP+Apache环境安装与配置
  7. php $_SERVER中的SERVER_NAME 和HTTP_HOS
  8. 无法在Yii中更改项目的文件夹名称
  9. Mysql使用高流量数据库上的过滤器计算行
  10. PHP/MySQL性能测试