天天看點

android 5.1 添加自定義的SystemServer服務

    某些情況下,在系統研發時,需要加入自定義的SystemServer服務,以便為應用提供自定義的功能。

    下面介紹如果添加自定義的SystemServer系統服務。

    本示例基于Android 5.1版本,如果是其他的android版本,可參考。

    以自定義DDTS服務為例,步驟如下:

1、建立自定義服務的aidl檔案

    建立aidl檔案目錄:frameworks/base/core/java/android/app

    在上面的目錄下,建立IDDTSManager.aidl檔案,aidl檔案中定義需要服務實作的接口

package android.app;

interface IDDTSManager {
    boolean setValue(boolean val);
    boolean getValue();
}
           

2、把aidl檔案添加到Android.mk中參與編譯

   打開檔案:frameworks/base/Android.mk

   在“LOCAL_SRC_FILES”變量中添加aidl的檔案。建議找到“app”目錄對應的分類,并在後面添加,這樣代碼工整點。

LOCAL_SRC_FILES += \
    ......
    core/java/android/app/backup/IRestoreSession.aidl \
    core/java/android/app/usage/IUsageStatsManager.aidl \
    core/java/android/app/IDDTSManager.aidl \
    core/java/android/wipower/IWipower.aidl \
           

3、建立DDTSManagerService.java檔案實作IDDTSManager.aidl中定義的接口

    建立目錄:frameworks/base/services/core/java/com/android/server

     PS:如果服務端檔案比較多,或者想把伺服器檔案放在同一個檔案夾下,可以建立個檔案夾存放

    如:frameworks/base/services/core/java/com/android/server/DDTS,如果定義了自定義目錄,注意DDTSManagerService.java的包名

package com.android.server.DDTS
import android.content.Context;

pulic class DDTSManagerService extends IDDTSManager.stub {
    private final Context mContext;
    private boolean mVal;
    
    public DDTSManagerService(Context context) {
        mContext = context;
    }
    
    @Override
    public boolean setValue(boolean val) {
        mVal = val;
        return true;
    }
    
    @Override
    public boolean getValue() {
        return mVal;
    }
}
           

4、在SystemServer中注冊自定義的Service

    打開檔案:frameworks/base/services/java/com/android/server/SystemServer.java

    在private void startOtherServices()函數中添加自定義的Service

try {
    Slog.i(TAG,"DDTS Service");
    ServiceManager.addService(Context.DDTS_SERVICE, new DDTSManagerService(context));
} catch (Throwable e) {
    reportWtf("starting DDTS Service fail:",e);
}
           

在addService中的Context.DDTS_SERVICE為服務端的名稱。

DDTS_SERVICE要在Context.java中添加

打開檔案:frameworks/base/core/java/android/content/Context.java

添加

public static final String DDTS_SERVICE = "ddts";
           

5、建立DDTSManager.java檔案

      DDTSManager.java主要是給應用調用的類,DDTSManager通過binder調用到DDTSManagerService實作的aidl接口。完成最終的服務。

     建立目錄:frameworks/base/core/java/android/app

package android.app;
import android.content.Context;

public class DDTSManager
{
    private static IDDTSManager mService;
    private final Context mContext;
    
    DDTSManager(Context context) {
        mContext = context;
        mService = IDDTSManager.Stub.asInterface(ServiceManager.getService(Context.DDTS_SERVICE));
    }
    
    public boolean setValue(boolean val) {
        try {
            return mService.setValue(val);
        } catch (RemoteException e){
            return false;
        }
    }
    
    public boolean getValue() {
        try {
            return mService.getValue();
        } catch (RemoteException e){
            return false;
        }
    }
}
           

6、把DDTSManager注冊到ContextImpl中

     在ContextImpl.java中的static{}代碼中,添加注冊代碼,DDTSManager通過registerService函數注冊服務,這樣應用可以調用getSystemService擷取到DDTSManager,進而調用DDTSManager中的接口,最終調用到DDTSManagerService

registerService(DDTS_SERVICE,new ServiceFetcher() {
        public Object createService(ContextImpl ctx) {
            return new DDTSManager(ctx.getOuterContext());
        }});
           

7、添加SELinux Policy權限

    打開檔案:external/sepolicy/service_contexts

    在檔案中添加:

ddts   u:object_r:system_server_service:s0
           

   其中:ddts為SystemServer注冊服務時ServiceManager.addService函數中的Context.DDTS_SERVICE,也就是服務的名稱。

8、編譯framework.jar和Service.jar,并替換手機中的相應jar包。

寫一個apk測試服務是否能用。

1、在Android studio中建立一個android library的項目。

     包名命名為:android.app(這個包名必須和DDTSManager.java的包名一緻)

    并在android/app目錄下建立一個java檔案,檔案名稱和内容與DDTSManager.java一緻。

    建立這個工程主要是因為要得到一個DDTSManager檔案對應的jar,把這個jar包放在apk工程中,這樣編譯apk時不會報錯。

2、建立一個apk工程,并把DDTSManager檔案對應的jar包放入到apk工程的libs目錄下。

     把apk工程中的build.gradle檔案的dependecies中增加provided依賴

dependencies {
    provided fileTree(include: ['*.jar'], dir: 'libs')
    //compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
    compile files('libs/DDTSManager.jar')
}
           

編譯好apk後,就可以在手機上驗證了。