当前位置:操作系统 > 安卓/Android >>

Android 应用五大核心块 --- Service后台服务

Android 应用五大核心块 --- Service后台服务

概念:
Service:后台服务,用于将一些计算或常用系统通用功能放在一个独立的进程中进行处理,这样主进程可以全力并快速处理界面响应,提高用户体验效果。

下面以 packages\apps\Phone 应用举例说明:

编写应用时定义:AndroidManifest.xml
<!-- CDMA Emergency Callback Mode -->
   <service android:name="EmergencyCallbackModeService">
  </service>

EmergencyCallbackModeService.java 中如此定义:
public class EmergencyCallbackModeService extends Service
继承于 android.app.Service 类,重载其父类函数,此Service启动点:

PhoneAppBroadcastReceiver @ PhoneApp.java
// Start Emergency Callback Mode service
if (intent.getBooleanExtra("phoneinECMState", false)) {
    context.startService(new Intent(context,
            EmergencyCallbackModeService.class));
}
                   
ok, 表时Servie服务是利用 startService 函数而利用 Intent 类启动的。


几个类的关系如下:
public abstract class Context

public class ContextImpl extends Context
public class ContextWrapper extends Context


public class ContextThemeWrapper extends ContextWrapper             
public class Activity extends ContextThemeWrapper
 
即Activity继承了ContextWrapper类,而在ContextWrapper类中,实现了startService函数。在ContextWrapper类中,有一个成员变量mBase,它是一个ContextImpl实例,而ContextImpl类和ContextWrapper类一样继承于Context类,ContextWrapper类的startService函数最终过调用ContextImpl类的startService函数来实现。

既然理清楚了这几者关系,下面开始按照代码走一下完整的流程:

=========================主进程调用到ActivityManagerService进程中,完成新进程的创建============
startService @ ContextImpl.java
public ComponentName startService(Intent service) {
    ComponentName cn = ActivityManagerNative.getDefault().startService(
        mMainThread.getApplicationThread(), service,
        service.resolveTypeIfNeeded(getContentResolver()));
}
这里利用Binder进行通讯:
startService @ ActivityManagerNative.java
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
这里是利用 Binder 驱动程序发送请求给报务端,即此时的 mRemote(Binder对象)就是 ActivityManagerService
而ActivityManagerService这边就是等待Client的请求:


startService @ ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType) {

// 利用 Binder 对象获取到 pid,uid 等参数
      final int callingPid = Binder.getCallingPid();
      final int callingUid = Binder.getCallingUid();
      final long origId = Binder.clearCallingIdentity();
      ComponentName res = startServiceLocked(caller, service,
              resolvedType, callingPid, callingUid);
}
caller、service和resolvedType分别对应ActivityManagerProxy.startService传进来的三个参数
-->
这里简单看一下调用逻辑:
startServiceLocked() --> bringUpServiceLocked() --> startProcessLocked:

private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
....
int pid = Process.start("android.app.ActivityThread",
                    mSimpleProcessManagement ? app.processName : null, uid, uid,
                    gids, debugFlags, null);
...
}

start @ Process.java
public static final int start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int debugFlags,
                              String[] zygoteArgs)
{
if (supportsProcesses()) {
return startViaZygote(processClass, niceName, uid, gid, gids,
                        debugFlags, zygoteArgs);
}else {

// Running in single-process mode
Process.invokeStaticMain(processClass);          
}
}


这里通过函数 openZygoteSocketIfNeeded 与 Zygote Socket 之间进行通讯,fork出一个新的
进程,然后导入 android.app.ActivityThread 线程,执行其main函数。

=========新进程调用到ActivityManagerService进程中,获取要在新进程启动的服务的相关信息=======

main @ ActivityThread.java
public static final void main(String[] args) {
// 这里设定 Activity 的主 Looper
    Looper.prepareMainLooper();


// 创建 ActivityThread 线程实例www.zzzyk.com
    ActivityThread thread = new ActivityThread();
   
    thread.attach(false);

    Looper.loop();
}
这里在新的进程中运行了,这里就是用来启动服务的。在Android应用程序中,每一个进程对应一个ActivityThread实例,所以,这个函数会创建一个thread实例,然后调用ActivityThread.attach函数进一步处理。

attach @ ActivityThread.java
private final void attach(boolean system){
...
IActivityManager mgr = ActivityManagerNative.getDefault();

  try {
      mgr.attachApplication(mAppThread);
  } catch (RemoteException ex) {
  }
}

哟,,这里又要调用 ActivityManagerNative ,嗯,根据前面的分析大家应该知道了吧:)
attachApplication @ ActivityManagerNative.java
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
利用 Binder 对象调用到服务端:
attachApplication @ ActivityManagerService.java
attachApplicationLocked

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
// Find any services that should be running in this process...
        if (!badApp && mPendingServices.size() > 0) {
  realStartServiceLocked(sr, app);
        }
}
-->
这里开始时利用mPidsSelfLocked变量将进程的一些信息存入了ServiceRecord类
app.thread.scheduleCreateService(r, r.serviceInfo);
scheduleCreateService @ ApplicationThreadNative.java
public final void scheduleCreateService(IBinder token, ServiceInfo info){
mRemote.transact(SCHEDULE_CREATE_SE

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,