Android Framework学习

161 阅读2分钟

SoDemo:

1、编写so动态库

#include <string>
class LoginClient
{
private:
    /* data */
public:
    LoginClient(std::string str);
    ~LoginClient();
    
    int getCount();
};
#include "LoginClient.hpp"

LoginClient::LoginClient(std::string str){
    
}

int LoginClient::getCount(){
    return 1;
}

LoginClient::~LoginClient(){
    
}
// 应该没什么用的主函数
#include "LoginClient.hpp"

int main(){
    LoginClient client("hello");
    client.getCount();
    return 1;
}
cc_library_shared {
    name:"libTestLoginService",
    local_include_dirs:[
        "cpp"
    ],
    srcs:[
        "cpp/LoginClient.cpp",
        "cpp/Server.cpp"
    ],
    // 暴露cpp目录下的所有文件,用来在JNI层直接调用cpp目录下的.cpp文件
    // 与java调用so库的方式不同
    export_include_dirs:[
        "cpp"
    ],
    // 用来编译32位和64位
    compile_multilib:"both"
}

项目结构: image.png

2、Jni层

JNI层也会编译出一个动态so库,同时也可以生成lib的jar包,用来其他app直接调用

#include <android/log.h>
#include <jni.h>
// 调用so库
#include "../../server/cpp/LoginClient.hpp"

extern "C"
JNIEXPORT jint JNICALL
Java_com_yfve_sodemo_LoginManager_nativeGetCount(JNIEnv *env, jobject thiz) {
    LoginClient client("hello111");
    return client.getCount();
}
package com.exp.sodemo;

public interface LoginInterface {
    int count();
}
package com.exp.sodemo;

public class LoginManager implements LoginInterface{
    public LoginManager() {
        // 这里的加载的so库名与定义的不同,少了前缀lib,需要注意
        System.loadLibrary("TestLoginServiceJNI");
    }

    @Override
    public int count() {
        return nativeGetCount();
    }

    native int nativeGetCount();
}
// 编译jni的.so
cc_library_shared {
    name:"libTestLoginServiceJNI",
    srcs:[
        "cpp/LoginClientJNI.cpp"
    ],
    shared_libs:[
        "libTestLoginService"
    ]
}

// 编译.jar
java_binary {
    name : "LoginSoDemo",
    srcs : [
        "java/**/*.java"
    ]
}

项目结构: image.png

lib库的顶层mk文件:

LOCAL_MULTILIB := both
PRODUCT_PACKETS += \
    LoginSoDemo \
    libTestLoginServiceJNI \
    libTestLoginService 

app调用:

直接导入jar包使用即可,需要注意的点是:app的mk文件中 需要添加:

LOCAL_STATIC_JAVA_LIBRARIES += \
        LoginSoDemo

整个项目的结构:

image.png

app的mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-java-files-under, app/src/main)
LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/app/src/main/res
# system cert
LOCAL_CERTIFICATE := platform

LOCAL_PACKAGE_NAME := SoTestDemo

LOCAL_PRIVATE_PLATFORM_APIS := true

LOCAL_MODULE_TAGS := optional

LOCAL_PROGUARD_ENABLED := disabled

LOCAL_DEX_PREOPT := false

LOCAL_USE_AAPT2 := true

LOCAL_STATIC_JAVA_LIBRARIES += \
        LoginSoDemo

LOCAL_STATIC_ANDROID_LIBRARIES := \
        com.google.android.material_material \
        androidx.appcompat_appcompat

include $(BUILD_PACKAGE)

顶层mk:

# 包含路径下的两个mk文件
-include vendor/soDemo/SoTestDemo/Android.mk
-include vendor/lib/SoTestDemo/Android.mk

这里即为一个小型的framework的jar包的整个流程,app调用jar包,jar包调用jni层去访问hal层底层的数据,如一些硬件层的读写。