您的位置:首页 > 移动开发 > Android开发

在android源码中添加库模块&&jni实例二

2011-12-15 17:57 555 查看
AndroidManifest.xml 根据Android的make file的结构,我们可以在源码中方便的添加Native Lib,linux application,java application,这些都可以在源代码中添加,并且进行编译。后面三个类型模块的添加,编译都会举出简单的例子,具体一些一些做法的原理,还需要继续研究,下面将开始介绍如何添加以上三种模块到我们的android source中。

1. Native Lib的添加

这里对于本地库的引用原来对于JNI实例的说明:

本地库的编写,我选择在android的源代码中进行。在源码中,development目录下建立一个testjni的文件夹,

里面创建2个文件,一个是testjni.c一个Android.mk文件,前者是本地库的c语言实现,Android.mk是makefile文件,用于

*.so的生成。

testjni.c的内容为:

#include <jni.h>

#define LOG_TAG "testjni"

#undef LOG

#include <utils/Log.h>

JNIEXPORT void JNICALL Java_com_test_TestJNI_TestJNI_testjniprint

(JNIEnv * env, jobject jobj)

{

LOGE("********testjni!!!**********s\n");

}

Android.mk的内容为:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

testjni.c

LOCAL_C_INCLUDES := \

$(JNI_H_INCLUDE)

LOCAL_SHARED_LIBRARIES := \

libutils

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := libtestjni

include $(BUILD_SHARED_LIBRARY)

mk文件的编写可以参考源码中的samplejni里面的进行编写。

注意本地库函数的命名,com_test_TestJNI是包的名自,TestJNI是类名, testjniprint为方法名。

编译:

source code目录下,make libtestjni,编译后,可以在out/target/product/generic/system/lib/目录下找到 libtestjni.so这个库,但是,system.img没有被更新,要更新img直接make,或者用rootfs的文件去制作img文件。

对于本地库,建立的文件的位置,我将这个文件夹在development目录下放过,其他目录没有放过进行过实验,但是根据Android的 makefile的原理,只要Android.mk的编写没有问题,就可以了,对于具体模块的源文件放置的位置,没有什么影响,但是以后具体工作的时候,相应的模块还是需要放在一起,这样便于代码的管理和阅读。

2. linux application的添加

同样,我在多个目录下都进行过实验,都可以正确编译出执行的可以运行的linux bin,生成的bin在rootfs中的都是system/bin目录下。

在development目录下建立一个hello目录:里面2个文件,hello.c Android.mk

hello.c:

#include <stdio.h>

void main()

{

printf("helloworld this is makefile test!\n");

}

非常简单的一个C程序。

Android.mk:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

hello.c

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := hellomakefile

include $(BUILD_EXECUTABLE)

然后在根目录:make hellomakefile在system/bin文件夹下生成linux的运行程序。导入emulator可以正常运行。

3. java application的添加

java应用程序我把文件夹建立在了packages/apps下,建立了一个Helloworld的文件夹,里面有2个文件夹,2个文件,2个文件夹分别为:src源代码文件夹,res资源文件,实验过,这个资源文件是不能缺少的,资源文件夹,我是通过 eclipse自动建立的**中copy出来的。二个文件就是Android.mk和AndroidManifest.xml,前面的文件是java应用程序的makefile,后面的文件是从eclipse**中copy过来的,里面记录了一些app的信息。

src的文件夹结构,按照java原文件中的打包规则进行建立,在src中,eclipse中自动生成的**有R.java这个文件,但是在 android source这个结构里,不需要这个文件,否则编译会提示重复定义。

Helloworld.java:

package com.app.Helloworld;

import android.app.Activity;

import android.os.Bundle;

public class Helloworld extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

}

源文件的内容就是eclipse自动生成的内容。

Android.mk:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS = eng development

LOCAL_SRC_FILES := $(call all-subdir-java-files)

LOCAL_PACKAGE_NAME := Helloworld

include $(BUILD_PACKAGE)

编译是make Helloworld就可以了,在out/target/product/generic/system/app目录下面就可以找到我们新添加的app的 apk了。app中的makefile都需要一个LOCAL_MODULE_TAGS 的宏,这个宏的值有几种:eng,user,optional,development,这几种,而且在makefile中没有这个编译宏,编译过程也是不能过去的,但是对于这个tegs的作用,以及这几个赋值的区别,还需要进一步研究。

总结:三种模块的添加编译,其实都是差不多的,关键就是在于make对于Android.mk的遍历,以及Android.mk中绿字的部分,他们决定了 make的时候编译工具的选择,以及生成文件的输出路径。库有库的标识,上层java应用有上层java应用的标识。具体不同模块的makefile,具体必须有什么内容,后面还需要继续深入研究。

=======================================================================

=======

在编译自己的Android library时可能会出现

library 'XXX.so' not in prelink map 错误,

这是由于Android的预编译设置引起的,/build/core/prelink-linux-arm.map文件描述了预编译的模块

需要修改所在文件夹下的android.mk文件

增加

LOCAL_PRELINK_MODULE := false

将预编译关闭,即可通过。

====================================================================================

/*  HelloWorld.c  */

#include"jni.h"

#include"HelloWorld.h"

#include<stdio.h>
#include<stdlib.h>

JNIEXPORT jstring JNICALL Java_com_demo_jni_JNIActivity_stringFromJNI(JNIEnv *env,jobject obj)

{

return  (*env)->NewStringUTF(env,"Hello from JNI ********* !");

}
/* HelloWorld.h  ava java 生成的头文件  */

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_demo_jni_JNIActivity */

#ifndef _Included_com_demo_jni_JNIActivity
#define _Included_com_demo_jni_JNIActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     com_demo_jni_JNIActivity
* Method:    stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_demo_jni_JNIActivity_stringFromJNI
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


Android.mk文件

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libhello

LOCAL_SRC_FILES := HelloWorld.c

#include $(BUILD_EXECUTABLE)

LOCAL_PRELINK_MODULE := false

include $(BUILD_SHARED_LIBRARY)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: