栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android系统开发 ----- 系统服务开发

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android系统开发 ----- 系统服务开发

系列文章目录

Android系统启动 ---- 主要流程类_MrDarly的博客-CSDN博客Android系统启动Zygote关系主要的类https://blog.csdn.net/weixin_68948960/article/details/125310042


前言

Android系统开发之系统服务开发。

问题:用户操作无界面,但是需要Android启动时,操作服务也进行启动,跟随系统关闭服务关闭。该服务提供打开某个APP功能,调用打开APP进行副屏投屏功能。移交给其他APP进行调用开启。系统提供服务,其他APP进行调用打开。


一、系统服务

Android开发过程中经常会用到各种各样的系统管理服务,

如进行窗口相关的操作会用到窗口管理服务WindowManager,

进行电源相关的操作会用到电源管理服务PowerManager,

还有很多其他的系统管理服务,如通知管理服务NotifacationManager、振动管理服务Vibrator、电池管理服务BatteryManager

这些Manager提供了很多对系统层的控制接口。对于App开发者,只需要了解这些接口的使用方式就可以方便的进行系统控制,获得系统各个服务的信息,而不需要了解这些接口的具体实现方式。而对于Framework开发者,则需要了解这些Manager服务的常用实现模式,维护这些Manager的接口,扩展这些接口,或者实现新的Manager。

Android中的系统服务分为两个部分:

1、C或C++层实现Service Framework。

2、Java层实现Service Framework

本次新加的系统服务就是Java层Service Framework。

由于本人对C和C++不熟悉,现阶段无法进入更深层次的Native Service Framework,所以只是浅层的进行Java Service Framework进行调整和增加。

二、实现步骤 1、环境搭建

 想进行Framework层开发,需要搭建基本的开发环境。本小节介绍环境的搭建

工具:Android Studio Ubuntu 系统。

默认已经参考网上教程已经下载好AOSP原始代码,并切编译成功。

第一步:生成iml和ipr文件

source build/envsetup.sh
lunch aosp_x86-eng # 或者直接输入lunch,然后选择对应的target
make idegen
development/tools/idegen/idegen.sh

情况一:代码在远程Ubuntu服务器中,电脑在本地使用putty进行链接操作,所有编译都在远程进行。由于我们只调整Framework代码,AOSP其他代码都不用同步到本地,当然网络好的情况下,直接打开也可以。

情况二:本地电脑是Ubuntu系统,代码下载到本地电脑,并使用Ubuntu进行了编译,安装了Android Studio工具,电脑性能可观可以进行全量打开,当然最好还是只打开我们调整的framework目录。

第二步:代码导入到Android Studio

在Project Structure下进行代码关联

选择源码位置进行关联,可以分目录,分文件进行关联,也可以一次性全部关联。AOSP代码在远程这里的错误可以不理会。AOSP代码在本地这里没有错误展示。

 

 

点击保存,进行代码同步关联后,查看frameworks中的代码就可以进行跳转,查看。

到此为止,可以在Android Studio中进行编写代码了,这里不能进行编译,需要在Ubuntu下使用命令进行编译。

2、代码分析

第一步:分层

服务层

Java Service Framework没有Service Manager统一的管理类, 所以要单独自行实现一个Manager(应用可以获取该服务,并进行调用的管理类)

xxxManager源码位置

RPC层

AIDL编写的接口,系统编译器自动生成服务代理和服务Stub。直接可用Stub和Stub.Proxy

aidl源码位置

IPC层

新增的服务和Stub.Proxy通过Binder IPC进行交互。调用JNI也属于IPC层

xxxService 实现aidl的源码位置

代码包总览如下图:

第二步:调整代码

在frameworks/base/core/java/android/app/目录下新建ota文件夹,

存放两个类IOtaService.aidl文件和OtaManager.java文件

IOtaService.aidl是RPC层

package android.app.ota;

//测试OTA 第一步:添加接口
interface IOtaService{
    int initDisplay();

    int startVideo(String url);

    int startImage(String url);

    void openMediaCenter();

}

OtaManager.java是服务层

package android.app.ota;

import android.util.Slog;
import android.os.RemoteException;
import android.annotation.SystemService;
import android.content.Context;

//测试OTA 第三步:添加系统服务的Manager
public class OtaManager {

    private final IOtaService mService;

    public static final int SENT_STREAM_VIDEO = 0;

    public static final int SENT_STREAM_IMAGE = 1;

    public static final int SENT_STREAM_TEXT = 2;

    public OtaManager(IOtaService mService) {
        this.mService = mService;
    }

    public int initDisplay() {
        int result = 0;
        try {
            result = mService.initDisplay();
            Slog.i("OtaManager", "IOtaService getCpuTemperature:" + result);
        } catch (RemoteException ex) {
            ex.printStackTrace();
        }
        return result;
    }

    public int setInputFlowerToDisplay(String url, int type) {
        int result = 0;
        try {
            if (type == SENT_STREAM_VIDEO) {
               result =  mService.startVideo(url);
            } else if (type == SENT_STREAM_IMAGE || type == SENT_STREAM_TEXT) {
                result =  mService.startImage(url);
            }
            Slog.i("OtaManager", "setInputFlowerToDisplay:" + result);
        } catch (RemoteException ex) {
            ex.printStackTrace();
        }
        return result;
    }

    public void openMediaCenter(){
        try {
            mService.openMediaCenter();
            Slog.i("OtaManager", "openMediaCenter");
        } catch (RemoteException ex) {
            ex.printStackTrace();
        }
    }
}

在frameworks/base/services/core/java/com/android/server/目录下,新建ota文件夹存放OtaManagerService.java是IPC层

package com.android.server.ota;

import android.hardware.display.DisplayManager;
import android.view.Display;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;


import android.app.ota.IOtaService;
import android.content.Context;
import android.util.Slog;

//测试OTA 第二步:添加系统服务,实现aidl文件的接口
public class OtaManagerService extends IOtaService.Stub {

    private Context mContext;

    private int display = 0;

    public OtaManagerService(Context context) {
        mContext = context;
        Slog.d("OTAManagerService", "Construct");
    }

    @Override
    public int initDisplay() {
            DisplayManager  mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);//屏幕管理类
            Slog.i("initDisplay-->DisplayManager", "获取DisplayManager" + mDisplayManager);
            if(mDisplayManager == null){
                return -1;
            }else{
                Display[] displays = mDisplayManager.getDisplays(); //得到显示器数组
                Slog.i("initDisplay-->Display", "获取Display显示器数组" + displays);
                if (displays != null && displays.length >= 2) {
                    display = displays[1].getDisplayId();
                    return display;
                } else {
                    return -1;
                }
            }
    }

    @Override
    public int startVideo(String url) {
        if(display == 0){
            //没有拿到屏幕信息
            Slog.i("startVideo-->display", "没有拿到屏幕信息" + display);
            return -1;
        }else{
            // 启动客显屏Activity
            Intent intent = mContext.getPackageManager().getLaunchIntentForPackage("com.darly.otamedia");
            Slog.i("startVideo-->intent", "拿到的Intent数据" + intent);
            if (intent != null) {
                intent.putExtra("video_url", url);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                ActivityOptions options = ActivityOptions.makeBasic();
                options.setLaunchDisplayId(display);
                mContext.startActivity(intent, options.toBundle());
                return 100;
            }else{
                return -1;
            }
        }
    }

    @Override
    public int startImage(String url) {
        if(display == 0){
            //没有拿到屏幕信息
            Slog.i("startImage-->display", "没有拿到屏幕信息" + display);
            return -1;
        }else{
            // 启动客显屏Activity
            Intent intent = mContext.getPackageManager().getLaunchIntentForPackage("com.darly.otamedia");
            Slog.i("startImage-->intent", "拿到的Intent数据" + intent);
            if (intent != null) {
                intent.putExtra("image_url", url);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                ActivityOptions options = ActivityOptions.makeBasic();
                options.setLaunchDisplayId(display);
                mContext.startActivity(intent, options.toBundle());
                return 100;
            }else{
                return -1;
            }
        }
    }


    @Override
    public void openMediaCenter() {
        Intent intent = mContext.getPackageManager().getLaunchIntentForPackage("com.android.htmlviewer");
        Slog.i("openMediaCenter-->intent", "拿到的Intent数据" + intent);
        if (intent != null) {
            mContext.startActivity(intent);
        }
    }
    
}

第三步:注册以及绑定

在frameworks/base/core/java/android/content/Context.java中增加新标签

    //测试OTA 第四步:添加OTA_SERVICE常量
    public static final String OTA_DM_SERVICE = "ota_dm";

在frameworks/base/core/java/android/app/SystemServiceRegistry.java中将新服务注册到系统中

//测试OTA 第五步:将实现的服务注册到系统中去
registerService(Context.OTA_DM_SERVICE,  OtaManager.class,
     new CachedServiceFetcher() {
         @Override
         public OtaManager createService(ContextImpl ctx) {
             IBinder dm = ServiceManager.getService(Context.OTA_DM_SERVICE);
             return new OtaManager(IOtaService.Stub.asInterface(dm));
         }});	

在frameworks/base/services/java/com/android/server/SystemServer.java的startOtherServices方法中进行IPC层注册和启动

        //测试OTA 第六步:将注册的服务设置成开机启动服务
        t.traceBegin("OtaManagerService");
        ServiceManager.addService(Context.OTA_DM_SERVICE, new OtaManagerService(context));
        t.traceEnd();

第四步:查看编译

首先查看Ubuntu下,修改文件的编码格式是不是UTF-8,其次查看文件权限是不是被调整。

其次进行如下操作,进行编译,将增加修改的代码编译到System.img中

source build/envsetup.sh
lunch aosp_x86-eng # 或者直接输入lunch,然后选择对应的target
make update-api # 完成后,进行整体项目编译
make -j6

编译完成后,查看对应out目录下找到img文件。

3、运行调试

情况一:有实体手机,运行烧录到手机中,测试APP中使用

OtaManager manager = (OtaManager) context.getSystemService(Context.OTA_DM_SERVICE);

获取调用,输出日志正常。

情况二:无实体手机,如果代码本地,直接启动虚拟机。测试APP中使用

OtaManager manager = (OtaManager) context.getSystemService(Context.OTA_DM_SERVICE);

进行调用,输出日志正常。


总结

其实如果只是Java代码,针对Android应用开发的朋友还是比较轻松的。AOSP 的Framework层概念比较多,有时候就是简单的一个调用,书本中能写一两页,赋予不同的名称不同的功能。看书和代码同步进行是最快的学习方式。

由于Framework层动不动就调到Native层代码,但AOSP源码超级大,导致源码查找不方便,学习成本增加。Native层代码看懂还真不容易。而且更多的是调用到内核中,更让人看不懂。所以学习Framework层,还是先从Java开始,遇到Native慢慢研究,慢慢深入,日后都是大牛。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/987857.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号